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