From owner-p4-projects@FreeBSD.ORG Mon Feb 11 04:50:26 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 1019516A41A; Mon, 11 Feb 2008 04:50:26 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C98E516A418 for ; Mon, 11 Feb 2008 04:50:25 +0000 (UTC) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id B3A4513C447 for ; Mon, 11 Feb 2008 04:50:25 +0000 (UTC) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m1B4oPo7038092 for ; Mon, 11 Feb 2008 04:50:25 GMT (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m1B4oP5K038089 for perforce@freebsd.org; Mon, 11 Feb 2008 04:50:25 GMT (envelope-from sam@freebsd.org) Date: Mon, 11 Feb 2008 04:50:25 GMT Message-Id: <200802110450.m1B4oP5K038089@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Cc: Subject: PERFORCE change 135194 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 11 Feb 2008 04:50:26 -0000 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]);