aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-10-01 16:06:29 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-10-07 16:33:49 -0400
commitfbc44bf7177dfd61381da55405550b693943a432 (patch)
tree9869e534f828dd3377cffd2917dfdb6cc72023d3 /net
parent727c988593271599c9e5943699426afcce1a62d6 (diff)
mac80211: fix vlan and optimise RX
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>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/rx.c10
-rw-r--r--net/mac80211/sta_info.c2
-rw-r--r--net/mac80211/tx.c3
3 files changed, 12 insertions, 3 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index c01588f9d453..865fbc09be1a 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2164,11 +2164,17 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2164 2164
2165 skb = rx.skb; 2165 skb = rx.skb;
2166 2166
2167 list_for_each_entry_rcu(sdata, &local->interfaces, list) { 2167 if (rx.sdata && ieee80211_is_data(hdr->frame_control)) {
2168 rx.flags |= IEEE80211_RX_RA_MATCH;
2169 prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
2170 if (prepares)
2171 prev = rx.sdata;
2172 } else list_for_each_entry_rcu(sdata, &local->interfaces, list) {
2168 if (!netif_running(sdata->dev)) 2173 if (!netif_running(sdata->dev))
2169 continue; 2174 continue;
2170 2175
2171 if (sdata->vif.type == NL80211_IFTYPE_MONITOR) 2176 if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
2177 sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
2172 continue; 2178 continue;
2173 2179
2174 rx.flags |= IEEE80211_RX_RA_MATCH; 2180 rx.flags |= IEEE80211_RX_RA_MATCH;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index eec001491e66..594f2318c3d8 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -361,6 +361,7 @@ int sta_info_insert(struct sta_info *sta)
361 u.ap); 361 u.ap);
362 362
363 drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta); 363 drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta);
364 sdata = sta->sdata;
364 } 365 }
365 366
366#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 367#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
@@ -496,6 +497,7 @@ static void __sta_info_unlink(struct sta_info **sta)
496 497
497 drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, 498 drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE,
498 &(*sta)->sta); 499 &(*sta)->sta);
500 sdata = (*sta)->sdata;
499 } 501 }
500 502
501 if (ieee80211_vif_is_mesh(&sdata->vif)) { 503 if (ieee80211_vif_is_mesh(&sdata->vif)) {
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index fd4028296613..db4bda681ec9 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1704,7 +1704,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1704 if (!is_multicast_ether_addr(hdr.addr1)) { 1704 if (!is_multicast_ether_addr(hdr.addr1)) {
1705 rcu_read_lock(); 1705 rcu_read_lock();
1706 sta = sta_info_get(local, hdr.addr1); 1706 sta = sta_info_get(local, hdr.addr1);
1707 if (sta) 1707 /* XXX: in the future, use sdata to look up the sta */
1708 if (sta && sta->sdata == sdata)
1708 sta_flags = get_sta_flags(sta); 1709 sta_flags = get_sta_flags(sta);
1709 rcu_read_unlock(); 1710 rcu_read_unlock();
1710 } 1711 }