2011-10-13 19:09:04

by Christian Lamparter

[permalink] [raw]
Subject: [PATCH] mac80211: handle HT PHY BSS membership selector value correctly

802.11n-2009 extends the supported rates element with a
magic value which can be used to prevent legacy stations
from joining the BSS.

However, this magic value is not a rate like the others
and the magic can simply be ignored/skipped at this late
stage.

Signed-off-by: Christian Lamparter <[email protected]>
---
pending... still testing.
---
include/linux/ieee80211.h | 4 ++
net/mac80211/mlme.c | 71 ++++++++++++++++++++++++--------------------
2 files changed, 42 insertions(+), 33 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 48363c3..7d2c72d 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -770,6 +770,10 @@ struct ieee80211_mgmt {
} u;
} __attribute__ ((packed));

+/* Supported Rates flags and value encodings in 802.11n-2009 7.3.2.2 */
+#define BSS_MEMBERSHIP_SELECTOR BIT(7)
+#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
+
/* mgmt header + 1 byte category code */
#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 0e5d8da..5619fd5 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1463,6 +1463,38 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
return RX_MGMT_CFG80211_DISASSOC;
}

+static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
+ u8 *supp_rates, unsigned int supp_rates_len,
+ u32 *rates, u32 *basic_rates,
+ bool *have_higher_than_11mbit)
+{
+ int i, j;
+
+ for (i = 0; i < supp_rates_len; i++) {
+ int rate = (supp_rates[i] & 0x7f) * 5;
+ bool is_basic = !!(supp_rates[i] & BSS_MEMBERSHIP_SELECTOR);
+
+ if (rate > 110)
+ *have_higher_than_11mbit = true;
+
+ /*
+ * BSS_MEMBERSHIP_SELECTOR_HT_PHY is defined in 802.11n-2009
+ * 7.3.2.2 as a magic value instead of a rate. Hence, skip it.
+ */
+ if (is_basic &&
+ (supp_rates[i] & 0x7f) == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
+ continue;
+
+ for (j = 0; j < sband->n_bitrates; j++) {
+ if (sband->bitrates[j].bitrate == rate) {
+ *rates |= BIT(j);
+ if (is_basic)
+ *basic_rates |= BIT(j);
+ break;
+ }
+ }
+ }
+}

static bool ieee80211_assoc_success(struct ieee80211_work *wk,
struct ieee80211_mgmt *mgmt, size_t len)
@@ -1479,7 +1511,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
struct ieee802_11_elems elems;
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
u32 changed = 0;
- int i, j, err;
+ int err;
bool have_higher_than_11mbit = false;
u16 ap_ht_cap_flags;

@@ -1525,39 +1557,12 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
basic_rates = 0;
sband = local->hw.wiphy->bands[wk->chan->band];

- for (i = 0; i < elems.supp_rates_len; i++) {
- int rate = (elems.supp_rates[i] & 0x7f) * 5;
- bool is_basic = !!(elems.supp_rates[i] & 0x80);
-
- if (rate > 110)
- have_higher_than_11mbit = true;
-
- for (j = 0; j < sband->n_bitrates; j++) {
- if (sband->bitrates[j].bitrate == rate) {
- rates |= BIT(j);
- if (is_basic)
- basic_rates |= BIT(j);
- break;
- }
- }
- }
-
- for (i = 0; i < elems.ext_supp_rates_len; i++) {
- int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
- bool is_basic = !!(elems.ext_supp_rates[i] & 0x80);
+ ieee80211_get_rates(sband, elems.supp_rates, elems.supp_rates_len,
+ &rates, &basic_rates, &have_higher_than_11mbit);

- if (rate > 110)
- have_higher_than_11mbit = true;
-
- for (j = 0; j < sband->n_bitrates; j++) {
- if (sband->bitrates[j].bitrate == rate) {
- rates |= BIT(j);
- if (is_basic)
- basic_rates |= BIT(j);
- break;
- }
- }
- }
+ ieee80211_get_rates(sband, elems.ext_supp_rates,
+ elems.ext_supp_rates_len, &rates, &basic_rates,
+ &have_higher_than_11mbit);

sta->sta.supp_rates[wk->chan->band] = rates;
sdata->vif.bss_conf.basic_rates = basic_rates;
--
1.7.7



2011-10-14 08:12:45

by Christian Lamparter

[permalink] [raw]
Subject: Re: [PATCH] mac80211: handle HT PHY BSS membership selector value correctly

[Hit 'sent' by accident]

On Friday, October 14, 2011 09:42:36 AM Christian Lamparter wrote:
> On Friday, October 14, 2011 12:45:32 AM Jouni Malinen wrote:
> > On Thu, Oct 13, 2011 at 09:08:49PM +0200, Christian Lamparter wrote:
> > > 802.11n-2009 extends the supported rates element with a
> > > magic value which can be used to prevent legacy stations
> > > from joining the BSS.
> >
> > Well, it can be used to try to make legacy stations not attempt
> > connection, but no guarantees on them actually checking whether they
> > support all the "basic rates".. For example, where is mac80211 (or
> > wpa_supplicant) doing that check? ;-)
>
Actually, you have already implemented the check in hostapd :)

