mac80211: fix vlan and optimise RX
authorJohannes Berg <johannes@sipsolutions.net>
Thu, 1 Oct 2009 20:06:29 +0000 (22:06 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 7 Oct 2009 20:33:49 +0000 (16:33 -0400)
When receiving data frames, we can send them only to
the interface they belong to based on transmitting
station (this doesn't work for probe requests). Also,
don't try to handle other frames for AP_VLAN at all
since those interface should only receive data.

Additionally, the transmit side must check that the
station we're sending a frame to is actually on the
interface we're transmitting on, and not transmit
packets to functions that live on other interfaces,
so validate that as well.

Another bug fix is needed in sta_info.c where in the
VLAN case when adding/removing stations we overwrite
the sdata variable we still need.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: stable@kernel.org
Signed-off-by: John W. Linville <linville@tuxdriver.com>
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/tx.c

index c01588f9d453595bb1f36e05c8c418171ff1211b..865fbc09be1adbca316e06c44beb485b4a46cef9 100644 (file)
@@ -2164,11 +2164,17 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 
        skb = rx.skb;
 
 
        skb = rx.skb;
 
-       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+       if (rx.sdata && ieee80211_is_data(hdr->frame_control)) {
+               rx.flags |= IEEE80211_RX_RA_MATCH;
+               prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
+               if (prepares)
+                       prev = rx.sdata;
+       } else list_for_each_entry_rcu(sdata, &local->interfaces, list) {
                if (!netif_running(sdata->dev))
                        continue;
 
                if (!netif_running(sdata->dev))
                        continue;
 
-               if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+               if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
+                   sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
                        continue;
 
                rx.flags |= IEEE80211_RX_RA_MATCH;
                        continue;
 
                rx.flags |= IEEE80211_RX_RA_MATCH;
index eec001491e66f6bfba75ca7bf41d22d9563c6788..594f2318c3d82daf25dfac1cc387ac01500f0dc8 100644 (file)
@@ -361,6 +361,7 @@ int sta_info_insert(struct sta_info *sta)
                                             u.ap);
 
                drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta);
                                             u.ap);
 
                drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta);
+               sdata = sta->sdata;
        }
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
        }
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
@@ -496,6 +497,7 @@ static void __sta_info_unlink(struct sta_info **sta)
 
                drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE,
                               &(*sta)->sta);
 
                drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE,
                               &(*sta)->sta);
+               sdata = (*sta)->sdata;
        }
 
        if (ieee80211_vif_is_mesh(&sdata->vif)) {
        }
 
        if (ieee80211_vif_is_mesh(&sdata->vif)) {
index fd40282966132d9c76719bda986732ce4d511bc5..db4bda681ec97f49c60162c923513219629840b8 100644 (file)
@@ -1704,7 +1704,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
        if (!is_multicast_ether_addr(hdr.addr1)) {
                rcu_read_lock();
                sta = sta_info_get(local, hdr.addr1);
        if (!is_multicast_ether_addr(hdr.addr1)) {
                rcu_read_lock();
                sta = sta_info_get(local, hdr.addr1);
-               if (sta)
+               /* XXX: in the future, use sdata to look up the sta */
+               if (sta && sta->sdata == sdata)
                        sta_flags = get_sta_flags(sta);
                rcu_read_unlock();
        }
                        sta_flags = get_sta_flags(sta);
                rcu_read_unlock();
        }