]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: mac80211: refactor ieee80211_rx_monitor
authorFelix Fietkau <nbd@nbd.name>
Wed, 9 Oct 2024 08:25:51 +0000 (10:25 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 23 Oct 2024 14:46:26 +0000 (16:46 +0200)
Rework the monitor mode interface iteration to get rid of the last_monitor
condition. Preparation for further filtering received monitor packets.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
Link: https://patch.msgid.link/d57d82f109643894325beb9db6da8f001fc533eb.1728462320.git-series.nbd@nbd.name
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/rx.c

index d032bfb00ade24366db549bbc6a0be5d0deee127..4849af232ee6fb8923dc200fa2ebfedf649639b1 100644 (file)
@@ -762,8 +762,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
                     struct ieee80211_rate *rate)
 {
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb);
-       struct ieee80211_sub_if_data *sdata;
-       struct sk_buff *monskb = NULL;
+       struct ieee80211_sub_if_data *sdata, *prev_sdata = NULL;
+       struct sk_buff *skb, *monskb = NULL;
        int present_fcs_len = 0;
        unsigned int rtap_space = 0;
        struct ieee80211_sub_if_data *monitor_sdata =
@@ -837,8 +837,10 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
        ieee80211_handle_mu_mimo_mon(monitor_sdata, origskb, rtap_space);
 
        list_for_each_entry_rcu(sdata, &local->mon_list, u.mntr.list) {
-               bool last_monitor = list_is_last(&sdata->u.mntr.list,
-                                                &local->mon_list);
+               if (!prev_sdata) {
+                       prev_sdata = sdata;
+                       continue;
+               }
 
                if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
                        ieee80211_handle_mu_mimo_mon(sdata, origskb, rtap_space);
@@ -846,34 +848,34 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
                if (!monskb)
                        monskb = ieee80211_make_monitor_skb(local, &origskb,
                                                            rate, rtap_space,
-                                                           only_monitor &&
-                                                           last_monitor);
+                                                           false);
+               if (!monskb)
+                       continue;
 
-               if (monskb) {
-                       struct sk_buff *skb;
+               skb = skb_clone(monskb, GFP_ATOMIC);
+               if (!skb)
+                       continue;
 
-                       if (last_monitor) {
-                               skb = monskb;
-                               monskb = NULL;
-                       } else {
-                               skb = skb_clone(monskb, GFP_ATOMIC);
-                       }
+               skb->dev = prev_sdata->dev;
+               dev_sw_netstats_rx_add(skb->dev, skb->len);
+               netif_receive_skb(skb);
+               prev_sdata = sdata;
+       }
 
-                       if (skb) {
-                               skb->dev = sdata->dev;
-                               dev_sw_netstats_rx_add(skb->dev, skb->len);
-                               netif_receive_skb(skb);
-                       }
+       if (prev_sdata) {
+               if (monskb)
+                       skb = monskb;
+               else
+                       skb = ieee80211_make_monitor_skb(local, &origskb,
+                                                        rate, rtap_space,
+                                                        only_monitor);
+               if (skb) {
+                       skb->dev = prev_sdata->dev;
+                       dev_sw_netstats_rx_add(skb->dev, skb->len);
+                       netif_receive_skb(skb);
                }
-
-               if (last_monitor)
-                       break;
        }
 
-       /* this happens if last_monitor was erroneously false */
-       dev_kfree_skb(monskb);
-
-       /* ditto */
        if (!origskb)
                return NULL;