commit 2944824315b7c74838c551ef08c9843e02de1d46
Author: Jouni Malinen <[email protected]>
Date: Wed Feb 9 15:08:47 2011 +0200

line 682:
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
!(sta->flags & WLAN_STA_HT)) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "Station does not support "
"mandatory HT PHY - reject association");
return WLAN_STATUS_ASSOC_DENIED_NO_HT;
}

so if a legacy station decides to join a require_ht = 1 BSS
then the AP will refuse it with WLAN_STATUS_ASSOC_DENIED_NO_HT
and the wpa_supp client will blacklist the AP because of that
and it will choose a different AP for the next try.

> > > diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
> > > @@ -1463,6 +1463,38 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
> > > +static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
> >
> > > + for (i = 0; i < supp_rates_len; i++) {
> > > + int rate = (supp_rates[i] & 0x7f) * 5;
> > > + bool is_basic = !!(supp_rates[i] & BSS_MEMBERSHIP_SELECTOR);
> >
> > This looks a bit odd since the BSS_MEMBERSHIP_SELECTOR is not exactly
> > same as basic rate indicator even through they share the same bit. We
> > used to have the magic 0x80 value here which could actually look less
> > confusing than the mixing of basic and BSS membership terms.
So, what's the exact difference between then BasicRate and a MembershipRate
in this context then? Is a rate called "basic rate" when it's one of the
legacy e.g.: 6, 12, 24 Mbit rates [And likewise: is a rate called a MembershipRate
when only in the magic 127 HT PHY case?]

> >
> > > + if (rate > 110)
> > > + *have_higher_than_11mbit = true;
> > While this is not really introduced by this patch, this looks quite
> > bogus since the higher-than-11Mbps is then used to figure out whether
> > this was a 802.11g network. That is not correct since a network with a
> > single supported rate 6 Mbps should also get that behavior.. More robust
> > mechanism would be to check for any OFDM rate being listed.
Also, there's 22mbit 8-PSK PBCC [I think mwl8k supports it and some TI
stuff could support it as well]. The check is questionable, but fixing
it may no be trivial either. [Anyway, it's a bit outside the scope and
requires another patch]

Regards,
Chr

2011-10-13 22:45:56

by Jouni Malinen

[permalink] [raw]
Subject: Re: [PATCH] mac80211: handle HT PHY BSS membership selector value correctly

On Thu, Oct 13, 2011 at 09:08:49PM +0200, Christian Lamparter wrote:
> 802.11n-2009 extends the supported rates element with a
> magic value which can be used to prevent legacy stations
> from joining the BSS.

