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