A wifi driver's newassoc routine gets invoked excessively often in IBSS mode.
It runs whenever a probe response is received. Showing output from a patched
newassoc routine which prints "new node <address>":
Jan 10 02:01:09 jim /bsd: new node 00:24:fe:44:07:bb
Jan 10 02:01:09 jim /bsd: new node 88:25:2c:bf:81:59
Jan 10 02:01:09 jim /bsd: new node 34:81:c4:ac:4e:f0
Jan 10 02:01:09 jim /bsd: new node bc:05:43:c9:8b:d3
Jan 10 02:01:09 jim /bsd: new node 00:0e:8e:24:52:7d
Jan 10 02:01:09 jim /bsd: new node 00:0e:2e:5c:55:4f
Jan 10 02:01:09 jim /bsd: new node 00:24:fe:44:07:bb
Jan 10 02:01:09 jim /bsd: new node 34:81:c4:ac:4e:f0
Jan 10 02:01:09 jim /bsd: new node bc:05:43:c9:8b:d3
Jan 10 02:01:09 jim /bsd: new node 00:0e:8e:24:52:7d
Jan 10 02:01:09 jim /bsd: new node 00:0e:2e:5c:55:4f
Jan 10 02:01:09 jim /bsd: new node 34:81:c4:ac:4e:f0
Jan 10 02:01:09 jim /bsd: new node 00:0e:8e:24:52:7d
It keeps being called for the same nodes, very often. Since drivers
usually reset the node's tx rate in newassoc() this seems rather strange.
Looking at the history of ieee80211_input.c I believe a mistake crept
in several years ago in r1.4:
- if (ic->ic_state == IEEE80211_S_SCAN)
- ieee80211_unref_node(&ni); /* NB: do not free */
- else if (ic->ic_opmode == IEEE80211_M_IBSS &&
- allocbs && isprobe) {
+ if (ic->ic_opmode == IEEE80211_M_IBSS || (is_new &&
+ ISPROBE(subtype))) {
Note how && was changed to || in this revision and has since been kept.
The original code in r1.1 in this if-block applied only to IBSS mode:
else if (ic->ic_opmode == IEEE80211_M_IBSS &&
allocbs && isprobe) {
/*
* Fake an association so the driver can setup it's
* private state. The rate set has been setup above;
* there is no handshake as in ap/station operation.
*/
if (ic->ic_newassoc)
(*ic->ic_newassoc)(ic, ni, 1);
In AP and station modes newassoc is called via ieee80211_node_join()
so there is no reason to call it for probe responses.
Proposed fix restores the original behaviour and removes an outdated comment.
Index: ieee80211_input.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_input.c,v
retrieving revision 1.128
diff -u -p -r1.128 ieee80211_input.c
--- ieee80211_input.c 23 Dec 2014 03:24:08 -0000 1.128
+++ ieee80211_input.c 10 Jan 2015 02:16:59 -0000
@@ -1633,18 +1633,8 @@ ieee80211_recv_probe_resp(struct ieee802
/* NB: must be after ni_chan is setup */
ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT);
- /*
- * When scanning we record results (nodes) with a zero
- * refcnt. Otherwise we want to hold the reference for
- * ibss neighbors so the nodes don't get released prematurely.
- * Anything else can be discarded (XXX and should be handled
- * above so we don't do so much work).
- */
- if (
#ifndef IEEE80211_STA_ONLY
- ic->ic_opmode == IEEE80211_M_IBSS ||
-#endif
- (is_new && isprobe)) {
+ if (ic->ic_opmode == IEEE80211_M_IBSS && is_new && isprobe) {
/*
* Fake an association so the driver can setup it's
* private state. The rate set has been setup above;
@@ -1653,6 +1643,7 @@ ieee80211_recv_probe_resp(struct ieee802
if (ic->ic_newassoc)
(*ic->ic_newassoc)(ic, ni, 1);
}
+#endif
}
#ifndef IEEE80211_STA_ONLY