]> git.karo-electronics.de Git - linux-beck.git/blobdiff - net/mac80211/status.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[linux-beck.git] / net / mac80211 / status.c
index 3ed7ddfbf8e840d4c910b0e9452c06843031c91d..9169ccc36534bc308132166797c3e61e7271feba 100644 (file)
@@ -669,16 +669,70 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_tx_status_noskb);
 
-void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
+void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb,
+                         struct ieee80211_supported_band *sband,
+                         int retry_count, int shift, bool send_to_cooked)
 {
        struct sk_buff *skb2;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_sub_if_data *sdata;
+       struct net_device *prev_dev = NULL;
+       int rtap_len;
+
+       /* send frame to monitor interfaces now */
+       rtap_len = ieee80211_tx_radiotap_len(info);
+       if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
+               pr_err("ieee80211_tx_status: headroom too small\n");
+               dev_kfree_skb(skb);
+               return;
+       }
+       ieee80211_add_tx_radiotap_header(local, sband, skb, retry_count,
+                                        rtap_len, shift);
+
+       /* XXX: is this sufficient for BPF? */
+       skb_set_mac_header(skb, 0);
+       skb->ip_summed = CHECKSUM_UNNECESSARY;
+       skb->pkt_type = PACKET_OTHERHOST;
+       skb->protocol = htons(ETH_P_802_2);
+       memset(skb->cb, 0, sizeof(skb->cb));
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+               if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
+                       if (!ieee80211_sdata_running(sdata))
+                               continue;
+
+                       if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) &&
+                           !send_to_cooked)
+                               continue;
+
+                       if (prev_dev) {
+                               skb2 = skb_clone(skb, GFP_ATOMIC);
+                               if (skb2) {
+                                       skb2->dev = prev_dev;
+                                       netif_rx(skb2);
+                               }
+                       }
+
+                       prev_dev = sdata->dev;
+               }
+       }
+       if (prev_dev) {
+               skb->dev = prev_dev;
+               netif_rx(skb);
+               skb = NULL;
+       }
+       rcu_read_unlock();
+       dev_kfree_skb(skb);
+}
+
+void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
        struct ieee80211_local *local = hw_to_local(hw);
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        __le16 fc;
        struct ieee80211_supported_band *sband;
-       struct ieee80211_sub_if_data *sdata;
-       struct net_device *prev_dev = NULL;
        struct sta_info *sta;
        struct rhash_head *tmp;
        int retry_count;
@@ -686,7 +740,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
        bool send_to_cooked;
        bool acked;
        struct ieee80211_bar *bar;
-       int rtap_len;
        int shift = 0;
        int tid = IEEE80211_NUM_TIDS;
        const struct bucket_table *tbl;
@@ -879,51 +932,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
                return;
        }
 
-       /* send frame to monitor interfaces now */
-       rtap_len = ieee80211_tx_radiotap_len(info);
-       if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
-               pr_err("ieee80211_tx_status: headroom too small\n");
-               dev_kfree_skb(skb);
-               return;
-       }
-       ieee80211_add_tx_radiotap_header(local, sband, skb, retry_count,
-                                        rtap_len, shift);
-
-       /* XXX: is this sufficient for BPF? */
-       skb_set_mac_header(skb, 0);
-       skb->ip_summed = CHECKSUM_UNNECESSARY;
-       skb->pkt_type = PACKET_OTHERHOST;
-       skb->protocol = htons(ETH_P_802_2);
-       memset(skb->cb, 0, sizeof(skb->cb));
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-               if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
-                       if (!ieee80211_sdata_running(sdata))
-                               continue;
-
-                       if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) &&
-                           !send_to_cooked)
-                               continue;
-
-                       if (prev_dev) {
-                               skb2 = skb_clone(skb, GFP_ATOMIC);
-                               if (skb2) {
-                                       skb2->dev = prev_dev;
-                                       netif_rx(skb2);
-                               }
-                       }
-
-                       prev_dev = sdata->dev;
-               }
-       }
-       if (prev_dev) {
-               skb->dev = prev_dev;
-               netif_rx(skb);
-               skb = NULL;
-       }
-       rcu_read_unlock();
-       dev_kfree_skb(skb);
+       /* send to monitor interfaces */
+       ieee80211_tx_monitor(local, skb, sband, retry_count, shift, send_to_cooked);
 }
 EXPORT_SYMBOL(ieee80211_tx_status);