Well, it can be used to try to make legacy stations not attempt
connection, but no guarantees on them actually checking whether they
support all the "basic rates".. For example, where is mac80211 (or
wpa_supplicant) doing that check? ;-)

> diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
> @@ -1463,6 +1463,38 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
> +static void ieee80211_get_rates(struct ieee80211_supported_band *sband,

> + for (i = 0; i < supp_rates_len; i++) {
> + int rate = (supp_rates[i] & 0x7f) * 5;
> + bool is_basic = !!(supp_rates[i] & BSS_MEMBERSHIP_SELECTOR);

This looks a bit odd since the BSS_MEMBERSHIP_SELECTOR is not exactly
same as basic rate indicator even through they share the same bit. We
used to have the magic 0x80 value here which could actually look less
confusing than the mixing of basic and BSS membership terms.

> + if (rate > 110)
> + *have_higher_than_11mbit = true;

While this is not really introduced by this patch, this looks quite
bogus since the higher-than-11Mbps is then used to figure out whether
this was a 802.11g network. That is not correct since a network with a
single supported rate 6 Mbps should also get that behavior.. More robust
mechanism would be to check for any OFDM rate being listed.

> + ieee80211_get_rates(sband, elems.supp_rates, elems.supp_rates_len,
> + &rates, &basic_rates, &have_higher_than_11mbit);

> + ieee80211_get_rates(sband, elems.ext_supp_rates,
> + elems.ext_supp_rates_len, &rates, &basic_rates,
> + &have_higher_than_11mbit);

Yay for getting rid of the duplicated loop :-).

--
Jouni Malinen PGP id EFC895FA

2011-10-15 08:50:24

by Jouni Malinen

[permalink] [raw]
Subject: Re: [PATCH] mac80211: handle HT PHY BSS membership selector value correctly

On Fri, Oct 14, 2011 at 10:12:20AM +0200, Christian Lamparter wrote:
> > On Friday, October 14, 2011 12:45:32 AM Jouni Malinen wrote:
> > > Well, it can be used to try to make legacy stations not attempt
> > > connection, but no guarantees on them actually checking whether they
> > > support all the "basic rates".. For example, where is mac80211 (or
> > > wpa_supplicant) doing that check? ;-)
> >
> Actually, you have already implemented the check in hostapd :)

That's for AP mode which does not really use the BSS membership selector
in any way. The point of this mechanism is that it is supposed to allow
legacy stations to not even try to associate with the AP that requires
some new functionality that the station is not even aware of. For this
to have any real benefit, the station would need verify whether they
support all "basic rates" (i.e., these would look like basic rates for
them, but BSS membership selectors for any station that is aware of the
new functionality). This would allow mandating this type of new
requirement on BSS by BSS basis in an ESS without causing problems to
the legacy stations.

> So, what's the exact difference between then BasicRate and a MembershipRate
> in this context then? Is a rate called "basic rate" when it's one of the
> legacy e.g.: 6, 12, 24 Mbit rates [And likewise: is a rate called a MembershipRate
> when only in the magic 127 HT PHY case?]

More or less (though, I would not call the membership selector a
"rate"). This is not really that clearly described, but I would indeed
split the values in Supported Rates element (and Extended Supported
Rates elements) in that way. This obviously depends on knowing
the full list of rates or full list of membership selectors (which may
be the easier thing to know in full).

The exact definition of what the value is does not really matter for a
legacy station since the rule for them is that they would need to
support any rate (& 0x7f) that has the 0x80 bit set.

> Also, there's 22mbit 8-PSK PBCC [I think mwl8k supports it and some TI
> stuff could support it as well]. The check is questionable, but fixing
> it may no be trivial either. [Anyway, it's a bit outside the scope and
> requires another patch]

Agreed.

--
Jouni Malinen PGP id EFC895FA

2011-10-14 22:14:55

by Christian Lamparter

