PERFORCE change 87230 for review

Sam Leffler sam at FreeBSD.org
Sat Nov 26 00:54:22 GMT 2005


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

Change 87230 by sam at sam_ebb on 2005/11/26 00:53:34

	Handle mgt frame tx timeouts using a callback: driver
	must respond when frame has been sent and indicate
	whether an ack was received; 802.11 layer then processes
	failure directly or starts a timer waiting for the response.
	Reduces auth+assoc failures from 5 secs to ms which makes
	ap switches (e.g. when roaming) much faster.

Affected files ...

.. //depot/projects/wifi/sys/net80211/ieee80211_freebsd.c#19 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_freebsd.h#19 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_node.c#68 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_node.h#35 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_output.c#58 edit

Differences ...

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

@@ -188,6 +188,39 @@
 	return m;
 }
 
+int
+ieee80211_add_callback(struct mbuf *m,
+	void (*func)(struct ieee80211_node *, void *, int), void *arg)
+{
+	struct m_tag *mtag;
+	struct ieee80211_cb *cb;
+
+	mtag = m_tag_alloc(MTAG_ABI_NET80211, NET80211_TAG_CALLBACK,
+			sizeof(struct ieee80211_cb), M_NOWAIT);
+	if (mtag == NULL)
+		return 0;
+
+	cb = (struct ieee80211_cb *)(mtag+1);
+	cb->func = func;
+	cb->arg = arg;
+	m_tag_prepend(m, mtag);
+	m->m_flags |= M_TXCB;
+	return 1;
+}
+
+void
+ieee80211_process_callback(struct ieee80211_node *ni,
+	struct mbuf *m, int status)
+{
+	struct m_tag *mtag;
+
+	mtag = m_tag_locate(m, MTAG_ABI_NET80211, NET80211_TAG_CALLBACK, NULL);
+	if (mtag != NULL) {
+		struct ieee80211_cb *cb = (struct ieee80211_cb *)(mtag+1);
+		cb->func(ni, cb->arg, status);
+	}
+}
+
 #include <sys/libkern.h>
 
 void

==== //depot/projects/wifi/sys/net80211/ieee80211_freebsd.h#19 (text+ko) ====

@@ -171,6 +171,7 @@
 #define	M_PWR_SAV	M_PROTO4		/* bypass PS handling */
 #define	M_MORE_DATA	M_PROTO5		/* more data frames to follow */
 #define	M_FF		0x20000			/* fast frame */
+#define	M_TXCB		0x40000			/* do tx complete callback */
 /*
  * Encode WME access control bits in the PROTO flags.
  * This is safe since it's passed directly in to the
@@ -195,6 +196,17 @@
 #define	M_AGE_GET(m)		(m->m_pkthdr.csum_data)
 #define	M_AGE_SUB(m,adj)	(m->m_pkthdr.csum_data -= adj)
 
+#define	MTAG_ABI_NET80211	1132948340	/* net80211 ABI */
+
+struct ieee80211_cb {
+	void	(*func)(struct ieee80211_node *, void *, int status);
+	void	*arg;
+};
+#define	NET80211_TAG_CALLBACK	0	/* xmit complete callback */
+int	ieee80211_add_callback(struct mbuf *m,
+		void (*func)(struct ieee80211_node *, void *, int), void *arg);
+void	ieee80211_process_callback(struct ieee80211_node *, struct mbuf *, int);
+
 void	get_random_bytes(void *, size_t);
 
 struct ieee80211com;

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

@@ -926,6 +926,7 @@
 	/* NB: must be after ni_chan is setup */
 	ieee80211_setup_rates(ni, sp->rates, sp->xrates, IEEE80211_F_DOSORT);
 }
+
 /*
  * Do node discovery in adhoc mode on receipt of a beacon
  * or probe response frame.  Note that for the driver's

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

@@ -58,7 +58,7 @@
 #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) */
+#define	IEEE80211_TRANS_WAIT 	2		/* mgt frame tx timer (secs) */
 
 #define	IEEE80211_NODE_HASHSIZE	32
 /* simple hash is enough for variation of macaddr */

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

