On 10:23, Edd Barrett wrote:
> I will be willing to test any diffs relating to this. I have some soekris
> with Ral cards which i intended to use in hostap mode.

Hi,

I think finally we have a solution for this :)

First you'll need to apply the two recent CVS commits by Stefan Sperling, 
ieee80211_node.c,v 1.64 and ieee80211_proto.c,v 1.46.

You may then try his 'inactivity' patch included below, otherwise active 
stations could be deauthed when the node cache becomes full.  There used to be 
an LRU list that would caused inactive entries to be removed first, but 
unfortunately that is gone so this seems to be necessary instead.

And I suggest applying my small diff which follows it, to fix the behaviour of 
the clean_nodes function, otherwise it would have tried to clear more nodes out 
of the cache than was intended.

I'm currently trialling these diffs in production, so far with success.  
Further testing would be very helpful right now.  Thanks!


Index: ieee80211_node.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_node.c,v
retrieving revision 1.64
diff -u -p -r1.64 ieee80211_node.c
--- ieee80211_node.c    18 Jan 2012 14:35:34 -0000      1.64
+++ ieee80211_node.c    18 Jan 2012 23:21:30 -0000
@@ -95,10 +95,35 @@ void ieee80211_node_leave_ht(struct ieee
 void ieee80211_node_leave_rsn(struct ieee80211com *, struct ieee80211_node *);
 void ieee80211_node_leave_11g(struct ieee80211com *, struct ieee80211_node *);
 void ieee80211_set_tim(struct ieee80211com *, int, int);
+void ieee80211_inact_timeout(void *);
 #endif
 
 #define M_80211_NODE   M_DEVBUF
 
+#ifndef IEEE80211_STA_ONLY
+void ieee80211_inact_timeout(void *arg)
+{
+       struct ieee80211com *ic = arg;
+       struct ieee80211_node *ni, *next_ni;
+       int s;
+
+       s = splnet();
+       for (ni = RB_MIN(ieee80211_tree, &ic->ic_tree);
+           ni != NULL; ni = next_ni) {
+               next_ni = RB_NEXT(ieee80211_tree, &ic->ic_tree, ni);
+               if (ni == ic->ic_bss)
+                       continue;
+               if (ni->ni_refcnt > 0)
+                       continue;
+               if (ni->ni_inact < IEEE80211_INACT_MAX)
+                       ni->ni_inact++;
+       }
+       splx(s);
+
+       timeout_add_sec(&ic->ic_inact_timeout, IEEE80211_INACT_WAIT);
+}
+#endif
+
 void
 ieee80211_node_attach(struct ifnet *ifp)
 {
@@ -138,6 +163,8 @@ ieee80211_node_attach(struct ifnet *ifp)
                        ic->ic_set_tim = ieee80211_set_tim;
                timeout_set(&ic->ic_rsn_timeout,
                    ieee80211_gtk_rekey_timeout, ic);
+               timeout_set(&ic->ic_inact_timeout,
+                   ieee80211_inact_timeout, ic);
        }
 #endif
 }
@@ -185,6 +212,7 @@ ieee80211_node_detach(struct ifnet *ifp)
                free(ic->ic_aid_bitmap, M_DEVBUF);
        if (ic->ic_tim_bitmap != NULL)
                free(ic->ic_tim_bitmap, M_DEVBUF);
+       timeout_del(&ic->ic_inact_timeout);
 #endif
        timeout_del(&ic->ic_rsn_timeout);
 }
@@ -378,6 +406,7 @@ ieee80211_create_ibss(struct ieee80211co
                /* schedule a GTK/IGTK rekeying after 3600s */
                timeout_add_sec(&ic->ic_rsn_timeout, 3600);
        }
+       timeout_add_sec(&ic->ic_inact_timeout, IEEE80211_INACT_WAIT);
        ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
 }
 #endif /* IEEE80211_STA_ONLY */
