Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 Feb 2008 04:50:25 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 135194 for review
Message-ID:  <200802110450.m1B4oP5K038089@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=135194

Change 135194 by sam@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]);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200802110450.m1B4oP5K038089>