[permalink] [raw]
Subject: [PATCH v2] mac80211: handle HT PHY BSS membership selector value correctly

802.11n-2009 extends the supported rates element with a
magic value which can be used to prevent legacy stations
from joining the BSS.

However, this magic value is not a rate like the others
and the magic can simply be ignored/skipped at this late
stage.

Signed-off-by: Christian Lamparter <[email protected]>---
---
v2:
Jouni's comment... Although I'm still not sure what is
the difference between the membership and basic
rate flag at this point.
---
include/linux/ieee80211.h | 3 ++
net/mac80211/mlme.c | 75 +++++++++++++++++++++++++--------------------
2 files changed, 45 insertions(+), 33 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 48363c3..9789aed 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -770,6 +770,9 @@ struct ieee80211_mgmt {
} u;
} __attribute__ ((packed));

+/* Supported Rates value encodings in 802.11n-2009 7.3.2.2 */
+#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
+
/* mgmt header + 1 byte category code */
#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 0e5d8da..c0e54c5 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1463,6 +1463,42 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
return RX_MGMT_CFG80211_DISASSOC;
}

+static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
+ u8 *supp_rates, unsigned int supp_rates_len,
+ u32 *rates, u32 *basic_rates,
+ bool *have_higher_than_11mbit)
+{
+ int i, j;
+
+ for (i = 0; i < supp_rates_len; i++) {
+ int rate = (supp_rates[i] & 0x7f) * 5;
+ bool is_basic = !!(supp_rates[i] & 0x80);
+
+ if (rate > 110)
+ *have_higher_than_11mbit = true;
+
+ /*
+ * BSS_MEMBERSHIP_SELECTOR_HT_PHY is defined in 802.11n-2009
+ * 7.3.2.2 as a magic value instead of a rate. Hence, skip it.
+ *
+ * Note: Even through the membership selector and the basic
+ * rate flag share the same bit, they are not exactly
+ * the same.
+ */
+ if (!!(supp_rates[i] & 0x80) &&
+ (supp_rates[i] & 0x7f) == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
+ continue;
+
+ for (j = 0; j < sband->n_bitrates; j++) {
+ if (sband->bitrates[j].bitrate == rate) {
+ *rates |= BIT(j);
+ if (is_basic)
+ *basic_rates |= BIT(j);
+ break;
+ }
+ }
+ }
+}

static bool ieee80211_assoc_success(struct ieee80211_work *wk,
struct ieee80211_mgmt *mgmt, size_t len)
@@ -1479,7 +1515,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
struct ieee802_11_elems elems;
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
u32 changed = 0;
- int i, j, err;
+ int err;
bool have_higher_than_11mbit = false;
u16 ap_ht_cap_flags;

@@ -1525,39 +1561,12 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
basic_rates = 0;
sband = local->hw.wiphy->bands[wk->chan->band];

- for (i = 0; i < elems.supp_rates_len; i++) {
- int rate = (elems.supp_rates[i] & 0x7f) * 5;
- bool is_basic = !!(elems.supp_rates[i] & 0x80);
-
- if (rate > 110)
- have_higher_than_11mbit = true;
-
- for (j = 0; j < sband->n_bitrates; j++) {
- if (sband->bitrates[j].bitrate == rate) {
- rates |= BIT(j);
- if (is_basic)
- basic_rates |= BIT(j);
- break;
- }
- }
- }
-
- for (i = 0; i < elems.ext_supp_rates_len; i++) {
- int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
- bool is_basic = !!(elems.ext_supp_rates[i] & 0x80);
+ ieee80211_get_rates(sband, elems.supp_rates, elems.supp_rates_len,
+ &rates, &basic_rates, &have_higher_than_11mbit);

- if (rate > 110)
- have_higher_than_11mbit = true;
-
- for (j = 0; j < sband->n_bitrates; j++) {
- if (sband->bitrates[j].bitrate == rate) {
- rates |= BIT(j);
- if (is_basic)
- basic_rates |= BIT(j);
- break;
- }
- }
- }
+ ieee80211_get_rates(sband, elems.ext_supp_rates,
+ elems.ext_supp_rates_len, &rates, &basic_rates,
+ &have_higher_than_11mbit);

sta->sta.supp_rates[wk->chan->band] = rates;
sdata->vif.bss_conf.basic_rates = basic_rates;
--
1.7.6.3

2011-10-14 07:43:02

by Christian Lamparter

[permalink] [raw]
Subject: Re: [PATCH] mac80211: handle HT PHY BSS membership selector value correctly

On Friday, October 14, 2011 12:45:32 AM Jouni Malinen wrote:
> On Thu, Oct 13, 2011 at 09:08:49PM +0200, Christian Lamparter wrote:
> > 802.11n-2009 extends the supported rates element with a
> > magic value which can be used to prevent legacy stations
> > from joining the BSS.
>
> Well, it can be used to try to make legacy stations not attempt
> connection, but no guarantees on them actually checking whether they
> support all the "basic rates".. For example, where is mac80211 (or
> wpa_supplicant) doing that check? ;-)