@@ -771,20 +800,7 @@ ieee80211_setup_node(struct ieee80211com
        timeout_set(&ni->ni_eapol_to, ieee80211_eapol_timeout, ni);
        timeout_set(&ni->ni_sa_query_to, ieee80211_sa_query_timeout, ni);
 #endif
-
-       /*
-        * Note we don't enable the inactive timer when acting
-        * as a station.  Nodes created in this mode represent
-        * AP's identified while scanning.  If we time them out
-        * then several things happen: we can't return the data
-        * to users to show the list of AP's we encountered, and
-        * more importantly, we'll incorrectly deauthenticate
-        * ourself because the inactivity timer will kick us off.
-        */
        s = splnet();
-       if (ic->ic_opmode != IEEE80211_M_STA &&
-           RB_EMPTY(&ic->ic_tree))
-               ic->ic_inact_timer = IEEE80211_INACT_WAIT;
        RB_INSERT(ieee80211_tree, &ic->ic_tree, ni);
        splx(s);
 }
@@ -1067,8 +1083,6 @@ ieee80211_free_node(struct ieee80211com 
                        (*ic->ic_set_tim)(ic, ni->ni_associd, 0);
        }
 #endif
-       if (RB_EMPTY(&ic->ic_tree))
-               ic->ic_inact_timer = 0;
        (*ic->ic_node_free)(ic, ni);
        /* TBD indicate to drivers that a new node can be allocated */
 }
@@ -1125,6 +1139,13 @@ ieee80211_clean_nodes(struct ieee80211co
                ni->ni_scangen = gen;
                if (ni->ni_refcnt > 0)
                        continue;
+#ifndef IEEE80211_STA_ONLY
+               if ((ic->ic_opmode == IEEE80211_M_HOSTAP ||
+                   ic->ic_opmode == IEEE80211_M_IBSS) &&
+                   ic->ic_state == IEEE80211_S_RUN &&
+                   ni->ni_inact < IEEE80211_INACT_MAX)
+                       continue;
+#endif
                DPRINTF(("station %s purged from LRU cache\n",
                    ether_sprintf(ni->ni_macaddr)));
                /*
Index: ieee80211_var.h
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_var.h,v
retrieving revision 1.61
diff -u -p -r1.61 ieee80211_var.h
--- ieee80211_var.h     19 Jul 2010 18:53:52 -0000      1.61
+++ ieee80211_var.h     18 Jan 2012 20:15:20 -0000
@@ -269,7 +269,9 @@ struct ieee80211com {
        u_int16_t               ic_rsnsta;      /* # RSN stations */
        u_int16_t               ic_pssta;       /* # ps mode stations */
        int                     ic_mgt_timer;   /* mgmt timeout */
-       int                     ic_inact_timer; /* inactivity timer wait */
+#ifndef IEEE80211_STA_ONLY
+       struct timeout          ic_inact_timeout; /* inactivity timeout */
+#endif
        int                     ic_des_esslen;
        u_int8_t                ic_des_essid[IEEE80211_NWID_LEN];
        struct ieee80211_channel *ic_des_chan;  /* desired channel */



--- ieee80211_node.c.orig       Thu Jan 19 22:46:06 2012
+++ ieee80211_node.c    Thu Jan 19 23:17:33 2012
@@ -1145,21 +1145,23 @@ ieee80211_clean_nodes(struct ieee80211com *ic)
                    ic->ic_state == IEEE80211_S_RUN &&
                    ni->ni_inact < IEEE80211_INACT_MAX)
                        continue;
 #endif
                DPRINTF(("station %s purged from LRU cache\n",
                    ether_sprintf(ni->ni_macaddr)));
                /*
                 * Send a deauthenticate frame.
                 */
 #ifndef IEEE80211_STA_ONLY
-               if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
+               if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
+                   ni->ni_state >= IEEE80211_STA_AUTH &&
+                   ni->ni_state != IEEE80211_STA_COLLECT) {
                        splx(s);
                        IEEE80211_SEND_MGMT(ic, ni,
                            IEEE80211_FC0_SUBTYPE_DEAUTH,
                            IEEE80211_REASON_AUTH_EXPIRE);
                        s = splnet();
                        ieee80211_node_leave(ic, ni);
                } else
 #endif
                        ieee80211_free_node(ic, ni);
                ic->ic_stats.is_node_timeout++;

-- 
Steven Chamberlain
[email protected]

Reply via email to