On 27 April 2016 at 17:33, Stefan Sperling <[email protected]> wrote:

> This version includes minor tweak: When the AP goes down, we don't
> need to send disassoc frames to nodes in COLLECT state.

While testing this diff I found some additional ieee80211 code paths
that rely on ni_associd == 0 to detect a non-associated node. These
caused issues for rt2860.

a) The rt2860 driver removes the corresponding WCID from the hardware
table when a node dissociates. The WCID is added when the ic_newassoc()
hook is called with the newassoc flag set. However, ieee80211_node_join()
relies on ni_associd == 0 to determine whether to set the newassoc flag.
If a cached node that already has a non-zero aid is reused the newassoc
flag is not set and the WCID is not added to the hardware table.

b) A node that is inactive for a long period is placed into
IEEE80211_STA_COLLECT by ieee80211_clean_nodes() and must reassociate
before it can exchange data. If the node believes it is still associated
then it will continue to use the defunct association. There is code in
ieee80211_input() to detect this and send a management frame informing
the node that it must reassociate. The detection also relies on
ni_associd == 0, so a previously associated node that has retained its
ni_associd will not be instructed to reassociate and will continue to
use the defunct association (I saw this behaviour with android phones).

With the approach of retaining the aid for nodes in IEEE80211_STA_COLLECT
ni_associd == 0 is no longer a reliable way to infer node state. I think
it is better to rely on the node state directly. The diff below includes
stsp@'s diff along with additional changes to use the node state directly
to drive the logic.

Nathanael

Index: ieee80211_input.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_input.c,v
retrieving revision 1.176
diff -u -p -r1.176 ieee80211_input.c
--- ieee80211_input.c   2 May 2016 09:35:49 -0000       1.176
+++ ieee80211_input.c   10 May 2016 01:05:22 -0000
@@ -447,7 +447,7 @@ ieee80211_input(struct ifnet *ifp, struc
                                ic->ic_stats.is_rx_notassoc++;
                                goto err;
                        }
-                       if (ni->ni_associd == 0) {
+                       if (ni->ni_state != IEEE80211_STA_ASSOC) {
                                DPRINTF(("data from unassoc src %s\n",
                                    ether_sprintf(wh->i_addr2)));
                                IEEE80211_SEND_MGMT(ic, ni,
Index: ieee80211_node.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_node.c,v
retrieving revision 1.101
diff -u -p -r1.101 ieee80211_node.c
--- ieee80211_node.c    12 Apr 2016 14:33:27 -0000      1.101
+++ ieee80211_node.c    10 May 2016 01:05:22 -0000
@@ -1496,7 +1496,10 @@ void
 ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni,
     int resp)
 {
-       int newassoc;
+       int newassoc = 1;
+
+       if (ni->ni_state == IEEE80211_STA_ASSOC)
+               newassoc = 0;
 
        if (ni->ni_associd == 0) {
                u_int16_t aid;
@@ -1518,13 +1521,11 @@ ieee80211_node_join(struct ieee80211com 
                }
                ni->ni_associd = aid | 0xc000;
                IEEE80211_AID_SET(ni->ni_associd, ic->ic_aid_bitmap);
-               newassoc = 1;
                if (ic->ic_curmode == IEEE80211_MODE_11G ||
                    (ic->ic_curmode == IEEE80211_MODE_11N &&
                    IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan)))
                        ieee80211_node_join_11g(ic, ni);
-       } else
-               newassoc = 0;
+       }
 
        DPRINTF(("station %s %s associated at aid %d\n",
            ether_sprintf(ni->ni_macaddr), newassoc ? "newly" : "already",
@@ -1699,8 +1700,6 @@ ieee80211_node_leave(struct ieee80211com
        if (ic->ic_node_leave != NULL)
                (*ic->ic_node_leave)(ic, ni);
 
-       IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
-       ni->ni_associd = 0;
        ieee80211_node_newstate(ni, IEEE80211_STA_COLLECT);
 
 #if NBRIDGE > 0
Index: ieee80211_proto.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_proto.c,v
retrieving revision 1.66
diff -u -p -r1.66 ieee80211_proto.c
--- ieee80211_proto.c   27 Apr 2016 11:58:10 -0000      1.66
+++ ieee80211_proto.c   10 May 2016 01:05:22 -0000
@@ -852,7 +852,7 @@ ieee80211_newstate(struct ieee80211com *
                        case IEEE80211_M_HOSTAP:
                                s = splnet();
                                RB_FOREACH(ni, ieee80211_tree, &ic->ic_tree) {
-                                       if (ni->ni_associd == 0)
+                                       if (ni->ni_state != IEEE80211_STA_ASSOC)
                                                continue;
                                        IEEE80211_SEND_MGMT(ic, ni,
                                            IEEE80211_FC0_SUBTYPE_DISASSOC,

Reply via email to