Even though the 11n standard mandates MCS 0-15 for APs, some APs have config
knobs which disable a subset of MCS, and some admins do touch these knobs.
E.g. at 33C3 there are APs with: RxMCS 0xf8f8f800000000000000
The diff below makes OpenBSD clients work in 11n mode on such networks
by relaxing our "supported MCS" 11n feature check.
This is now possible because our new mira rate scaling implementation
skips MCS which aren't supported by both peers (whereas AMRR did not).
Also includes a fix where mira didn't account for missing MCS.
ok?
Index: ieee80211_mira.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_mira.c,v
retrieving revision 1.4
diff -u -p -r1.4 ieee80211_mira.c
--- ieee80211_mira.c 10 Dec 2016 14:46:04 -0000 1.4
+++ ieee80211_mira.c 26 Dec 2016 19:42:17 -0000
@@ -82,7 +82,7 @@ void ieee80211_mira_probe_next_rate(stru
struct ieee80211_node *);
uint32_t ieee80211_mira_valid_rates(struct ieee80211com *,
struct ieee80211_node *);
-uint32_t ieee80211_mira_mcs_below(int);
+uint32_t ieee80211_mira_mcs_below(struct ieee80211_mira_node *, int);
/* We use fixed point arithmetic with 64 bit integers. */
#define MIRA_FP_SHIFT 21
@@ -656,7 +656,8 @@ ieee80211_mira_probe_next_rateset(struct
(1 << ieee80211_mira_next_intra_rate(mn, ni));
} else if (mn->probing & IEEE80211_MIRA_PROBING_DOWN) {
#ifdef MIRA_AGGRESSIVE_DOWNWARDS_PROBING
- mn->candidate_rates |= ieee80211_mira_mcs_below(ni->ni_txmcs);
+ mn->candidate_rates |= ieee80211_mira_mcs_below(mn,
+ ni->ni_txmcs);
#else
mn->candidate_rates |=
(1 << ieee80211_mira_next_lower_intra_rate(mn, ni));
@@ -963,7 +964,7 @@ ieee80211_mira_valid_rates(struct ieee80
}
uint32_t
-ieee80211_mira_mcs_below(int mcs)
+ieee80211_mira_mcs_below(struct ieee80211_mira_node *mn, int mcs)
{
const struct ieee80211_mira_rateset *rs;
uint32_t mcs_mask;
@@ -971,8 +972,11 @@ ieee80211_mira_mcs_below(int mcs)
rs = ieee80211_mira_get_rateset(mcs);
mcs_mask = (1 << rs->min_mcs);
- for (i = rs->min_mcs + 1; i < mcs; i++)
+ for (i = rs->min_mcs + 1; i < mcs; i++) {
+ if ((mn->valid_rates & (1 << i)) == 0)
+ continue;
mcs_mask |= (1 << i);
+ }
return mcs_mask;
}
@@ -1050,7 +1054,8 @@ ieee80211_mira_choose(struct ieee80211_m
mn->probed_rates = 0;
#ifdef MIRA_AGGRESSIVE_DOWNWARDS_PROBING
/* Allow for probing all the way down within this rateset. */
- mn->candidate_rates = ieee80211_mira_mcs_below(ni->ni_txmcs);
+ mn->candidate_rates = ieee80211_mira_mcs_below(mn,
+ ni->ni_txmcs);
#else
/* Probe the lower candidate rate to see if it's any better. */
mn->candidate_rates =
Index: ieee80211_proto.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_proto.c,v
retrieving revision 1.69
diff -u -p -r1.69 ieee80211_proto.c
--- ieee80211_proto.c 15 Sep 2016 03:32:48 -0000 1.69
+++ ieee80211_proto.c 26 Dec 2016 19:34:50 -0000
@@ -555,8 +555,12 @@ ieee80211_ht_negotiate(struct ieee80211c
if ((ic->ic_flags & IEEE80211_F_HTON) == 0)
return;
- /* Check if the peer supports HT. MCS 0-7 are mandatory. */
- if (ni->ni_rxmcs[0] != 0xff) {
+ /*
+ * Check if the peer supports HT.
+ * Require at least one of the mandatory MCS.
+ * MCS 0-7 are mandatory but some APs have particular MCS disabled.
+ */
+ if ((ni->ni_rxmcs[0] & 0xff) == 0) {
ic->ic_stats.is_ht_nego_no_mandatory_mcs++;
return;
}