aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2017-02-27 03:38:11 -0500
committerJohannes Berg <johannes.berg@intel.com>2017-02-28 01:42:05 -0500
commit19d19e960598161be92a7e4828eb7706c6410ce6 (patch)
tree883afa1a2e507d58d32c5340b73a3fb2be40d574 /net
parentff4dd73dd2b4806419f8ff65cbce11d5019548d0 (diff)
mac80211: use driver-indicated transmitter STA only for data frames
When I originally introduced using the driver-indicated station as an optimisation to avoid the hashtable lookup/iteration, of course it wasn't intended to really functionally change anything. I neglected, however, to take into account VLAN interfaces, which have the property that management and data frames are handled differently: data frames go directly to the station and the VLAN while management frames continue to be processed over the underlying/associated AP-type interface. As a consequence, when a driver used this optimisation for management frames and the user enabled VLANs, my change broke things since any management frames, particularly disassoc/deauth, were missed by hostapd. Fix this by restoring the original code path for non-data frames, they aren't critical for performance to begin with. This fixes https://bugzilla.kernel.org/show_bug.cgi?id=194713. Big thanks goes to Jarek who bisected the issue and provided a very detailed bug report, including the crucial information that he was using VLANs in his configuration. Cc: stable@vger.kernel.org Fixes: 771e846bea9e ("mac80211: allow passing transmitter station on RX") Reported-and-tested-by: Jarek KamiƄski <jarek@freeside.be> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/rx.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 28cc494a774d..e48724a6725e 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -4086,15 +4086,17 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
4086 ieee80211_is_beacon(hdr->frame_control))) 4086 ieee80211_is_beacon(hdr->frame_control)))
4087 ieee80211_scan_rx(local, skb); 4087 ieee80211_scan_rx(local, skb);
4088 4088
4089 if (pubsta) { 4089 if (ieee80211_is_data(fc)) {
4090 rx.sta = container_of(pubsta, struct sta_info, sta);
4091 rx.sdata = rx.sta->sdata;
4092 if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
4093 return;
4094 goto out;
4095 } else if (ieee80211_is_data(fc)) {
4096 struct sta_info *sta, *prev_sta; 4090 struct sta_info *sta, *prev_sta;
4097 4091
4092 if (pubsta) {
4093 rx.sta = container_of(pubsta, struct sta_info, sta);
4094 rx.sdata = rx.sta->sdata;
4095 if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
4096 return;
4097 goto out;
4098 }
4099
4098 prev_sta = NULL; 4100 prev_sta = NULL;
4099 4101
4100 for_each_sta_info(local, hdr->addr2, sta, tmp) { 4102 for_each_sta_info(local, hdr->addr2, sta, tmp) {