ieee80211_ht.c revision 219456
1/*-
2 * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include <sys/cdefs.h>
27#ifdef __FreeBSD__
28__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_ht.c 219456 2011-03-10 18:17:24Z bschmidt $");
29#endif
30
31/*
32 * IEEE 802.11n protocol support.
33 */
34
35#include "opt_inet.h"
36#include "opt_wlan.h"
37
38#include <sys/param.h>
39#include <sys/kernel.h>
40#include <sys/systm.h>
41#include <sys/endian.h>
42
43#include <sys/socket.h>
44
45#include <net/if.h>
46#include <net/if_media.h>
47#include <net/ethernet.h>
48
49#include <net80211/ieee80211_var.h>
50#include <net80211/ieee80211_action.h>
51#include <net80211/ieee80211_input.h>
52
53/* define here, used throughout file */
54#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
55#define	SM(_v, _f)	(((_v) << _f##_S) & _f)
56
57const struct ieee80211_mcs_rates ieee80211_htrates[IEEE80211_HTRATE_MAXSIZE] = {
58	{  13,  14,   27,   30 },	/* MCS 0 */
59	{  26,  29,   54,   60 },	/* MCS 1 */
60	{  39,  43,   81,   90 },	/* MCS 2 */
61	{  52,  58,  108,  120 },	/* MCS 3 */
62	{  78,  87,  162,  180 },	/* MCS 4 */
63	{ 104, 116,  216,  240 },	/* MCS 5 */
64	{ 117, 130,  243,  270 },	/* MCS 6 */
65	{ 130, 144,  270,  300 },	/* MCS 7 */
66	{  26,  29,   54,   60 },	/* MCS 8 */
67	{  52,  58,  108,  120 },	/* MCS 9 */
68	{  78,  87,  162,  180 },	/* MCS 10 */
69	{ 104, 116,  216,  240 },	/* MCS 11 */
70	{ 156, 173,  324,  360 },	/* MCS 12 */
71	{ 208, 231,  432,  480 },	/* MCS 13 */
72	{ 234, 260,  486,  540 },	/* MCS 14 */
73	{ 260, 289,  540,  600 },	/* MCS 15 */
74	{  39,  43,   81,   90 },	/* MCS 16 */
75	{  78,  87,  162,  180 },	/* MCS 17 */
76	{ 117, 130,  243,  270 },	/* MCS 18 */
77	{ 156, 173,  324,  360 },	/* MCS 19 */
78	{ 234, 260,  486,  540 },	/* MCS 20 */
79	{ 312, 347,  648,  720 },	/* MCS 21 */
80	{ 351, 390,  729,  810 },	/* MCS 22 */
81	{ 390, 433,  810,  900 },	/* MCS 23 */
82	{  52,  58,  108,  120 },	/* MCS 24 */
83	{ 104, 116,  216,  240 },	/* MCS 25 */
84	{ 156, 173,  324,  360 },	/* MCS 26 */
85	{ 208, 231,  432,  480 },	/* MCS 27 */
86	{ 312, 347,  648,  720 },	/* MCS 28 */
87	{ 416, 462,  864,  960 },	/* MCS 29 */
88	{ 468, 520,  972, 1080 },	/* MCS 30 */
89	{ 520, 578, 1080, 1200 },	/* MCS 31 */
90	{   0,   0,   12,   13 },	/* MCS 32 */
91	{  78,  87,  162,  180 },	/* MCS 33 */
92	{ 104, 116,  216,  240 },	/* MCS 34 */
93	{ 130, 144,  270,  300 },	/* MCS 35 */
94	{ 117, 130,  243,  270 },	/* MCS 36 */
95	{ 156, 173,  324,  360 },	/* MCS 37 */
96	{ 195, 217,  405,  450 },	/* MCS 38 */
97	{ 104, 116,  216,  240 },	/* MCS 39 */
98	{ 130, 144,  270,  300 },	/* MCS 40 */
99	{ 130, 144,  270,  300 },	/* MCS 41 */
100	{ 156, 173,  324,  360 },	/* MCS 42 */
101	{ 182, 202,  378,  420 },	/* MCS 43 */
102	{ 182, 202,  378,  420 },	/* MCS 44 */
103	{ 208, 231,  432,  480 },	/* MCS 45 */
104	{ 156, 173,  324,  360 },	/* MCS 46 */
105	{ 195, 217,  405,  450 },	/* MCS 47 */
106	{ 195, 217,  405,  450 },	/* MCS 48 */
107	{ 234, 260,  486,  540 },	/* MCS 49 */
108	{ 273, 303,  567,  630 },	/* MCS 50 */
109	{ 273, 303,  567,  630 },	/* MCS 51 */
110	{ 312, 347,  648,  720 },	/* MCS 52 */
111	{ 130, 144,  270,  300 },	/* MCS 53 */
112	{ 156, 173,  324,  360 },	/* MCS 54 */
113	{ 182, 202,  378,  420 },	/* MCS 55 */
114	{ 156, 173,  324,  360 },	/* MCS 56 */
115	{ 182, 202,  378,  420 },	/* MCS 57 */
116	{ 208, 231,  432,  480 },	/* MCS 58 */
117	{ 234, 260,  486,  540 },	/* MCS 59 */
118	{ 208, 231,  432,  480 },	/* MCS 60 */
119	{ 234, 260,  486,  540 },	/* MCS 61 */
120	{ 260, 289,  540,  600 },	/* MCS 62 */
121	{ 260, 289,  540,  600 },	/* MCS 63 */
122	{ 286, 318,  594,  660 },	/* MCS 64 */
123	{ 195, 217,  405,  450 },	/* MCS 65 */
124	{ 234, 260,  486,  540 },	/* MCS 66 */
125	{ 273, 303,  567,  630 },	/* MCS 67 */
126	{ 234, 260,  486,  540 },	/* MCS 68 */
127	{ 273, 303,  567,  630 },	/* MCS 69 */
128	{ 312, 347,  648,  720 },	/* MCS 70 */
129	{ 351, 390,  729,  810 },	/* MCS 71 */
130	{ 312, 347,  648,  720 },	/* MCS 72 */
131	{ 351, 390,  729,  810 },	/* MCS 73 */
132	{ 390, 433,  810,  900 },	/* MCS 74 */
133	{ 390, 433,  810,  900 },	/* MCS 75 */
134	{ 429, 477,  891,  990 },	/* MCS 76 */
135};
136
137static const struct ieee80211_htrateset ieee80211_rateset_11n =
138	{ 16, {
139	          0,   1,   2,   3,   4,  5,   6,  7,  8,  9,
140		 10,  11,  12,  13,  14,  15 }
141	};
142
143#ifdef IEEE80211_AMPDU_AGE
144static	int ieee80211_ampdu_age = -1;	/* threshold for ampdu reorder q (ms) */
145SYSCTL_PROC(_net_wlan, OID_AUTO, ampdu_age, CTLTYPE_INT | CTLFLAG_RW,
146	&ieee80211_ampdu_age, 0, ieee80211_sysctl_msecs_ticks, "I",
147	"AMPDU max reorder age (ms)");
148#endif
149
150static	int ieee80211_recv_bar_ena = 1;
151SYSCTL_INT(_net_wlan, OID_AUTO, recv_bar, CTLFLAG_RW, &ieee80211_recv_bar_ena,
152	    0, "BAR frame processing (ena/dis)");
153
154static	int ieee80211_addba_timeout = -1;/* timeout for ADDBA response */
155SYSCTL_PROC(_net_wlan, OID_AUTO, addba_timeout, CTLTYPE_INT | CTLFLAG_RW,
156	&ieee80211_addba_timeout, 0, ieee80211_sysctl_msecs_ticks, "I",
157	"ADDBA request timeout (ms)");
158static	int ieee80211_addba_backoff = -1;/* backoff after max ADDBA requests */
159SYSCTL_PROC(_net_wlan, OID_AUTO, addba_backoff, CTLTYPE_INT | CTLFLAG_RW,
160	&ieee80211_addba_backoff, 0, ieee80211_sysctl_msecs_ticks, "I",
161	"ADDBA request backoff (ms)");
162static	int ieee80211_addba_maxtries = 3;/* max ADDBA requests before backoff */
163SYSCTL_INT(_net_wlan, OID_AUTO, addba_maxtries, CTLTYPE_INT | CTLFLAG_RW,
164	&ieee80211_addba_maxtries, 0, "max ADDBA requests sent before backoff");
165
166static	int ieee80211_bar_timeout = -1;	/* timeout waiting for BAR response */
167static	int ieee80211_bar_maxtries = 50;/* max BAR requests before DELBA */
168
169static	ieee80211_recv_action_func ht_recv_action_ba_addba_request;
170static	ieee80211_recv_action_func ht_recv_action_ba_addba_response;
171static	ieee80211_recv_action_func ht_recv_action_ba_delba;
172static	ieee80211_recv_action_func ht_recv_action_ht_mimopwrsave;
173static	ieee80211_recv_action_func ht_recv_action_ht_txchwidth;
174
175static	ieee80211_send_action_func ht_send_action_ba_addba;
176static	ieee80211_send_action_func ht_send_action_ba_delba;
177static	ieee80211_send_action_func ht_send_action_ht_txchwidth;
178
179static void
180ieee80211_ht_init(void)
181{
182	/*
183	 * Setup HT parameters that depends on the clock frequency.
184	 */
185#ifdef IEEE80211_AMPDU_AGE
186	ieee80211_ampdu_age = msecs_to_ticks(500);
187#endif
188	ieee80211_addba_timeout = msecs_to_ticks(250);
189	ieee80211_addba_backoff = msecs_to_ticks(10*1000);
190	ieee80211_bar_timeout = msecs_to_ticks(250);
191	/*
192	 * Register action frame handlers.
193	 */
194	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_BA,
195	    IEEE80211_ACTION_BA_ADDBA_REQUEST, ht_recv_action_ba_addba_request);
196	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_BA,
197	    IEEE80211_ACTION_BA_ADDBA_RESPONSE, ht_recv_action_ba_addba_response);
198	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_BA,
199	    IEEE80211_ACTION_BA_DELBA, ht_recv_action_ba_delba);
200	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_HT,
201	    IEEE80211_ACTION_HT_MIMOPWRSAVE, ht_recv_action_ht_mimopwrsave);
202	ieee80211_recv_action_register(IEEE80211_ACTION_CAT_HT,
203	    IEEE80211_ACTION_HT_TXCHWIDTH, ht_recv_action_ht_txchwidth);
204
205	ieee80211_send_action_register(IEEE80211_ACTION_CAT_BA,
206	    IEEE80211_ACTION_BA_ADDBA_REQUEST, ht_send_action_ba_addba);
207	ieee80211_send_action_register(IEEE80211_ACTION_CAT_BA,
208	    IEEE80211_ACTION_BA_ADDBA_RESPONSE, ht_send_action_ba_addba);
209	ieee80211_send_action_register(IEEE80211_ACTION_CAT_BA,
210	    IEEE80211_ACTION_BA_DELBA, ht_send_action_ba_delba);
211	ieee80211_send_action_register(IEEE80211_ACTION_CAT_HT,
212	    IEEE80211_ACTION_HT_TXCHWIDTH, ht_send_action_ht_txchwidth);
213}
214SYSINIT(wlan_ht, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_ht_init, NULL);
215
216static int ieee80211_ampdu_enable(struct ieee80211_node *ni,
217	struct ieee80211_tx_ampdu *tap);
218static int ieee80211_addba_request(struct ieee80211_node *ni,
219	struct ieee80211_tx_ampdu *tap,
220	int dialogtoken, int baparamset, int batimeout);
221static int ieee80211_addba_response(struct ieee80211_node *ni,
222	struct ieee80211_tx_ampdu *tap,
223	int code, int baparamset, int batimeout);
224static void ieee80211_addba_stop(struct ieee80211_node *ni,
225	struct ieee80211_tx_ampdu *tap);
226static void ieee80211_bar_response(struct ieee80211_node *ni,
227	struct ieee80211_tx_ampdu *tap, int status);
228static void ampdu_tx_stop(struct ieee80211_tx_ampdu *tap);
229static void bar_stop_timer(struct ieee80211_tx_ampdu *tap);
230static int ampdu_rx_start(struct ieee80211_node *, struct ieee80211_rx_ampdu *,
231	int baparamset, int batimeout, int baseqctl);
232static void ampdu_rx_stop(struct ieee80211_node *, struct ieee80211_rx_ampdu *);
233
234void
235ieee80211_ht_attach(struct ieee80211com *ic)
236{
237	/* setup default aggregation policy */
238	ic->ic_recv_action = ieee80211_recv_action;
239	ic->ic_send_action = ieee80211_send_action;
240	ic->ic_ampdu_enable = ieee80211_ampdu_enable;
241	ic->ic_addba_request = ieee80211_addba_request;
242	ic->ic_addba_response = ieee80211_addba_response;
243	ic->ic_addba_stop = ieee80211_addba_stop;
244	ic->ic_bar_response = ieee80211_bar_response;
245	ic->ic_ampdu_rx_start = ampdu_rx_start;
246	ic->ic_ampdu_rx_stop = ampdu_rx_stop;
247
248	ic->ic_htprotmode = IEEE80211_PROT_RTSCTS;
249	ic->ic_curhtprotmode = IEEE80211_HTINFO_OPMODE_PURE;
250}
251
252void
253ieee80211_ht_detach(struct ieee80211com *ic)
254{
255}
256
257void
258ieee80211_ht_vattach(struct ieee80211vap *vap)
259{
260
261	/* driver can override defaults */
262	vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_8K;
263	vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_NA;
264	vap->iv_ampdu_limit = vap->iv_ampdu_rxmax;
265	vap->iv_amsdu_limit = vap->iv_htcaps & IEEE80211_HTCAP_MAXAMSDU;
266	/* tx aggregation traffic thresholds */
267	vap->iv_ampdu_mintraffic[WME_AC_BK] = 128;
268	vap->iv_ampdu_mintraffic[WME_AC_BE] = 64;
269	vap->iv_ampdu_mintraffic[WME_AC_VO] = 32;
270	vap->iv_ampdu_mintraffic[WME_AC_VI] = 32;
271
272	if (vap->iv_htcaps & IEEE80211_HTC_HT) {
273		/*
274		 * Device is HT capable; enable all HT-related
275		 * facilities by default.
276		 * XXX these choices may be too aggressive.
277		 */
278		vap->iv_flags_ht |= IEEE80211_FHT_HT
279				 |  IEEE80211_FHT_HTCOMPAT
280				 ;
281		if (vap->iv_htcaps & IEEE80211_HTCAP_SHORTGI20)
282			vap->iv_flags_ht |= IEEE80211_FHT_SHORTGI20;
283		/* XXX infer from channel list? */
284		if (vap->iv_htcaps & IEEE80211_HTCAP_CHWIDTH40) {
285			vap->iv_flags_ht |= IEEE80211_FHT_USEHT40;
286			if (vap->iv_htcaps & IEEE80211_HTCAP_SHORTGI40)
287				vap->iv_flags_ht |= IEEE80211_FHT_SHORTGI40;
288		}
289		/* enable RIFS if capable */
290		if (vap->iv_htcaps & IEEE80211_HTC_RIFS)
291			vap->iv_flags_ht |= IEEE80211_FHT_RIFS;
292
293		/* NB: A-MPDU and A-MSDU rx are mandated, these are tx only */
294		vap->iv_flags_ht |= IEEE80211_FHT_AMPDU_RX;
295		if (vap->iv_htcaps & IEEE80211_HTC_AMPDU)
296			vap->iv_flags_ht |= IEEE80211_FHT_AMPDU_TX;
297		vap->iv_flags_ht |= IEEE80211_FHT_AMSDU_RX;
298		if (vap->iv_htcaps & IEEE80211_HTC_AMSDU)
299			vap->iv_flags_ht |= IEEE80211_FHT_AMSDU_TX;
300	}
301	/* NB: disable default legacy WDS, too many issues right now */
302	if (vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY)
303		vap->iv_flags_ht &= ~IEEE80211_FHT_HT;
304}
305
306void
307ieee80211_ht_vdetach(struct ieee80211vap *vap)
308{
309}
310
311static void
312ht_rateprint(struct ieee80211com *ic, int mode,
313	const struct ieee80211_htrateset *rs, int maxmcs, int ratetype)
314{
315	int i, rate, mword;
316
317	for (i = 0; i < rs->rs_nrates && i < maxmcs; i++) {
318		mword = ieee80211_rate2media(ic,
319		    rs->rs_rates[i] | IEEE80211_RATE_MCS, mode);
320		if (IFM_SUBTYPE(mword) != IFM_IEEE80211_MCS)
321			continue;
322		switch (ratetype) {
323		case 0:
324			rate = ieee80211_htrates[
325			    rs->rs_rates[i]].ht20_rate_800ns;
326			break;
327		case 1:
328			rate = ieee80211_htrates[
329			    rs->rs_rates[i]].ht20_rate_400ns;
330			break;
331		case 2:
332			rate = ieee80211_htrates[
333			    rs->rs_rates[i]].ht40_rate_800ns;
334			break;
335		default:
336			rate = ieee80211_htrates[
337			    rs->rs_rates[i]].ht40_rate_400ns;
338			break;
339		}
340		printf("%s%d%sMbps", (i != 0 ? " " : ""),
341		    rate / 2, ((rate & 0x1) != 0 ? ".5" : ""));
342	}
343	printf("\n");
344}
345
346static void
347ht_announce(struct ieee80211com *ic, int mode,
348	const struct ieee80211_htrateset *rs)
349{
350	struct ifnet *ifp = ic->ic_ifp;
351	int maxmcs = 2 * 8;
352	const char *modestr = ieee80211_phymode_name[mode];
353
354	KASSERT(maxmcs <= 16, ("maxmcs > 16"));
355	if_printf(ifp, "%d MCS rates\n", maxmcs);
356	if_printf(ifp, "%s MCS 20Mhz: ", modestr);
357	ht_rateprint(ic, mode, rs, maxmcs, 0);
358	if_printf(ifp, "%s MCS 20Mhz SGI: ", modestr);
359	ht_rateprint(ic, mode, rs, maxmcs, 1);
360	if_printf(ifp, "%s MCS 40Mhz: ", modestr);
361	ht_rateprint(ic, mode, rs, maxmcs, 2);
362	if_printf(ifp, "%s MCS 40Mhz SGI: ", modestr);
363	ht_rateprint(ic, mode, rs, maxmcs, 3);
364}
365
366void
367ieee80211_ht_announce(struct ieee80211com *ic)
368{
369	if (isset(ic->ic_modecaps, IEEE80211_MODE_11NA))
370		ht_announce(ic, IEEE80211_MODE_11NA, &ieee80211_rateset_11n);
371	if (isset(ic->ic_modecaps, IEEE80211_MODE_11NG))
372		ht_announce(ic, IEEE80211_MODE_11NG, &ieee80211_rateset_11n);
373}
374
375const struct ieee80211_htrateset *
376ieee80211_get_suphtrates(struct ieee80211com *ic,
377	const struct ieee80211_channel *c)
378{
379	return &ieee80211_rateset_11n;
380}
381
382/*
383 * Receive processing.
384 */
385
386/*
387 * Decap the encapsulated A-MSDU frames and dispatch all but
388 * the last for delivery.  The last frame is returned for
389 * delivery via the normal path.
390 */
391struct mbuf *
392ieee80211_decap_amsdu(struct ieee80211_node *ni, struct mbuf *m)
393{
394	struct ieee80211vap *vap = ni->ni_vap;
395	int framelen;
396	struct mbuf *n;
397
398	/* discard 802.3 header inserted by ieee80211_decap */
399	m_adj(m, sizeof(struct ether_header));
400
401	vap->iv_stats.is_amsdu_decap++;
402
403	for (;;) {
404		/*
405		 * Decap the first frame, bust it apart from the
406		 * remainder and deliver.  We leave the last frame
407		 * delivery to the caller (for consistency with other
408		 * code paths, could also do it here).
409		 */
410		m = ieee80211_decap1(m, &framelen);
411		if (m == NULL) {
412			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
413			    ni->ni_macaddr, "a-msdu", "%s", "decap failed");
414			vap->iv_stats.is_amsdu_tooshort++;
415			return NULL;
416		}
417		if (m->m_pkthdr.len == framelen)
418			break;
419		n = m_split(m, framelen, M_NOWAIT);
420		if (n == NULL) {
421			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
422			    ni->ni_macaddr, "a-msdu",
423			    "%s", "unable to split encapsulated frames");
424			vap->iv_stats.is_amsdu_split++;
425			m_freem(m);			/* NB: must reclaim */
426			return NULL;
427		}
428		vap->iv_deliver_data(vap, ni, m);
429
430		/*
431		 * Remove frame contents; each intermediate frame
432		 * is required to be aligned to a 4-byte boundary.
433		 */
434		m = n;
435		m_adj(m, roundup2(framelen, 4) - framelen);	/* padding */
436	}
437	return m;				/* last delivered by caller */
438}
439
440/*
441 * Purge all frames in the A-MPDU re-order queue.
442 */
443static void
444ampdu_rx_purge(struct ieee80211_rx_ampdu *rap)
445{
446	struct mbuf *m;
447	int i;
448
449	for (i = 0; i < rap->rxa_wnd; i++) {
450		m = rap->rxa_m[i];
451		if (m != NULL) {
452			rap->rxa_m[i] = NULL;
453			rap->rxa_qbytes -= m->m_pkthdr.len;
454			m_freem(m);
455			if (--rap->rxa_qframes == 0)
456				break;
457		}
458	}
459	KASSERT(rap->rxa_qbytes == 0 && rap->rxa_qframes == 0,
460	    ("lost %u data, %u frames on ampdu rx q",
461	    rap->rxa_qbytes, rap->rxa_qframes));
462}
463
464/*
465 * Start A-MPDU rx/re-order processing for the specified TID.
466 */
467static int
468ampdu_rx_start(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap,
469	int baparamset, int batimeout, int baseqctl)
470{
471	int bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ);
472
473	if (rap->rxa_flags & IEEE80211_AGGR_RUNNING) {
474		/*
475		 * AMPDU previously setup and not terminated with a DELBA,
476		 * flush the reorder q's in case anything remains.
477		 */
478		ampdu_rx_purge(rap);
479	}
480	memset(rap, 0, sizeof(*rap));
481	rap->rxa_wnd = (bufsiz == 0) ?
482	    IEEE80211_AGGR_BAWMAX : min(bufsiz, IEEE80211_AGGR_BAWMAX);
483	rap->rxa_start = MS(baseqctl, IEEE80211_BASEQ_START);
484	rap->rxa_flags |=  IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_XCHGPEND;
485
486	return 0;
487}
488
489/*
490 * Stop A-MPDU rx processing for the specified TID.
491 */
492static void
493ampdu_rx_stop(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap)
494{
495
496	ampdu_rx_purge(rap);
497	rap->rxa_flags &= ~(IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_XCHGPEND);
498}
499
500/*
501 * Dispatch a frame from the A-MPDU reorder queue.  The
502 * frame is fed back into ieee80211_input marked with an
503 * M_AMPDU_MPDU flag so it doesn't come back to us (it also
504 * permits ieee80211_input to optimize re-processing).
505 */
506static __inline void
507ampdu_dispatch(struct ieee80211_node *ni, struct mbuf *m)
508{
509	m->m_flags |= M_AMPDU_MPDU;	/* bypass normal processing */
510	/* NB: rssi and noise are ignored w/ M_AMPDU_MPDU set */
511	(void) ieee80211_input(ni, m, 0, 0);
512}
513
514/*
515 * Dispatch as many frames as possible from the re-order queue.
516 * Frames will always be "at the front"; we process all frames
517 * up to the first empty slot in the window.  On completion we
518 * cleanup state if there are still pending frames in the current
519 * BA window.  We assume the frame at slot 0 is already handled
520 * by the caller; we always start at slot 1.
521 */
522static void
523ampdu_rx_dispatch(struct ieee80211_rx_ampdu *rap, struct ieee80211_node *ni)
524{
525	struct ieee80211vap *vap = ni->ni_vap;
526	struct mbuf *m;
527	int i;
528
529	/* flush run of frames */
530	for (i = 1; i < rap->rxa_wnd; i++) {
531		m = rap->rxa_m[i];
532		if (m == NULL)
533			break;
534		rap->rxa_m[i] = NULL;
535		rap->rxa_qbytes -= m->m_pkthdr.len;
536		rap->rxa_qframes--;
537
538		ampdu_dispatch(ni, m);
539	}
540	/*
541	 * If frames remain, copy the mbuf pointers down so
542	 * they correspond to the offsets in the new window.
543	 */
544	if (rap->rxa_qframes != 0) {
545		int n = rap->rxa_qframes, j;
546		for (j = i+1; j < rap->rxa_wnd; j++) {
547			if (rap->rxa_m[j] != NULL) {
548				rap->rxa_m[j-i] = rap->rxa_m[j];
549				rap->rxa_m[j] = NULL;
550				if (--n == 0)
551					break;
552			}
553		}
554		KASSERT(n == 0, ("lost %d frames", n));
555		vap->iv_stats.is_ampdu_rx_copy += rap->rxa_qframes;
556	}
557	/*
558	 * Adjust the start of the BA window to
559	 * reflect the frames just dispatched.
560	 */
561	rap->rxa_start = IEEE80211_SEQ_ADD(rap->rxa_start, i);
562	vap->iv_stats.is_ampdu_rx_oor += i;
563}
564
565#ifdef IEEE80211_AMPDU_AGE
566/*
567 * Dispatch all frames in the A-MPDU re-order queue.
568 */
569static void
570ampdu_rx_flush(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap)
571{
572	struct ieee80211vap *vap = ni->ni_vap;
573	struct mbuf *m;
574	int i;
575
576	for (i = 0; i < rap->rxa_wnd; i++) {
577		m = rap->rxa_m[i];
578		if (m == NULL)
579			continue;
580		rap->rxa_m[i] = NULL;
581		rap->rxa_qbytes -= m->m_pkthdr.len;
582		rap->rxa_qframes--;
583		vap->iv_stats.is_ampdu_rx_oor++;
584
585		ampdu_dispatch(ni, m);
586		if (rap->rxa_qframes == 0)
587			break;
588	}
589}
590#endif /* IEEE80211_AMPDU_AGE */
591
592/*
593 * Dispatch all frames in the A-MPDU re-order queue
594 * preceding the specified sequence number.  This logic
595 * handles window moves due to a received MSDU or BAR.
596 */
597static void
598ampdu_rx_flush_upto(struct ieee80211_node *ni,
599	struct ieee80211_rx_ampdu *rap, ieee80211_seq winstart)
600{
601	struct ieee80211vap *vap = ni->ni_vap;
602	struct mbuf *m;
603	ieee80211_seq seqno;
604	int i;
605
606	/*
607	 * Flush any complete MSDU's with a sequence number lower
608	 * than winstart.  Gaps may exist.  Note that we may actually
609	 * dispatch frames past winstart if a run continues; this is
610	 * an optimization that avoids having to do a separate pass
611	 * to dispatch frames after moving the BA window start.
612	 */
613	seqno = rap->rxa_start;
614	for (i = 0; i < rap->rxa_wnd; i++) {
615		m = rap->rxa_m[i];
616		if (m != NULL) {
617			rap->rxa_m[i] = NULL;
618			rap->rxa_qbytes -= m->m_pkthdr.len;
619			rap->rxa_qframes--;
620			vap->iv_stats.is_ampdu_rx_oor++;
621
622			ampdu_dispatch(ni, m);
623		} else {
624			if (!IEEE80211_SEQ_BA_BEFORE(seqno, winstart))
625				break;
626		}
627		seqno = IEEE80211_SEQ_INC(seqno);
628	}
629	/*
630	 * If frames remain, copy the mbuf pointers down so
631	 * they correspond to the offsets in the new window.
632	 */
633	if (rap->rxa_qframes != 0) {
634		int n = rap->rxa_qframes, j;
635
636		/* NB: this loop assumes i > 0 and/or rxa_m[0] is NULL */
637		KASSERT(rap->rxa_m[0] == NULL,
638		    ("%s: BA window slot 0 occupied", __func__));
639		for (j = i+1; j < rap->rxa_wnd; j++) {
640			if (rap->rxa_m[j] != NULL) {
641				rap->rxa_m[j-i] = rap->rxa_m[j];
642				rap->rxa_m[j] = NULL;
643				if (--n == 0)
644					break;
645			}
646		}
647		KASSERT(n == 0, ("%s: lost %d frames, qframes %d off %d "
648		    "BA win <%d:%d> winstart %d",
649		    __func__, n, rap->rxa_qframes, i, rap->rxa_start,
650		    IEEE80211_SEQ_ADD(rap->rxa_start, rap->rxa_wnd-1),
651		    winstart));
652		vap->iv_stats.is_ampdu_rx_copy += rap->rxa_qframes;
653	}
654	/*
655	 * Move the start of the BA window; we use the
656	 * sequence number of the last MSDU that was
657	 * passed up the stack+1 or winstart if stopped on
658	 * a gap in the reorder buffer.
659	 */
660	rap->rxa_start = seqno;
661}
662
663/*
664 * Process a received QoS data frame for an HT station.  Handle
665 * A-MPDU reordering: if this frame is received out of order
666 * and falls within the BA window hold onto it.  Otherwise if
667 * this frame completes a run, flush any pending frames.  We
668 * return 1 if the frame is consumed.  A 0 is returned if
669 * the frame should be processed normally by the caller.
670 */
671int
672ieee80211_ampdu_reorder(struct ieee80211_node *ni, struct mbuf *m)
673{
674#define	IEEE80211_FC0_QOSDATA \
675	(IEEE80211_FC0_TYPE_DATA|IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_VERSION_0)
676#define	PROCESS		0	/* caller should process frame */
677#define	CONSUMED	1	/* frame consumed, caller does nothing */
678	struct ieee80211vap *vap = ni->ni_vap;
679	struct ieee80211_qosframe *wh;
680	struct ieee80211_rx_ampdu *rap;
681	ieee80211_seq rxseq;
682	uint8_t tid;
683	int off;
684
685	KASSERT((m->m_flags & (M_AMPDU | M_AMPDU_MPDU)) == M_AMPDU,
686	    ("!a-mpdu or already re-ordered, flags 0x%x", m->m_flags));
687	KASSERT(ni->ni_flags & IEEE80211_NODE_HT, ("not an HT sta"));
688
689	/* NB: m_len known to be sufficient */
690	wh = mtod(m, struct ieee80211_qosframe *);
691	if (wh->i_fc[0] != IEEE80211_FC0_QOSDATA) {
692		/*
693		 * Not QoS data, shouldn't get here but just
694		 * return it to the caller for processing.
695		 */
696		return PROCESS;
697	}
698	if (IEEE80211_IS_DSTODS(wh))
699		tid = ((struct ieee80211_qosframe_addr4 *)wh)->i_qos[0];
700	else
701		tid = wh->i_qos[0];
702	tid &= IEEE80211_QOS_TID;
703	rap = &ni->ni_rx_ampdu[tid];
704	if ((rap->rxa_flags & IEEE80211_AGGR_XCHGPEND) == 0) {
705		/*
706		 * No ADDBA request yet, don't touch.
707		 */
708		return PROCESS;
709	}
710	rxseq = le16toh(*(uint16_t *)wh->i_seq);
711	if ((rxseq & IEEE80211_SEQ_FRAG_MASK) != 0) {
712		/*
713		 * Fragments are not allowed; toss.
714		 */
715		IEEE80211_DISCARD_MAC(vap,
716		    IEEE80211_MSG_INPUT | IEEE80211_MSG_11N, ni->ni_macaddr,
717		    "A-MPDU", "fragment, rxseq 0x%x tid %u%s", rxseq, tid,
718		    wh->i_fc[1] & IEEE80211_FC1_RETRY ? " (retransmit)" : "");
719		vap->iv_stats.is_ampdu_rx_drop++;
720		IEEE80211_NODE_STAT(ni, rx_drop);
721		m_freem(m);
722		return CONSUMED;
723	}
724	rxseq >>= IEEE80211_SEQ_SEQ_SHIFT;
725	rap->rxa_nframes++;
726again:
727	if (rxseq == rap->rxa_start) {
728		/*
729		 * First frame in window.
730		 */
731		if (rap->rxa_qframes != 0) {
732			/*
733			 * Dispatch as many packets as we can.
734			 */
735			KASSERT(rap->rxa_m[0] == NULL, ("unexpected dup"));
736			ampdu_dispatch(ni, m);
737			ampdu_rx_dispatch(rap, ni);
738			return CONSUMED;
739		} else {
740			/*
741			 * In order; advance window and notify
742			 * caller to dispatch directly.
743			 */
744			rap->rxa_start = IEEE80211_SEQ_INC(rxseq);
745			return PROCESS;
746		}
747	}
748	/*
749	 * Frame is out of order; store if in the BA window.
750	 */
751	/* calculate offset in BA window */
752	off = IEEE80211_SEQ_SUB(rxseq, rap->rxa_start);
753	if (off < rap->rxa_wnd) {
754		/*
755		 * Common case (hopefully): in the BA window.
756		 * Sec 9.10.7.6.2 a) (p.137)
757		 */
758#ifdef IEEE80211_AMPDU_AGE
759		/*
760		 * Check for frames sitting too long in the reorder queue.
761		 * This should only ever happen if frames are not delivered
762		 * without the sender otherwise notifying us (e.g. with a
763		 * BAR to move the window).  Typically this happens because
764		 * of vendor bugs that cause the sequence number to jump.
765		 * When this happens we get a gap in the reorder queue that
766		 * leaves frame sitting on the queue until they get pushed
767		 * out due to window moves.  When the vendor does not send
768		 * BAR this move only happens due to explicit packet sends
769		 *
770		 * NB: we only track the time of the oldest frame in the
771		 * reorder q; this means that if we flush we might push
772		 * frames that still "new"; if this happens then subsequent
773		 * frames will result in BA window moves which cost something
774		 * but is still better than a big throughput dip.
775		 */
776		if (rap->rxa_qframes != 0) {
777			/* XXX honor batimeout? */
778			if (ticks - rap->rxa_age > ieee80211_ampdu_age) {
779				/*
780				 * Too long since we received the first
781				 * frame; flush the reorder buffer.
782				 */
783				if (rap->rxa_qframes != 0) {
784					vap->iv_stats.is_ampdu_rx_age +=
785					    rap->rxa_qframes;
786					ampdu_rx_flush(ni, rap);
787				}
788				rap->rxa_start = IEEE80211_SEQ_INC(rxseq);
789				return PROCESS;
790			}
791		} else {
792			/*
793			 * First frame, start aging timer.
794			 */
795			rap->rxa_age = ticks;
796		}
797#endif /* IEEE80211_AMPDU_AGE */
798		/* save packet */
799		if (rap->rxa_m[off] == NULL) {
800			rap->rxa_m[off] = m;
801			rap->rxa_qframes++;
802			rap->rxa_qbytes += m->m_pkthdr.len;
803			vap->iv_stats.is_ampdu_rx_reorder++;
804		} else {
805			IEEE80211_DISCARD_MAC(vap,
806			    IEEE80211_MSG_INPUT | IEEE80211_MSG_11N,
807			    ni->ni_macaddr, "a-mpdu duplicate",
808			    "seqno %u tid %u BA win <%u:%u>",
809			    rxseq, tid, rap->rxa_start,
810			    IEEE80211_SEQ_ADD(rap->rxa_start, rap->rxa_wnd-1));
811			vap->iv_stats.is_rx_dup++;
812			IEEE80211_NODE_STAT(ni, rx_dup);
813			m_freem(m);
814		}
815		return CONSUMED;
816	}
817	if (off < IEEE80211_SEQ_BA_RANGE) {
818		/*
819		 * Outside the BA window, but within range;
820		 * flush the reorder q and move the window.
821		 * Sec 9.10.7.6.2 b) (p.138)
822		 */
823		IEEE80211_NOTE(vap, IEEE80211_MSG_11N, ni,
824		    "move BA win <%u:%u> (%u frames) rxseq %u tid %u",
825		    rap->rxa_start,
826		    IEEE80211_SEQ_ADD(rap->rxa_start, rap->rxa_wnd-1),
827		    rap->rxa_qframes, rxseq, tid);
828		vap->iv_stats.is_ampdu_rx_move++;
829
830		/*
831		 * The spec says to flush frames up to but not including:
832		 * 	WinStart_B = rxseq - rap->rxa_wnd + 1
833		 * Then insert the frame or notify the caller to process
834		 * it immediately.  We can safely do this by just starting
835		 * over again because we know the frame will now be within
836		 * the BA window.
837		 */
838		/* NB: rxa_wnd known to be >0 */
839		ampdu_rx_flush_upto(ni, rap,
840		    IEEE80211_SEQ_SUB(rxseq, rap->rxa_wnd-1));
841		goto again;
842	} else {
843		/*
844		 * Outside the BA window and out of range; toss.
845		 * Sec 9.10.7.6.2 c) (p.138)
846		 */
847		IEEE80211_DISCARD_MAC(vap,
848		    IEEE80211_MSG_INPUT | IEEE80211_MSG_11N, ni->ni_macaddr,
849		    "MPDU", "BA win <%u:%u> (%u frames) rxseq %u tid %u%s",
850		    rap->rxa_start,
851		    IEEE80211_SEQ_ADD(rap->rxa_start, rap->rxa_wnd-1),
852		    rap->rxa_qframes, rxseq, tid,
853		    wh->i_fc[1] & IEEE80211_FC1_RETRY ? " (retransmit)" : "");
854		vap->iv_stats.is_ampdu_rx_drop++;
855		IEEE80211_NODE_STAT(ni, rx_drop);
856		m_freem(m);
857		return CONSUMED;
858	}
859#undef CONSUMED
860#undef PROCESS
861#undef IEEE80211_FC0_QOSDATA
862}
863
864/*
865 * Process a BAR ctl frame.  Dispatch all frames up to
866 * the sequence number of the frame.  If this frame is
867 * out of range it's discarded.
868 */
869void
870ieee80211_recv_bar(struct ieee80211_node *ni, struct mbuf *m0)
871{
872	struct ieee80211vap *vap = ni->ni_vap;
873	struct ieee80211_frame_bar *wh;
874	struct ieee80211_rx_ampdu *rap;
875	ieee80211_seq rxseq;
876	int tid, off;
877
878	if (!ieee80211_recv_bar_ena) {
879#if 0
880		IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_11N,
881		    ni->ni_macaddr, "BAR", "%s", "processing disabled");
882#endif
883		vap->iv_stats.is_ampdu_bar_bad++;
884		return;
885	}
886	wh = mtod(m0, struct ieee80211_frame_bar *);
887	/* XXX check basic BAR */
888	tid = MS(le16toh(wh->i_ctl), IEEE80211_BAR_TID);
889	rap = &ni->ni_rx_ampdu[tid];
890	if ((rap->rxa_flags & IEEE80211_AGGR_XCHGPEND) == 0) {
891		/*
892		 * No ADDBA request yet, don't touch.
893		 */
894		IEEE80211_DISCARD_MAC(vap,
895		    IEEE80211_MSG_INPUT | IEEE80211_MSG_11N,
896		    ni->ni_macaddr, "BAR", "no BA stream, tid %u", tid);
897		vap->iv_stats.is_ampdu_bar_bad++;
898		return;
899	}
900	vap->iv_stats.is_ampdu_bar_rx++;
901	rxseq = le16toh(wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT;
902	if (rxseq == rap->rxa_start)
903		return;
904	/* calculate offset in BA window */
905	off = IEEE80211_SEQ_SUB(rxseq, rap->rxa_start);
906	if (off < IEEE80211_SEQ_BA_RANGE) {
907		/*
908		 * Flush the reorder q up to rxseq and move the window.
909		 * Sec 9.10.7.6.3 a) (p.138)
910		 */
911		IEEE80211_NOTE(vap, IEEE80211_MSG_11N, ni,
912		    "BAR moves BA win <%u:%u> (%u frames) rxseq %u tid %u",
913		    rap->rxa_start,
914		    IEEE80211_SEQ_ADD(rap->rxa_start, rap->rxa_wnd-1),
915		    rap->rxa_qframes, rxseq, tid);
916		vap->iv_stats.is_ampdu_bar_move++;
917
918		ampdu_rx_flush_upto(ni, rap, rxseq);
919		if (off >= rap->rxa_wnd) {
920			/*
921			 * BAR specifies a window start to the right of BA
922			 * window; we must move it explicitly since
923			 * ampdu_rx_flush_upto will not.
924			 */
925			rap->rxa_start = rxseq;
926		}
927	} else {
928		/*
929		 * Out of range; toss.
930		 * Sec 9.10.7.6.3 b) (p.138)
931		 */
932		IEEE80211_DISCARD_MAC(vap,
933		    IEEE80211_MSG_INPUT | IEEE80211_MSG_11N, ni->ni_macaddr,
934		    "BAR", "BA win <%u:%u> (%u frames) rxseq %u tid %u%s",
935		    rap->rxa_start,
936		    IEEE80211_SEQ_ADD(rap->rxa_start, rap->rxa_wnd-1),
937		    rap->rxa_qframes, rxseq, tid,
938		    wh->i_fc[1] & IEEE80211_FC1_RETRY ? " (retransmit)" : "");
939		vap->iv_stats.is_ampdu_bar_oow++;
940		IEEE80211_NODE_STAT(ni, rx_drop);
941	}
942}
943
944/*
945 * Setup HT-specific state in a node.  Called only
946 * when HT use is negotiated so we don't do extra
947 * work for temporary and/or legacy sta's.
948 */
949void
950ieee80211_ht_node_init(struct ieee80211_node *ni)
951{
952	struct ieee80211_tx_ampdu *tap;
953	int ac;
954
955	if (ni->ni_flags & IEEE80211_NODE_HT) {
956		/*
957		 * Clean AMPDU state on re-associate.  This handles the case
958		 * where a station leaves w/o notifying us and then returns
959		 * before node is reaped for inactivity.
960		 */
961		ieee80211_ht_node_cleanup(ni);
962	}
963	for (ac = 0; ac < WME_NUM_AC; ac++) {
964		tap = &ni->ni_tx_ampdu[ac];
965		tap->txa_ac = ac;
966		tap->txa_ni = ni;
967		/* NB: further initialization deferred */
968	}
969	ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU;
970}
971
972/*
973 * Cleanup HT-specific state in a node.  Called only
974 * when HT use has been marked.
975 */
976void
977ieee80211_ht_node_cleanup(struct ieee80211_node *ni)
978{
979	struct ieee80211com *ic = ni->ni_ic;
980	int i;
981
982	KASSERT(ni->ni_flags & IEEE80211_NODE_HT, ("not an HT node"));
983
984	/* XXX optimize this */
985	for (i = 0; i < WME_NUM_AC; i++) {
986		struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[i];
987		if (tap->txa_flags & IEEE80211_AGGR_SETUP)
988			ampdu_tx_stop(tap);
989	}
990	for (i = 0; i < WME_NUM_TID; i++)
991		ic->ic_ampdu_rx_stop(ni, &ni->ni_rx_ampdu[i]);
992
993	ni->ni_htcap = 0;
994	ni->ni_flags &= ~IEEE80211_NODE_HT_ALL;
995}
996
997/*
998 * Age out HT resources for a station.
999 */
1000void
1001ieee80211_ht_node_age(struct ieee80211_node *ni)
1002{
1003#ifdef IEEE80211_AMPDU_AGE
1004	struct ieee80211vap *vap = ni->ni_vap;
1005	uint8_t tid;
1006#endif
1007
1008	KASSERT(ni->ni_flags & IEEE80211_NODE_HT, ("not an HT sta"));
1009
1010#ifdef IEEE80211_AMPDU_AGE
1011	for (tid = 0; tid < WME_NUM_TID; tid++) {
1012		struct ieee80211_rx_ampdu *rap;
1013
1014		rap = &ni->ni_rx_ampdu[tid];
1015		if ((rap->rxa_flags & IEEE80211_AGGR_XCHGPEND) == 0)
1016			continue;
1017		if (rap->rxa_qframes == 0)
1018			continue;
1019		/*
1020		 * Check for frames sitting too long in the reorder queue.
1021		 * See above for more details on what's happening here.
1022		 */
1023		/* XXX honor batimeout? */
1024		if (ticks - rap->rxa_age > ieee80211_ampdu_age) {
1025			/*
1026			 * Too long since we received the first
1027			 * frame; flush the reorder buffer.
1028			 */
1029			vap->iv_stats.is_ampdu_rx_age += rap->rxa_qframes;
1030			ampdu_rx_flush(ni, rap);
1031		}
1032	}
1033#endif /* IEEE80211_AMPDU_AGE */
1034}
1035
1036static struct ieee80211_channel *
1037findhtchan(struct ieee80211com *ic, struct ieee80211_channel *c, int htflags)
1038{
1039	return ieee80211_find_channel(ic, c->ic_freq,
1040	    (c->ic_flags &~ IEEE80211_CHAN_HT) | htflags);
1041}
1042
1043/*
1044 * Adjust a channel to be HT/non-HT according to the vap's configuration.
1045 */
1046struct ieee80211_channel *
1047ieee80211_ht_adjust_channel(struct ieee80211com *ic,
1048	struct ieee80211_channel *chan, int flags)
1049{
1050	struct ieee80211_channel *c;
1051
1052	if (flags & IEEE80211_FHT_HT) {
1053		/* promote to HT if possible */
1054		if (flags & IEEE80211_FHT_USEHT40) {
1055			if (!IEEE80211_IS_CHAN_HT40(chan)) {
1056				/* NB: arbitrarily pick ht40+ over ht40- */
1057				c = findhtchan(ic, chan, IEEE80211_CHAN_HT40U);
1058				if (c == NULL)
1059					c = findhtchan(ic, chan,
1060						IEEE80211_CHAN_HT40D);
1061				if (c == NULL)
1062					c = findhtchan(ic, chan,
1063						IEEE80211_CHAN_HT20);
1064				if (c != NULL)
1065					chan = c;
1066			}
1067		} else if (!IEEE80211_IS_CHAN_HT20(chan)) {
1068			c = findhtchan(ic, chan, IEEE80211_CHAN_HT20);
1069			if (c != NULL)
1070				chan = c;
1071		}
1072	} else if (IEEE80211_IS_CHAN_HT(chan)) {
1073		/* demote to legacy, HT use is disabled */
1074		c = ieee80211_find_channel(ic, chan->ic_freq,
1075		    chan->ic_flags &~ IEEE80211_CHAN_HT);
1076		if (c != NULL)
1077			chan = c;
1078	}
1079	return chan;
1080}
1081
1082/*
1083 * Setup HT-specific state for a legacy WDS peer.
1084 */
1085void
1086ieee80211_ht_wds_init(struct ieee80211_node *ni)
1087{
1088	struct ieee80211vap *vap = ni->ni_vap;
1089	struct ieee80211_tx_ampdu *tap;
1090	int ac;
1091
1092	KASSERT(vap->iv_flags_ht & IEEE80211_FHT_HT, ("no HT requested"));
1093
1094	/* XXX check scan cache in case peer has an ap and we have info */
1095	/*
1096	 * If setup with a legacy channel; locate an HT channel.
1097	 * Otherwise if the inherited channel (from a companion
1098	 * AP) is suitable use it so we use the same location
1099	 * for the extension channel).
1100	 */
1101	ni->ni_chan = ieee80211_ht_adjust_channel(ni->ni_ic,
1102	    ni->ni_chan, ieee80211_htchanflags(ni->ni_chan));
1103
1104	ni->ni_htcap = 0;
1105	if (vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20)
1106		ni->ni_htcap |= IEEE80211_HTCAP_SHORTGI20;
1107	if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) {
1108		ni->ni_htcap |= IEEE80211_HTCAP_CHWIDTH40;
1109		ni->ni_chw = 40;
1110		if (IEEE80211_IS_CHAN_HT40U(ni->ni_chan))
1111			ni->ni_ht2ndchan = IEEE80211_HTINFO_2NDCHAN_ABOVE;
1112		else if (IEEE80211_IS_CHAN_HT40D(ni->ni_chan))
1113			ni->ni_ht2ndchan = IEEE80211_HTINFO_2NDCHAN_BELOW;
1114		if (vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40)
1115			ni->ni_htcap |= IEEE80211_HTCAP_SHORTGI40;
1116	} else {
1117		ni->ni_chw = 20;
1118		ni->ni_ht2ndchan = IEEE80211_HTINFO_2NDCHAN_NONE;
1119	}
1120	ni->ni_htctlchan = ni->ni_chan->ic_ieee;
1121	if (vap->iv_flags_ht & IEEE80211_FHT_RIFS)
1122		ni->ni_flags |= IEEE80211_NODE_RIFS;
1123	/* XXX does it make sense to enable SMPS? */
1124
1125	ni->ni_htopmode = 0;		/* XXX need protection state */
1126	ni->ni_htstbc = 0;		/* XXX need info */
1127
1128	for (ac = 0; ac < WME_NUM_AC; ac++) {
1129		tap = &ni->ni_tx_ampdu[ac];
1130		tap->txa_ac = ac;
1131	}
1132	/* NB: AMPDU tx/rx governed by IEEE80211_FHT_AMPDU_{TX,RX} */
1133	ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU;
1134}
1135
1136/*
1137 * Notify hostap vaps of a change in the HTINFO ie.
1138 */
1139static void
1140htinfo_notify(struct ieee80211com *ic)
1141{
1142	struct ieee80211vap *vap;
1143	int first = 1;
1144
1145	IEEE80211_LOCK_ASSERT(ic);
1146
1147	TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
1148		if (vap->iv_opmode != IEEE80211_M_HOSTAP)
1149			continue;
1150		if (vap->iv_state != IEEE80211_S_RUN ||
1151		    !IEEE80211_IS_CHAN_HT(vap->iv_bss->ni_chan))
1152			continue;
1153		if (first) {
1154			IEEE80211_NOTE(vap,
1155			    IEEE80211_MSG_ASSOC | IEEE80211_MSG_11N,
1156			    vap->iv_bss,
1157			    "HT bss occupancy change: %d sta, %d ht, "
1158			    "%d ht40%s, HT protmode now 0x%x"
1159			    , ic->ic_sta_assoc
1160			    , ic->ic_ht_sta_assoc
1161			    , ic->ic_ht40_sta_assoc
1162			    , (ic->ic_flags_ht & IEEE80211_FHT_NONHT_PR) ?
1163				 ", non-HT sta present" : ""
1164			    , ic->ic_curhtprotmode);
1165			first = 0;
1166		}
1167		ieee80211_beacon_notify(vap, IEEE80211_BEACON_HTINFO);
1168	}
1169}
1170
1171/*
1172 * Calculate HT protection mode from current
1173 * state and handle updates.
1174 */
1175static void
1176htinfo_update(struct ieee80211com *ic)
1177{
1178	uint8_t protmode;
1179
1180	if (ic->ic_sta_assoc != ic->ic_ht_sta_assoc) {
1181		protmode = IEEE80211_HTINFO_OPMODE_MIXED
1182			 | IEEE80211_HTINFO_NONHT_PRESENT;
1183	} else if (ic->ic_flags_ht & IEEE80211_FHT_NONHT_PR) {
1184		protmode = IEEE80211_HTINFO_OPMODE_PROTOPT
1185			 | IEEE80211_HTINFO_NONHT_PRESENT;
1186	} else if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
1187	    IEEE80211_IS_CHAN_HT40(ic->ic_bsschan) &&
1188	    ic->ic_sta_assoc != ic->ic_ht40_sta_assoc) {
1189		protmode = IEEE80211_HTINFO_OPMODE_HT20PR;
1190	} else {
1191		protmode = IEEE80211_HTINFO_OPMODE_PURE;
1192	}
1193	if (protmode != ic->ic_curhtprotmode) {
1194		ic->ic_curhtprotmode = protmode;
1195		htinfo_notify(ic);
1196	}
1197}
1198
1199/*
1200 * Handle an HT station joining a BSS.
1201 */
1202void
1203ieee80211_ht_node_join(struct ieee80211_node *ni)
1204{
1205	struct ieee80211com *ic = ni->ni_ic;
1206
1207	IEEE80211_LOCK_ASSERT(ic);
1208
1209	if (ni->ni_flags & IEEE80211_NODE_HT) {
1210		ic->ic_ht_sta_assoc++;
1211		if (ni->ni_chw == 40)
1212			ic->ic_ht40_sta_assoc++;
1213	}
1214	htinfo_update(ic);
1215}
1216
1217/*
1218 * Handle an HT station leaving a BSS.
1219 */
1220void
1221ieee80211_ht_node_leave(struct ieee80211_node *ni)
1222{
1223	struct ieee80211com *ic = ni->ni_ic;
1224
1225	IEEE80211_LOCK_ASSERT(ic);
1226
1227	if (ni->ni_flags & IEEE80211_NODE_HT) {
1228		ic->ic_ht_sta_assoc--;
1229		if (ni->ni_chw == 40)
1230			ic->ic_ht40_sta_assoc--;
1231	}
1232	htinfo_update(ic);
1233}
1234
1235/*
1236 * Public version of htinfo_update; used for processing
1237 * beacon frames from overlapping bss.
1238 *
1239 * Caller can specify either IEEE80211_HTINFO_OPMODE_MIXED
1240 * (on receipt of a beacon that advertises MIXED) or
1241 * IEEE80211_HTINFO_OPMODE_PROTOPT (on receipt of a beacon
1242 * from an overlapping legacy bss).  We treat MIXED with
1243 * a higher precedence than PROTOPT (i.e. we will not change
1244 * change PROTOPT -> MIXED; only MIXED -> PROTOPT).  This
1245 * corresponds to how we handle things in htinfo_update.
1246 */
1247void
1248ieee80211_htprot_update(struct ieee80211com *ic, int protmode)
1249{
1250#define	OPMODE(x)	SM(x, IEEE80211_HTINFO_OPMODE)
1251	IEEE80211_LOCK(ic);
1252
1253	/* track non-HT station presence */
1254	KASSERT(protmode & IEEE80211_HTINFO_NONHT_PRESENT,
1255	    ("protmode 0x%x", protmode));
1256	ic->ic_flags_ht |= IEEE80211_FHT_NONHT_PR;
1257	ic->ic_lastnonht = ticks;
1258
1259	if (protmode != ic->ic_curhtprotmode &&
1260	    (OPMODE(ic->ic_curhtprotmode) != IEEE80211_HTINFO_OPMODE_MIXED ||
1261	     OPMODE(protmode) == IEEE80211_HTINFO_OPMODE_PROTOPT)) {
1262		/* push beacon update */
1263		ic->ic_curhtprotmode = protmode;
1264		htinfo_notify(ic);
1265	}
1266	IEEE80211_UNLOCK(ic);
1267#undef OPMODE
1268}
1269
1270/*
1271 * Time out presence of an overlapping bss with non-HT
1272 * stations.  When operating in hostap mode we listen for
1273 * beacons from other stations and if we identify a non-HT
1274 * station is present we update the opmode field of the
1275 * HTINFO ie.  To identify when all non-HT stations are
1276 * gone we time out this condition.
1277 */
1278void
1279ieee80211_ht_timeout(struct ieee80211com *ic)
1280{
1281	IEEE80211_LOCK_ASSERT(ic);
1282
1283	if ((ic->ic_flags_ht & IEEE80211_FHT_NONHT_PR) &&
1284	    time_after(ticks, ic->ic_lastnonht + IEEE80211_NONHT_PRESENT_AGE)) {
1285#if 0
1286		IEEE80211_NOTE(vap, IEEE80211_MSG_11N, ni,
1287		    "%s", "time out non-HT STA present on channel");
1288#endif
1289		ic->ic_flags_ht &= ~IEEE80211_FHT_NONHT_PR;
1290		htinfo_update(ic);
1291	}
1292}
1293
1294/* unalligned little endian access */
1295#define LE_READ_2(p)					\
1296	((uint16_t)					\
1297	 ((((const uint8_t *)(p))[0]      ) |		\
1298	  (((const uint8_t *)(p))[1] <<  8)))
1299
1300/*
1301 * Process an 802.11n HT capabilities ie.
1302 */
1303void
1304ieee80211_parse_htcap(struct ieee80211_node *ni, const uint8_t *ie)
1305{
1306	if (ie[0] == IEEE80211_ELEMID_VENDOR) {
1307		/*
1308		 * Station used Vendor OUI ie to associate;
1309		 * mark the node so when we respond we'll use
1310		 * the Vendor OUI's and not the standard ie's.
1311		 */
1312		ni->ni_flags |= IEEE80211_NODE_HTCOMPAT;
1313		ie += 4;
1314	} else
1315		ni->ni_flags &= ~IEEE80211_NODE_HTCOMPAT;
1316
1317	ni->ni_htcap = LE_READ_2(ie +
1318		__offsetof(struct ieee80211_ie_htcap, hc_cap));
1319	ni->ni_htparam = ie[__offsetof(struct ieee80211_ie_htcap, hc_param)];
1320}
1321
1322static void
1323htinfo_parse(struct ieee80211_node *ni,
1324	const struct ieee80211_ie_htinfo *htinfo)
1325{
1326	uint16_t w;
1327
1328	ni->ni_htctlchan = htinfo->hi_ctrlchannel;
1329	ni->ni_ht2ndchan = SM(htinfo->hi_byte1, IEEE80211_HTINFO_2NDCHAN);
1330	w = LE_READ_2(&htinfo->hi_byte2);
1331	ni->ni_htopmode = SM(w, IEEE80211_HTINFO_OPMODE);
1332	w = LE_READ_2(&htinfo->hi_byte45);
1333	ni->ni_htstbc = SM(w, IEEE80211_HTINFO_BASIC_STBCMCS);
1334}
1335
1336/*
1337 * Parse an 802.11n HT info ie and save useful information
1338 * to the node state.  Note this does not effect any state
1339 * changes such as for channel width change.
1340 */
1341void
1342ieee80211_parse_htinfo(struct ieee80211_node *ni, const uint8_t *ie)
1343{
1344	if (ie[0] == IEEE80211_ELEMID_VENDOR)
1345		ie += 4;
1346	htinfo_parse(ni, (const struct ieee80211_ie_htinfo *) ie);
1347}
1348
1349/*
1350 * Handle 11n channel switch.  Use the received HT ie's to
1351 * identify the right channel to use.  If we cannot locate it
1352 * in the channel table then fallback to legacy operation.
1353 * Note that we use this information to identify the node's
1354 * channel only; the caller is responsible for insuring any
1355 * required channel change is done (e.g. in sta mode when
1356 * parsing the contents of a beacon frame).
1357 */
1358static void
1359htinfo_update_chw(struct ieee80211_node *ni, int htflags)
1360{
1361	struct ieee80211com *ic = ni->ni_ic;
1362	struct ieee80211_channel *c;
1363	int chanflags;
1364
1365	chanflags = (ni->ni_chan->ic_flags &~ IEEE80211_CHAN_HT) | htflags;
1366	if (chanflags != ni->ni_chan->ic_flags) {
1367		/* XXX not right for ht40- */
1368		c = ieee80211_find_channel(ic, ni->ni_chan->ic_freq, chanflags);
1369		if (c == NULL && (htflags & IEEE80211_CHAN_HT40)) {
1370			/*
1371			 * No HT40 channel entry in our table; fall back
1372			 * to HT20 operation.  This should not happen.
1373			 */
1374			c = findhtchan(ic, ni->ni_chan, IEEE80211_CHAN_HT20);
1375#if 0
1376			IEEE80211_NOTE(ni->ni_vap,
1377			    IEEE80211_MSG_ASSOC | IEEE80211_MSG_11N, ni,
1378			    "no HT40 channel (freq %u), falling back to HT20",
1379			    ni->ni_chan->ic_freq);
1380#endif
1381			/* XXX stat */
1382		}
1383		if (c != NULL && c != ni->ni_chan) {
1384			IEEE80211_NOTE(ni->ni_vap,
1385			    IEEE80211_MSG_ASSOC | IEEE80211_MSG_11N, ni,
1386			    "switch station to HT%d channel %u/0x%x",
1387			    IEEE80211_IS_CHAN_HT40(c) ? 40 : 20,
1388			    c->ic_freq, c->ic_flags);
1389			ni->ni_chan = c;
1390		}
1391		/* NB: caller responsible for forcing any channel change */
1392	}
1393	/* update node's tx channel width */
1394	ni->ni_chw = IEEE80211_IS_CHAN_HT40(ni->ni_chan)? 40 : 20;
1395}
1396
1397/*
1398 * Update 11n MIMO PS state according to received htcap.
1399 */
1400static __inline int
1401htcap_update_mimo_ps(struct ieee80211_node *ni)
1402{
1403	uint16_t oflags = ni->ni_flags;
1404
1405	switch (ni->ni_htcap & IEEE80211_HTCAP_SMPS) {
1406	case IEEE80211_HTCAP_SMPS_DYNAMIC:
1407		ni->ni_flags |= IEEE80211_NODE_MIMO_PS;
1408		ni->ni_flags |= IEEE80211_NODE_MIMO_RTS;
1409		break;
1410	case IEEE80211_HTCAP_SMPS_ENA:
1411		ni->ni_flags |= IEEE80211_NODE_MIMO_PS;
1412		ni->ni_flags &= ~IEEE80211_NODE_MIMO_RTS;
1413		break;
1414	case IEEE80211_HTCAP_SMPS_OFF:
1415	default:		/* disable on rx of reserved value */
1416		ni->ni_flags &= ~IEEE80211_NODE_MIMO_PS;
1417		ni->ni_flags &= ~IEEE80211_NODE_MIMO_RTS;
1418		break;
1419	}
1420	return (oflags ^ ni->ni_flags);
1421}
1422
1423/*
1424 * Update short GI state according to received htcap
1425 * and local settings.
1426 */
1427static __inline void
1428htcap_update_shortgi(struct ieee80211_node *ni)
1429{
1430	struct ieee80211vap *vap = ni->ni_vap;
1431
1432	ni->ni_flags &= ~(IEEE80211_NODE_SGI20|IEEE80211_NODE_SGI40);
1433	if ((ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) &&
1434	    (vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20))
1435		ni->ni_flags |= IEEE80211_NODE_SGI20;
1436	if ((ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) &&
1437	    (vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40))
1438		ni->ni_flags |= IEEE80211_NODE_SGI40;
1439}
1440
1441/*
1442 * Parse and update HT-related state extracted from
1443 * the HT cap and info ie's.
1444 */
1445void
1446ieee80211_ht_updateparams(struct ieee80211_node *ni,
1447	const uint8_t *htcapie, const uint8_t *htinfoie)
1448{
1449	struct ieee80211vap *vap = ni->ni_vap;
1450	const struct ieee80211_ie_htinfo *htinfo;
1451	int htflags;
1452
1453	ieee80211_parse_htcap(ni, htcapie);
1454	if (vap->iv_htcaps & IEEE80211_HTCAP_SMPS)
1455		htcap_update_mimo_ps(ni);
1456	htcap_update_shortgi(ni);
1457
1458	if (htinfoie[0] == IEEE80211_ELEMID_VENDOR)
1459		htinfoie += 4;
1460	htinfo = (const struct ieee80211_ie_htinfo *) htinfoie;
1461	htinfo_parse(ni, htinfo);
1462
1463	htflags = (vap->iv_flags_ht & IEEE80211_FHT_HT) ?
1464	    IEEE80211_CHAN_HT20 : 0;
1465	/* NB: honor operating mode constraint */
1466	if ((htinfo->hi_byte1 & IEEE80211_HTINFO_TXWIDTH_2040) &&
1467	    (vap->iv_flags_ht & IEEE80211_FHT_USEHT40)) {
1468		if (ni->ni_ht2ndchan == IEEE80211_HTINFO_2NDCHAN_ABOVE)
1469			htflags = IEEE80211_CHAN_HT40U;
1470		else if (ni->ni_ht2ndchan == IEEE80211_HTINFO_2NDCHAN_BELOW)
1471			htflags = IEEE80211_CHAN_HT40D;
1472	}
1473	htinfo_update_chw(ni, htflags);
1474
1475	if ((htinfo->hi_byte1 & IEEE80211_HTINFO_RIFSMODE_PERM) &&
1476	    (vap->iv_flags_ht & IEEE80211_FHT_RIFS))
1477		ni->ni_flags |= IEEE80211_NODE_RIFS;
1478	else
1479		ni->ni_flags &= ~IEEE80211_NODE_RIFS;
1480}
1481
1482/*
1483 * Parse and update HT-related state extracted from the HT cap ie
1484 * for a station joining an HT BSS.
1485 */
1486void
1487ieee80211_ht_updatehtcap(struct ieee80211_node *ni, const uint8_t *htcapie)
1488{
1489	struct ieee80211vap *vap = ni->ni_vap;
1490	int htflags;
1491
1492	ieee80211_parse_htcap(ni, htcapie);
1493	if (vap->iv_htcaps & IEEE80211_HTCAP_SMPS)
1494		htcap_update_mimo_ps(ni);
1495	htcap_update_shortgi(ni);
1496
1497	/* NB: honor operating mode constraint */
1498	/* XXX 40 MHZ intolerant */
1499	htflags = (vap->iv_flags_ht & IEEE80211_FHT_HT) ?
1500	    IEEE80211_CHAN_HT20 : 0;
1501	if ((ni->ni_htcap & IEEE80211_HTCAP_CHWIDTH40) &&
1502	    (vap->iv_flags_ht & IEEE80211_FHT_USEHT40)) {
1503		if (IEEE80211_IS_CHAN_HT40U(vap->iv_bss->ni_chan))
1504			htflags = IEEE80211_CHAN_HT40U;
1505		else if (IEEE80211_IS_CHAN_HT40D(vap->iv_bss->ni_chan))
1506			htflags = IEEE80211_CHAN_HT40D;
1507	}
1508	htinfo_update_chw(ni, htflags);
1509}
1510
1511/*
1512 * Install received HT rate set by parsing the HT cap ie.
1513 */
1514int
1515ieee80211_setup_htrates(struct ieee80211_node *ni, const uint8_t *ie, int flags)
1516{
1517	struct ieee80211vap *vap = ni->ni_vap;
1518	const struct ieee80211_ie_htcap *htcap;
1519	struct ieee80211_htrateset *rs;
1520	int i;
1521
1522	rs = &ni->ni_htrates;
1523	memset(rs, 0, sizeof(*rs));
1524	if (ie != NULL) {
1525		if (ie[0] == IEEE80211_ELEMID_VENDOR)
1526			ie += 4;
1527		htcap = (const struct ieee80211_ie_htcap *) ie;
1528		for (i = 0; i < IEEE80211_HTRATE_MAXSIZE; i++) {
1529			if (isclr(htcap->hc_mcsset, i))
1530				continue;
1531			if (rs->rs_nrates == IEEE80211_HTRATE_MAXSIZE) {
1532				IEEE80211_NOTE(vap,
1533				    IEEE80211_MSG_XRATE | IEEE80211_MSG_11N, ni,
1534				    "WARNING, HT rate set too large; only "
1535				    "using %u rates", IEEE80211_HTRATE_MAXSIZE);
1536				vap->iv_stats.is_rx_rstoobig++;
1537				break;
1538			}
1539			rs->rs_rates[rs->rs_nrates++] = i;
1540		}
1541	}
1542	return ieee80211_fix_rate(ni, (struct ieee80211_rateset *) rs, flags);
1543}
1544
1545/*
1546 * Mark rates in a node's HT rate set as basic according
1547 * to the information in the supplied HT info ie.
1548 */
1549void
1550ieee80211_setup_basic_htrates(struct ieee80211_node *ni, const uint8_t *ie)
1551{
1552	const struct ieee80211_ie_htinfo *htinfo;
1553	struct ieee80211_htrateset *rs;
1554	int i, j;
1555
1556	if (ie[0] == IEEE80211_ELEMID_VENDOR)
1557		ie += 4;
1558	htinfo = (const struct ieee80211_ie_htinfo *) ie;
1559	rs = &ni->ni_htrates;
1560	if (rs->rs_nrates == 0) {
1561		IEEE80211_NOTE(ni->ni_vap,
1562		    IEEE80211_MSG_XRATE | IEEE80211_MSG_11N, ni,
1563		    "%s", "WARNING, empty HT rate set");
1564		return;
1565	}
1566	for (i = 0; i < IEEE80211_HTRATE_MAXSIZE; i++) {
1567		if (isclr(htinfo->hi_basicmcsset, i))
1568			continue;
1569		for (j = 0; j < rs->rs_nrates; j++)
1570			if ((rs->rs_rates[j] & IEEE80211_RATE_VAL) == i)
1571				rs->rs_rates[j] |= IEEE80211_RATE_BASIC;
1572	}
1573}
1574
1575static void
1576ampdu_tx_setup(struct ieee80211_tx_ampdu *tap)
1577{
1578	callout_init(&tap->txa_timer, CALLOUT_MPSAFE);
1579	tap->txa_flags |= IEEE80211_AGGR_SETUP;
1580}
1581
1582static void
1583ampdu_tx_stop(struct ieee80211_tx_ampdu *tap)
1584{
1585	struct ieee80211_node *ni = tap->txa_ni;
1586	struct ieee80211com *ic = ni->ni_ic;
1587
1588	KASSERT(tap->txa_flags & IEEE80211_AGGR_SETUP,
1589	    ("txa_flags 0x%x ac %d", tap->txa_flags, tap->txa_ac));
1590
1591	/*
1592	 * Stop BA stream if setup so driver has a chance
1593	 * to reclaim any resources it might have allocated.
1594	 */
1595	ic->ic_addba_stop(ni, tap);
1596	/*
1597	 * Stop any pending BAR transmit.
1598	 */
1599	bar_stop_timer(tap);
1600
1601	tap->txa_lastsample = 0;
1602	tap->txa_avgpps = 0;
1603	/* NB: clearing NAK means we may re-send ADDBA */
1604	tap->txa_flags &= ~(IEEE80211_AGGR_SETUP | IEEE80211_AGGR_NAK);
1605}
1606
1607static void
1608addba_timeout(void *arg)
1609{
1610	struct ieee80211_tx_ampdu *tap = arg;
1611
1612	/* XXX ? */
1613	tap->txa_flags &= ~IEEE80211_AGGR_XCHGPEND;
1614	tap->txa_attempts++;
1615}
1616
1617static void
1618addba_start_timeout(struct ieee80211_tx_ampdu *tap)
1619{
1620	/* XXX use CALLOUT_PENDING instead? */
1621	callout_reset(&tap->txa_timer, ieee80211_addba_timeout,
1622	    addba_timeout, tap);
1623	tap->txa_flags |= IEEE80211_AGGR_XCHGPEND;
1624	tap->txa_nextrequest = ticks + ieee80211_addba_timeout;
1625}
1626
1627static void
1628addba_stop_timeout(struct ieee80211_tx_ampdu *tap)
1629{
1630	/* XXX use CALLOUT_PENDING instead? */
1631	if (tap->txa_flags & IEEE80211_AGGR_XCHGPEND) {
1632		callout_stop(&tap->txa_timer);
1633		tap->txa_flags &= ~IEEE80211_AGGR_XCHGPEND;
1634	}
1635}
1636
1637/*
1638 * Default method for requesting A-MPDU tx aggregation.
1639 * We setup the specified state block and start a timer
1640 * to wait for an ADDBA response frame.
1641 */
1642static int
1643ieee80211_addba_request(struct ieee80211_node *ni,
1644	struct ieee80211_tx_ampdu *tap,
1645	int dialogtoken, int baparamset, int batimeout)
1646{
1647	int bufsiz;
1648
1649	/* XXX locking */
1650	tap->txa_token = dialogtoken;
1651	tap->txa_flags |= IEEE80211_AGGR_IMMEDIATE;
1652	bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ);
1653	tap->txa_wnd = (bufsiz == 0) ?
1654	    IEEE80211_AGGR_BAWMAX : min(bufsiz, IEEE80211_AGGR_BAWMAX);
1655	addba_start_timeout(tap);
1656	return 1;
1657}
1658
1659/*
1660 * Default method for processing an A-MPDU tx aggregation
1661 * response.  We shutdown any pending timer and update the
1662 * state block according to the reply.
1663 */
1664static int
1665ieee80211_addba_response(struct ieee80211_node *ni,
1666	struct ieee80211_tx_ampdu *tap,
1667	int status, int baparamset, int batimeout)
1668{
1669	int bufsiz, tid;
1670
1671	/* XXX locking */
1672	addba_stop_timeout(tap);
1673	if (status == IEEE80211_STATUS_SUCCESS) {
1674		bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ);
1675		/* XXX override our request? */
1676		tap->txa_wnd = (bufsiz == 0) ?
1677		    IEEE80211_AGGR_BAWMAX : min(bufsiz, IEEE80211_AGGR_BAWMAX);
1678		/* XXX AC/TID */
1679		tid = MS(baparamset, IEEE80211_BAPS_TID);
1680		tap->txa_flags |= IEEE80211_AGGR_RUNNING;
1681		tap->txa_attempts = 0;
1682	} else {
1683		/* mark tid so we don't try again */
1684		tap->txa_flags |= IEEE80211_AGGR_NAK;
1685	}
1686	return 1;
1687}
1688
1689/*
1690 * Default method for stopping A-MPDU tx aggregation.
1691 * Any timer is cleared and we drain any pending frames.
1692 */
1693static void
1694ieee80211_addba_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
1695{
1696	/* XXX locking */
1697	addba_stop_timeout(tap);
1698	if (tap->txa_flags & IEEE80211_AGGR_RUNNING) {
1699		/* XXX clear aggregation queue */
1700		tap->txa_flags &= ~IEEE80211_AGGR_RUNNING;
1701	}
1702	tap->txa_attempts = 0;
1703}
1704
1705/*
1706 * Process a received action frame using the default aggregation
1707 * policy.  We intercept ADDBA-related frames and use them to
1708 * update our aggregation state.  All other frames are passed up
1709 * for processing by ieee80211_recv_action.
1710 */
1711static int
1712ht_recv_action_ba_addba_request(struct ieee80211_node *ni,
1713	const struct ieee80211_frame *wh,
1714	const uint8_t *frm, const uint8_t *efrm)
1715{
1716	struct ieee80211com *ic = ni->ni_ic;
1717	struct ieee80211vap *vap = ni->ni_vap;
1718	struct ieee80211_rx_ampdu *rap;
1719	uint8_t dialogtoken;
1720	uint16_t baparamset, batimeout, baseqctl;
1721	uint16_t args[5];
1722	int tid;
1723
1724	dialogtoken = frm[2];
1725	baparamset = LE_READ_2(frm+3);
1726	batimeout = LE_READ_2(frm+5);
1727	baseqctl = LE_READ_2(frm+7);
1728
1729	tid = MS(baparamset, IEEE80211_BAPS_TID);
1730
1731	IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
1732	    "recv ADDBA request: dialogtoken %u baparamset 0x%x "
1733	    "(tid %d bufsiz %d) batimeout %d baseqctl %d:%d",
1734	    dialogtoken, baparamset,
1735	    tid, MS(baparamset, IEEE80211_BAPS_BUFSIZ),
1736	    batimeout,
1737	    MS(baseqctl, IEEE80211_BASEQ_START),
1738	    MS(baseqctl, IEEE80211_BASEQ_FRAG));
1739
1740	rap = &ni->ni_rx_ampdu[tid];
1741
1742	/* Send ADDBA response */
1743	args[0] = dialogtoken;
1744	/*
1745	 * NB: We ack only if the sta associated with HT and
1746	 * the ap is configured to do AMPDU rx (the latter
1747	 * violates the 11n spec and is mostly for testing).
1748	 */
1749	if ((ni->ni_flags & IEEE80211_NODE_AMPDU_RX) &&
1750	    (vap->iv_flags_ht & IEEE80211_FHT_AMPDU_RX)) {
1751		/* XXX handle ampdu_rx_start failure */
1752		ic->ic_ampdu_rx_start(ni, rap,
1753		    baparamset, batimeout, baseqctl);
1754
1755		args[1] = IEEE80211_STATUS_SUCCESS;
1756	} else {
1757		IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
1758		    ni, "reject ADDBA request: %s",
1759		    ni->ni_flags & IEEE80211_NODE_AMPDU_RX ?
1760		       "administratively disabled" :
1761		       "not negotiated for station");
1762		vap->iv_stats.is_addba_reject++;
1763		args[1] = IEEE80211_STATUS_UNSPECIFIED;
1764	}
1765	/* XXX honor rap flags? */
1766	args[2] = IEEE80211_BAPS_POLICY_IMMEDIATE
1767		| SM(tid, IEEE80211_BAPS_TID)
1768		| SM(rap->rxa_wnd, IEEE80211_BAPS_BUFSIZ)
1769		;
1770	args[3] = 0;
1771	args[4] = 0;
1772	ic->ic_send_action(ni, IEEE80211_ACTION_CAT_BA,
1773		IEEE80211_ACTION_BA_ADDBA_RESPONSE, args);
1774	return 0;
1775}
1776
1777static int
1778ht_recv_action_ba_addba_response(struct ieee80211_node *ni,
1779	const struct ieee80211_frame *wh,
1780	const uint8_t *frm, const uint8_t *efrm)
1781{
1782	struct ieee80211com *ic = ni->ni_ic;
1783	struct ieee80211vap *vap = ni->ni_vap;
1784	struct ieee80211_tx_ampdu *tap;
1785	uint8_t dialogtoken, policy;
1786	uint16_t baparamset, batimeout, code;
1787	int tid, ac, bufsiz;
1788
1789	dialogtoken = frm[2];
1790	code = LE_READ_2(frm+3);
1791	baparamset = LE_READ_2(frm+5);
1792	tid = MS(baparamset, IEEE80211_BAPS_TID);
1793	bufsiz = MS(baparamset, IEEE80211_BAPS_BUFSIZ);
1794	policy = MS(baparamset, IEEE80211_BAPS_POLICY);
1795	batimeout = LE_READ_2(frm+7);
1796
1797	ac = TID_TO_WME_AC(tid);
1798	tap = &ni->ni_tx_ampdu[ac];
1799	if ((tap->txa_flags & IEEE80211_AGGR_XCHGPEND) == 0) {
1800		IEEE80211_DISCARD_MAC(vap,
1801		    IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
1802		    ni->ni_macaddr, "ADDBA response",
1803		    "no pending ADDBA, tid %d dialogtoken %u "
1804		    "code %d", tid, dialogtoken, code);
1805		vap->iv_stats.is_addba_norequest++;
1806		return 0;
1807	}
1808	if (dialogtoken != tap->txa_token) {
1809		IEEE80211_DISCARD_MAC(vap,
1810		    IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
1811		    ni->ni_macaddr, "ADDBA response",
1812		    "dialogtoken mismatch: waiting for %d, "
1813		    "received %d, tid %d code %d",
1814		    tap->txa_token, dialogtoken, tid, code);
1815		vap->iv_stats.is_addba_badtoken++;
1816		return 0;
1817	}
1818	/* NB: assumes IEEE80211_AGGR_IMMEDIATE is 1 */
1819	if (policy != (tap->txa_flags & IEEE80211_AGGR_IMMEDIATE)) {
1820		IEEE80211_DISCARD_MAC(vap,
1821		    IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
1822		    ni->ni_macaddr, "ADDBA response",
1823		    "policy mismatch: expecting %s, "
1824		    "received %s, tid %d code %d",
1825		    tap->txa_flags & IEEE80211_AGGR_IMMEDIATE,
1826		    policy, tid, code);
1827		vap->iv_stats.is_addba_badpolicy++;
1828		return 0;
1829	}
1830#if 0
1831	/* XXX we take MIN in ieee80211_addba_response */
1832	if (bufsiz > IEEE80211_AGGR_BAWMAX) {
1833		IEEE80211_DISCARD_MAC(vap,
1834		    IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
1835		    ni->ni_macaddr, "ADDBA response",
1836		    "BA window too large: max %d, "
1837		    "received %d, tid %d code %d",
1838		    bufsiz, IEEE80211_AGGR_BAWMAX, tid, code);
1839		vap->iv_stats.is_addba_badbawinsize++;
1840		return 0;
1841	}
1842#endif
1843	IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
1844	    "recv ADDBA response: dialogtoken %u code %d "
1845	    "baparamset 0x%x (tid %d bufsiz %d) batimeout %d",
1846	    dialogtoken, code, baparamset, tid, bufsiz,
1847	    batimeout);
1848	ic->ic_addba_response(ni, tap, code, baparamset, batimeout);
1849	return 0;
1850}
1851
1852static int
1853ht_recv_action_ba_delba(struct ieee80211_node *ni,
1854	const struct ieee80211_frame *wh,
1855	const uint8_t *frm, const uint8_t *efrm)
1856{
1857	struct ieee80211com *ic = ni->ni_ic;
1858	struct ieee80211_rx_ampdu *rap;
1859	struct ieee80211_tx_ampdu *tap;
1860	uint16_t baparamset, code;
1861	int tid, ac;
1862
1863	baparamset = LE_READ_2(frm+2);
1864	code = LE_READ_2(frm+4);
1865
1866	tid = MS(baparamset, IEEE80211_DELBAPS_TID);
1867
1868	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
1869	    "recv DELBA: baparamset 0x%x (tid %d initiator %d) "
1870	    "code %d", baparamset, tid,
1871	    MS(baparamset, IEEE80211_DELBAPS_INIT), code);
1872
1873	if ((baparamset & IEEE80211_DELBAPS_INIT) == 0) {
1874		ac = TID_TO_WME_AC(tid);
1875		tap = &ni->ni_tx_ampdu[ac];
1876		ic->ic_addba_stop(ni, tap);
1877	} else {
1878		rap = &ni->ni_rx_ampdu[tid];
1879		ic->ic_ampdu_rx_stop(ni, rap);
1880	}
1881	return 0;
1882}
1883
1884static int
1885ht_recv_action_ht_txchwidth(struct ieee80211_node *ni,
1886	const struct ieee80211_frame *wh,
1887	const uint8_t *frm, const uint8_t *efrm)
1888{
1889	int chw;
1890
1891	chw = (frm[2] == IEEE80211_A_HT_TXCHWIDTH_2040) ? 40 : 20;
1892
1893	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
1894	    "%s: HT txchwidth, width %d%s",
1895	    __func__, chw, ni->ni_chw != chw ? "*" : "");
1896	if (chw != ni->ni_chw) {
1897		ni->ni_chw = chw;
1898		/* XXX notify on change */
1899	}
1900	return 0;
1901}
1902
1903static int
1904ht_recv_action_ht_mimopwrsave(struct ieee80211_node *ni,
1905	const struct ieee80211_frame *wh,
1906	const uint8_t *frm, const uint8_t *efrm)
1907{
1908	const struct ieee80211_action_ht_mimopowersave *mps =
1909	    (const struct ieee80211_action_ht_mimopowersave *) frm;
1910
1911	/* XXX check iv_htcaps */
1912	if (mps->am_control & IEEE80211_A_HT_MIMOPWRSAVE_ENA)
1913		ni->ni_flags |= IEEE80211_NODE_MIMO_PS;
1914	else
1915		ni->ni_flags &= ~IEEE80211_NODE_MIMO_PS;
1916	if (mps->am_control & IEEE80211_A_HT_MIMOPWRSAVE_MODE)
1917		ni->ni_flags |= IEEE80211_NODE_MIMO_RTS;
1918	else
1919		ni->ni_flags &= ~IEEE80211_NODE_MIMO_RTS;
1920	/* XXX notify on change */
1921	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
1922	    "%s: HT MIMO PS (%s%s)", __func__,
1923	    (ni->ni_flags & IEEE80211_NODE_MIMO_PS) ?  "on" : "off",
1924	    (ni->ni_flags & IEEE80211_NODE_MIMO_RTS) ?  "+rts" : ""
1925	);
1926	return 0;
1927}
1928
1929/*
1930 * Transmit processing.
1931 */
1932
1933/*
1934 * Check if A-MPDU should be requested/enabled for a stream.
1935 * We require a traffic rate above a per-AC threshold and we
1936 * also handle backoff from previous failed attempts.
1937 *
1938 * Drivers may override this method to bring in information
1939 * such as link state conditions in making the decision.
1940 */
1941static int
1942ieee80211_ampdu_enable(struct ieee80211_node *ni,
1943	struct ieee80211_tx_ampdu *tap)
1944{
1945	struct ieee80211vap *vap = ni->ni_vap;
1946
1947	if (tap->txa_avgpps < vap->iv_ampdu_mintraffic[tap->txa_ac])
1948		return 0;
1949	/* XXX check rssi? */
1950	if (tap->txa_attempts >= ieee80211_addba_maxtries &&
1951	    ticks < tap->txa_nextrequest) {
1952		/*
1953		 * Don't retry too often; txa_nextrequest is set
1954		 * to the minimum interval we'll retry after
1955		 * ieee80211_addba_maxtries failed attempts are made.
1956		 */
1957		return 0;
1958	}
1959	IEEE80211_NOTE(vap, IEEE80211_MSG_11N, ni,
1960	    "enable AMPDU on %s, avgpps %d pkts %d",
1961	    ieee80211_wme_acnames[tap->txa_ac], tap->txa_avgpps, tap->txa_pkts);
1962	return 1;
1963}
1964
1965/*
1966 * Request A-MPDU tx aggregation.  Setup local state and
1967 * issue an ADDBA request.  BA use will only happen after
1968 * the other end replies with ADDBA response.
1969 */
1970int
1971ieee80211_ampdu_request(struct ieee80211_node *ni,
1972	struct ieee80211_tx_ampdu *tap)
1973{
1974	struct ieee80211com *ic = ni->ni_ic;
1975	uint16_t args[5];
1976	int tid, dialogtoken;
1977	static int tokens = 0;	/* XXX */
1978
1979	/* XXX locking */
1980	if ((tap->txa_flags & IEEE80211_AGGR_SETUP) == 0) {
1981		/* do deferred setup of state */
1982		ampdu_tx_setup(tap);
1983	}
1984	/* XXX hack for not doing proper locking */
1985	tap->txa_flags &= ~IEEE80211_AGGR_NAK;
1986
1987	dialogtoken = (tokens+1) % 63;		/* XXX */
1988	tid = WME_AC_TO_TID(tap->txa_ac);
1989	tap->txa_start = ni->ni_txseqs[tid];
1990
1991	args[0] = dialogtoken;
1992	args[1] = 0;	/* NB: status code not used */
1993	args[2]	= IEEE80211_BAPS_POLICY_IMMEDIATE
1994		| SM(tid, IEEE80211_BAPS_TID)
1995		| SM(IEEE80211_AGGR_BAWMAX, IEEE80211_BAPS_BUFSIZ)
1996		;
1997	args[3] = 0;	/* batimeout */
1998	/* NB: do first so there's no race against reply */
1999	if (!ic->ic_addba_request(ni, tap, dialogtoken, args[2], args[3])) {
2000		/* unable to setup state, don't make request */
2001		IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
2002		    ni, "%s: could not setup BA stream for AC %d",
2003		    __func__, tap->txa_ac);
2004		/* defer next try so we don't slam the driver with requests */
2005		tap->txa_attempts = ieee80211_addba_maxtries;
2006		/* NB: check in case driver wants to override */
2007		if (tap->txa_nextrequest <= ticks)
2008			tap->txa_nextrequest = ticks + ieee80211_addba_backoff;
2009		return 0;
2010	}
2011	tokens = dialogtoken;			/* allocate token */
2012	/* NB: after calling ic_addba_request so driver can set txa_start */
2013	args[4] = SM(tap->txa_start, IEEE80211_BASEQ_START)
2014		| SM(0, IEEE80211_BASEQ_FRAG)
2015		;
2016	return ic->ic_send_action(ni, IEEE80211_ACTION_CAT_BA,
2017		IEEE80211_ACTION_BA_ADDBA_REQUEST, args);
2018}
2019
2020/*
2021 * Terminate an AMPDU tx stream.  State is reclaimed
2022 * and the peer notified with a DelBA Action frame.
2023 */
2024void
2025ieee80211_ampdu_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
2026	int reason)
2027{
2028	struct ieee80211com *ic = ni->ni_ic;
2029	struct ieee80211vap *vap = ni->ni_vap;
2030	uint16_t args[4];
2031
2032	/* XXX locking */
2033	tap->txa_flags &= ~IEEE80211_AGGR_BARPEND;
2034	if (IEEE80211_AMPDU_RUNNING(tap)) {
2035		IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
2036		    ni, "%s: stop BA stream for AC %d (reason %d)",
2037		    __func__, tap->txa_ac, reason);
2038		vap->iv_stats.is_ampdu_stop++;
2039
2040		ic->ic_addba_stop(ni, tap);
2041		args[0] = WME_AC_TO_TID(tap->txa_ac);
2042		args[1] = IEEE80211_DELBAPS_INIT;
2043		args[2] = reason;			/* XXX reason code */
2044		ic->ic_send_action(ni, IEEE80211_ACTION_CAT_BA,
2045			IEEE80211_ACTION_BA_DELBA, args);
2046	} else {
2047		IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
2048		    ni, "%s: BA stream for AC %d not running (reason %d)",
2049		    __func__, tap->txa_ac, reason);
2050		vap->iv_stats.is_ampdu_stop_failed++;
2051	}
2052}
2053
2054static void
2055bar_timeout(void *arg)
2056{
2057	struct ieee80211_tx_ampdu *tap = arg;
2058	struct ieee80211_node *ni = tap->txa_ni;
2059
2060	KASSERT((tap->txa_flags & IEEE80211_AGGR_XCHGPEND) == 0,
2061	    ("bar/addba collision, flags 0x%x", tap->txa_flags));
2062
2063	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
2064	    ni, "%s: tid %u flags 0x%x attempts %d", __func__,
2065	    tap->txa_ac, tap->txa_flags, tap->txa_attempts);
2066
2067	/* guard against race with bar_tx_complete */
2068	if ((tap->txa_flags & IEEE80211_AGGR_BARPEND) == 0)
2069		return;
2070	/* XXX ? */
2071	if (tap->txa_attempts >= ieee80211_bar_maxtries)
2072		ieee80211_ampdu_stop(ni, tap, IEEE80211_REASON_TIMEOUT);
2073	else
2074		ieee80211_send_bar(ni, tap, tap->txa_seqpending);
2075}
2076
2077static void
2078bar_start_timer(struct ieee80211_tx_ampdu *tap)
2079{
2080	callout_reset(&tap->txa_timer, ieee80211_bar_timeout, bar_timeout, tap);
2081}
2082
2083static void
2084bar_stop_timer(struct ieee80211_tx_ampdu *tap)
2085{
2086	callout_stop(&tap->txa_timer);
2087}
2088
2089static void
2090bar_tx_complete(struct ieee80211_node *ni, void *arg, int status)
2091{
2092	struct ieee80211_tx_ampdu *tap = arg;
2093
2094	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
2095	    ni, "%s: tid %u flags 0x%x pending %d status %d",
2096	    __func__, tap->txa_ac, tap->txa_flags,
2097	    callout_pending(&tap->txa_timer), status);
2098
2099	/* XXX locking */
2100	if ((tap->txa_flags & IEEE80211_AGGR_BARPEND) &&
2101	    callout_pending(&tap->txa_timer)) {
2102		struct ieee80211com *ic = ni->ni_ic;
2103
2104		if (status)		/* ACK'd */
2105			bar_stop_timer(tap);
2106		ic->ic_bar_response(ni, tap, status);
2107		/* NB: just let timer expire so we pace requests */
2108	}
2109}
2110
2111static void
2112ieee80211_bar_response(struct ieee80211_node *ni,
2113	struct ieee80211_tx_ampdu *tap, int status)
2114{
2115
2116	if (status != 0) {		/* got ACK */
2117		IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
2118		    ni, "BAR moves BA win <%u:%u> (%u frames) txseq %u tid %u",
2119		    tap->txa_start,
2120		    IEEE80211_SEQ_ADD(tap->txa_start, tap->txa_wnd-1),
2121		    tap->txa_qframes, tap->txa_seqpending,
2122		    WME_AC_TO_TID(tap->txa_ac));
2123
2124		/* NB: timer already stopped in bar_tx_complete */
2125		tap->txa_start = tap->txa_seqpending;
2126		tap->txa_flags &= ~IEEE80211_AGGR_BARPEND;
2127	}
2128}
2129
2130/*
2131 * Transmit a BAR frame to the specified node.  The
2132 * BAR contents are drawn from the supplied aggregation
2133 * state associated with the node.
2134 *
2135 * NB: we only handle immediate ACK w/ compressed bitmap.
2136 */
2137int
2138ieee80211_send_bar(struct ieee80211_node *ni,
2139	struct ieee80211_tx_ampdu *tap, ieee80211_seq seq)
2140{
2141#define	senderr(_x, _v)	do { vap->iv_stats._v++; ret = _x; goto bad; } while (0)
2142	struct ieee80211vap *vap = ni->ni_vap;
2143	struct ieee80211com *ic = ni->ni_ic;
2144	struct ieee80211_frame_bar *bar;
2145	struct mbuf *m;
2146	uint16_t barctl, barseqctl;
2147	uint8_t *frm;
2148	int tid, ret;
2149
2150	if ((tap->txa_flags & IEEE80211_AGGR_RUNNING) == 0) {
2151		/* no ADDBA response, should not happen */
2152		/* XXX stat+msg */
2153		return EINVAL;
2154	}
2155	/* XXX locking */
2156	bar_stop_timer(tap);
2157
2158	ieee80211_ref_node(ni);
2159
2160	m = ieee80211_getmgtframe(&frm, ic->ic_headroom, sizeof(*bar));
2161	if (m == NULL)
2162		senderr(ENOMEM, is_tx_nobuf);
2163
2164	if (!ieee80211_add_callback(m, bar_tx_complete, tap)) {
2165		m_freem(m);
2166		senderr(ENOMEM, is_tx_nobuf);	/* XXX */
2167		/* NOTREACHED */
2168	}
2169
2170	bar = mtod(m, struct ieee80211_frame_bar *);
2171	bar->i_fc[0] = IEEE80211_FC0_VERSION_0 |
2172		IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_BAR;
2173	bar->i_fc[1] = 0;
2174	IEEE80211_ADDR_COPY(bar->i_ra, ni->ni_macaddr);
2175	IEEE80211_ADDR_COPY(bar->i_ta, vap->iv_myaddr);
2176
2177	tid = WME_AC_TO_TID(tap->txa_ac);
2178	barctl 	= (tap->txa_flags & IEEE80211_AGGR_IMMEDIATE ?
2179			0 : IEEE80211_BAR_NOACK)
2180		| IEEE80211_BAR_COMP
2181		| SM(tid, IEEE80211_BAR_TID)
2182		;
2183	barseqctl = SM(seq, IEEE80211_BAR_SEQ_START);
2184	/* NB: known to have proper alignment */
2185	bar->i_ctl = htole16(barctl);
2186	bar->i_seq = htole16(barseqctl);
2187	m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame_bar);
2188
2189	M_WME_SETAC(m, WME_AC_VO);
2190
2191	IEEE80211_NODE_STAT(ni, tx_mgmt);	/* XXX tx_ctl? */
2192
2193	/* XXX locking */
2194	/* init/bump attempts counter */
2195	if ((tap->txa_flags & IEEE80211_AGGR_BARPEND) == 0)
2196		tap->txa_attempts = 1;
2197	else
2198		tap->txa_attempts++;
2199	tap->txa_seqpending = seq;
2200	tap->txa_flags |= IEEE80211_AGGR_BARPEND;
2201
2202	IEEE80211_NOTE(vap, IEEE80211_MSG_DEBUG | IEEE80211_MSG_11N,
2203	    ni, "send BAR: tid %u ctl 0x%x start %u (attempt %d)",
2204	    tid, barctl, seq, tap->txa_attempts);
2205
2206	ret = ic->ic_raw_xmit(ni, m, NULL);
2207	if (ret != 0) {
2208		/* xmit failed, clear state flag */
2209		tap->txa_flags &= ~IEEE80211_AGGR_BARPEND;
2210		goto bad;
2211	}
2212	/* XXX hack against tx complete happening before timer is started */
2213	if (tap->txa_flags & IEEE80211_AGGR_BARPEND)
2214		bar_start_timer(tap);
2215	return 0;
2216bad:
2217	ieee80211_free_node(ni);
2218	return ret;
2219#undef senderr
2220}
2221
2222static int
2223ht_action_output(struct ieee80211_node *ni, struct mbuf *m)
2224{
2225	struct ieee80211_bpf_params params;
2226
2227	memset(&params, 0, sizeof(params));
2228	params.ibp_pri = WME_AC_VO;
2229	params.ibp_rate0 = ni->ni_txparms->mgmtrate;
2230	/* NB: we know all frames are unicast */
2231	params.ibp_try0 = ni->ni_txparms->maxretry;
2232	params.ibp_power = ni->ni_txpower;
2233	return ieee80211_mgmt_output(ni, m, IEEE80211_FC0_SUBTYPE_ACTION,
2234	     &params);
2235}
2236
2237#define	ADDSHORT(frm, v) do {			\
2238	frm[0] = (v) & 0xff;			\
2239	frm[1] = (v) >> 8;			\
2240	frm += 2;				\
2241} while (0)
2242
2243/*
2244 * Send an action management frame.  The arguments are stuff
2245 * into a frame without inspection; the caller is assumed to
2246 * prepare them carefully (e.g. based on the aggregation state).
2247 */
2248static int
2249ht_send_action_ba_addba(struct ieee80211_node *ni,
2250	int category, int action, void *arg0)
2251{
2252	struct ieee80211vap *vap = ni->ni_vap;
2253	struct ieee80211com *ic = ni->ni_ic;
2254	uint16_t *args = arg0;
2255	struct mbuf *m;
2256	uint8_t *frm;
2257
2258	IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
2259	    "send ADDBA %s: dialogtoken %d status %d "
2260	    "baparamset 0x%x (tid %d) batimeout 0x%x baseqctl 0x%x",
2261	    (action == IEEE80211_ACTION_BA_ADDBA_REQUEST) ?
2262		"request" : "response",
2263	    args[0], args[1], args[2], MS(args[2], IEEE80211_BAPS_TID),
2264	    args[3], args[4]);
2265
2266	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
2267	    "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
2268	    ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
2269	ieee80211_ref_node(ni);
2270
2271	m = ieee80211_getmgtframe(&frm,
2272	    ic->ic_headroom + sizeof(struct ieee80211_frame),
2273	    sizeof(uint16_t)	/* action+category */
2274	    /* XXX may action payload */
2275	    + sizeof(struct ieee80211_action_ba_addbaresponse)
2276	);
2277	if (m != NULL) {
2278		*frm++ = category;
2279		*frm++ = action;
2280		*frm++ = args[0];		/* dialog token */
2281		if (action == IEEE80211_ACTION_BA_ADDBA_RESPONSE)
2282			ADDSHORT(frm, args[1]);	/* status code */
2283		ADDSHORT(frm, args[2]);		/* baparamset */
2284		ADDSHORT(frm, args[3]);		/* batimeout */
2285		if (action == IEEE80211_ACTION_BA_ADDBA_REQUEST)
2286			ADDSHORT(frm, args[4]);	/* baseqctl */
2287		m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
2288		return ht_action_output(ni, m);
2289	} else {
2290		vap->iv_stats.is_tx_nobuf++;
2291		ieee80211_free_node(ni);
2292		return ENOMEM;
2293	}
2294}
2295
2296static int
2297ht_send_action_ba_delba(struct ieee80211_node *ni,
2298	int category, int action, void *arg0)
2299{
2300	struct ieee80211vap *vap = ni->ni_vap;
2301	struct ieee80211com *ic = ni->ni_ic;
2302	uint16_t *args = arg0;
2303	struct mbuf *m;
2304	uint16_t baparamset;
2305	uint8_t *frm;
2306
2307	baparamset = SM(args[0], IEEE80211_DELBAPS_TID)
2308		   | args[1]
2309		   ;
2310	IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
2311	    "send DELBA action: tid %d, initiator %d reason %d",
2312	    args[0], args[1], args[2]);
2313
2314	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
2315	    "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
2316	    ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
2317	ieee80211_ref_node(ni);
2318
2319	m = ieee80211_getmgtframe(&frm,
2320	    ic->ic_headroom + sizeof(struct ieee80211_frame),
2321	    sizeof(uint16_t)	/* action+category */
2322	    /* XXX may action payload */
2323	    + sizeof(struct ieee80211_action_ba_addbaresponse)
2324	);
2325	if (m != NULL) {
2326		*frm++ = category;
2327		*frm++ = action;
2328		ADDSHORT(frm, baparamset);
2329		ADDSHORT(frm, args[2]);		/* reason code */
2330		m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
2331		return ht_action_output(ni, m);
2332	} else {
2333		vap->iv_stats.is_tx_nobuf++;
2334		ieee80211_free_node(ni);
2335		return ENOMEM;
2336	}
2337}
2338
2339static int
2340ht_send_action_ht_txchwidth(struct ieee80211_node *ni,
2341	int category, int action, void *arg0)
2342{
2343	struct ieee80211vap *vap = ni->ni_vap;
2344	struct ieee80211com *ic = ni->ni_ic;
2345	struct mbuf *m;
2346	uint8_t *frm;
2347
2348	IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
2349	    "send HT txchwidth: width %d",
2350	    IEEE80211_IS_CHAN_HT40(ni->ni_chan) ? 40 : 20);
2351
2352	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
2353	    "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
2354	    ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
2355	ieee80211_ref_node(ni);
2356
2357	m = ieee80211_getmgtframe(&frm,
2358	    ic->ic_headroom + sizeof(struct ieee80211_frame),
2359	    sizeof(uint16_t)	/* action+category */
2360	    /* XXX may action payload */
2361	    + sizeof(struct ieee80211_action_ba_addbaresponse)
2362	);
2363	if (m != NULL) {
2364		*frm++ = category;
2365		*frm++ = action;
2366		*frm++ = IEEE80211_IS_CHAN_HT40(ni->ni_chan) ?
2367			IEEE80211_A_HT_TXCHWIDTH_2040 :
2368			IEEE80211_A_HT_TXCHWIDTH_20;
2369		m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
2370		return ht_action_output(ni, m);
2371	} else {
2372		vap->iv_stats.is_tx_nobuf++;
2373		ieee80211_free_node(ni);
2374		return ENOMEM;
2375	}
2376}
2377#undef ADDSHORT
2378
2379/*
2380 * Construct the MCS bit mask for inclusion
2381 * in an HT information element.
2382 */
2383static void
2384ieee80211_set_htrates(uint8_t *frm, const struct ieee80211_htrateset *rs)
2385{
2386	int i;
2387
2388	for (i = 0; i < rs->rs_nrates; i++) {
2389		int r = rs->rs_rates[i] & IEEE80211_RATE_VAL;
2390		if (r < IEEE80211_HTRATE_MAXSIZE) {	/* XXX? */
2391			/* NB: this assumes a particular implementation */
2392			setbit(frm, r);
2393		}
2394	}
2395}
2396
2397/*
2398 * Add body of an HTCAP information element.
2399 */
2400static uint8_t *
2401ieee80211_add_htcap_body(uint8_t *frm, struct ieee80211_node *ni)
2402{
2403#define	ADDSHORT(frm, v) do {			\
2404	frm[0] = (v) & 0xff;			\
2405	frm[1] = (v) >> 8;			\
2406	frm += 2;				\
2407} while (0)
2408	struct ieee80211vap *vap = ni->ni_vap;
2409	uint16_t caps, extcaps;
2410	int rxmax, density;
2411
2412	/* HT capabilities */
2413	caps = vap->iv_htcaps & 0xffff;
2414	/*
2415	 * Note channel width depends on whether we are operating as
2416	 * a sta or not.  When operating as a sta we are generating
2417	 * a request based on our desired configuration.  Otherwise
2418	 * we are operational and the channel attributes identify
2419	 * how we've been setup (which might be different if a fixed
2420	 * channel is specified).
2421	 */
2422	if (vap->iv_opmode == IEEE80211_M_STA) {
2423		/* override 20/40 use based on config */
2424		if (vap->iv_flags_ht & IEEE80211_FHT_USEHT40)
2425			caps |= IEEE80211_HTCAP_CHWIDTH40;
2426		else
2427			caps &= ~IEEE80211_HTCAP_CHWIDTH40;
2428		/* use advertised setting (XXX locally constraint) */
2429		rxmax = MS(ni->ni_htparam, IEEE80211_HTCAP_MAXRXAMPDU);
2430		density = MS(ni->ni_htparam, IEEE80211_HTCAP_MPDUDENSITY);
2431	} else {
2432		/* override 20/40 use based on current channel */
2433		if (IEEE80211_IS_CHAN_HT40(ni->ni_chan))
2434			caps |= IEEE80211_HTCAP_CHWIDTH40;
2435		else
2436			caps &= ~IEEE80211_HTCAP_CHWIDTH40;
2437		rxmax = vap->iv_ampdu_rxmax;
2438		density = vap->iv_ampdu_density;
2439	}
2440	/* adjust short GI based on channel and config */
2441	if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20) == 0)
2442		caps &= ~IEEE80211_HTCAP_SHORTGI20;
2443	if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40) == 0 ||
2444	    (caps & IEEE80211_HTCAP_CHWIDTH40) == 0)
2445		caps &= ~IEEE80211_HTCAP_SHORTGI40;
2446	ADDSHORT(frm, caps);
2447
2448	/* HT parameters */
2449	*frm = SM(rxmax, IEEE80211_HTCAP_MAXRXAMPDU)
2450	     | SM(density, IEEE80211_HTCAP_MPDUDENSITY)
2451	     ;
2452	frm++;
2453
2454	/* pre-zero remainder of ie */
2455	memset(frm, 0, sizeof(struct ieee80211_ie_htcap) -
2456		__offsetof(struct ieee80211_ie_htcap, hc_mcsset));
2457
2458	/* supported MCS set */
2459	/*
2460	 * XXX it would better to get the rate set from ni_htrates
2461	 * so we can restrict it but for sta mode ni_htrates isn't
2462	 * setup when we're called to form an AssocReq frame so for
2463	 * now we're restricted to the default HT rate set.
2464	 */
2465	ieee80211_set_htrates(frm, &ieee80211_rateset_11n);
2466
2467	frm += __offsetof(struct ieee80211_ie_htcap, hc_extcap) -
2468		__offsetof(struct ieee80211_ie_htcap, hc_mcsset);
2469
2470	/* HT extended capabilities */
2471	extcaps = vap->iv_htextcaps & 0xffff;
2472
2473	ADDSHORT(frm, extcaps);
2474
2475	frm += sizeof(struct ieee80211_ie_htcap) -
2476		__offsetof(struct ieee80211_ie_htcap, hc_txbf);
2477
2478	return frm;
2479#undef ADDSHORT
2480}
2481
2482/*
2483 * Add 802.11n HT capabilities information element
2484 */
2485uint8_t *
2486ieee80211_add_htcap(uint8_t *frm, struct ieee80211_node *ni)
2487{
2488	frm[0] = IEEE80211_ELEMID_HTCAP;
2489	frm[1] = sizeof(struct ieee80211_ie_htcap) - 2;
2490	return ieee80211_add_htcap_body(frm + 2, ni);
2491}
2492
2493/*
2494 * Add Broadcom OUI wrapped standard HTCAP ie; this is
2495 * used for compatibility w/ pre-draft implementations.
2496 */
2497uint8_t *
2498ieee80211_add_htcap_vendor(uint8_t *frm, struct ieee80211_node *ni)
2499{
2500	frm[0] = IEEE80211_ELEMID_VENDOR;
2501	frm[1] = 4 + sizeof(struct ieee80211_ie_htcap) - 2;
2502	frm[2] = (BCM_OUI >> 0) & 0xff;
2503	frm[3] = (BCM_OUI >> 8) & 0xff;
2504	frm[4] = (BCM_OUI >> 16) & 0xff;
2505	frm[5] = BCM_OUI_HTCAP;
2506	return ieee80211_add_htcap_body(frm + 6, ni);
2507}
2508
2509/*
2510 * Construct the MCS bit mask of basic rates
2511 * for inclusion in an HT information element.
2512 */
2513static void
2514ieee80211_set_basic_htrates(uint8_t *frm, const struct ieee80211_htrateset *rs)
2515{
2516	int i;
2517
2518	for (i = 0; i < rs->rs_nrates; i++) {
2519		int r = rs->rs_rates[i] & IEEE80211_RATE_VAL;
2520		if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) &&
2521		    r < IEEE80211_HTRATE_MAXSIZE) {
2522			/* NB: this assumes a particular implementation */
2523			setbit(frm, r);
2524		}
2525	}
2526}
2527
2528/*
2529 * Update the HTINFO ie for a beacon frame.
2530 */
2531void
2532ieee80211_ht_update_beacon(struct ieee80211vap *vap,
2533	struct ieee80211_beacon_offsets *bo)
2534{
2535#define	PROTMODE	(IEEE80211_HTINFO_OPMODE|IEEE80211_HTINFO_NONHT_PRESENT)
2536	const struct ieee80211_channel *bsschan = vap->iv_bss->ni_chan;
2537	struct ieee80211com *ic = vap->iv_ic;
2538	struct ieee80211_ie_htinfo *ht =
2539	   (struct ieee80211_ie_htinfo *) bo->bo_htinfo;
2540
2541	/* XXX only update on channel change */
2542	ht->hi_ctrlchannel = ieee80211_chan2ieee(ic, bsschan);
2543	if (vap->iv_flags_ht & IEEE80211_FHT_RIFS)
2544		ht->hi_byte1 = IEEE80211_HTINFO_RIFSMODE_PERM;
2545	else
2546		ht->hi_byte1 = IEEE80211_HTINFO_RIFSMODE_PROH;
2547	if (IEEE80211_IS_CHAN_HT40U(bsschan))
2548		ht->hi_byte1 |= IEEE80211_HTINFO_2NDCHAN_ABOVE;
2549	else if (IEEE80211_IS_CHAN_HT40D(bsschan))
2550		ht->hi_byte1 |= IEEE80211_HTINFO_2NDCHAN_BELOW;
2551	else
2552		ht->hi_byte1 |= IEEE80211_HTINFO_2NDCHAN_NONE;
2553	if (IEEE80211_IS_CHAN_HT40(bsschan))
2554		ht->hi_byte1 |= IEEE80211_HTINFO_TXWIDTH_2040;
2555
2556	/* protection mode */
2557	ht->hi_byte2 = (ht->hi_byte2 &~ PROTMODE) | ic->ic_curhtprotmode;
2558
2559	/* XXX propagate to vendor ie's */
2560#undef PROTMODE
2561}
2562
2563/*
2564 * Add body of an HTINFO information element.
2565 *
2566 * NB: We don't use struct ieee80211_ie_htinfo because we can
2567 * be called to fillin both a standard ie and a compat ie that
2568 * has a vendor OUI at the front.
2569 */
2570static uint8_t *
2571ieee80211_add_htinfo_body(uint8_t *frm, struct ieee80211_node *ni)
2572{
2573	struct ieee80211vap *vap = ni->ni_vap;
2574	struct ieee80211com *ic = ni->ni_ic;
2575
2576	/* pre-zero remainder of ie */
2577	memset(frm, 0, sizeof(struct ieee80211_ie_htinfo) - 2);
2578
2579	/* primary/control channel center */
2580	*frm++ = ieee80211_chan2ieee(ic, ni->ni_chan);
2581
2582	if (vap->iv_flags_ht & IEEE80211_FHT_RIFS)
2583		frm[0] = IEEE80211_HTINFO_RIFSMODE_PERM;
2584	else
2585		frm[0] = IEEE80211_HTINFO_RIFSMODE_PROH;
2586	if (IEEE80211_IS_CHAN_HT40U(ni->ni_chan))
2587		frm[0] |= IEEE80211_HTINFO_2NDCHAN_ABOVE;
2588	else if (IEEE80211_IS_CHAN_HT40D(ni->ni_chan))
2589		frm[0] |= IEEE80211_HTINFO_2NDCHAN_BELOW;
2590	else
2591		frm[0] |= IEEE80211_HTINFO_2NDCHAN_NONE;
2592	if (IEEE80211_IS_CHAN_HT40(ni->ni_chan))
2593		frm[0] |= IEEE80211_HTINFO_TXWIDTH_2040;
2594
2595	frm[1] = ic->ic_curhtprotmode;
2596
2597	frm += 5;
2598
2599	/* basic MCS set */
2600	ieee80211_set_basic_htrates(frm, &ni->ni_htrates);
2601	frm += sizeof(struct ieee80211_ie_htinfo) -
2602		__offsetof(struct ieee80211_ie_htinfo, hi_basicmcsset);
2603	return frm;
2604}
2605
2606/*
2607 * Add 802.11n HT information information element.
2608 */
2609uint8_t *
2610ieee80211_add_htinfo(uint8_t *frm, struct ieee80211_node *ni)
2611{
2612	frm[0] = IEEE80211_ELEMID_HTINFO;
2613	frm[1] = sizeof(struct ieee80211_ie_htinfo) - 2;
2614	return ieee80211_add_htinfo_body(frm + 2, ni);
2615}
2616
2617/*
2618 * Add Broadcom OUI wrapped standard HTINFO ie; this is
2619 * used for compatibility w/ pre-draft implementations.
2620 */
2621uint8_t *
2622ieee80211_add_htinfo_vendor(uint8_t *frm, struct ieee80211_node *ni)
2623{
2624	frm[0] = IEEE80211_ELEMID_VENDOR;
2625	frm[1] = 4 + sizeof(struct ieee80211_ie_htinfo) - 2;
2626	frm[2] = (BCM_OUI >> 0) & 0xff;
2627	frm[3] = (BCM_OUI >> 8) & 0xff;
2628	frm[4] = (BCM_OUI >> 16) & 0xff;
2629	frm[5] = BCM_OUI_HTINFO;
2630	return ieee80211_add_htinfo_body(frm + 6, ni);
2631}
2632