On Wed, May 18, 2016 at 06:24:15AM +0800, Nathanael Rensen wrote: > On 27 April 2016 at 17:33, Stefan Sperling <s...@stsp.name> 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
Thanks, committed with a slight tweak: @@ -1496,7 +1496,7 @@ void ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni, int resp) { - int newassoc; + int newassoc = (ni->ni_state != IEEE80211_STA_ASSOC); if (ni->ni_associd == 0) { u_int16_t aid; Please help me with watching the lists for regression reports. > 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, >