aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-01-20 07:55:24 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-02-06 14:50:37 -0500
commit7852e36186d2a1983c215836d7e3d7b8927c930d (patch)
tree191ab7c06b1ab871b95c1d732e9ca67482dbce9d /net
parenta4ec45a421b80bc36fd37578accf081f32527a7f (diff)
mac80211: remove dummy STA support
The dummy STA support was added because I didn't want to change the driver API at the time. Now that we have state transitions triggering station add/remove in the driver, we only call add once a station reaches ASSOCIATED, so we can remove the dummy station stuff again. While at it, tighten the RX check and accept only port control (EAP) frames from the AP station if it's not associated yet -- in other cases there's no race. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/mlme.c15
-rw-r--r--net/mac80211/rx.c13
-rw-r--r--net/mac80211/sta_info.c135
-rw-r--r--net/mac80211/sta_info.h30
4 files changed, 38 insertions, 155 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 40b929d57a97..d04811a29cdf 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1581,7 +1581,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1581 * station info was already allocated and inserted before 1581 * station info was already allocated and inserted before
1582 * the association and should be available to us 1582 * the association and should be available to us
1583 */ 1583 */
1584 sta = sta_info_get_rx(sdata, cbss->bssid); 1584 sta = sta_info_get(sdata, cbss->bssid);
1585 if (WARN_ON(!sta)) { 1585 if (WARN_ON(!sta)) {
1586 mutex_unlock(&sdata->local->sta_mtx); 1586 mutex_unlock(&sdata->local->sta_mtx);
1587 return false; 1587 return false;
@@ -1648,14 +1648,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1648 return false; 1648 return false;
1649 } 1649 }
1650 1650
1651 /* sta_info_reinsert will also unlock the mutex lock */ 1651 mutex_unlock(&sdata->local->sta_mtx);
1652 err = sta_info_reinsert(sta);
1653 sta = NULL;
1654 if (err) {
1655 printk(KERN_DEBUG "%s: failed to insert STA entry for"
1656 " the AP (error %d)\n", sdata->name, err);
1657 return false;
1658 }
1659 1652
1660 /* 1653 /*
1661 * Always handle WMM once after association regardless 1654 * Always handle WMM once after association regardless
@@ -2536,12 +2529,10 @@ static int ieee80211_pre_assoc(struct ieee80211_sub_if_data *sdata,
2536 if (!sta) 2529 if (!sta)
2537 return -ENOMEM; 2530 return -ENOMEM;
2538 2531
2539 sta->dummy = true;
2540
2541 err = sta_info_insert(sta); 2532 err = sta_info_insert(sta);
2542 sta = NULL; 2533 sta = NULL;
2543 if (err) { 2534 if (err) {
2544 printk(KERN_DEBUG "%s: failed to insert Dummy STA entry for" 2535 printk(KERN_DEBUG "%s: failed to insert STA entry for"
2545 " the AP (error %d)\n", sdata->name, err); 2536 " the AP (error %d)\n", sdata->name, err);
2546 return err; 2537 return err;
2547 } 2538 }
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index ab29253fb4f2..8d6fa674f53e 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -859,7 +859,12 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
859 rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && 859 rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
860 rx->sdata->vif.type != NL80211_IFTYPE_WDS && 860 rx->sdata->vif.type != NL80211_IFTYPE_WDS &&
861 (!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) { 861 (!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) {
862 if (rx->sta && rx->sta->dummy && 862 /*
863 * accept port control frames from the AP even when it's not
864 * yet marked ASSOC to prevent a race where we don't set the
865 * assoc bit quickly enough before it sends the first frame
866 */
867 if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
863 ieee80211_is_data_present(hdr->frame_control)) { 868 ieee80211_is_data_present(hdr->frame_control)) {
864 u16 ethertype; 869 u16 ethertype;
865 u8 *payload; 870 u8 *payload;
@@ -2949,7 +2954,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2949 if (ieee80211_is_data(fc)) { 2954 if (ieee80211_is_data(fc)) {
2950 prev_sta = NULL; 2955 prev_sta = NULL;
2951 2956
2952 for_each_sta_info_rx(local, hdr->addr2, sta, tmp) { 2957 for_each_sta_info(local, hdr->addr2, sta, tmp) {
2953 if (!prev_sta) { 2958 if (!prev_sta) {
2954 prev_sta = sta; 2959 prev_sta = sta;
2955 continue; 2960 continue;
@@ -2993,7 +2998,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2993 continue; 2998 continue;
2994 } 2999 }
2995 3000
2996 rx.sta = sta_info_get_bss_rx(prev, hdr->addr2); 3001 rx.sta = sta_info_get_bss(prev, hdr->addr2);
2997 rx.sdata = prev; 3002 rx.sdata = prev;
2998 ieee80211_prepare_and_rx_handle(&rx, skb, false); 3003 ieee80211_prepare_and_rx_handle(&rx, skb, false);
2999 3004
@@ -3001,7 +3006,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
3001 } 3006 }
3002 3007
3003 if (prev) { 3008 if (prev) {
3004 rx.sta = sta_info_get_bss_rx(prev, hdr->addr2); 3009 rx.sta = sta_info_get_bss(prev, hdr->addr2);
3005 rx.sdata = prev; 3010 rx.sdata = prev;
3006 3011
3007 if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) 3012 if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 5e577bd0e6aa..31cd6d92531c 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -100,25 +100,6 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
100 sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], 100 sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
101 lockdep_is_held(&local->sta_mtx)); 101 lockdep_is_held(&local->sta_mtx));
102 while (sta) { 102 while (sta) {
103 if (sta->sdata == sdata && !sta->dummy &&
104 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
105 break;
106 sta = rcu_dereference_check(sta->hnext,
107 lockdep_is_held(&local->sta_mtx));
108 }
109 return sta;
110}
111
112/* get a station info entry even if it is a dummy station*/
113struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata,
114 const u8 *addr)
115{
116 struct ieee80211_local *local = sdata->local;
117 struct sta_info *sta;
118
119 sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
120 lockdep_is_held(&local->sta_mtx));
121 while (sta) {
122 if (sta->sdata == sdata && 103 if (sta->sdata == sdata &&
123 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) 104 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
124 break; 105 break;
@@ -143,30 +124,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
143 while (sta) { 124 while (sta) {
144 if ((sta->sdata == sdata || 125 if ((sta->sdata == sdata ||
145 (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && 126 (sta->sdata->bss && sta->sdata->bss == sdata->bss)) &&
146 !sta->dummy &&
147 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
148 break;
149 sta = rcu_dereference_check(sta->hnext,
150 lockdep_is_held(&local->sta_mtx));
151 }
152 return sta;
153}
154
155/*
156 * Get sta info either from the specified interface
157 * or from one of its vlans (including dummy stations)
158 */
159struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata,
160 const u8 *addr)
161{
162 struct ieee80211_local *local = sdata->local;
163 struct sta_info *sta;
164
165 sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
166 lockdep_is_held(&local->sta_mtx));
167 while (sta) {
168 if ((sta->sdata == sdata ||
169 (sta->sdata->bss && sta->sdata->bss == sdata->bss)) &&
170 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) 127 memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
171 break; 128 break;
172 sta = rcu_dereference_check(sta->hnext, 129 sta = rcu_dereference_check(sta->hnext,
@@ -397,66 +354,43 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
397{ 354{
398 struct ieee80211_local *local = sta->local; 355 struct ieee80211_local *local = sta->local;
399 struct ieee80211_sub_if_data *sdata = sta->sdata; 356 struct ieee80211_sub_if_data *sdata = sta->sdata;
400 struct sta_info *exist_sta; 357 struct station_info sinfo;
401 bool dummy_reinsert = false;
402 int err = 0; 358 int err = 0;
403 359
404 lockdep_assert_held(&local->sta_mtx); 360 lockdep_assert_held(&local->sta_mtx);
405 361
406 /* 362 /* check if STA exists already */
407 * check if STA exists already. 363 if (sta_info_get_bss(sdata, sta->sta.addr)) {
408 * only accept a scenario of a second call to sta_info_insert_finish 364 err = -EEXIST;
409 * with a dummy station entry that was inserted earlier 365 goto out_err;
410 * in that case - assume that the dummy station flag should
411 * be removed.
412 */
413 exist_sta = sta_info_get_bss_rx(sdata, sta->sta.addr);
414 if (exist_sta) {
415 if (exist_sta == sta && sta->dummy) {
416 dummy_reinsert = true;
417 } else {
418 err = -EEXIST;
419 goto out_err;
420 }
421 }
422
423 if (!sta->dummy || dummy_reinsert) {
424 /* notify driver */
425 err = sta_info_insert_drv_state(local, sdata, sta);
426 if (err)
427 goto out_err;
428 } 366 }
429 367
430 if (!dummy_reinsert) { 368 /* notify driver */
431 local->num_sta++; 369 err = sta_info_insert_drv_state(local, sdata, sta);
432 local->sta_generation++; 370 if (err)
433 smp_mb(); 371 goto out_err;
434 372
435 /* make the station visible */ 373 local->num_sta++;
436 sta_info_hash_add(local, sta); 374 local->sta_generation++;
375 smp_mb();
437 376
438 list_add(&sta->list, &local->sta_list); 377 /* make the station visible */
378 sta_info_hash_add(local, sta);
439 379
440 set_sta_flag(sta, WLAN_STA_INSERTED); 380 list_add(&sta->list, &local->sta_list);
441 } else {
442 sta->dummy = false;
443 }
444 381
445 if (!sta->dummy) { 382 set_sta_flag(sta, WLAN_STA_INSERTED);
446 struct station_info sinfo;
447 383
448 ieee80211_sta_debugfs_add(sta); 384 ieee80211_sta_debugfs_add(sta);
449 rate_control_add_sta_debugfs(sta); 385 rate_control_add_sta_debugfs(sta);
450 386
451 memset(&sinfo, 0, sizeof(sinfo)); 387 memset(&sinfo, 0, sizeof(sinfo));
452 sinfo.filled = 0; 388 sinfo.filled = 0;
453 sinfo.generation = local->sta_generation; 389 sinfo.generation = local->sta_generation;
454 cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); 390 cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);
455 }
456 391
457#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 392#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
458 wiphy_debug(local->hw.wiphy, "Inserted %sSTA %pM\n", 393 wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr);
459 sta->dummy ? "dummy " : "", sta->sta.addr);
460#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ 394#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
461 395
462 /* move reference to rcu-protected */ 396 /* move reference to rcu-protected */
@@ -508,25 +442,6 @@ int sta_info_insert(struct sta_info *sta)
508 return err; 442 return err;
509} 443}
510 444
511/* Caller must hold sta->local->sta_mtx */
512int sta_info_reinsert(struct sta_info *sta)
513{
514 struct ieee80211_local *local = sta->local;
515 int err = 0;
516
517 err = sta_info_insert_check(sta);
518 if (err) {
519 mutex_unlock(&local->sta_mtx);
520 return err;
521 }
522
523 might_sleep();
524
525 err = sta_info_insert_finish(sta);
526 rcu_read_unlock();
527 return err;
528}
529
530static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) 445static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)
531{ 446{
532 /* 447 /*
@@ -873,7 +788,7 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr)
873 int ret; 788 int ret;
874 789
875 mutex_lock(&sdata->local->sta_mtx); 790 mutex_lock(&sdata->local->sta_mtx);
876 sta = sta_info_get_rx(sdata, addr); 791 sta = sta_info_get(sdata, addr);
877 ret = __sta_info_destroy(sta); 792 ret = __sta_info_destroy(sta);
878 mutex_unlock(&sdata->local->sta_mtx); 793 mutex_unlock(&sdata->local->sta_mtx);
879 794
@@ -887,7 +802,7 @@ int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata,
887 int ret; 802 int ret;
888 803
889 mutex_lock(&sdata->local->sta_mtx); 804 mutex_lock(&sdata->local->sta_mtx);
890 sta = sta_info_get_bss_rx(sdata, addr); 805 sta = sta_info_get_bss(sdata, addr);
891 ret = __sta_info_destroy(sta); 806 ret = __sta_info_destroy(sta);
892 mutex_unlock(&sdata->local->sta_mtx); 807 mutex_unlock(&sdata->local->sta_mtx);
893 808
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 2ee808860007..03f249bc2766 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -265,8 +265,6 @@ struct sta_ampdu_mlme {
265 * @dead: set to true when sta is unlinked 265 * @dead: set to true when sta is unlinked
266 * @uploaded: set to true when sta is uploaded to the driver 266 * @uploaded: set to true when sta is uploaded to the driver
267 * @lost_packets: number of consecutive lost packets 267 * @lost_packets: number of consecutive lost packets
268 * @dummy: indicate a dummy station created for receiving
269 * EAP frames before association
270 * @sta: station information we share with the driver 268 * @sta: station information we share with the driver
271 * @sta_state: duplicates information about station state (for debug) 269 * @sta_state: duplicates information about station state (for debug)
272 * @beacon_loss_count: number of times beacon loss has triggered 270 * @beacon_loss_count: number of times beacon loss has triggered
@@ -364,9 +362,6 @@ struct sta_info {
364 unsigned int lost_packets; 362 unsigned int lost_packets;
365 unsigned int beacon_loss_count; 363 unsigned int beacon_loss_count;
366 364
367 /* should be right in front of sta to be in the same cache line */
368 bool dummy;
369
370 /* keep last! */ 365 /* keep last! */
371 struct ieee80211_sta sta; 366 struct ieee80211_sta sta;
372}; 367};
@@ -468,15 +463,9 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid)
468struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, 463struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
469 const u8 *addr); 464 const u8 *addr);
470 465
471struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata,
472 const u8 *addr);
473
474struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, 466struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
475 const u8 *addr); 467 const u8 *addr);
476 468
477struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata,
478 const u8 *addr);
479
480static inline 469static inline
481void for_each_sta_info_type_check(struct ieee80211_local *local, 470void for_each_sta_info_type_check(struct ieee80211_local *local,
482 const u8 *addr, 471 const u8 *addr,
@@ -485,23 +474,7 @@ void for_each_sta_info_type_check(struct ieee80211_local *local,
485{ 474{
486} 475}
487 476
488#define for_each_sta_info(local, _addr, _sta, nxt) \ 477#define for_each_sta_info(local, _addr, _sta, nxt) \
489 for ( /* initialise loop */ \
490 _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\
491 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \
492 /* typecheck */ \
493 for_each_sta_info_type_check(local, (_addr), _sta, nxt),\
494 /* continue condition */ \
495 _sta; \
496 /* advance loop */ \
497 _sta = nxt, \
498 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \
499 ) \
500 /* run code only if address matches and it's not a dummy sta */ \
501 if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0 && \
502 !_sta->dummy)
503
504#define for_each_sta_info_rx(local, _addr, _sta, nxt) \
505 for ( /* initialise loop */ \ 478 for ( /* initialise loop */ \
506 _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ 479 _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\
507 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \ 480 nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \
@@ -540,7 +513,6 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta);
540 */ 513 */
541int sta_info_insert(struct sta_info *sta); 514int sta_info_insert(struct sta_info *sta);
542int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); 515int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU);
543int sta_info_reinsert(struct sta_info *sta);
544 516
545int __must_check __sta_info_destroy(struct sta_info *sta); 517int __must_check __sta_info_destroy(struct sta_info *sta);
546int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, 518int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata,