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