I noticed that an 11a/b ath(4) card, which does not support 11g,
includes 11g rates ("xrates") in association requests it sends on 2GHz:

20:55:03.490128 802.11 flags=0<>: association request, \
caps=2041<ESS,SHORT_PREAMBLE,SHORT_SLOTTIME>, ssid (stsp.name), \
rates 1M* 2M* 5M 6M 9M 11M 12M 18M, xrates 24M 36M 48M 54M, \
rsn 0x0100000fac040100000fac040100000fac0200000000, \
<radiotap v0, 1Mbit/s, chan 5, 11g, sig -26dBm, noise -89dBm>

This is wrong. On 2GHz this client should only advertise 11b rates,
i.e. rates up to and including 11M.

This happens because invalid rates are not discarded from ni->ni_rates
early enough. By default this rateset includes the 11a rates (which
overlap with 11g ones). ieee80211_get_assoc_req() copies rateset
information from ni->ni_rates and includes these bogus rates.

To fix this, call ieee80211_fix_rate() after choosing an AP.
The most important flag parameter here is DODEL which removes invalid rates.
DODEL only takes effect if DOSORT and DONEGO are also set, so just pass
all the flags.

Now this client sends a proper 11b rateset in its assoc request:

21:49:36.934631 802.11 flags=0<>: association request, \
caps=2041<ESS,SHORT_PREAMBLE,SHORT_SLOTTIME>, ssid (stsp.name), \
rates 1M* 2M* 5M 11M, rsn 0x0100000fac040100000fac040100000fac0200000000, \
<radiotap v0, 1Mbit/s, chan 5, 11g, sig -20dBm, noise -89dBm>

Note that rates get fixed up again after association is confirmed,
via ieee80211_recv_assoc_resp() -> ieee80211_setup_rates().
Which is why 11b clients were already working fine in spite of sending
a bogus rateset in the association request.

Index: ieee80211_node.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_node.c,v
retrieving revision 1.113
diff -u -p -r1.113 ieee80211_node.c
--- ieee80211_node.c    2 Feb 2017 16:47:53 -0000       1.113
+++ ieee80211_node.c    2 Feb 2017 20:50:36 -0000
@@ -676,6 +676,12 @@ ieee80211_end_scan(struct ifnet *ifp)
 
        ic->ic_curmode = ieee80211_chan2mode(ic, ni->ni_chan);
 
+       /* Make sure we send valid rates in an association request. */
+       if (ic->ic_opmode == IEEE80211_M_STA)
+               ieee80211_fix_rate(ic, ni,
+                   IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
+                   IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
+
        if (ic->ic_flags & IEEE80211_F_RSNON)
                ieee80211_choose_rsnparams(ic);
        else if (ic->ic_flags & IEEE80211_F_WEPON)

Reply via email to