From f259deab931b36f85048a8d21272b2a9a4071954 Mon Sep 17 00:00:00 2001 From: mentor Date: Fri, 6 Jun 2008 19:21:33 +0000 Subject: [PATCH] In some parts of Madwifi, SKBs are dispatched from the VAP device to the physical device using Linux kernel queuing, which does not understand our node reference system, so node references are carefully cleaned up if the packet is dropped. 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 | 37 ++++++++++++++++-------------------- net80211/ieee80211_monitor.c | 16 +++++++--------- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/net80211/ieee80211_input.c b/net80211/ieee80211_input.c index ae306f9..14e539d 100644 --- a/net80211/ieee80211_input.c +++ b/net80211/ieee80211_input.c @@ -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++; } } diff --git a/net80211/ieee80211_monitor.c b/net80211/ieee80211_monitor.c index 04457ed..4dc60f6 100644 --- a/net80211/ieee80211_monitor.c +++ b/net80211/ieee80211_monitor.c @@ -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; } } }