In some parts of Madwifi, SKBs are dispatched from the VAP device to the physical...
authormentor <mentor@0192ed92-7a03-0410-a25b-9323aeb14dbd>
Fri, 6 Jun 2008 19:21:33 +0000 (19:21 +0000)
committermentor <mentor@0192ed92-7a03-0410-a25b-9323aeb14dbd>
Fri, 6 Jun 2008 19:21:33 +0000 (19:21 +0000)
However, the netif_rx and vlan_hwaccel_receive_skb functions dispatch the SKB to the higher networking levels, out of our domain.

Therefore, handle node references as appropriate.

git-svn-id: http://madwifi-project.org/svn/madwifi/trunk@3708 0192ed92-7a03-0410-a25b-9323aeb14dbd

net80211/ieee80211_input.c
net80211/ieee80211_monitor.c

index ae306f95cf5e7449c626cfaf1c4f2e39c2753251..14e539d7a1aab6d3dcbb142e05b227b38d371536 100644 (file)
@@ -1103,7 +1103,7 @@ ieee80211_deliver_data(struct ieee80211_node *ni, struct sk_buff *skb)
 {
        struct ieee80211vap *vap = ni->ni_vap;
        struct net_device *dev = vap->iv_dev;
-       struct ether_header *eh = (struct ether_header *) skb->data;
+       struct ether_header *eh = (struct ether_header *)skb->data;
        struct ieee80211_node *tni;
        int ret;
 
@@ -1149,19 +1149,21 @@ ieee80211_deliver_data(struct ieee80211_node *ni, struct sk_buff *skb)
                        }
                }
                if (skb1 != NULL) {
-                       struct ieee80211_node *tni;
                        skb1->dev = dev;
                        skb_reset_mac_header(skb1);
                        skb_set_network_header(skb1, sizeof(struct ether_header));
 
                        skb1->protocol = __constant_htons(ETH_P_802_2);
+
+                       /* This SKB is being emitted to the physical/parent
+                        * device, which maintains node references. However,
+                        * there is kernel code in between which does not.
+                        * Therefore, the ref. is cleaned if the SKB is
+                        * dropped. */
+                       tni = SKB_NI(skb1);
                        /* XXX: Insert vlan tag before queuing it? */
-                       tni = SKB_NI(skb1); /* Remember node so we can free it. */
                        if (dev_queue_xmit(skb1) == NET_XMIT_DROP) {
-                               /* If queue dropped the packet because device
-                                * was too busy */
                                vap->iv_devstats.tx_dropped++;
-                               /* node reference was leaked */
                                if (tni != NULL)
                                        ieee80211_unref_node(&tni);
                        }
@@ -1188,12 +1190,10 @@ ieee80211_deliver_data(struct ieee80211_node *ni, struct sk_buff *skb)
                                        vap->iv_vlgrp, ni->ni_vlan);
                else
                        ret = netif_rx(skb);
-               if (ret == NET_RX_DROP) {
-                       /* Cleanup if passing SKB to ourselves failed. */
-                       if (tni != NULL)
-                               ieee80211_unref_node(&tni);
+               if (ret == NET_RX_DROP)
                        vap->iv_devstats.rx_dropped++;
-               }
+               if (tni != NULL)
+                       ieee80211_unref_node(&tni);
                skb = NULL; /* SKB is no longer ours */
        }
 }
@@ -2285,18 +2285,13 @@ forward_mgmt_to_app(struct ieee80211vap *vap, int subtype, struct sk_buff *skb,
                skb1->pkt_type = PACKET_OTHERHOST;
                skb1->protocol = __constant_htons(0x0019);  /* ETH_P_80211_RAW */
 
-               tni = SKB_NI(skb1);
-               if (netif_rx(skb1) == NET_RX_DROP) {
-                       /* If netif_rx dropped the packet because 
-                        * device was too busy */
-                       if (tni != NULL) {
-                               /* node reference was leaked */
-                               ieee80211_unref_node(&tni);
-                       }
-                       vap->iv_devstats.rx_dropped++;
-               }
                vap->iv_devstats.rx_packets++;
                vap->iv_devstats.rx_bytes += skb1->len;
+
+               if (SKB_NI(skb1) != NULL)
+                       ieee80211_unref_node(&SKB_NI(skb1));
+               if (netif_rx(skb1) == NET_RX_DROP)
+                       vap->iv_devstats.rx_dropped++;
        }
 }
 
index 04457ed73843dd38ff748aa83ca44e22fe7c9c0b..4dc60f69f0d7705bc973a95e56c6b9e8eb3bad80 100644 (file)
@@ -302,6 +302,7 @@ ieee80211_input_monitor(struct ieee80211com *ic, struct sk_buff *skb,
        int noise = 0, antenna = 0, ieeerate = 0;
        u_int32_t rssi = 0;
        u_int8_t pkttype = 0;
+
        if (tx) {
                rssi = bf->bf_dsstatus.ds_txstat.ts_rssi;
                antenna = bf->bf_dsstatus.ds_txstat.ts_antenna;
@@ -574,17 +575,14 @@ ieee80211_input_monitor(struct ieee80211com *ic, struct sk_buff *skb,
                        skb1->protocol = 
                                __constant_htons(0x0019); /* ETH_P_80211_RAW */
 
-                       if (netif_rx(skb1) == NET_RX_DROP) {
-                               /* If netif_rx dropped the packet because 
-                                * device was too busy, reclaim the ref. in 
-                                * the skb. */
-                               if (SKB_NI(skb1) != NULL)
-                                       ieee80211_unref_node(&SKB_NI(skb1));
-                               vap->iv_devstats.rx_dropped++;
-                       }
-
                        vap->iv_devstats.rx_packets++;
                        vap->iv_devstats.rx_bytes += skb1->len;
+
+                       if (SKB_NI(skb1) != NULL)
+                               ieee80211_unref_node(&SKB_NI(skb1));
+                       if (netif_rx(skb1) == NET_RX_DROP)
+                               vap->iv_devstats.rx_dropped++;
+                       skb1 = NULL;
                }
        }
 }