On Fri, Dec 18, 2015 at 03:16:52PM +0100, David Coppa wrote: > On Thu, Dec 17, 2015 at 10:34 PM, Stefan Sperling <s...@stsp.name> wrote: > > On Thu, Dec 17, 2015 at 08:13:03PM +0100, Stefan Sperling wrote: > >> This should fix the infinite scanning loops people have been > >> reporting with 11n-enabled iwn(4), as well as the issue where > >> clients associating to 11g APs end up in 11b mode and can't > >> use OFDM data rates. > >> > >> ok? > > > > Updated diff which allows scanning to work after somebody decided > > to run 'ifconfig iwn0 media autoselect mode 11n' for some reason. > > (Don't do that, it won't enforce 11n -- 11n cannot really be set > > a priori because it's negotiated during association.) > > > > Also delete a bit of code from ieee80211_newstate() in ieee80211_proto.c > > which is pointless now that ieee80211_chan2mode() won't return MODE_11N. > > A minor problem I've noticed was dhclient being slower to get the link > from my AP. > The patch below fixed it.
Here's yet another update. I hope this also fixes a transmit problem on 2GHz reported by sthen@. For some reason ieee80211_end_scan() handled some parts of setting up 11g ERP but that's now much too early in the association process. I've moved this code into ieee80211_recv_assoc_resp() because before then we just don't know whether we're going to end up in 11g or 11n mode. Index: ieee80211.c =================================================================== RCS file: /cvs/src/sys/net80211/ieee80211.c,v retrieving revision 1.53 diff -u -p -r1.53 ieee80211.c --- ieee80211.c 18 Dec 2015 07:42:24 -0000 1.53 +++ ieee80211.c 18 Dec 2015 14:23:08 -0000 @@ -875,6 +875,14 @@ ieee80211_next_mode(struct ifnet *ifp) /* Wrap around and ignore turbo mode */ if (ic->ic_curmode == IEEE80211_MODE_TURBO) continue; +#ifndef IEEE80211_NO_HT + /* + * Skip over 11n mode. Its set of channels is the superset + * of all channels supported by the other modes. + */ + if (ic->ic_curmode == IEEE80211_MODE_11N) + continue; +#endif if (ic->ic_curmode >= IEEE80211_MODE_MAX) { ic->ic_curmode = IEEE80211_MODE_AUTO; break; @@ -894,6 +902,11 @@ ieee80211_next_mode(struct ifnet *ifp) * caller can select a rate set. This is problematic and the * work here assumes how things work elsewhere in this code. * + * Because the result of this function is ultimately used to select + * a rate from the rate set of the returned mode, it must not return + * IEEE80211_MODE_11N. This function may be called in 11n mode to find + * a non-MCS rate to use for sending frames to non-HT STAs. + * * XXX never returns turbo modes -dcy */ enum ieee80211_phymode @@ -904,19 +917,15 @@ ieee80211_chan2mode(struct ieee80211com * NB: this assumes the channel would not be supplied to us * unless it was already compatible with the current mode. */ - if (ic->ic_curmode != IEEE80211_MODE_AUTO || - chan == IEEE80211_CHAN_ANYC) + if (ic->ic_curmode != IEEE80211_MODE_11N && + (ic->ic_curmode != IEEE80211_MODE_AUTO || + chan == IEEE80211_CHAN_ANYC)) return ic->ic_curmode; /* - * In autoselect mode; deduce a mode based on the channel + * In autoselect or 11n mode; deduce a mode based on the channel * characteristics. We assume that turbo-only channels * are not considered when the channel set is constructed. */ -#ifndef IEEE80211_NO_HT - if (IEEE80211_IS_CHAN_N(chan)) - return IEEE80211_MODE_11N; - else -#endif if (IEEE80211_IS_CHAN_T(chan)) return IEEE80211_MODE_TURBO; else if (IEEE80211_IS_CHAN_5GHZ(chan)) Index: ieee80211_input.c =================================================================== RCS file: /cvs/src/sys/net80211/ieee80211_input.c,v retrieving revision 1.145 diff -u -p -r1.145 ieee80211_input.c --- ieee80211_input.c 12 Dec 2015 13:56:10 -0000 1.145 +++ ieee80211_input.c 18 Dec 2015 13:35:17 -0000 @@ -210,8 +210,7 @@ ieee80211_input_print(struct ieee80211co "%s: received %s from %s rssi %d mode %s\n", ifp->if_xname, ieee80211_mgt_subtype_name[subtype >> IEEE80211_FC0_SUBTYPE_SHIFT], ether_sprintf(wh->i_addr2), rxi->rxi_rssi, - ieee80211_phymode_name[ieee80211_chan2mode( - ic, ic->ic_bss->ni_chan)]); + ieee80211_phymode_name[ic->ic_curmode]); task_set(&msg->task, ieee80211_input_print_task, msg); task_add(systq, &msg->task); @@ -2250,24 +2249,17 @@ ieee80211_recv_assoc_resp(struct ieee802 ieee80211_ht_negotiate(ic, ni); /* Hop into 11n mode after associating to an HT AP in a non-11n mode. */ - if (ic->ic_curmode != IEEE80211_MODE_AUTO && - ic->ic_curmode != IEEE80211_MODE_11N && - (ni->ni_flags & IEEE80211_NODE_HT)) + if (ni->ni_flags & IEEE80211_NODE_HT) ieee80211_setmode(ic, IEEE80211_MODE_11N); - - /* Hop out of 11n mode after associating to a non-HT AP. */ - if (ic->ic_curmode == IEEE80211_MODE_11N && - (ni->ni_flags & IEEE80211_NODE_HT) == 0) { - if (IEEE80211_IS_CHAN_T(ni->ni_chan)) - ieee80211_setmode(ic, IEEE80211_MODE_TURBO); - else if (IEEE80211_IS_CHAN_A(ni->ni_chan)) - ieee80211_setmode(ic, IEEE80211_MODE_11A); - else if (IEEE80211_IS_CHAN_G(ni->ni_chan)) - ieee80211_setmode(ic, IEEE80211_MODE_11G); - else - ieee80211_setmode(ic, IEEE80211_MODE_11B); - } + else #endif + ieee80211_setmode(ic, ieee80211_chan2mode(ic, ni->ni_chan)); + /* + * Reset the erp state (mostly the slot time) now that + * our operating mode has been nailed down. + */ + ieee80211_reset_erp(ic); + /* * Configure state now that we are associated. */ Index: ieee80211_node.c =================================================================== RCS file: /cvs/src/sys/net80211/ieee80211_node.c,v retrieving revision 1.93 diff -u -p -r1.93 ieee80211_node.c --- ieee80211_node.c 12 Dec 2015 11:25:46 -0000 1.93 +++ ieee80211_node.c 18 Dec 2015 13:11:35 -0000 @@ -637,14 +637,6 @@ ieee80211_end_scan(struct ifnet *ifp) (*ic->ic_node_copy)(ic, ic->ic_bss, selbs); ni = ic->ic_bss; - /* - * Set the erp state (mostly the slot time) to deal with - * the auto-select case; this should be redundant if the - * mode is locked. - */ - ic->ic_curmode = ieee80211_chan2mode(ic, ni->ni_chan); - ieee80211_reset_erp(ic); - if (ic->ic_flags & IEEE80211_F_RSNON) ieee80211_choose_rsnparams(ic); else if (ic->ic_flags & IEEE80211_F_WEPON) Index: ieee80211_proto.c =================================================================== RCS file: /cvs/src/sys/net80211/ieee80211_proto.c,v retrieving revision 1.56 diff -u -p -r1.56 ieee80211_proto.c --- ieee80211_proto.c 24 Nov 2015 13:45:06 -0000 1.56 +++ ieee80211_proto.c 18 Dec 2015 14:38:07 -0000 @@ -894,15 +894,8 @@ justcleanup: /* initialize bss for probe request */ IEEE80211_ADDR_COPY(ni->ni_macaddr, etherbroadcastaddr); IEEE80211_ADDR_COPY(ni->ni_bssid, etherbroadcastaddr); -#ifndef IEEE80211_NO_HT - if (ic->ic_curmode == IEEE80211_MODE_11N) - ni->ni_rates = ic->ic_sup_rates[ - IEEE80211_IS_CHAN_2GHZ(ni->ni_chan) ? - IEEE80211_MODE_11G : IEEE80211_MODE_11A]; - else -#endif - ni->ni_rates = ic->ic_sup_rates[ - ieee80211_chan2mode(ic, ni->ni_chan)]; + ni->ni_rates = ic->ic_sup_rates[ + ieee80211_chan2mode(ic, ni->ni_chan)]; ni->ni_associd = 0; ni->ni_rstamp = 0; switch (ostate) {