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.
Index: ieee80211.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211.c,v
retrieving revision 1.52
diff -u -p -r1.52 ieee80211.c
--- ieee80211.c 16 Dec 2015 12:52:03 -0000 1.52
+++ ieee80211.c 17 Dec 2015 21:16:03 -0000
@@ -856,10 +856,12 @@ ieee80211_next_mode(struct ifnet *ifp)
{
struct ieee80211com *ic = (void *)ifp;
- if (IFM_MODE(ic->ic_media.ifm_cur->ifm_media) != IFM_AUTO) {
+ if (IFM_MODE(ic->ic_media.ifm_cur->ifm_media) != IFM_AUTO &&
+ ic->ic_curmode != IEEE80211_MODE_11N) {
/*
* Reset the scan state and indicate a wrap around
* if we're running in a fixed, user-specified phy mode.
+ * But 11n is not a valid phy mode for scanning (see below).
*/
ieee80211_reset_scan(ifp);
return (IEEE80211_MODE_AUTO);
@@ -874,6 +876,16 @@ 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 11n mode while scanning. Its set of channels is
+ * the superset of all channels supported by other modes
+ * and 11n features cannot be negotiated without exchanging
+ * frames in another mode first.
+ */
+ if (ic->ic_curmode == IEEE80211_MODE_11N)
+ continue;
+#endif
if (ic->ic_curmode >= IEEE80211_MODE_MAX) {
ic->ic_curmode = IEEE80211_MODE_AUTO;
break;
@@ -893,6 +905,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
@@ -911,11 +928,6 @@ ieee80211_chan2mode(struct ieee80211com
* 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 17 Dec 2015 18:42:06 -0000
@@ -2257,16 +2257,8 @@ ieee80211_recv_assoc_resp(struct ieee802
/* 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);
- }
+ (ni->ni_flags & IEEE80211_NODE_HT) == 0)
+ ieee80211_setmode(ic, ieee80211_chan2mode(ic, ni->ni_chan));
#endif
/*
* Configure state now that we are associated.
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 17 Dec 2015 20:58:40 -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) {