PERFORCE change 135194 for review
Sam Leffler
sam at FreeBSD.org
Sun Feb 10 20:50:26 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=135194
Change 135194 by sam at sam_ebb on 2008/02/11 04:49:54
o hookup station inactivity timeout to ht support; the new
ieee80211_ht_node_age routine handles HT-related work
o move station resource aging work to an ic_node_age method that
drivers can override (default method ages power save and wds q's
and calls ieee80211_ht_node_age for HT nodes)
o add drain mechanism for forcibly reclaiming resources held at
the net80211 layer: ieee80211_drain can be called to do this
and per-station work is done with ic_node_drain method that
drivers can hook
o add some comments
Affected files ...
.. //depot/projects/vap/sys/net80211/ieee80211_ht.c#14 edit
.. //depot/projects/vap/sys/net80211/ieee80211_ht.h#10 edit
.. //depot/projects/vap/sys/net80211/ieee80211_node.c#27 edit
.. //depot/projects/vap/sys/net80211/ieee80211_var.h#28 edit
Differences ...
==== //depot/projects/vap/sys/net80211/ieee80211_ht.c#14 (text+ko) ====
@@ -87,9 +87,9 @@
int ieee80211_ampdu_age = -1; /* threshold for ampdu reorder q (ms) */
#endif
int ieee80211_recv_bar_ena = 1;
-int ieee80211_addba_timeout = -1;
-int ieee80211_addba_backoff = -1;
-int ieee80211_addba_maxtries = 3;
+int ieee80211_addba_timeout = -1; /* timeout waiting for ADDBA response */
+int ieee80211_addba_backoff = -1; /* backoff after max ADDBA requests */
+int ieee80211_addba_maxtries = 3; /* max ADDBA requests before backoff */
/*
* Setup HT parameters that depends on the clock frequency.
@@ -813,6 +813,45 @@
IEEE80211_NODE_AMPDU);
}
+/*
+ * Age out HT resources for a station.
+ */
+void
+ieee80211_ht_node_age(struct ieee80211_node *ni)
+{
+#ifdef IEEE80211_AMPDU_AGE
+ struct ieee80211vap *vap = ni->ni_vap;
+ uint8_t tid;
+#endif
+
+ KASSERT(ni->ni_flags & IEEE80211_NODE_HT, ("not an HT sta"));
+
+#ifdef IEEE80211_AMPDU_AGE
+ for (tid = 0; tid < WME_NUM_TID; tid++) {
+ struct ieee80211_rx_ampdu *rap;
+
+ rap = &ni->ni_rx_ampdu[tid];
+ if ((rap->rxa_flags & IEEE80211_AGGR_XCHGPEND) == 0)
+ continue;
+ if (rap->rxa_qframes == 0)
+ continue;
+ /*
+ * Check for frames sitting too long in the reorder queue.
+ * See above for more details on what's happening here.
+ */
+ /* XXX honor batimeout? */
+ if (ticks - rap->rxa_age > ieee80211_ampdu_age) {
+ /*
+ * Too long since we received the first
+ * frame; flush the reorder buffer.
+ */
+ vap->iv_stats.is_ampdu_rx_age += rap->rxa_qframes;
+ ampdu_rx_flush(ni, rap);
+ }
+ }
+#endif /* IEEE80211_AMPDU_AGE */
+}
+
static struct ieee80211_channel *
findhtchan(struct ieee80211com *ic, struct ieee80211_channel *c, int htflags)
{
==== //depot/projects/vap/sys/net80211/ieee80211_ht.h#10 (text+ko) ====
@@ -162,6 +162,7 @@
void ieee80211_recv_bar(struct ieee80211_node *, struct mbuf *);
void ieee80211_ht_node_init(struct ieee80211_node *, const uint8_t *);
void ieee80211_ht_node_cleanup(struct ieee80211_node *);
+void ieee80211_ht_node_age(struct ieee80211_node *);
struct ieee80211_channel *ieee80211_ht_adjust_channel(struct ieee80211com *,
struct ieee80211_channel *, int);
==== //depot/projects/vap/sys/net80211/ieee80211_node.c#27 (text+ko) ====
@@ -70,6 +70,7 @@
static struct ieee80211_node *node_alloc(struct ieee80211_node_table *);
static void node_cleanup(struct ieee80211_node *);
static void node_free(struct ieee80211_node *);
+static void node_age(struct ieee80211_node *);
static int8_t node_getrssi(const struct ieee80211_node *);
static void node_getsignal(const struct ieee80211_node *, int8_t *, int8_t *);
static void node_getmimoinfo(const struct ieee80211_node *,
@@ -101,6 +102,8 @@
ic->ic_node_alloc = node_alloc;
ic->ic_node_free = node_free;
ic->ic_node_cleanup = node_cleanup;
+ ic->ic_node_age = node_age;
+ ic->ic_node_drain = node_age; /* NB: same as age */
ic->ic_node_getrssi = node_getrssi;
ic->ic_node_getsignal = node_getsignal;
ic->ic_node_getmimoinfo = node_getmimoinfo;
@@ -884,6 +887,33 @@
FREE(ni, M_80211_NODE);
}
+static void
+node_age(struct ieee80211_node *ni)
+{
+ struct ieee80211vap *vap = ni->ni_vap;
+#if 0
+ IEEE80211_NODE_LOCK_ASSERT(&ic->ic_sta);
+#endif
+ /*
+ * Age frames on the power save queue.
+ */
+ if (ieee80211_node_saveq_age(ni) != 0 &&
+ IEEE80211_NODE_SAVEQ_QLEN(ni) == 0 &&
+ vap->iv_set_tim != NULL)
+ vap->iv_set_tim(ni, 0);
+ /*
+ * Age frames on the wds pending queue.
+ */
+ if (IEEE80211_NODE_WDSQ_QLEN(ni) != 0)
+ ieee80211_node_wdsq_age(ni);
+ /*
+ * Age out HT resources (e.g. frames on the
+ * A-MPDU reorder queues).
+ */
+ if (ni->ni_associd != 0 && (ni->ni_flags & IEEE80211_NODE_HT))
+ ieee80211_ht_node_age(ni);
+}
+
static int8_t
node_getrssi(const struct ieee80211_node *ni)
{
@@ -1757,8 +1787,9 @@
* process each node only once.
*/
static void
-ieee80211_timeout_stations(struct ieee80211_node_table *nt)
+ieee80211_timeout_stations(struct ieee80211com *ic)
{
+ struct ieee80211_node_table *nt = &ic->ic_sta;
struct ieee80211vap *vap;
struct ieee80211_node *ni;
u_int gen;
@@ -1795,7 +1826,7 @@
/*
* Free fragment if not needed anymore
* (last fragment older than 1s).
- * XXX doesn't belong here
+ * XXX doesn't belong here, move to node_age
*/
if (ni->ni_rxfrag[0] != NULL &&
ticks > ni->ni_rxfragstamp + hz) {
@@ -1807,6 +1838,7 @@
/*
* Special case ourself; we may be idle for extended periods
* of time and regardless reclaiming our state is wrong.
+ * XXX run ic_node_age
*/
if (ni == vap->iv_bss)
continue;
@@ -1814,17 +1846,9 @@
(vap->iv_opmode == IEEE80211_M_IBSS ||
vap->iv_opmode == IEEE80211_M_AHDEMO)) {
/*
- * Age frames on the power save queue.
+ * Age/drain resources held by the station.
*/
- if (ieee80211_node_saveq_age(ni) != 0 &&
- IEEE80211_NODE_SAVEQ_QLEN(ni) == 0 &&
- vap->iv_set_tim != NULL)
- vap->iv_set_tim(ni, 0);
- /*
- * Age frames on the wds pending queue.
- */
- if (IEEE80211_NODE_WDSQ_QLEN(ni) != 0)
- ieee80211_node_wdsq_age(ni);
+ ic->ic_node_age(ni);
/*
* Probe the station before time it out. We
* send a null data frame which may not be
@@ -1899,6 +1923,56 @@
}
/*
+ * Aggressively reclaim resources. This should be used
+ * only in a critical situation to reclaim mbuf resources.
+ */
+void
+ieee80211_drain(struct ieee80211com *ic)
+{
+ struct ieee80211_node_table *nt = &ic->ic_sta;
+ struct ieee80211vap *vap;
+ struct ieee80211_node *ni;
+
+ IEEE80211_NODE_LOCK(nt);
+ TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
+ /*
+ * Ignore entries for which have yet to receive an
+ * authentication frame. These are transient and
+ * will be reclaimed when the last reference to them
+ * goes away (when frame xmits complete).
+ */
+ vap = ni->ni_vap;
+ /*
+ * Only process stations when in RUN state. This
+ * insures, for example, that we don't timeout an
+ * inactive station during CAC. Note that CSA state
+ * is actually handled in ieee80211_node_timeout as
+ * it applies to more than timeout processing.
+ */
+ if (vap->iv_state != IEEE80211_S_RUN)
+ continue;
+ /* XXX can vap be NULL? */
+ if ((vap->iv_opmode == IEEE80211_M_HOSTAP ||
+ vap->iv_opmode == IEEE80211_M_STA) &&
+ (ni->ni_flags & IEEE80211_NODE_AREF) == 0)
+ continue;
+ /*
+ * Free fragments.
+ * XXX doesn't belong here, move to node_drain
+ */
+ if (ni->ni_rxfrag[0] != NULL) {
+ m_freem(ni->ni_rxfrag[0]);
+ ni->ni_rxfrag[0] = NULL;
+ }
+ /*
+ * Drain resources held by the station.
+ */
+ ic->ic_node_drain(ni);
+ }
+ IEEE80211_NODE_UNLOCK(nt);
+}
+
+/*
* Per-ieee80211com inactivity timer callback.
*/
void
@@ -1917,7 +1991,7 @@
*/
if ((ic->ic_flags & IEEE80211_F_CSAPENDING) == 0) {
ieee80211_scan_timeout(ic);
- ieee80211_timeout_stations(&ic->ic_sta);
+ ieee80211_timeout_stations(ic);
IEEE80211_LOCK(ic);
ieee80211_erp_timeout(ic);
==== //depot/projects/vap/sys/net80211/ieee80211_var.h#28 (text+ko) ====
@@ -222,6 +222,8 @@
struct ieee80211_node* (*ic_node_alloc)(struct ieee80211_node_table *);
void (*ic_node_free)(struct ieee80211_node *);
void (*ic_node_cleanup)(struct ieee80211_node *);
+ void (*ic_node_age)(struct ieee80211_node *);
+ void (*ic_node_drain)(struct ieee80211_node *);
int8_t (*ic_node_getrssi)(const struct ieee80211_node*);
void (*ic_node_getsignal)(const struct ieee80211_node*,
int8_t *, int8_t *);
@@ -536,6 +538,7 @@
const struct ieee80211_channel *);
void ieee80211_announce(struct ieee80211com *);
void ieee80211_announce_channels(struct ieee80211com *);
+void ieee80211_drain(struct ieee80211com *);
void ieee80211_media_init(struct ieee80211com *,
ifm_change_cb_t, ifm_stat_cb_t);
struct ieee80211com *ieee80211_find_vap(const uint8_t mac[IEEE80211_ADDR_LEN]);
More information about the p4-projects
mailing list