aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-04-16 11:43:20 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-04-16 16:00:03 -0400
commit30b89b0f5e1313c8a5a039abeaa89248b6338d81 (patch)
tree1e9de745debf9df518b38ada3a1322bdb5999e63 /net
parent194828a292db3cf421ae7f82232f2fc655fbbc3c (diff)
mac80211: rework scanning to account for probe response/beacon difference
This patch reworks the scanning code (ieee80211_rx_bss_info) to take more parameters from beacons and keep a BSS info structure alive when only beacons for it are received. This fixes a problem with iwlwifi drivers (where we don't understand the root cause of the problem yet) and another driver for some broken hardware (which cannot send probe requests unless associated, so can't always actively scan.) Signed-off-by: Bill Moss <bmoss@clemson.edu> [jmberg: reformatted comments, make probe_resp a bool] Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/mlme.c85
2 files changed, 52 insertions, 35 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ce566f3e0169..8e53ce7ed444 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -102,7 +102,7 @@ struct ieee80211_sta_bss {
102 u64 timestamp; 102 u64 timestamp;
103 int beacon_int; 103 int beacon_int;
104 104
105 int probe_resp; 105 bool probe_resp;
106 unsigned long last_update; 106 unsigned long last_update;
107 107
108 /* during assocation, we save an ERP value from a probe response so 108 /* during assocation, we save an ERP value from a probe response so
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index e3f2cb086588..6b75cb6c6300 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2588,22 +2588,29 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2588#endif 2588#endif
2589 } 2589 }
2590 2590
2591 bss->band = rx_status->band;
2592
2593 if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
2594 bss->probe_resp && beacon) {
2595 /* STA mode:
2596 * Do not allow beacon to override data from Probe Response. */
2597 ieee80211_rx_bss_put(dev, bss);
2598 return;
2599 }
2600
2601 /* save the ERP value so that it is available at association time */ 2591 /* save the ERP value so that it is available at association time */
2602 if (elems.erp_info && elems.erp_info_len >= 1) { 2592 if (elems.erp_info && elems.erp_info_len >= 1) {
2603 bss->erp_value = elems.erp_info[0]; 2593 bss->erp_value = elems.erp_info[0];
2604 bss->has_erp_value = 1; 2594 bss->has_erp_value = 1;
2605 } 2595 }
2606 2596
2597 if (elems.ht_cap_elem &&
2598 (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len ||
2599 memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) {
2600 kfree(bss->ht_ie);
2601 bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC);
2602 if (bss->ht_ie) {
2603 memcpy(bss->ht_ie, elems.ht_cap_elem - 2,
2604 elems.ht_cap_elem_len + 2);
2605 bss->ht_ie_len = elems.ht_cap_elem_len + 2;
2606 } else
2607 bss->ht_ie_len = 0;
2608 } else if (!elems.ht_cap_elem && bss->ht_ie) {
2609 kfree(bss->ht_ie);
2610 bss->ht_ie = NULL;
2611 bss->ht_ie_len = 0;
2612 }
2613
2607 bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); 2614 bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
2608 bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); 2615 bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
2609 2616
@@ -2625,6 +2632,26 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2625 bss->supp_rates_len += clen; 2632 bss->supp_rates_len += clen;
2626 } 2633 }
2627 2634
2635 bss->band = rx_status->band;
2636
2637 bss->timestamp = beacon_timestamp;
2638 bss->last_update = jiffies;
2639 bss->rssi = rx_status->ssi;
2640 bss->signal = rx_status->signal;
2641 bss->noise = rx_status->noise;
2642 if (!beacon && !bss->probe_resp)
2643 bss->probe_resp = true;
2644
2645 /*
2646 * In STA mode, the remaining parameters should not be overridden
2647 * by beacons because they're not necessarily accurate there.
2648 */
2649 if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
2650 bss->probe_resp && beacon) {
2651 ieee80211_rx_bss_put(dev, bss);
2652 return;
2653 }
2654
2628 if (elems.wpa && 2655 if (elems.wpa &&
2629 (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len || 2656 (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len ||
2630 memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) { 2657 memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) {
@@ -2657,6 +2684,20 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2657 bss->rsn_ie_len = 0; 2684 bss->rsn_ie_len = 0;
2658 } 2685 }
2659 2686
2687 /*
2688 * Cf.
2689 * http://www.wipo.int/pctdb/en/wo.jsp?wo=2007047181&IA=WO2007047181&DISPLAY=DESC
2690 *
2691 * quoting:
2692 *
2693 * In particular, "Wi-Fi CERTIFIED for WMM - Support for Multimedia
2694 * Applications with Quality of Service in Wi-Fi Networks," Wi- Fi
2695 * Alliance (September 1, 2004) is incorporated by reference herein.
2696 * The inclusion of the WMM Parameters in probe responses and
2697 * association responses is mandatory for WMM enabled networks. The
2698 * inclusion of the WMM Parameters in beacons, however, is optional.
2699 */
2700
2660 if (elems.wmm_param && 2701 if (elems.wmm_param &&
2661 (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len || 2702 (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len ||
2662 memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) { 2703 memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) {
@@ -2673,30 +2714,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
2673 bss->wmm_ie = NULL; 2714 bss->wmm_ie = NULL;
2674 bss->wmm_ie_len = 0; 2715 bss->wmm_ie_len = 0;
2675 } 2716 }
2676 if (elems.ht_cap_elem &&
2677 (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len ||
2678 memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) {
2679 kfree(bss->ht_ie);
2680 bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC);
2681 if (bss->ht_ie) {
2682 memcpy(bss->ht_ie, elems.ht_cap_elem - 2,
2683 elems.ht_cap_elem_len + 2);
2684 bss->ht_ie_len = elems.ht_cap_elem_len + 2;
2685 } else
2686 bss->ht_ie_len = 0;
2687 } else if (!elems.ht_cap_elem && bss->ht_ie) {
2688 kfree(bss->ht_ie);
2689 bss->ht_ie = NULL;
2690 bss->ht_ie_len = 0;
2691 }
2692
2693 bss->timestamp = beacon_timestamp;
2694 bss->last_update = jiffies;
2695 bss->rssi = rx_status->ssi;
2696 bss->signal = rx_status->signal;
2697 bss->noise = rx_status->noise;
2698 if (!beacon)
2699 bss->probe_resp++;
2700 2717
2701 /* check if we need to merge IBSS */ 2718 /* check if we need to merge IBSS */
2702 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon && 2719 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon &&