PERFORCE change 66240 for review

Sam Leffler sam at FreeBSD.org
Wed Dec 1 21:31:10 PST 2004


http://perforce.freebsd.org/chv.cgi?CH=66240

Change 66240 by sam at sam_ebb on 2004/12/02 05:30:51

	Revamp sta inactivity handling:
	o set a reload value in each node that's loaded into ni_inact
	  on frame rx (rather than sprinkling reloads around)
	o have ath driver reload ni_inact on notice of frame ACK (need
	  to update other drivers)
	o add an inactivity probe threshold, when it's hit we send a
	  null data frame which should be ack'd and reset ni_inact
	o add mib variable for inact_probe
	
	This eliminates gratuitous station deauthentication which is
	important when authenticated with WPA/802.1x.

Affected files ...

.. //depot/projects/wifi/sys/dev/ath/if_ath.c#36 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_freebsd.c#6 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_input.c#21 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_node.c#22 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_node.h#15 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_output.c#18 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_var.h#14 edit

Differences ...

==== //depot/projects/wifi/sys/dev/ath/if_ath.c#36 (text+ko) ====

@@ -3353,6 +3353,7 @@
 				pri = M_WME_GETAC(bf->bf_m);
 				if (pri >= WME_AC_VO)
 					ic->ic_wme.wme_hipri_traffic++;
+				ni->ni_inact = ni->ni_inact_reload;
 			} else {
 				if (ds->ds_txstat.ts_status & HAL_TXERR_XRETRY)
 					sc->sc_stats.ast_tx_xretries++;

==== //depot/projects/wifi/sys/net80211/ieee80211_freebsd.c#6 (text+ko) ====

@@ -110,6 +110,10 @@
 		ieee80211_sysctl_inact, "I",
 		"station inactivity timeout (sec)");
 	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+		"inact_probe", CTLTYPE_INT | CTLFLAG_RW, &ic->ic_inact_probe, 0,
+		ieee80211_sysctl_inact, "I",
+		"station inactivity probe timeout (sec)");
+	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
 		"inact_auth", CTLTYPE_INT | CTLFLAG_RW, &ic->ic_inact_auth, 0,
 		ieee80211_sysctl_inact, "I",
 		"station authentication timeout (sec)");

==== //depot/projects/wifi/sys/net80211/ieee80211_input.c#21 (text+ko) ====

@@ -119,6 +119,7 @@
 	u_int16_t rxseq;
 
 	KASSERT(ni != NULL, ("null node"));
+	ni->ni_inact = ni->ni_inact_reload;
 
 	/* trim CRC here so WEP can find its own CRC at the end of packet. */
 	if (m->m_flags & M_HASFCS) {
@@ -458,7 +459,6 @@
 				IEEE80211_NODE_STAT(ni, rx_unauth);
 				goto err;
 			}
-			ni->ni_inact = ic->ic_inact_auth;
 		} else {
 			/*
 			 * When denying unencrypted frames, discard
@@ -474,7 +474,6 @@
 				IEEE80211_NODE_STAT(ni, rx_unencrypted);
 				goto out;
 			}
-			ni->ni_inact = ic->ic_inact_run;
 		}
 		ifp->if_ipackets++;
 		IEEE80211_NODE_STAT(ni, rx_data);
@@ -866,8 +865,7 @@
 			if (ni == NULL)
 				return;
 		}
-		ni->ni_rssi = rssi;
-		ni->ni_rstamp = rstamp;
+		ni->ni_inact_reload = ic->ic_inact_auth;
 		IEEE80211_SEND_MGMT(ic, ni,
 			IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);
 		IEEE80211_DPRINTF(ic, IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
@@ -1049,6 +1047,7 @@
 				estatus = IEEE80211_STATUS_CHALLENGE;
 				goto bad;
 			}
+			ni->ni_inact_reload = ic->ic_inact_auth;
 			IEEE80211_DPRINTF(ic,
 				IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
 				"station %s authenticated (shared key)\n",
@@ -1832,7 +1831,6 @@
 			}
 			if (wme != NULL && ieee80211_parse_wmeparams(ic, wme))
 				ieee80211_wme_updateparams(ic);
-			ni->ni_inact = ic->ic_inact_run;
 			/* NB: don't need the rest of this */
 			return;
 		}
@@ -1863,26 +1861,23 @@
 			ni->ni_esslen = ssid[1];
 			memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
 			memcpy(ni->ni_essid, ssid + 2, ssid[1]);
-		} else {
-			ni->ni_inact = ic->ic_inact_run;	/* XXX? */
-			if (ssid[1] != 0 &&
-			    (ISPROBE(subtype) || ni->ni_esslen == 0)) {
-				/*
-				 * Update ESSID at probe response to adopt
-				 * hidden AP by Lucent/Cisco, which announces
-				 * null ESSID in beacon.
-				 */
+		} else if (ssid[1] != 0 &&
+		    (ISPROBE(subtype) || ni->ni_esslen == 0)) {
+			/*
+			 * Update ESSID at probe response to adopt
+			 * hidden AP by Lucent/Cisco, which announces
+			 * null ESSID in beacon.
+			 */
 #ifdef IEEE80211_DEBUG
-				if (ieee80211_msg_scan(ic) ||
-				    ieee80211_msg_debug(ic))
-					dump_probe_beacon(subtype, 0,
-					    wh->i_addr2, chan, bchan, capinfo,
-					    bintval, erp, ssid, country);
+			if (ieee80211_msg_scan(ic) ||
+			    ieee80211_msg_debug(ic))
+				dump_probe_beacon(subtype, 0,
+				    wh->i_addr2, chan, bchan, capinfo,
+				    bintval, erp, ssid, country);
 #endif
-				ni->ni_esslen = ssid[1];
-				memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
-				memcpy(ni->ni_essid, ssid + 2, ssid[1]);
-			}
+			ni->ni_esslen = ssid[1];
+			memset(ni->ni_essid, 0, sizeof(ni->ni_essid));
+			memcpy(ni->ni_essid, ssid + 2, ssid[1]);
 		}
 		ni->ni_scangen = ic->ic_scan.nt_scangen;
 		IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
@@ -2371,7 +2366,6 @@
 			ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : "",
 			ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : ""
 		);
-		ni->ni_inact = ic->ic_inact_run;
 		ieee80211_new_state(ic, IEEE80211_S_RUN, subtype);
 		break;
 	}
@@ -2393,7 +2387,6 @@
 		IEEE80211_NODE_STAT(ni, rx_deauth);
 		switch (ic->ic_opmode) {
 		case IEEE80211_M_STA:
-			ni->ni_inact = ic->ic_inact_run;
 			ieee80211_new_state(ic, IEEE80211_S_AUTH,
 			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
 			break;
@@ -2431,7 +2424,6 @@
 		IEEE80211_NODE_STAT(ni, rx_disassoc);
 		switch (ic->ic_opmode) {
 		case IEEE80211_M_STA:
-			ni->ni_inact = ic->ic_inact_run;
 			ieee80211_new_state(ic, IEEE80211_S_ASSOC,
 			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
 			break;
@@ -2555,7 +2547,6 @@
 			IEEE80211_REASON_NOT_ASSOCED);
 		return;
 	}
-	ni->ni_inact = ic->ic_inact_run;
 
 	/* Okay, take the first queued packet and put it out... */
 	IEEE80211_NODE_SAVEQ_DEQUEUE(ni, m, qlen);

==== //depot/projects/wifi/sys/net80211/ieee80211_node.c#22 (text+ko) ====

@@ -92,6 +92,7 @@
 	ic->ic_inact_init = IEEE80211_INACT_INIT;
 	ic->ic_inact_auth = IEEE80211_INACT_AUTH;
 	ic->ic_inact_run = IEEE80211_INACT_RUN;
+	ic->ic_inact_probe = IEEE80211_INACT_PROBE;
 
 	/* XXX defer */
 	if (ic->ic_max_aid == 0)
@@ -906,7 +907,7 @@
 	ni->ni_authmode = IEEE80211_AUTH_OPEN;
 	ni->ni_txpower = ic->ic_txpowlimit;	/* max power */
 	ieee80211_crypto_resetkey(ic, &ni->ni_ucastkey, IEEE80211_KEYIX_NONE);
-	ni->ni_inact = nt->nt_inact_init;
+	ni->ni_inact = ni->ni_inact_reload = nt->nt_inact_init;
 	IEEE80211_NODE_SAVEQ_INIT(ni, "unknown");
 
 	IEEE80211_NODE_LOCK(nt);
@@ -1400,6 +1401,21 @@
 						ic->ic_set_tim(ic, ni, 0);
 				}
 			}
