aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/sta_info.h
diff options
context:
space:
mode:
authorGuy Eilam <guy@wizery.com>2011-08-17 08:18:15 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-08-26 10:47:55 -0400
commit2a33bee2753bf28411de8822e3e3c7501966eb1b (patch)
treedac6419b65bdd79da56c6855bbf4a439f424e05c /net/mac80211/sta_info.h
parent8c71df7a2f6a5345d6cad34e810c50edeca81521 (diff)
mac80211: fix race condition between assoc_done and first EAP packet
When associating to an AP, the station might miss the first EAP packet that the AP sends due to a race condition between the association success procedure and the rx flow in mac80211. In such cases, the packet might fall in ieee80211_rx_h_check due to the fact that the relevant rx->sta wasn't allocated yet. Allocation of the relevant station info struct before actually sending the association request and setting it with a new dummy_sta flag solve this problem. The station will accept only EAP packets from the AP while it is in the pre-association/dummy state. This dummy station entry is not seen by normal sta_info_get() calls, only by sta_info_get_bss_rx(). The driver is not notified for the first insertion of the dummy station. The driver is notified only after the association is complete and the dummy flag is removed from the station entry. That way, all the rest of the code flow should be untouched by this change. Signed-off-by: Guy Eilam <guy@wizery.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/sta_info.h')
-rw-r--r--net/mac80211/sta_info.h30
1 files changed, 29 insertions, 1 deletions
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 28beb78e601e..e9eb565506da 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -238,10 +238,12 @@ struct sta_ampdu_mlme {
238 * @plink_timer: peer link watch timer 238 * @plink_timer: peer link watch timer
239 * @plink_timer_was_running: used by suspend/resume to restore timers 239 * @plink_timer_was_running: used by suspend/resume to restore timers
240 * @debugfs: debug filesystem info 240 * @debugfs: debug filesystem info
241 * @sta: station information we share with the driver
242 * @dead: set to true when sta is unlinked 241 * @dead: set to true when sta is unlinked
243 * @uploaded: set to true when sta is uploaded to the driver 242 * @uploaded: set to true when sta is uploaded to the driver
244 * @lost_packets: number of consecutive lost packets 243 * @lost_packets: number of consecutive lost packets
244 * @dummy: indicate a dummy station created for receiving
245 * EAP frames before association
246 * @sta: station information we share with the driver
245 */ 247 */
246struct sta_info { 248struct sta_info {
247 /* General information, mostly static */ 249 /* General information, mostly static */
@@ -336,6 +338,9 @@ struct sta_info {
336 338
337 unsigned int lost_packets; 339 unsigned int lost_packets;
338 340
341 /* should be right in front of sta to be in the same cache line */
342 bool dummy;
343
339 /* keep last! */ 344 /* keep last! */
340 struct ieee80211_sta sta; 345 struct ieee80211_sta sta;
341}; 346};
@@ -436,9 +441,15 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid)
436struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, 441struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
437 const u8 *addr); 442 const u8 *addr);
438 443
444struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata,
445 const u8 *addr);
446
439struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, 447struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
440 const u8 *addr); 448 const u8 *addr);
441 449
450struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata,
451 const u8 *addr);
452
442static inline 453static inline
443void for_each_sta_info_type_check(struct ieee80211_local *local, 454void for_each_sta_info_type_check(struct ieee80211_local *local,
444 const u8 *addr, 455 const u8 *addr,
@@ -459,6 +470,22 @@ void for_each_sta_info_type_check(struct ieee80211_local *local,
459 _sta = nxt, \ 470 _sta = nxt, \
460 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \ 471 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \
461 ) \ 472 ) \
473 /* run code only if address matches and it's not a dummy sta */ \
474 if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0 && \
475 !_sta->dummy)
476
477#define for_each_sta_info_rx(local, _addr, _sta, nxt) \
478 for ( /* initialise loop */ \
479 _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\
480 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \
481 /* typecheck */ \
482 for_each_sta_info_type_check(local, (_addr), _sta, nxt),\
483 /* continue condition */ \
484 _sta; \
485 /* advance loop */ \
486 _sta = nxt, \
487 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \
488 ) \
462 /* compare address and run code only if it matches */ \ 489 /* compare address and run code only if it matches */ \
463 if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0) 490 if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0)
464 491
@@ -484,6 +511,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
484int sta_info_insert(struct sta_info *sta); 511int sta_info_insert(struct sta_info *sta);
485int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); 512int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU);
486int sta_info_insert_atomic(struct sta_info *sta); 513int sta_info_insert_atomic(struct sta_info *sta);
514int sta_info_reinsert(struct sta_info *sta);
487 515
488int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, 516int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata,
489 const u8 *addr); 517 const u8 *addr);