Commit 7852e36186d2a1983c215836d7e3d7b8927c930d
Committed by
John W. Linville
1 parent
a4ec45a421
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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>
Showing 4 changed files with 38 additions and 155 deletions Side-by-side Diff
net/mac80211/mlme.c
... | ... | @@ -1581,7 +1581,7 @@ |
1581 | 1581 | * station info was already allocated and inserted before |
1582 | 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 | 1585 | if (WARN_ON(!sta)) { |
1586 | 1586 | mutex_unlock(&sdata->local->sta_mtx); |
1587 | 1587 | return false; |
... | ... | @@ -1648,14 +1648,7 @@ |
1648 | 1648 | return false; |
1649 | 1649 | } |
1650 | 1650 | |
1651 | - /* sta_info_reinsert will also unlock the mutex lock */ | |
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 | - } | |
1651 | + mutex_unlock(&sdata->local->sta_mtx); | |
1659 | 1652 | |
1660 | 1653 | /* |
1661 | 1654 | * Always handle WMM once after association regardless |
1662 | 1655 | |
... | ... | @@ -2536,12 +2529,10 @@ |
2536 | 2529 | if (!sta) |
2537 | 2530 | return -ENOMEM; |
2538 | 2531 | |
2539 | - sta->dummy = true; | |
2540 | - | |
2541 | 2532 | err = sta_info_insert(sta); |
2542 | 2533 | sta = NULL; |
2543 | 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 | 2536 | " the AP (error %d)\n", sdata->name, err); |
2546 | 2537 | return err; |
2547 | 2538 | } |
net/mac80211/rx.c
... | ... | @@ -859,7 +859,12 @@ |
859 | 859 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && |
860 | 860 | rx->sdata->vif.type != NL80211_IFTYPE_WDS && |
861 | 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 | 868 | ieee80211_is_data_present(hdr->frame_control)) { |
864 | 869 | u16 ethertype; |
865 | 870 | u8 *payload; |
... | ... | @@ -2949,7 +2954,7 @@ |
2949 | 2954 | if (ieee80211_is_data(fc)) { |
2950 | 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 | 2958 | if (!prev_sta) { |
2954 | 2959 | prev_sta = sta; |
2955 | 2960 | continue; |
... | ... | @@ -2993,7 +2998,7 @@ |
2993 | 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 | 3002 | rx.sdata = prev; |
2998 | 3003 | ieee80211_prepare_and_rx_handle(&rx, skb, false); |
2999 | 3004 | |
... | ... | @@ -3001,7 +3006,7 @@ |
3001 | 3006 | } |
3002 | 3007 | |
3003 | 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 | 3010 | rx.sdata = prev; |
3006 | 3011 | |
3007 | 3012 | if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) |
net/mac80211/sta_info.c
... | ... | @@ -100,25 +100,6 @@ |
100 | 100 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
101 | 101 | lockdep_is_held(&local->sta_mtx)); |
102 | 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*/ | |
113 | -struct 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 | 103 | if (sta->sdata == sdata && |
123 | 104 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
124 | 105 | break; |
... | ... | @@ -143,7 +124,6 @@ |
143 | 124 | while (sta) { |
144 | 125 | if ((sta->sdata == sdata || |
145 | 126 | (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && |
146 | - !sta->dummy && | |
147 | 127 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
148 | 128 | break; |
149 | 129 | sta = rcu_dereference_check(sta->hnext, |
... | ... | @@ -152,29 +132,6 @@ |
152 | 132 | return sta; |
153 | 133 | } |
154 | 134 | |
155 | -/* | |
156 | - * Get sta info either from the specified interface | |
157 | - * or from one of its vlans (including dummy stations) | |
158 | - */ | |
159 | -struct 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) | |
171 | - break; | |
172 | - sta = rcu_dereference_check(sta->hnext, | |
173 | - lockdep_is_held(&local->sta_mtx)); | |
174 | - } | |
175 | - return sta; | |
176 | -} | |
177 | - | |
178 | 135 | struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, |
179 | 136 | int idx) |
180 | 137 | { |
181 | 138 | |
182 | 139 | |
183 | 140 | |
184 | 141 | |
185 | 142 | |
186 | 143 | |
187 | 144 | |
188 | 145 | |
189 | 146 | |
190 | 147 | |
... | ... | @@ -397,66 +354,43 @@ |
397 | 354 | { |
398 | 355 | struct ieee80211_local *local = sta->local; |
399 | 356 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
400 | - struct sta_info *exist_sta; | |
401 | - bool dummy_reinsert = false; | |
357 | + struct station_info sinfo; | |
402 | 358 | int err = 0; |
403 | 359 | |
404 | 360 | lockdep_assert_held(&local->sta_mtx); |
405 | 361 | |
406 | - /* | |
407 | - * check if STA exists already. | |
408 | - * only accept a scenario of a second call to sta_info_insert_finish | |
409 | - * with a dummy station entry that was inserted earlier | |
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 | - } | |
362 | + /* check if STA exists already */ | |
363 | + if (sta_info_get_bss(sdata, sta->sta.addr)) { | |
364 | + err = -EEXIST; | |
365 | + goto out_err; | |
421 | 366 | } |
422 | 367 | |
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 | - } | |
368 | + /* notify driver */ | |
369 | + err = sta_info_insert_drv_state(local, sdata, sta); | |
370 | + if (err) | |
371 | + goto out_err; | |
429 | 372 | |
430 | - if (!dummy_reinsert) { | |
431 | - local->num_sta++; | |
432 | - local->sta_generation++; | |
433 | - smp_mb(); | |
373 | + local->num_sta++; | |
374 | + local->sta_generation++; | |
375 | + smp_mb(); | |
434 | 376 | |
435 | - /* make the station visible */ | |
436 | - sta_info_hash_add(local, sta); | |
377 | + /* make the station visible */ | |
378 | + sta_info_hash_add(local, sta); | |
437 | 379 | |
438 | - list_add(&sta->list, &local->sta_list); | |
380 | + list_add(&sta->list, &local->sta_list); | |
439 | 381 | |
440 | - set_sta_flag(sta, WLAN_STA_INSERTED); | |
441 | - } else { | |
442 | - sta->dummy = false; | |
443 | - } | |
382 | + set_sta_flag(sta, WLAN_STA_INSERTED); | |
444 | 383 | |
445 | - if (!sta->dummy) { | |
446 | - struct station_info sinfo; | |
384 | + ieee80211_sta_debugfs_add(sta); | |
385 | + rate_control_add_sta_debugfs(sta); | |
447 | 386 | |
448 | - ieee80211_sta_debugfs_add(sta); | |
449 | - rate_control_add_sta_debugfs(sta); | |
387 | + memset(&sinfo, 0, sizeof(sinfo)); | |
388 | + sinfo.filled = 0; | |
389 | + sinfo.generation = local->sta_generation; | |
390 | + cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); | |
450 | 391 | |
451 | - memset(&sinfo, 0, sizeof(sinfo)); | |
452 | - sinfo.filled = 0; | |
453 | - sinfo.generation = local->sta_generation; | |
454 | - cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); | |
455 | - } | |
456 | - | |
457 | 392 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
458 | - wiphy_debug(local->hw.wiphy, "Inserted %sSTA %pM\n", | |
459 | - sta->dummy ? "dummy " : "", sta->sta.addr); | |
393 | + wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr); | |
460 | 394 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
461 | 395 | |
462 | 396 | /* move reference to rcu-protected */ |
... | ... | @@ -508,25 +442,6 @@ |
508 | 442 | return err; |
509 | 443 | } |
510 | 444 | |
511 | -/* Caller must hold sta->local->sta_mtx */ | |
512 | -int 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 | - | |
530 | 445 | static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid) |
531 | 446 | { |
532 | 447 | /* |
... | ... | @@ -873,7 +788,7 @@ |
873 | 788 | int ret; |
874 | 789 | |
875 | 790 | mutex_lock(&sdata->local->sta_mtx); |
876 | - sta = sta_info_get_rx(sdata, addr); | |
791 | + sta = sta_info_get(sdata, addr); | |
877 | 792 | ret = __sta_info_destroy(sta); |
878 | 793 | mutex_unlock(&sdata->local->sta_mtx); |
879 | 794 | |
... | ... | @@ -887,7 +802,7 @@ |
887 | 802 | int ret; |
888 | 803 | |
889 | 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 | 806 | ret = __sta_info_destroy(sta); |
892 | 807 | mutex_unlock(&sdata->local->sta_mtx); |
893 | 808 |
net/mac80211/sta_info.h
... | ... | @@ -265,8 +265,6 @@ |
265 | 265 | * @dead: set to true when sta is unlinked |
266 | 266 | * @uploaded: set to true when sta is uploaded to the driver |
267 | 267 | * @lost_packets: number of consecutive lost packets |
268 | - * @dummy: indicate a dummy station created for receiving | |
269 | - * EAP frames before association | |
270 | 268 | * @sta: station information we share with the driver |
271 | 269 | * @sta_state: duplicates information about station state (for debug) |
272 | 270 | * @beacon_loss_count: number of times beacon loss has triggered |
... | ... | @@ -364,9 +362,6 @@ |
364 | 362 | unsigned int lost_packets; |
365 | 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 | 365 | /* keep last! */ |
371 | 366 | struct ieee80211_sta sta; |
372 | 367 | }; |
373 | 368 | |
... | ... | @@ -468,15 +463,9 @@ |
468 | 463 | struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, |
469 | 464 | const u8 *addr); |
470 | 465 | |
471 | -struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, | |
472 | - const u8 *addr); | |
473 | - | |
474 | 466 | struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, |
475 | 467 | const u8 *addr); |
476 | 468 | |
477 | -struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, | |
478 | - const u8 *addr); | |
479 | - | |
480 | 469 | static inline |
481 | 470 | void for_each_sta_info_type_check(struct ieee80211_local *local, |
482 | 471 | const u8 *addr, |
... | ... | @@ -485,7 +474,7 @@ |
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 | 478 | for ( /* initialise loop */ \ |
490 | 479 | _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ |
491 | 480 | nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \ |
... | ... | @@ -497,22 +486,6 @@ |
497 | 486 | _sta = nxt, \ |
498 | 487 | nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \ |
499 | 488 | ) \ |
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 */ \ | |
506 | - _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ | |
507 | - nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \ | |
508 | - /* typecheck */ \ | |
509 | - for_each_sta_info_type_check(local, (_addr), _sta, nxt),\ | |
510 | - /* continue condition */ \ | |
511 | - _sta; \ | |
512 | - /* advance loop */ \ | |
513 | - _sta = nxt, \ | |
514 | - nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \ | |
515 | - ) \ | |
516 | 489 | /* compare address and run code only if it matches */ \ |
517 | 490 | if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0) |
518 | 491 | |
... | ... | @@ -540,7 +513,6 @@ |
540 | 513 | */ |
541 | 514 | int sta_info_insert(struct sta_info *sta); |
542 | 515 | int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); |
543 | -int sta_info_reinsert(struct sta_info *sta); | |
544 | 516 | |
545 | 517 | int __must_check __sta_info_destroy(struct sta_info *sta); |
546 | 518 | int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, |