@@ -64,7 +64,7 @@
 	struct mbuf *m2, const struct ether_header *eh2);
 static int ieee80211_fragment(struct ieee80211com *, struct mbuf *,
 	u_int hdrsize, u_int ciphdrsize, u_int mtu);
-static	void ieee80211_tx_timeout(void *);
+static	void ieee80211_tx_mgt_cb(struct ieee80211_node *, void *, int);
 
 #ifdef IEEE80211_DEBUG
 /*
@@ -207,7 +207,6 @@
 #endif
 	IEEE80211_NODE_STAT(ni, tx_mgmt);
 	IF_ENQUEUE(&ic->ic_mgtq, m);
-	ifp->if_timer = 1;
 	if_start(ifp);
 	return 0;
 }
@@ -1376,7 +1375,7 @@
 	struct mbuf *m;
 	u_int8_t *frm;
 	u_int16_t capinfo;
-	int has_challenge, is_shared_key, ret, timer, status;
+	int has_challenge, is_shared_key, ret, status;
 
 	KASSERT(ni != NULL, ("null node"));
 
@@ -1392,7 +1391,6 @@
 		ieee80211_node_refcnt(ni)+1);
 	ieee80211_ref_node(ni);
 
-	timer = 0;
 	switch (type) {
 	case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
 		/*
@@ -1542,7 +1540,8 @@
 			IEEE80211_NODE_STAT(ni, tx_auth_fail);
 
 		if (ic->ic_opmode == IEEE80211_M_STA)
-			timer = IEEE80211_TRANS_WAIT;
+			ieee80211_add_callback(m, ieee80211_tx_mgt_cb,
+				(void *) ic->ic_state);
 		break;
 
 	case IEEE80211_FC0_SUBTYPE_DEAUTH:
@@ -1635,7 +1634,8 @@
 		}
 		m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
 
-		timer = IEEE80211_TRANS_WAIT;
+		ieee80211_add_callback(m, ieee80211_tx_mgt_cb,
+			(void *) ic->ic_state);
 		break;
 
 	case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
@@ -1719,9 +1719,6 @@
 	ret = ieee80211_mgmt_output(ic, ni, m, type);
 	if (ret != 0)
 		goto bad;
-	if (timer)
-		callout_reset(&ic->ic_mgtsend, timer*hz,
-			ieee80211_tx_timeout, ic);
 	return 0;
 bad:
 	ieee80211_free_node(ni);
@@ -1730,9 +1727,10 @@
 }
 
 static void
-ieee80211_tx_timeout(void *arg)
+ieee80211_tx_mgt_timeout(void *arg)
 {
-	struct ieee80211com *ic	= arg;
+	struct ieee80211_node *ni = arg;
+	struct ieee80211com *ic	= ni->ni_ic;
 
 	if (ic->ic_state != IEEE80211_S_INIT &&
 	    (ic->ic_flags & IEEE80211_F_SCAN) == 0) {
@@ -1745,6 +1743,29 @@
 	}
 }
 
+static void
+ieee80211_tx_mgt_cb(struct ieee80211_node *ni, void *arg, int status)
+{
+	struct ieee80211com *ic = ni->ni_ic;
+	enum ieee80211_state ostate = (enum ieee80211_state) arg;
+
+	/*
+	 * Frame transmit completed; arrange timer callback.  If
+	 * transmit was successfuly we wait for response.  Otherwise
+	 * we arrange an immediate callback instead of doing the
+	 * callback directly since we don't know what state the driver
+	 * is in (e.g. what locks it is holding).  This work should
+	 * not be too time-critical and not happen too often so the
+	 * added overhead is acceptable.
+	 *
+	 * XXX what happens if !acked but response shows up before callback?
+	 */
+	if (ic->ic_state == ostate)
+		callout_reset(&ic->ic_mgtsend,
+			status == 0 ? IEEE80211_TRANS_WAIT*hz : 0,
+			ieee80211_tx_mgt_timeout, ni);
+}
+
 /*
  * Allocate a beacon frame and fillin the appropriate bits.
  */


More information about the p4-projects mailing list