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) {

Reply via email to