Actually, you have already implemented the check elsewhere :)


>
> > diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
> > @@ -1463,6 +1463,38 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
> > +static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
>
> > + for (i = 0; i < supp_rates_len; i++) {
> > + int rate = (supp_rates[i] & 0x7f) * 5;
> > + bool is_basic = !!(supp_rates[i] & BSS_MEMBERSHIP_SELECTOR);
>
> This looks a bit odd since the BSS_MEMBERSHIP_SELECTOR is not exactly
> same as basic rate indicator even through they share the same bit. We
> used to have the magic 0x80 value here which could actually look less
> confusing than the mixing of basic and BSS membership terms.
>
> > + if (rate > 110)
> > + *have_higher_than_11mbit = true;
>
> While this is not really introduced by this patch, this looks quite
> bogus since the higher-than-11Mbps is then used to figure out whether
> this was a 802.11g network. That is not correct since a network with a
> single supported rate 6 Mbps should also get that behavior.. More robust
> mechanism would be to check for any OFDM rate being listed.
>
> > + ieee80211_get_rates(sband, elems.supp_rates, elems.supp_rates_len,
> > + &rates, &basic_rates, &have_higher_than_11mbit);
>
> > + ieee80211_get_rates(sband, elems.ext_supp_rates,
> > + elems.ext_supp_rates_len, &rates, &basic_rates,
> > + &have_higher_than_11mbit);
>
> Yay for getting rid of the duplicated loop :-).
>
>

2011-11-09 21:15:15

by y

[permalink] [raw]
Subject: [PATCH v3] mac80211: handle HT PHY BSS membership selector value correctly

From: Christian Lamparter <[email protected]>

802.11n-2009 extends the supported rates element with a
magic value which can be used to prevent legacy stations
from joining the BSS.

However, this magic value is not a rate like the others
and the magic can simply be ignored/skipped at this late
stage.

Signed-off-by: Christian Lamparter <[email protected]>---
Signed-off-by: John W. Linville <[email protected]>
---
This is the version I've merged. The v2 version conflicted with
"mac80211: use min rate as basic rate for buggy APs" (commit
3432f9233704a66e6067944339a311744243707d).

Please take a close look to make sure I didn't mess it up!

include/linux/ieee80211.h | 3 +
net/mac80211/mlme.c | 90 ++++++++++++++++++++++++--------------------
2 files changed, 52 insertions(+), 41 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 48363c3..9789aed 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -770,6 +770,9 @@ struct ieee80211_mgmt {
} u;
} __attribute__ ((packed));