+			/*
+			 * Probe the station before time it out.  We
+			 * send a null data frame which may not be
+			 * universally supported by drivers (need it
+			 * for ps-poll support so it should be...).
+			 */
+			if (ni->ni_inact == ic->ic_inact_probe) {
+				IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
+				    "[%s] probe station due to inactivity\n",
+				    ether_sprintf(ni->ni_macaddr));
+				IEEE80211_NODE_UNLOCK(nt);
+				ieee80211_send_nulldata(ic, ni);
+				/* XXX stat? */
+				goto restart;
+			}
 		}
 		if (ni->ni_inact <= 0) {
 			IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
@@ -1599,6 +1615,7 @@
 	/* give driver a chance to setup state like ni_txrate */
 	if (ic->ic_newassoc)
 		ic->ic_newassoc(ic, ni, newassoc);
+	ni->ni_inact_reload = ic->ic_inact_run;
 	IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);
 	/* tell the authenticator about new station */
 	if (ic->ic_auth->ia_node_join != NULL)
@@ -1711,6 +1728,7 @@
 	 */
 	ieee80211_sta_leave(ic, ni);
 done:
+	ni->ni_inact_reload = ic->ic_inact_init;	/* just in case */
 	ieee80211_free_node(ni);
 }
 

==== //depot/projects/wifi/sys/net80211/ieee80211_node.h#15 (text+ko) ====

@@ -55,6 +55,7 @@
 #define	IEEE80211_INACT_INIT	(30/IEEE80211_INACT_WAIT)	/* initial */
 #define	IEEE80211_INACT_AUTH	(180/IEEE80211_INACT_WAIT)	/* associated but not authorized */
 #define	IEEE80211_INACT_RUN	(300/IEEE80211_INACT_WAIT)	/* authorized */
+#define	IEEE80211_INACT_PROBE	(30/IEEE80211_INACT_WAIT)	/* probe */
 #define	IEEE80211_INACT_SCAN	(300/IEEE80211_INACT_WAIT)	/* scanned */
 
 #define	IEEE80211_TRANS_WAIT 	5		/* mgt frame tx timer (secs) */
@@ -138,7 +139,8 @@
 
 	/* others */
 	int			ni_fails;	/* failure count to associate */
-	int			ni_inact;	/* inactivity mark count */
+	short			ni_inact;	/* inactivity mark count */
+	short			ni_inact_reload;/* inactivity reload value */
 	int			ni_txrate;	/* index to ni_rates[] */
 	struct	ifqueue		ni_savedq;	/* ps-poll queue */
 	struct ieee80211_nodestats ni_stats;	/* per-node statistics */

==== //depot/projects/wifi/sys/net80211/ieee80211_output.c#18 (text+ko) ====

@@ -554,19 +554,6 @@
 		ni->ni_txseqs[0]++;
 	}
 
-	if (eh.ether_type != htons(ETHERTYPE_PAE)) {
-		/*
-		 * Reset the inactivity timer only for non-PAE traffic
-		 * to avoid a problem where the station leaves w/o
-		 * notice while we're requesting Identity.  In this
-		 * situation the 802.1x state machine will continue
-		 * to retransmit the requests because it assumes the
-		 * station will be timed out for inactivity, but our
-		 * retransmits will reset the inactivity timer.
-		 */ 
-		ni->ni_inact = ic->ic_inact_run;
-	}
-
 	IEEE80211_NODE_STAT(ni, tx_data);
 	IEEE80211_NODE_STAT_ADD(ni, tx_bytes, datalen);
 

==== //depot/projects/wifi/sys/net80211/ieee80211_var.h#14 (text+ko) ====

@@ -148,6 +148,7 @@
 	int			ic_inact_init;	/* initial setting */
 	int			ic_inact_auth;	/* auth but not assoc setting */
 	int			ic_inact_run;	/* authorized setting */
+	int			ic_inact_probe;	/* inactive probe time */
 
 	/*
 	 * WME/WMM state.


More information about the p4-projects mailing list