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]