+/* Supported Rates value encodings in 802.11n-2009 7.3.2.2 */
+#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
+
/* mgmt header + 1 byte category code */
#define IEEE80211_MIN_ACTION_SIZE offsetof(struct ieee80211_mgmt, u.action.u)

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index d3b408c..b25567a 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1466,6 +1466,47 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
return RX_MGMT_CFG80211_DISASSOC;
}

+static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
+ u8 *supp_rates, unsigned int supp_rates_len,
+ u32 *rates, u32 *basic_rates,
+ bool *have_higher_than_11mbit,
+ int *min_rate, int *min_rate_index)
+{
+ int i, j;
+
+ for (i = 0; i < supp_rates_len; i++) {
+ int rate = (supp_rates[i] & 0x7f) * 5;
+ bool is_basic = !!(supp_rates[i] & 0x80);
+
+ if (rate > 110)
+ *have_higher_than_11mbit = true;
+
+ /*
+ * BSS_MEMBERSHIP_SELECTOR_HT_PHY is defined in 802.11n-2009
+ * 7.3.2.2 as a magic value instead of a rate. Hence, skip it.
+ *
+ * Note: Even through the membership selector and the basic
+ * rate flag share the same bit, they are not exactly
+ * the same.
+ */
+ if (!!(supp_rates[i] & 0x80) &&
+ (supp_rates[i] & 0x7f) == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
+ continue;
+
+ for (j = 0; j < sband->n_bitrates; j++) {
+ if (sband->bitrates[j].bitrate == rate) {
+ *rates |= BIT(j);
+ if (is_basic)
+ *basic_rates |= BIT(j);
+ if (rate < *min_rate) {
+ *min_rate = rate;
+ *min_rate_index = j;
+ }
+ break;
+ }
+ }
+ }
+}

static bool ieee80211_assoc_success(struct ieee80211_work *wk,
struct ieee80211_mgmt *mgmt, size_t len)
@@ -1482,7 +1523,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
struct ieee802_11_elems elems;
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
u32 changed = 0;
- int i, j, err;
+ int err;
bool have_higher_than_11mbit = false;
u16 ap_ht_cap_flags;
int min_rate = INT_MAX, min_rate_index = -1;
@@ -1540,47 +1581,14 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
basic_rates = 0;
sband = local->hw.wiphy->bands[wk->chan->band];

- for (i = 0; i < elems.supp_rates_len; i++) {
- int rate = (elems.supp_rates[i] & 0x7f) * 5;
- bool is_basic = !!(elems.supp_rates[i] & 0x80);
-
- if (rate > 110)
- have_higher_than_11mbit = true;
+ ieee80211_get_rates(sband, elems.supp_rates, elems.supp_rates_len,
+ &rates, &basic_rates, &have_higher_than_11mbit,
+ &min_rate, &min_rate_index);

- for (j = 0; j < sband->n_bitrates; j++) {
- if (sband->bitrates[j].bitrate == rate) {
- rates |= BIT(j);
- if (is_basic)
- basic_rates |= BIT(j);
- if (rate < min_rate) {
- min_rate = rate;
- min_rate_index = j;
- }
- break;
- }
- }
- }
-
- for (i = 0; i < elems.ext_supp_rates_len; i++) {
- int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
- bool is_basic = !!(elems.ext_supp_rates[i] & 0x80);
-
- if (rate > 110)
- have_higher_than_11mbit = true;
-
- for (j = 0; j < sband->n_bitrates; j++) {
- if (sband->bitrates[j].bitrate == rate) {
- rates |= BIT(j);
- if (is_basic)
- basic_rates |= BIT(j);
- if (rate < min_rate) {
- min_rate = rate;
- min_rate_index = j;
- }
- break;
- }
- }
- }
+ ieee80211_get_rates(sband, elems.ext_supp_rates,
+ elems.ext_supp_rates_len, &rates, &basic_rates,
+ &have_higher_than_11mbit,
+ &min_rate, &min_rate_index);

/*
* some buggy APs don't advertise basic_rates. use the lowest
--
1.7.4.4