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