The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net80211/ieee80211_ht.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 #ifdef __FreeBSD__
   30 __FBSDID("$FreeBSD$");
   31 #endif
   32 
   33 /*
   34  * IEEE 802.11n protocol support.
   35  */
   36 
   37 #include "opt_inet.h"
   38 #include "opt_wlan.h"
   39 
   40 #include <sys/param.h>
   41 #include <sys/kernel.h>
   42 #include <sys/malloc.h>
   43 #include <sys/systm.h> 
   44 #include <sys/endian.h>
   45 
   46 #include <sys/socket.h>
   47 
   48 #include <net/if.h>
   49 #include <net/if_var.h>
   50 #include <net/if_media.h>
   51 #include <net/ethernet.h>
   52 
   53 #include <net80211/ieee80211_var.h>
   54 #include <net80211/ieee80211_action.h>
   55 #include <net80211/ieee80211_input.h>
   56 
   57 const struct ieee80211_mcs_rates ieee80211_htrates[IEEE80211_HTRATE_MAXSIZE] = {
   58         {  13,  14,   27,   30 },       /* MCS 0 */
   59         {  26,  29,   54,   60 },       /* MCS 1 */
   60         {  39,  43,   81,   90 },       /* MCS 2 */
   61         {  52,  58,  108,  120 },       /* MCS 3 */
   62         {  78,  87,  162,  180 },       /* MCS 4 */
   63         { 104, 116,  216,  240 },       /* MCS 5 */
   64         { 117, 130,  243,  270 },       /* MCS 6 */
   65         { 130, 144,  270,  300 },       /* MCS 7 */
   66         {  26,  29,   54,   60 },       /* MCS 8 */
   67         {  52,  58,  108,  120 },       /* MCS 9 */
   68         {  78,  87,  162,  180 },       /* MCS 10 */
   69         { 104, 116,  216,  240 },       /* MCS 11 */
   70         { 156, 173,  324,  360 },       /* MCS 12 */
   71         { 208, 231,  432,  480 },       /* MCS 13 */
   72         { 234, 260,  486,  540 },       /* MCS 14 */
   73         { 260, 289,  540,  600 },       /* MCS 15 */
   74         {  39,  43,   81,   90 },       /* MCS 16 */
   75         {  78,  87,  162,  180 },       /* MCS 17 */
   76         { 117, 130,  243,  270 },       /* MCS 18 */
   77         { 156, 173,  324,  360 },       /* MCS 19 */
   78         { 234, 260,  486,  540 },       /* MCS 20 */
   79         { 312, 347,  648,  720 },       /* MCS 21 */
   80         { 351, 390,  729,  810 },       /* MCS 22 */
   81         { 390, 433,  810,  900 },       /* MCS 23 */
   82         {  52,  58,  108,  120 },       /* MCS 24 */
   83         { 104, 116,  216,  240 },       /* MCS 25 */
   84         { 156, 173,  324,  360 },       /* MCS 26 */
   85         { 208, 231,  432,  480 },       /* MCS 27 */
   86         { 312, 347,  648,  720 },       /* MCS 28 */
   87         { 416, 462,  864,  960 },       /* MCS 29 */
   88         { 468, 520,  972, 1080 },       /* MCS 30 */
   89         { 520, 578, 1080, 1200 },       /* MCS 31 */
   90         {   0,   0,   12,   13 },       /* MCS 32 */
   91         {  78,  87,  162,  180 },       /* MCS 33 */
   92         { 104, 116,  216,  240 },       /* MCS 34 */
   93         { 130, 144,  270,  300 },       /* MCS 35 */
   94         { 117, 130,  243,  270 },       /* MCS 36 */
   95         { 156, 173,  324,  360 },       /* MCS 37 */
   96         { 195, 217,  405,  450 },       /* MCS 38 */
   97         { 104, 116,  216,  240 },       /* MCS 39 */
   98         { 130, 144,  270,  300 },       /* MCS 40 */
   99         { 130, 144,  270,  300 },       /* MCS 41 */
  100         { 156, 173,  324,  360 },       /* MCS 42 */
  101         { 182, 202,  378,  420 },       /* MCS 43 */
  102         { 182, 202,  378,  420 },       /* MCS 44 */
  103         { 208, 231,  432,  480 },       /* MCS 45 */
  104         { 156, 173,  324,  360 },       /* MCS 46 */
  105         { 195, 217,  405,  450 },       /* MCS 47 */
  106         { 195, 217,  405,  450 },       /* MCS 48 */
  107         { 234, 260,  486,  540 },       /* MCS 49 */
  108         { 273, 303,  567,  630 },       /* MCS 50 */
  109         { 273, 303,  567,  630 },       /* MCS 51 */
  110         { 312, 347,  648,  720 },       /* MCS 52 */
  111         { 130, 144,  270,  300 },       /* MCS 53 */
  112         { 156, 173,  324,  360 },       /* MCS 54 */
  113         { 182, 202,  378,  420 },       /* MCS 55 */
  114         { 156, 173,  324,  360 },       /* MCS 56 */
  115         { 182, 202,  378,  420 },       /* MCS 57 */
  116         { 208, 231,  432,  480 },       /* MCS 58 */
  117         { 234, 260,  486,  540 },       /* MCS 59 */
  118         { 208, 231,  432,  480 },       /* MCS 60 */
  119         { 234, 260,  486,  540 },       /* MCS 61 */
  120         { 260, 289,  540,  600 },       /* MCS 62 */
  121         { 260, 289,  540,  600 },       /* MCS 63 */
  122         { 286, 318,  594,  660 },       /* MCS 64 */
  123         { 195, 217,  405,  450 },       /* MCS 65 */
  124         { 234, 260,  486,  540 },       /* MCS 66 */
  125         { 273, 303,  567,  630 },       /* MCS 67 */
  126         { 234, 260,  486,  540 },       /* MCS 68 */
  127         { 273, 303,  567,  630 },       /* MCS 69 */
  128         { 312, 347,  648,  720 },       /* MCS 70 */
  129         { 351, 390,  729,  810 },       /* MCS 71 */
  130         { 312, 347,  648,  720 },       /* MCS 72 */
  131         { 351, 390,  729,  810 },       /* MCS 73 */
  132         { 390, 433,  810,  900 },       /* MCS 74 */
  133         { 390, 433,  810,  900 },       /* MCS 75 */
  134         { 429, 477,  891,  990 },       /* MCS 76 */
  135 };
  136 
  137 static  int ieee80211_ampdu_age = -1;   /* threshold for ampdu reorder q (ms) */
  138 SYSCTL_PROC(_net_wlan, OID_AUTO, ampdu_age,
  139     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
  140     &ieee80211_ampdu_age, 0, ieee80211_sysctl_msecs_ticks, "I",
  141     "AMPDU max reorder age (ms)");
  142 
  143 static  int ieee80211_recv_bar_ena = 1;
  144 SYSCTL_INT(_net_wlan, OID_AUTO, recv_bar, CTLFLAG_RW, &ieee80211_recv_bar_ena,
  145             0, "BAR frame processing (ena/dis)");
  146 
  147 static  int ieee80211_addba_timeout = -1;/* timeout for ADDBA response */
  148 SYSCTL_PROC(_net_wlan, OID_AUTO, addba_timeout,
  149     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
  150     &ieee80211_addba_timeout, 0, ieee80211_sysctl_msecs_ticks, "I",
  151     "ADDBA request timeout (ms)");
  152 static  int ieee80211_addba_backoff = -1;/* backoff after max ADDBA requests */
  153 SYSCTL_PROC(_net_wlan, OID_AUTO, addba_backoff,
  154     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
  155     &ieee80211_addba_backoff, 0, ieee80211_sysctl_msecs_ticks, "I",
  156     "ADDBA request backoff (ms)");
  157 static  int ieee80211_addba_maxtries = 3;/* max ADDBA requests before backoff */
  158 SYSCTL_INT(_net_wlan, OID_AUTO, addba_maxtries, CTLFLAG_RW,
  159         &ieee80211_addba_maxtries, 0, "max ADDBA requests sent before backoff");
  160 
  161 static  int ieee80211_bar_timeout = -1; /* timeout waiting for BAR response */
  162 static  int ieee80211_bar_maxtries = 50;/* max BAR requests before DELBA */
  163 
  164 static  ieee80211_recv_action_func ht_recv_action_ba_addba_request;
  165 static  ieee80211_recv_action_func ht_recv_action_ba_addba_response;
  166 static  ieee80211_recv_action_func ht_recv_action_ba_delba;
  167 static  ieee80211_recv_action_func ht_recv_action_ht_mimopwrsave;
  168 static  ieee80211_recv_action_func ht_recv_action_ht_txchwidth;
  169 
  170 static  ieee80211_send_action_func ht_send_action_ba_addba;
  171 static  ieee80211_send_action_func ht_send_action_ba_delba;
  172 static  ieee80211_send_action_func ht_send_action_ht_txchwidth;
  173 
  174 static void
  175 ieee80211_ht_init(void)
  176 {
  177         /*
  178          * Setup HT parameters that depends on the clock frequency.
  179          */
  180         ieee80211_ampdu_age = msecs_to_ticks(500);
  181         ieee80211_addba_timeout = msecs_to_ticks(250);
  182         ieee80211_addba_backoff = msecs_to_ticks(10*1000);
  183         ieee80211_bar_timeout = msecs_to_ticks(250);
  184         /*
  185          * Register action frame handlers.
  186          */
  187         ieee80211_recv_action_register(IEEE80211_ACTION_CAT_BA, 
  188             IEEE80211_ACTION_BA_ADDBA_REQUEST, ht_recv_action_ba_addba_request);
  189         ieee80211_recv_action_register(IEEE80211_ACTION_CAT_BA, 
  190             IEEE80211_ACTION_BA_ADDBA_RESPONSE, ht_recv_action_ba_addba_response);
  191         ieee80211_recv_action_register(IEEE80211_ACTION_CAT_BA, 
  192             IEEE80211_ACTION_BA_DELBA, ht_recv_action_ba_delba);
  193         ieee80211_recv_action_register(IEEE80211_ACTION_CAT_HT, 
  194             IEEE80211_ACTION_HT_MIMOPWRSAVE, ht_recv_action_ht_mimopwrsave);
  195         ieee80211_recv_action_register(IEEE80211_ACTION_CAT_HT, 
  196             IEEE80211_ACTION_HT_TXCHWIDTH, ht_recv_action_ht_txchwidth);
  197 
  198         ieee80211_send_action_register(IEEE80211_ACTION_CAT_BA, 
  199             IEEE80211_ACTION_BA_ADDBA_REQUEST, ht_send_action_ba_addba);
  200         ieee80211_send_action_register(IEEE80211_ACTION_CAT_BA, 
  201             IEEE80211_ACTION_BA_ADDBA_RESPONSE, ht_send_action_ba_addba);
  202         ieee80211_send_action_register(IEEE80211_ACTION_CAT_BA, 
  203             IEEE80211_ACTION_BA_DELBA, ht_send_action_ba_delba);
  204         ieee80211_send_action_register(IEEE80211_ACTION_CAT_HT, 
  205             IEEE80211_ACTION_HT_TXCHWIDTH, ht_send_action_ht_txchwidth);
  206 }
  207 SYSINIT(wlan_ht, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_ht_init, NULL);
  208 
  209 static int ieee80211_ampdu_enable(struct ieee80211_node *ni,
  210         struct ieee80211_tx_ampdu *tap);
  211 static int ieee80211_addba_request(struct ieee80211_node *ni,
  212         struct ieee80211_tx_ampdu *tap,
  213         int dialogtoken, int baparamset, int batimeout);
  214 static int ieee80211_addba_response(struct ieee80211_node *ni,
  215         struct ieee80211_tx_ampdu *tap,
  216         int code, int baparamset, int batimeout);
  217 static void ieee80211_addba_stop(struct ieee80211_node *ni,
  218         struct ieee80211_tx_ampdu *tap);
  219 static void null_addba_response_timeout(struct ieee80211_node *ni,
  220         struct ieee80211_tx_ampdu *tap);
  221 
  222 static void ieee80211_bar_response(struct ieee80211_node *ni,
  223         struct ieee80211_tx_ampdu *tap, int status);
  224 static void ampdu_tx_stop(struct ieee80211_tx_ampdu *tap);
  225 static void bar_stop_timer(struct ieee80211_tx_ampdu *tap);
  226 static int ampdu_rx_start(struct ieee80211_node *, struct ieee80211_rx_ampdu *,
  227         int baparamset, int batimeout, int baseqctl);
  228 static void ampdu_rx_stop(struct ieee80211_node *, struct ieee80211_rx_ampdu *);
  229 
  230 void
  231 ieee80211_ht_attach(struct ieee80211com *ic)
  232 {
  233         /* setup default aggregation policy */
  234         ic->ic_recv_action = ieee80211_recv_action;
  235         ic->ic_send_action = ieee80211_send_action;
  236         ic->ic_ampdu_enable = ieee80211_ampdu_enable;
  237         ic->ic_addba_request = ieee80211_addba_request;
  238         ic->ic_addba_response = ieee80211_addba_response;
  239         ic->ic_addba_response_timeout = null_addba_response_timeout;
  240         ic->ic_addba_stop = ieee80211_addba_stop;
  241         ic->ic_bar_response = ieee80211_bar_response;
  242         ic->ic_ampdu_rx_start = ampdu_rx_start;
  243         ic->ic_ampdu_rx_stop = ampdu_rx_stop;
  244 
  245         ic->ic_htprotmode = IEEE80211_PROT_RTSCTS;
  246         ic->ic_curhtprotmode = IEEE80211_HTINFO_OPMODE_PURE;
  247 }
  248 
  249 void
  250 ieee80211_ht_detach(struct ieee80211com *ic)
  251 {
  252 }
  253 
  254 void
  255 ieee80211_ht_vattach(struct ieee80211vap *vap)
  256 {
  257 
  258         /* driver can override defaults */
  259         vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_8K;
  260         vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_NA;
  261         vap->iv_ampdu_limit = vap->iv_ampdu_rxmax;
  262         vap->iv_amsdu_limit = vap->iv_htcaps & IEEE80211_HTCAP_MAXAMSDU;
  263         /* tx aggregation traffic thresholds */
  264         vap->iv_ampdu_mintraffic[WME_AC_BK] = 128;
  265         vap->iv_ampdu_mintraffic[WME_AC_BE] = 64;
  266         vap->iv_ampdu_mintraffic[WME_AC_VO] = 32;
  267         vap->iv_ampdu_mintraffic[WME_AC_VI] = 32;
  268 
  269         vap->iv_htprotmode = IEEE80211_PROT_RTSCTS;
  270         vap->iv_curhtprotmode = IEEE80211_HTINFO_OPMODE_PURE;
  271 
  272         if (vap->iv_htcaps & IEEE80211_HTC_HT) {
  273                 /*
  274                  * Device is HT capable; enable all HT-related
  275                  * facilities by default.
  276                  * XXX these choices may be too aggressive.
  277                  */
  278                 vap->iv_flags_ht |= IEEE80211_FHT_HT
  279                                  |  IEEE80211_FHT_HTCOMPAT
  280                                  ;
  281                 if (vap->iv_htcaps & IEEE80211_HTCAP_SHORTGI20)
  282                         vap->iv_flags_ht |= IEEE80211_FHT_SHORTGI20;
  283                 /* XXX infer from channel list? */
  284                 if (vap->iv_htcaps & IEEE80211_HTCAP_CHWIDTH40) {
  285                         vap->iv_flags_ht |= IEEE80211_FHT_USEHT40;
  286                         if (vap->iv_htcaps & IEEE80211_HTCAP_SHORTGI40)
  287                                 vap->iv_flags_ht |= IEEE80211_FHT_SHORTGI40;
  288                 }
  289                 /* enable RIFS if capable */
  290                 if (vap->iv_htcaps & IEEE80211_HTC_RIFS)
  291                         vap->iv_flags_ht |= IEEE80211_FHT_RIFS;
  292 
  293                 /* NB: A-MPDU and A-MSDU rx are mandated, these are tx only */
  294                 vap->iv_flags_ht |= IEEE80211_FHT_AMPDU_RX;
  295                 if (vap->iv_htcaps & IEEE80211_HTC_AMPDU)
  296                         vap->iv_flags_ht |= IEEE80211_FHT_AMPDU_TX;
  297                 vap->iv_flags_ht |= IEEE80211_FHT_AMSDU_RX;
  298                 if (vap->iv_htcaps & IEEE80211_HTC_AMSDU)
  299                         vap->iv_flags_ht |= IEEE80211_FHT_AMSDU_TX;
  300 
  301                 if (vap->iv_htcaps & IEEE80211_HTCAP_TXSTBC)
  302                         vap->iv_flags_ht |= IEEE80211_FHT_STBC_TX;
  303                 if (vap->iv_htcaps & IEEE80211_HTCAP_RXSTBC)
  304                         vap->iv_flags_ht |= IEEE80211_FHT_STBC_RX;
  305 
  306                 if (vap->iv_htcaps & IEEE80211_HTCAP_LDPC)
  307                         vap->iv_flags_ht |= IEEE80211_FHT_LDPC_RX;
  308                 if (vap->iv_htcaps & IEEE80211_HTC_TXLDPC)
  309                         vap->iv_flags_ht |= IEEE80211_FHT_LDPC_TX;
  310         }
  311         /* NB: disable default legacy WDS, too many issues right now */
  312         if (vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY)
  313                 vap->iv_flags_ht &= ~IEEE80211_FHT_HT;
  314 }
  315 
  316 void
  317 ieee80211_ht_vdetach(struct ieee80211vap *vap)
  318 {
  319 }
  320 
  321 static int
  322 ht_getrate(struct ieee80211com *ic, int index, enum ieee80211_phymode mode,
  323     int ratetype)
  324 {
  325         int mword, rate;
  326 
  327         mword = ieee80211_rate2media(ic, index | IEEE80211_RATE_MCS, mode);
  328         if (IFM_SUBTYPE(mword) != IFM_IEEE80211_MCS)
  329                 return (0);
  330         switch (ratetype) {
  331         case 0:
  332                 rate = ieee80211_htrates[index].ht20_rate_800ns;
  333                 break;
  334         case 1:
  335                 rate = ieee80211_htrates[index].ht20_rate_400ns;
  336                 break;
  337         case 2:
  338                 rate = ieee80211_htrates[index].ht40_rate_800ns;
  339                 break;
  340         default:
  341                 rate = ieee80211_htrates[index].ht40_rate_400ns;
  342                 break;
  343         }
  344         return (rate);
  345 }
  346 
  347 static struct printranges {
  348         int     minmcs;
  349         int     maxmcs;
  350         int     txstream;
  351         int     ratetype;
  352         int     htcapflags;
  353 } ranges[] = {
  354         {  0,  7, 1, 0, 0 },
  355         {  8, 15, 2, 0, 0 },
  356         { 16, 23, 3, 0, 0 },
  357         { 24, 31, 4, 0, 0 },
  358         { 32,  0, 1, 2, IEEE80211_HTC_TXMCS32 },
  359         { 33, 38, 2, 0, IEEE80211_HTC_TXUNEQUAL },
  360         { 39, 52, 3, 0, IEEE80211_HTC_TXUNEQUAL },
  361         { 53, 76, 4, 0, IEEE80211_HTC_TXUNEQUAL },
  362         {  0,  0, 0, 0, 0 },
  363 };
  364 
  365 static void
  366 ht_rateprint(struct ieee80211com *ic, enum ieee80211_phymode mode, int ratetype)
  367 {
  368         int minrate, maxrate;
  369         struct printranges *range;
  370 
  371         for (range = ranges; range->txstream != 0; range++) {
  372                 if (ic->ic_txstream < range->txstream)
  373                         continue;
  374                 if (range->htcapflags &&
  375                     (ic->ic_htcaps & range->htcapflags) == 0)
  376                         continue;
  377                 if (ratetype < range->ratetype)
  378                         continue;
  379                 minrate = ht_getrate(ic, range->minmcs, mode, ratetype);
  380                 maxrate = ht_getrate(ic, range->maxmcs, mode, ratetype);
  381                 if (range->maxmcs) {
  382                         ic_printf(ic, "MCS %d-%d: %d%sMbps - %d%sMbps\n",
  383                             range->minmcs, range->maxmcs,
  384                             minrate/2, ((minrate & 0x1) != 0 ? ".5" : ""),
  385                             maxrate/2, ((maxrate & 0x1) != 0 ? ".5" : ""));
  386                 } else {
  387                         ic_printf(ic, "MCS %d: %d%sMbps\n", range->minmcs,
  388                             minrate/2, ((minrate & 0x1) != 0 ? ".5" : ""));
  389                 }
  390         }
  391 }
  392 
  393 static void
  394 ht_announce(struct ieee80211com *ic, enum ieee80211_phymode mode)
  395 {
  396         const char *modestr = ieee80211_phymode_name[mode];
  397 
  398         ic_printf(ic, "%s MCS 20MHz\n", modestr);
  399         ht_rateprint(ic, mode, 0);
  400         if (ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20) {
  401                 ic_printf(ic, "%s MCS 20MHz SGI\n", modestr);
  402                 ht_rateprint(ic, mode, 1);
  403         }
  404         if (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) {
  405                 ic_printf(ic, "%s MCS 40MHz:\n", modestr);
  406                 ht_rateprint(ic, mode, 2);
  407         }
  408         if ((ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) &&
  409             (ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40)) {
  410                 ic_printf(ic, "%s MCS 40MHz SGI:\n", modestr);
  411                 ht_rateprint(ic, mode, 3);
  412         }
  413 }
  414 
  415 void
  416 ieee80211_ht_announce(struct ieee80211com *ic)
  417 {
  418 
  419         if (isset(ic->ic_modecaps, IEEE80211_MODE_11NA) ||
  420             isset(ic->ic_modecaps, IEEE80211_MODE_11NG))
  421                 ic_printf(ic, "%dT%dR\n", ic->ic_txstream, ic->ic_rxstream);
  422         if (isset(ic->ic_modecaps, IEEE80211_MODE_11NA))
  423                 ht_announce(ic, IEEE80211_MODE_11NA);
  424         if (isset(ic->ic_modecaps, IEEE80211_MODE_11NG))
  425                 ht_announce(ic, IEEE80211_MODE_11NG);
  426 }
  427 
  428 void
  429 ieee80211_init_suphtrates(struct ieee80211com *ic)
  430 {
  431 #define ADDRATE(x)      do {                                            \
  432         htrateset->rs_rates[htrateset->rs_nrates] = x;                  \
  433         htrateset->rs_nrates++;                                         \
  434 } while (0)
  435         struct ieee80211_htrateset *htrateset = &ic->ic_sup_htrates;
  436         int i;
  437 
  438         memset(htrateset, 0, sizeof(struct ieee80211_htrateset));
  439         for (i = 0; i < ic->ic_txstream * 8; i++)
  440                 ADDRATE(i);
  441         if ((ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) &&
  442             (ic->ic_htcaps & IEEE80211_HTC_TXMCS32))
  443                 ADDRATE(32);
  444         if (ic->ic_htcaps & IEEE80211_HTC_TXUNEQUAL) {
  445                 if (ic->ic_txstream >= 2) {
  446                          for (i = 33; i <= 38; i++)
  447                                 ADDRATE(i);
  448                 }
  449                 if (ic->ic_txstream >= 3) {
  450                         for (i = 39; i <= 52; i++)
  451                                 ADDRATE(i);
  452                 }
  453                 if (ic->ic_txstream == 4) {
  454                         for (i = 53; i <= 76; i++)
  455                                 ADDRATE(i);
  456                 }
  457         }
  458 #undef  ADDRATE
  459 }
  460 
  461 /*
  462  * Receive processing.
  463  */
  464 
  465 /*
  466  * Decap the encapsulated A-MSDU frames and dispatch all but
  467  * the last for delivery.  The last frame is returned for 
  468  * delivery via the normal path.
  469  */
  470 struct mbuf *
  471 ieee80211_decap_amsdu(struct ieee80211_node *ni, struct mbuf *m)
  472 {
  473         struct ieee80211vap *vap = ni->ni_vap;
  474         int framelen;
  475         struct mbuf *n;
  476 
  477         /* discard 802.3 header inserted by ieee80211_decap */
  478         m_adj(m, sizeof(struct ether_header));
  479 
  480         vap->iv_stats.is_amsdu_decap++;
  481 
  482         for (;;) {
  483                 /*
  484                  * Decap the first frame, bust it apart from the
  485                  * remainder and deliver.  We leave the last frame
  486                  * delivery to the caller (for consistency with other
  487                  * code paths, could also do it here).
  488                  */
  489                 m = ieee80211_decap1(m, &framelen);
  490                 if (m == NULL) {
  491                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
  492                             ni->ni_macaddr, "a-msdu", "%s", "decap failed");
  493                         vap->iv_stats.is_amsdu_tooshort++;
  494                         return NULL;
  495                 }
  496                 if (m->m_pkthdr.len == framelen)
  497                         break;
  498                 n = m_split(m, framelen, IEEE80211_M_NOWAIT);
  499                 if (n == NULL) {
  500                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
  501                             ni->ni_macaddr, "a-msdu",
  502                             "%s", "unable to split encapsulated frames");
  503                         vap->iv_stats.is_amsdu_split++;
  504                         m_freem(m);                     /* NB: must reclaim */
  505                         return NULL;
  506                 }
  507                 vap->iv_deliver_data(vap, ni, m);
  508 
  509                 /*
  510                  * Remove frame contents; each intermediate frame
  511                  * is required to be aligned to a 4-byte boundary.
  512                  */
  513                 m = n;
  514                 m_adj(m, roundup2(framelen, 4) - framelen);     /* padding */
  515         }
  516         return m;                               /* last delivered by caller */
  517 }
  518 
  519 static void
  520 ampdu_rx_purge_slot(struct ieee80211_rx_ampdu *rap, int i)
  521 {
  522         struct mbuf *m;
  523 
  524         /* Walk the queue, removing frames as appropriate */
  525         while (mbufq_len(&rap->rxa_mq[i]) != 0) {
  526                 m = mbufq_dequeue(&rap->rxa_mq[i]);
  527                 if (m == NULL)
  528                         break;
  529                 rap->rxa_qbytes -= m->m_pkthdr.len;
  530                 rap->rxa_qframes--;
  531                 m_freem(m);
  532         }
  533 }
  534 
  535 /*
  536  * Add the given frame to the current RX reorder slot.
  537  *
  538  * For future offloaded A-MSDU handling where multiple frames with
  539  * the same sequence number show up here, this routine will append
  540  * those frames as long as they're appropriately tagged.
  541  */
  542 static int
  543 ampdu_rx_add_slot(struct ieee80211_rx_ampdu *rap, int off, int tid,
  544     ieee80211_seq rxseq,
  545     struct ieee80211_node *ni,
  546     struct mbuf *m,
  547     const struct ieee80211_rx_stats *rxs)
  548 {
  549         const struct ieee80211_rx_stats *rxs_final = NULL;
  550         struct ieee80211vap *vap = ni->ni_vap;
  551         int toss_dup;
  552 #define PROCESS         0       /* caller should process frame */
  553 #define CONSUMED        1       /* frame consumed, caller does nothing */
  554 
  555         /*
  556          * Figure out if this is a duplicate frame for the given slot.
  557          *
  558          * We're assuming that the driver will hand us all the frames
  559          * for a given AMSDU decap pass and if we get /a/ frame
  560          * for an AMSDU decap then we'll get all of them.
  561          *
  562          * The tricksy bit is that we don't know when the /end/ of
  563          * the decap pass is, because we aren't tracking state here
  564          * per-slot to know that we've finished receiving the frame list.
  565          *
  566          * The driver sets RX_F_AMSDU and RX_F_AMSDU_MORE to tell us
  567          * what's going on; so ideally we'd just check the frame at the
  568          * end of the reassembly slot to see if its F_AMSDU w/ no F_AMSDU_MORE -
  569          * that means we've received the whole AMSDU decap pass.
  570          */
  571 
  572         /*
  573          * Get the rxs of the final mbuf in the slot, if one exists.
  574          */
  575         if (mbufq_len(&rap->rxa_mq[off]) != 0) {
  576                 rxs_final = ieee80211_get_rx_params_ptr(mbufq_last(&rap->rxa_mq[off]));
  577         }
  578 
  579         /* Default to tossing the duplicate frame */
  580         toss_dup = 1;
  581 
  582         /*
  583          * Check to see if the final frame has F_AMSDU and F_AMSDU set, AND
  584          * this frame has F_AMSDU set (MORE or otherwise.)  That's a sign
  585          * that more can come.
  586          */
  587 
  588         if ((rxs != NULL) && (rxs_final != NULL) &&
  589             ieee80211_check_rxseq_amsdu(rxs) &&
  590             ieee80211_check_rxseq_amsdu(rxs_final)) {
  591                 if (! ieee80211_check_rxseq_amsdu_more(rxs_final)) {
  592                         /*
  593                          * amsdu_more() returning 0 means "it's not the
  594                          * final frame" so we can append more
  595                          * frames here.
  596                          */
  597                         toss_dup = 0;
  598                 }
  599         }
  600 
  601         /*
  602          * If the list is empty OR we have determined we can put more
  603          * driver decap'ed AMSDU frames in here, then insert.
  604          */
  605         if ((mbufq_len(&rap->rxa_mq[off]) == 0) || (toss_dup == 0)) {
  606                 if (mbufq_enqueue(&rap->rxa_mq[off], m) != 0) {
  607                         IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT | IEEE80211_MSG_11N,
  608                             ni->ni_macaddr,
  609                             "a-mpdu queue fail",
  610                             "seqno %u tid %u BA win <%u:%u> off=%d, qlen=%d, maxqlen=%d",
  611                             rxseq, tid, rap->rxa_start,
  612                             IEEE80211_SEQ_ADD(rap->rxa_start, rap->rxa_wnd-1),
  613                             off,
  614                             mbufq_len(&rap->rxa_mq[off]),
  615                             rap->rxa_mq[off].mq_maxlen);
  616                         /* XXX error count */
  617                         m_freem(m);
  618                         return CONSUMED;
  619                 }
  620                 rap->rxa_qframes++;
  621                 rap->rxa_qbytes += m->m_pkthdr.len;
  622                 vap->iv_stats.is_ampdu_rx_reorder++;
  623                 /*
  624                  * Statistics for AMSDU decap.
  625                  */
  626                 if (rxs != NULL && ieee80211_check_rxseq_amsdu(rxs)) {
  627                         if (ieee80211_check_rxseq_amsdu_more(rxs)) {
  628                                 /* more=1, AMSDU, end of batch */
  629                                 IEEE80211_NODE_STAT(ni, rx_amsdu_more_end);
  630                         } else {
  631                                 IEEE80211_NODE_STAT(ni, rx_amsdu_more);
  632                         }
  633                 }
  634         } else {
  635                 IEEE80211_DISCARD_MAC(vap,
  636                     IEEE80211_MSG_INPUT | IEEE80211_MSG_11N,
  637                     ni->ni_macaddr, "a-mpdu duplicate",
  638                     "seqno %u tid %u BA win <%u:%u>",
  639                     rxseq, tid, rap->rxa_start,
  640                     IEEE80211_SEQ_ADD(rap->rxa_start, rap->rxa_wnd-1));
  641                 if (rxs != NULL) {
  642                         IEEE80211_DISCARD_MAC(vap,
  643                             IEEE80211_MSG_INPUT | IEEE80211_MSG_11N,
  644                             ni->ni_macaddr, "a-mpdu duplicate",
  645                             "seqno %d tid %u pktflags 0x%08x\n",
  646                             rxseq, tid, rxs->c_pktflags);
  647                 }
  648                 if (rxs_final != NULL) {
  649                         IEEE80211_DISCARD_MAC(vap,
  650                             IEEE80211_MSG_INPUT | IEEE80211_MSG_11N,
  651                             ni->ni_macaddr, "a-mpdu duplicate",
  652                             "final: pktflags 0x%08x\n",
  653                             rxs_final->c_pktflags);
  654                 }
  655                 vap->iv_stats.is_rx_dup++;
  656                 IEEE80211_NODE_STAT(ni, rx_dup);
  657                 m_freem(m);
  658         }
  659         return CONSUMED;
  660 #undef  CONSUMED
  661 #undef  PROCESS
  662 }
  663 
  664 /*
  665  * Purge all frames in the A-MPDU re-order queue.
  666  */
  667 static void
  668 ampdu_rx_purge(struct ieee80211_rx_ampdu *rap)
  669 {
  670         int i;
  671 
  672         for (i = 0; i < rap->rxa_wnd; i++) {
  673                 ampdu_rx_purge_slot(rap, i);
  674                 if (rap->rxa_qframes == 0)
  675                         break;
  676         }
  677         KASSERT(rap->rxa_qbytes == 0 && rap->rxa_qframes == 0,
  678             ("lost %u data, %u frames on ampdu rx q",
  679             rap->rxa_qbytes, rap->rxa_qframes));
  680 }
  681 
  682 static void
  683 ieee80211_ampdu_rx_init_rap(struct ieee80211_node *ni,
  684     struct ieee80211_rx_ampdu *rap)
  685 {
  686         int i;
  687 
  688         /* XXX TODO: ensure the queues are empty */
  689         memset(rap, 0, sizeof(*rap));
  690         for (i = 0; i < IEEE80211_AGGR_BAWMAX; i++)
  691                 mbufq_init(&rap->rxa_mq[i], 256);
  692 }
  693 
  694 /*
  695  * Start A-MPDU rx/re-order processing for the specified TID.
  696  */
  697 static int
  698 ampdu_rx_start(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap,
  699         int baparamset, int batimeout, int baseqctl)
  700 {
  701         struct ieee80211vap *vap = ni->ni_vap;
  702         int bufsiz = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_BUFSIZ);
  703 
  704         if (rap->rxa_flags & IEEE80211_AGGR_RUNNING) {
  705                 /*
  706                  * AMPDU previously setup and not terminated with a DELBA,
  707                  * flush the reorder q's in case anything remains.
  708                  */
  709                 ampdu_rx_purge(rap);
  710         }
  711         ieee80211_ampdu_rx_init_rap(ni, rap);
  712         rap->rxa_wnd = (bufsiz == 0) ?
  713             IEEE80211_AGGR_BAWMAX : min(bufsiz, IEEE80211_AGGR_BAWMAX);
  714         rap->rxa_start = _IEEE80211_MASKSHIFT(baseqctl, IEEE80211_BASEQ_START);
  715         rap->rxa_flags |=  IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_XCHGPEND;
  716 
  717         /* XXX this should be a configuration flag */
  718         if ((vap->iv_htcaps & IEEE80211_HTC_RX_AMSDU_AMPDU) &&
  719             (_IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_AMSDU)))
  720                 rap->rxa_flags |= IEEE80211_AGGR_AMSDU;
  721         else
  722                 rap->rxa_flags &= ~IEEE80211_AGGR_AMSDU;
  723 
  724         return 0;
  725 }
  726 
  727 /*
  728  * Public function; manually setup the RX ampdu state.
  729  */
  730 int
  731 ieee80211_ampdu_rx_start_ext(struct ieee80211_node *ni, int tid, int seq, int baw)
  732 {
  733         struct ieee80211_rx_ampdu *rap;
  734 
  735         /* XXX TODO: sanity check tid, seq, baw */
  736 
  737         rap = &ni->ni_rx_ampdu[tid];
  738 
  739         if (rap->rxa_flags & IEEE80211_AGGR_RUNNING) {
  740                 /*
  741                  * AMPDU previously setup and not terminated with a DELBA,
  742                  * flush the reorder q's in case anything remains.
  743                  */
  744                 ampdu_rx_purge(rap);
  745         }
  746 
  747         ieee80211_ampdu_rx_init_rap(ni, rap);
  748 
  749         rap->rxa_wnd = (baw== 0) ?
  750             IEEE80211_AGGR_BAWMAX : min(baw, IEEE80211_AGGR_BAWMAX);
  751         if (seq == -1) {
  752                 /* Wait for the first RX frame, use that as BAW */
  753                 rap->rxa_start = 0;
  754                 rap->rxa_flags |= IEEE80211_AGGR_WAITRX;
  755         } else {
  756                 rap->rxa_start = seq;
  757         }
  758         rap->rxa_flags |=  IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_XCHGPEND;
  759 
  760         /* XXX TODO: no amsdu flag */
  761 
  762         IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni,
  763             "%s: tid=%d, start=%d, wnd=%d, flags=0x%08x",
  764             __func__,
  765             tid,
  766             seq,
  767             rap->rxa_wnd,
  768             rap->rxa_flags);
  769 
  770         return 0;
  771 }
  772 
  773 /*
  774  * Public function; manually stop the RX AMPDU state.
  775  */
  776 void
  777 ieee80211_ampdu_rx_stop_ext(struct ieee80211_node *ni, int tid)
  778 {
  779         struct ieee80211_rx_ampdu *rap;
  780 
  781         /* XXX TODO: sanity check tid, seq, baw */
  782         rap = &ni->ni_rx_ampdu[tid];
  783         ampdu_rx_stop(ni, rap);
  784 }
  785 
  786 /*
  787  * Stop A-MPDU rx processing for the specified TID.
  788  */
  789 static void
  790 ampdu_rx_stop(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap)
  791 {
  792 
  793         ampdu_rx_purge(rap);
  794         rap->rxa_flags &= ~(IEEE80211_AGGR_RUNNING
  795             | IEEE80211_AGGR_XCHGPEND
  796             | IEEE80211_AGGR_WAITRX);
  797 }
  798 
  799 /*
  800  * Dispatch a frame from the A-MPDU reorder queue.  The
  801  * frame is fed back into ieee80211_input marked with an
  802  * M_AMPDU_MPDU flag so it doesn't come back to us (it also
  803  * permits ieee80211_input to optimize re-processing).
  804  */
  805 static __inline void
  806 ampdu_dispatch(struct ieee80211_node *ni, struct mbuf *m)
  807 {
  808         m->m_flags |= M_AMPDU_MPDU;     /* bypass normal processing */
  809         /* NB: rssi and noise are ignored w/ M_AMPDU_MPDU set */
  810         (void) ieee80211_input(ni, m, 0, 0);
  811 }
  812 
  813 static int
  814 ampdu_dispatch_slot(struct ieee80211_rx_ampdu *rap, struct ieee80211_node *ni,
  815     int i)
  816 {
  817         struct mbuf *m;
  818         int n = 0;
  819 
  820         while (mbufq_len(&rap->rxa_mq[i]) != 0) {
  821                 m = mbufq_dequeue(&rap->rxa_mq[i]);
  822                 if (m == NULL)
  823                         break;
  824                 n++;
  825 
  826                 rap->rxa_qbytes -= m->m_pkthdr.len;
  827                 rap->rxa_qframes--;
  828 
  829                 ampdu_dispatch(ni, m);
  830         }
  831         return (n);
  832 }
  833 
  834 static void
  835 ampdu_rx_moveup(struct ieee80211_rx_ampdu *rap, struct ieee80211_node *ni,
  836     int i, int winstart)
  837 {
  838         struct ieee80211vap *vap = ni->ni_vap;
  839 
  840         /*
  841          * If frames remain, copy the mbuf pointers down so
  842          * they correspond to the offsets in the new window.
  843          */
  844         if (rap->rxa_qframes != 0) {
  845                 int n = rap->rxa_qframes, j;
  846                 for (j = i+1; j < rap->rxa_wnd; j++) {
  847                         /*
  848                          * Concat the list contents over, which will
  849                          * blank the source list for us.
  850                          */
  851                         if (mbufq_len(&rap->rxa_mq[j]) != 0) {
  852                                 n = n - mbufq_len(&rap->rxa_mq[j]);
  853                                 mbufq_concat(&rap->rxa_mq[j-i], &rap->rxa_mq[j]);
  854                                 KASSERT(n >= 0, ("%s: n < 0 (%d)", __func__, n));
  855                                 if (n == 0)
  856                                         break;
  857                         }
  858                 }
  859                 KASSERT(n == 0, ("%s: lost %d frames, qframes %d off %d "
  860                     "BA win <%d:%d> winstart %d",
  861                     __func__, n, rap->rxa_qframes, i, rap->rxa_start,
  862                     IEEE80211_SEQ_ADD(rap->rxa_start, rap->rxa_wnd-1),
  863                     winstart));
  864                 vap->iv_stats.is_ampdu_rx_copy += rap->rxa_qframes;
  865         }
  866 }
  867 
  868 /*
  869  * Dispatch as many frames as possible from the re-order queue.
  870  * Frames will always be "at the front"; we process all frames
  871  * up to the first empty slot in the window.  On completion we
  872  * cleanup state if there are still pending frames in the current
  873  * BA window.  We assume the frame at slot 0 is already handled
  874  * by the caller; we always start at slot 1.
  875  */
  876 static void
  877 ampdu_rx_dispatch(struct ieee80211_rx_ampdu *rap, struct ieee80211_node *ni)
  878 {
  879         struct ieee80211vap *vap = ni->ni_vap;
  880         int i, r, r2;
  881 
  882         /* flush run of frames */
  883         r2 = 0;
  884         for (i = 1; i < rap->rxa_wnd; i++) {
  885                 r = ampdu_dispatch_slot(rap, ni, i);
  886                 if (r == 0)
  887                         break;
  888                 r2 += r;
  889         }
  890 
  891         /* move up frames */
  892         ampdu_rx_moveup(rap, ni, i, -1);
  893 
  894         /*
  895          * Adjust the start of the BA window to
  896          * reflect the frames just dispatched.
  897          */
  898         rap->rxa_start = IEEE80211_SEQ_ADD(rap->rxa_start, i);
  899         vap->iv_stats.is_ampdu_rx_oor += r2;
  900 
  901         IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni,
  902             "%s: moved slot up %d slots to start at %d (%d frames)",
  903             __func__,
  904             i,
  905             rap->rxa_start,
  906             r2);
  907 }
  908 
  909 /*
  910  * Dispatch all frames in the A-MPDU re-order queue.
  911  */
  912 static void
  913 ampdu_rx_flush(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap)
  914 {
  915         int i, r;
  916 
  917         for (i = 0; i < rap->rxa_wnd; i++) {
  918                 r = ampdu_dispatch_slot(rap, ni, i);
  919                 if (r == 0)
  920                         continue;
  921                 ni->ni_vap->iv_stats.is_ampdu_rx_oor += r;
  922 
  923                 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni,
  924                     "%s: moved slot up %d slots to start at %d (%d frames)",
  925                     __func__,
  926                     1,
  927                     rap->rxa_start,
  928                     r);
  929 
  930                 if (rap->rxa_qframes == 0)
  931                         break;
  932         }
  933 }
  934 
  935 /*
  936  * Dispatch all frames in the A-MPDU re-order queue
  937  * preceding the specified sequence number.  This logic
  938  * handles window moves due to a received MSDU or BAR.
  939  */
  940 static void
  941 ampdu_rx_flush_upto(struct ieee80211_node *ni,
  942         struct ieee80211_rx_ampdu *rap, ieee80211_seq winstart)
  943 {
  944         struct ieee80211vap *vap = ni->ni_vap;
  945         ieee80211_seq seqno;
  946         int i, r;
  947 
  948         /*
  949          * Flush any complete MSDU's with a sequence number lower
  950          * than winstart.  Gaps may exist.  Note that we may actually
  951          * dispatch frames past winstart if a run continues; this is
  952          * an optimization that avoids having to do a separate pass
  953          * to dispatch frames after moving the BA window start.
  954          */
  955         seqno = rap->rxa_start;
  956         for (i = 0; i < rap->rxa_wnd; i++) {
  957                 if ((r = mbufq_len(&rap->rxa_mq[i])) != 0) {
  958                         (void) ampdu_dispatch_slot(rap, ni, i);
  959                 } else {
  960                         if (!IEEE80211_SEQ_BA_BEFORE(seqno, winstart))
  961                                 break;
  962                 }
  963                 vap->iv_stats.is_ampdu_rx_oor += r;
  964                 seqno = IEEE80211_SEQ_INC(seqno);
  965 
  966                 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni,
  967                     "%s: moved slot up %d slots to start at %d (%d frames)",
  968                     __func__,
  969                     1,
  970                     seqno,
  971                     r);
  972         }
  973 
  974         /*
  975          * If frames remain, copy the mbuf pointers down so
  976          * they correspond to the offsets in the new window.
  977          */
  978         ampdu_rx_moveup(rap, ni, i, winstart);
  979 
  980         /*
  981          * Move the start of the BA window; we use the
  982          * sequence number of the last MSDU that was
  983          * passed up the stack+1 or winstart if stopped on
  984          * a gap in the reorder buffer.
  985          */
  986         rap->rxa_start = seqno;
  987 }
  988 
  989 /*
  990  * Process a received QoS data frame for an HT station.  Handle
  991  * A-MPDU reordering: if this frame is received out of order
  992  * and falls within the BA window hold onto it.  Otherwise if
  993  * this frame completes a run, flush any pending frames.  We
  994  * return 1 if the frame is consumed.  A 0 is returned if
  995  * the frame should be processed normally by the caller.
  996  *
  997  * A-MSDU: handle hardware decap'ed A-MSDU frames that are
  998  * pretending to be MPDU's.  They're dispatched directly if
  999  * able; or attempted to put into the receive reordering slot.
 1000  */
 1001 int
 1002 ieee80211_ampdu_reorder(struct ieee80211_node *ni, struct mbuf *m,
 1003     const struct ieee80211_rx_stats *rxs)
 1004 {
 1005 #define PROCESS         0       /* caller should process frame */
 1006 #define CONSUMED        1       /* frame consumed, caller does nothing */
 1007         struct ieee80211vap *vap = ni->ni_vap;
 1008         struct ieee80211_qosframe *wh;
 1009         struct ieee80211_rx_ampdu *rap;
 1010         ieee80211_seq rxseq;
 1011         uint8_t tid;
 1012         int off;
 1013         int amsdu = ieee80211_check_rxseq_amsdu(rxs);
 1014         int amsdu_end = ieee80211_check_rxseq_amsdu_more(rxs);
 1015 
 1016         KASSERT((m->m_flags & (M_AMPDU | M_AMPDU_MPDU)) == M_AMPDU,
 1017             ("!a-mpdu or already re-ordered, flags 0x%x", m->m_flags));
 1018         KASSERT(ni->ni_flags & IEEE80211_NODE_HT, ("not an HT sta"));
 1019 
 1020         /* NB: m_len known to be sufficient */
 1021         wh = mtod(m, struct ieee80211_qosframe *);
 1022         if (wh->i_fc[0] != IEEE80211_FC0_QOSDATA) {
 1023                 /*
 1024                  * Not QoS data, shouldn't get here but just
 1025                  * return it to the caller for processing.
 1026                  */
 1027                 return PROCESS;
 1028         }
 1029 
 1030         /*
 1031          * 802.11-2012 9.3.2.10 - Duplicate detection and recovery.
 1032          *
 1033          * Multicast QoS data frames are checked against a different
 1034          * counter, not the per-TID counter.
 1035          */
 1036         if (IEEE80211_IS_MULTICAST(wh->i_addr1))
 1037                 return PROCESS;
 1038 
 1039         tid = ieee80211_getqos(wh)[0];
 1040         tid &= IEEE80211_QOS_TID;
 1041         rap = &ni->ni_rx_ampdu[tid];
 1042         if ((rap->rxa_flags & IEEE80211_AGGR_XCHGPEND) == 0) {
 1043                 /*
 1044                  * No ADDBA request yet, don't touch.
 1045                  */
 1046                 return PROCESS;
 1047         }
 1048         rxseq = le16toh(*(uint16_t *)wh->i_seq);
 1049         if ((rxseq & IEEE80211_SEQ_FRAG_MASK) != 0) {
 1050                 /*
 1051                  * Fragments are not allowed; toss.
 1052                  */
 1053                 IEEE80211_DISCARD_MAC(vap,
 1054                     IEEE80211_MSG_INPUT | IEEE80211_MSG_11N, ni->ni_macaddr,
 1055                     "A-MPDU", "fragment, rxseq 0x%x tid %u%s", rxseq, tid,
 1056                     wh->i_fc[1] & IEEE80211_FC1_RETRY ? " (retransmit)" : "");
 1057                 vap->iv_stats.is_ampdu_rx_drop++;
 1058                 IEEE80211_NODE_STAT(ni, rx_drop);
 1059                 m_freem(m);
 1060                 return CONSUMED;
 1061         }
 1062         rxseq >>= IEEE80211_SEQ_SEQ_SHIFT;
 1063         rap->rxa_nframes++;
 1064 
 1065         /*
 1066          * Handle waiting for the first frame to define the BAW.
 1067          * Some firmware doesn't provide the RX of the starting point
 1068          * of the BAW and we have to cope.
 1069          */
 1070         if (rap->rxa_flags & IEEE80211_AGGR_WAITRX) {
 1071                 rap->rxa_flags &= ~IEEE80211_AGGR_WAITRX;
 1072                 rap->rxa_start = rxseq;
 1073         }
 1074 again:
 1075         if (rxseq == rap->rxa_start) {
 1076                 /*
 1077                  * First frame in window.
 1078                  */
 1079                 if (rap->rxa_qframes != 0) {
 1080                         /*
 1081                          * Dispatch as many packets as we can.
 1082                          */
 1083                         KASSERT((mbufq_len(&rap->rxa_mq[0]) == 0), ("unexpected dup"));
 1084                         ampdu_dispatch(ni, m);
 1085                         ampdu_rx_dispatch(rap, ni);
 1086                         return CONSUMED;
 1087                 } else {
 1088                         /*
 1089                          * In order; advance window if needed and notify
 1090                          * caller to dispatch directly.
 1091                          */
 1092                         if (amsdu) {
 1093                                 if (amsdu_end) {
 1094                                         rap->rxa_start = IEEE80211_SEQ_INC(rxseq);
 1095                                         IEEE80211_NODE_STAT(ni, rx_amsdu_more_end);
 1096                                 } else {
 1097                                         IEEE80211_NODE_STAT(ni, rx_amsdu_more);
 1098                                 }
 1099                         } else {
 1100                                 rap->rxa_start = IEEE80211_SEQ_INC(rxseq);
 1101                         }
 1102                         return PROCESS;
 1103                 }
 1104         }
 1105         /*
 1106          * Frame is out of order; store if in the BA window.
 1107          */
 1108         /* calculate offset in BA window */
 1109         off = IEEE80211_SEQ_SUB(rxseq, rap->rxa_start);
 1110         if (off < rap->rxa_wnd) {
 1111                 /*
 1112                  * Common case (hopefully): in the BA window.
 1113                  * Sec 9.10.7.6.2 a) (p.137)
 1114                  */
 1115 
 1116                 /* 
 1117                  * Check for frames sitting too long in the reorder queue.
 1118                  * This should only ever happen if frames are not delivered
 1119                  * without the sender otherwise notifying us (e.g. with a
 1120                  * BAR to move the window).  Typically this happens because
 1121                  * of vendor bugs that cause the sequence number to jump.
 1122                  * When this happens we get a gap in the reorder queue that
 1123                  * leaves frame sitting on the queue until they get pushed
 1124                  * out due to window moves.  When the vendor does not send
 1125                  * BAR this move only happens due to explicit packet sends
 1126                  *
 1127                  * NB: we only track the time of the oldest frame in the
 1128                  * reorder q; this means that if we flush we might push
 1129                  * frames that still "new"; if this happens then subsequent
 1130                  * frames will result in BA window moves which cost something
 1131                  * but is still better than a big throughput dip.
 1132                  */
 1133                 if (rap->rxa_qframes != 0) {
 1134                         /* XXX honor batimeout? */
 1135                         if (ticks - rap->rxa_age > ieee80211_ampdu_age) {
 1136                                 /*
 1137                                  * Too long since we received the first
 1138                                  * frame; flush the reorder buffer.
 1139                                  */
 1140                                 if (rap->rxa_qframes != 0) {
 1141                                         vap->iv_stats.is_ampdu_rx_age +=
 1142                                             rap->rxa_qframes;
 1143                                         ampdu_rx_flush(ni, rap);
 1144                                 }
 1145                                 /*
 1146                                  * Advance the window if needed and notify
 1147                                  * the caller to dispatch directly.
 1148                                  */
 1149                                 if (amsdu) {
 1150                                         if (amsdu_end) {
 1151                                                 rap->rxa_start =
 1152                                                     IEEE80211_SEQ_INC(rxseq);
 1153                                                 IEEE80211_NODE_STAT(ni,
 1154                                                     rx_amsdu_more_end);
 1155                                         } else {
 1156                                                 IEEE80211_NODE_STAT(ni,
 1157                                                     rx_amsdu_more);
 1158                                         }
 1159                                 } else {
 1160                                         rap->rxa_start =
 1161                                             IEEE80211_SEQ_INC(rxseq);
 1162                                 }
 1163                                 return PROCESS;
 1164                         }
 1165                 } else {
 1166                         /*
 1167                          * First frame, start aging timer.
 1168                          */
 1169                         rap->rxa_age = ticks;
 1170                 }
 1171 
 1172                 /* save packet - this consumes, no matter what */
 1173                 ampdu_rx_add_slot(rap, off, tid, rxseq, ni, m, rxs);
 1174                 return CONSUMED;
 1175         }
 1176         if (off < IEEE80211_SEQ_BA_RANGE) {
 1177                 /*
 1178                  * Outside the BA window, but within range;
 1179                  * flush the reorder q and move the window.
 1180                  * Sec 9.10.7.6.2 b) (p.138)
 1181                  */
 1182                 IEEE80211_NOTE(vap, IEEE80211_MSG_11N, ni,
 1183                     "move BA win <%u:%u> (%u frames) rxseq %u tid %u",
 1184                     rap->rxa_start,
 1185                     IEEE80211_SEQ_ADD(rap->rxa_start, rap->rxa_wnd-1),
 1186                     rap->rxa_qframes, rxseq, tid);
 1187                 vap->iv_stats.is_ampdu_rx_move++;
 1188 
 1189                 /*
 1190                  * The spec says to flush frames up to but not including:
 1191                  *      WinStart_B = rxseq - rap->rxa_wnd + 1
 1192                  * Then insert the frame or notify the caller to process
 1193                  * it immediately.  We can safely do this by just starting
 1194                  * over again because we know the frame will now be within
 1195                  * the BA window.
 1196                  */
 1197                 /* NB: rxa_wnd known to be >0 */
 1198                 ampdu_rx_flush_upto(ni, rap,
 1199                     IEEE80211_SEQ_SUB(rxseq, rap->rxa_wnd-1));
 1200                 goto again;
 1201         } else {
 1202                 /*
 1203                  * Outside the BA window and out of range; toss.
 1204                  * Sec 9.10.7.6.2 c) (p.138)
 1205                  */
 1206                 IEEE80211_DISCARD_MAC(vap,
 1207                     IEEE80211_MSG_INPUT | IEEE80211_MSG_11N, ni->ni_macaddr,
 1208                     "MPDU", "BA win <%u:%u> (%u frames) rxseq %u tid %u%s",
 1209                     rap->rxa_start,
 1210                     IEEE80211_SEQ_ADD(rap->rxa_start, rap->rxa_wnd-1),
 1211                     rap->rxa_qframes, rxseq, tid,
 1212                     wh->i_fc[1] & IEEE80211_FC1_RETRY ? " (retransmit)" : "");
 1213                 vap->iv_stats.is_ampdu_rx_drop++;
 1214                 IEEE80211_NODE_STAT(ni, rx_drop);
 1215                 m_freem(m);
 1216                 return CONSUMED;
 1217         }
 1218 #undef CONSUMED
 1219 #undef PROCESS
 1220 }
 1221 
 1222 /*
 1223  * Process a BAR ctl frame.  Dispatch all frames up to
 1224  * the sequence number of the frame.  If this frame is
 1225  * out of range it's discarded.
 1226  */
 1227 void
 1228 ieee80211_recv_bar(struct ieee80211_node *ni, struct mbuf *m0)
 1229 {
 1230         struct ieee80211vap *vap = ni->ni_vap;
 1231         struct ieee80211_frame_bar *wh;
 1232         struct ieee80211_rx_ampdu *rap;
 1233         ieee80211_seq rxseq;
 1234         int tid, off;
 1235 
 1236         if (!ieee80211_recv_bar_ena) {
 1237 #if 0
 1238                 IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_11N,
 1239                     ni->ni_macaddr, "BAR", "%s", "processing disabled");
 1240 #endif
 1241                 vap->iv_stats.is_ampdu_bar_bad++;
 1242                 return;
 1243         }
 1244         wh = mtod(m0, struct ieee80211_frame_bar *);
 1245         /* XXX check basic BAR */
 1246         tid = _IEEE80211_MASKSHIFT(le16toh(wh->i_ctl), IEEE80211_BAR_TID);
 1247         rap = &ni->ni_rx_ampdu[tid];
 1248         if ((rap->rxa_flags & IEEE80211_AGGR_XCHGPEND) == 0) {
 1249                 /*
 1250                  * No ADDBA request yet, don't touch.
 1251                  */
 1252                 IEEE80211_DISCARD_MAC(vap,
 1253                     IEEE80211_MSG_INPUT | IEEE80211_MSG_11N,
 1254                     ni->ni_macaddr, "BAR", "no BA stream, tid %u", tid);
 1255                 vap->iv_stats.is_ampdu_bar_bad++;
 1256                 return;
 1257         }
 1258         vap->iv_stats.is_ampdu_bar_rx++;
 1259         rxseq = le16toh(wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT;
 1260         if (rxseq == rap->rxa_start)
 1261                 return;
 1262         /* calculate offset in BA window */
 1263         off = IEEE80211_SEQ_SUB(rxseq, rap->rxa_start);
 1264         if (off < IEEE80211_SEQ_BA_RANGE) {
 1265                 /*
 1266                  * Flush the reorder q up to rxseq and move the window.
 1267                  * Sec 9.10.7.6.3 a) (p.138)
 1268                  */
 1269                 IEEE80211_NOTE(vap, IEEE80211_MSG_11N, ni,
 1270                     "BAR moves BA win <%u:%u> (%u frames) rxseq %u tid %u",
 1271                     rap->rxa_start,
 1272                     IEEE80211_SEQ_ADD(rap->rxa_start, rap->rxa_wnd-1),
 1273                     rap->rxa_qframes, rxseq, tid);
 1274                 vap->iv_stats.is_ampdu_bar_move++;
 1275 
 1276                 ampdu_rx_flush_upto(ni, rap, rxseq);
 1277                 if (off >= rap->rxa_wnd) {
 1278                         /*
 1279                          * BAR specifies a window start to the right of BA
 1280                          * window; we must move it explicitly since
 1281                          * ampdu_rx_flush_upto will not.
 1282                          */
 1283                         rap->rxa_start = rxseq;
 1284                 }
 1285         } else {
 1286                 /*
 1287                  * Out of range; toss.
 1288                  * Sec 9.10.7.6.3 b) (p.138)
 1289                  */
 1290                 IEEE80211_DISCARD_MAC(vap,
 1291                     IEEE80211_MSG_INPUT | IEEE80211_MSG_11N, ni->ni_macaddr,
 1292                     "BAR", "BA win <%u:%u> (%u frames) rxseq %u tid %u%s",
 1293                     rap->rxa_start,
 1294                     IEEE80211_SEQ_ADD(rap->rxa_start, rap->rxa_wnd-1),
 1295                     rap->rxa_qframes, rxseq, tid,
 1296                     wh->i_fc[1] & IEEE80211_FC1_RETRY ? " (retransmit)" : "");
 1297                 vap->iv_stats.is_ampdu_bar_oow++;
 1298                 IEEE80211_NODE_STAT(ni, rx_drop);
 1299         }
 1300 }
 1301 
 1302 /*
 1303  * Setup HT-specific state in a node.  Called only
 1304  * when HT use is negotiated so we don't do extra
 1305  * work for temporary and/or legacy sta's.
 1306  */
 1307 void
 1308 ieee80211_ht_node_init(struct ieee80211_node *ni)
 1309 {
 1310         struct ieee80211_tx_ampdu *tap;
 1311         int tid;
 1312 
 1313         IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
 1314             ni,
 1315             "%s: called (%p)",
 1316             __func__,
 1317             ni);
 1318 
 1319         if (ni->ni_flags & IEEE80211_NODE_HT) {
 1320                 /*
 1321                  * Clean AMPDU state on re-associate.  This handles the case
 1322                  * where a station leaves w/o notifying us and then returns
 1323                  * before node is reaped for inactivity.
 1324                  */
 1325                 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
 1326                     ni,
 1327                     "%s: calling cleanup (%p)",
 1328                     __func__, ni);
 1329                 ieee80211_ht_node_cleanup(ni);
 1330         }
 1331         for (tid = 0; tid < WME_NUM_TID; tid++) {
 1332                 tap = &ni->ni_tx_ampdu[tid];
 1333                 tap->txa_tid = tid;
 1334                 tap->txa_ni = ni;
 1335                 ieee80211_txampdu_init_pps(tap);
 1336                 /* NB: further initialization deferred */
 1337                 ieee80211_ampdu_rx_init_rap(ni, &ni->ni_rx_ampdu[tid]);
 1338         }
 1339         ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU |
 1340             IEEE80211_NODE_AMSDU;
 1341 }
 1342 
 1343 /*
 1344  * Cleanup HT-specific state in a node.  Called only
 1345  * when HT use has been marked.
 1346  */
 1347 void
 1348 ieee80211_ht_node_cleanup(struct ieee80211_node *ni)
 1349 {
 1350         struct ieee80211com *ic = ni->ni_ic;
 1351         int i;
 1352 
 1353         IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
 1354             ni,
 1355             "%s: called (%p)",
 1356             __func__, ni);
 1357 
 1358         KASSERT(ni->ni_flags & IEEE80211_NODE_HT, ("not an HT node"));
 1359 
 1360         /* XXX optimize this */
 1361         for (i = 0; i < WME_NUM_TID; i++) {
 1362                 struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[i];
 1363                 if (tap->txa_flags & IEEE80211_AGGR_SETUP)
 1364                         ampdu_tx_stop(tap);
 1365         }
 1366         for (i = 0; i < WME_NUM_TID; i++)
 1367                 ic->ic_ampdu_rx_stop(ni, &ni->ni_rx_ampdu[i]);
 1368 
 1369         ni->ni_htcap = 0;
 1370         ni->ni_flags &= ~IEEE80211_NODE_HT_ALL;
 1371 }
 1372 
 1373 /*
 1374  * Age out HT resources for a station.
 1375  */
 1376 void
 1377 ieee80211_ht_node_age(struct ieee80211_node *ni)
 1378 {
 1379         struct ieee80211vap *vap = ni->ni_vap;
 1380         uint8_t tid;
 1381 
 1382         KASSERT(ni->ni_flags & IEEE80211_NODE_HT, ("not an HT sta"));
 1383 
 1384         for (tid = 0; tid < WME_NUM_TID; tid++) {
 1385                 struct ieee80211_rx_ampdu *rap;
 1386 
 1387                 rap = &ni->ni_rx_ampdu[tid];
 1388                 if ((rap->rxa_flags & IEEE80211_AGGR_XCHGPEND) == 0)
 1389                         continue;
 1390                 if (rap->rxa_qframes == 0)
 1391                         continue;
 1392                 /* 
 1393                  * Check for frames sitting too long in the reorder queue.
 1394                  * See above for more details on what's happening here.
 1395                  */
 1396                 /* XXX honor batimeout? */
 1397                 if (ticks - rap->rxa_age > ieee80211_ampdu_age) {
 1398                         /*
 1399                          * Too long since we received the first
 1400                          * frame; flush the reorder buffer.
 1401                          */
 1402                         vap->iv_stats.is_ampdu_rx_age += rap->rxa_qframes;
 1403                         ampdu_rx_flush(ni, rap);
 1404                 }
 1405         }
 1406 }
 1407 
 1408 static struct ieee80211_channel *
 1409 findhtchan(struct ieee80211com *ic, struct ieee80211_channel *c, int htflags)
 1410 {
 1411         return ieee80211_find_channel(ic, c->ic_freq,
 1412             (c->ic_flags &~ IEEE80211_CHAN_HT) | htflags);
 1413 }
 1414 
 1415 /*
 1416  * Adjust a channel to be HT/non-HT according to the vap's configuration.
 1417  */
 1418 struct ieee80211_channel *
 1419 ieee80211_ht_adjust_channel(struct ieee80211com *ic,
 1420         struct ieee80211_channel *chan, int flags)
 1421 {
 1422         struct ieee80211_channel *c;
 1423 
 1424         if (flags & IEEE80211_FHT_HT) {
 1425                 /* promote to HT if possible */
 1426                 if (flags & IEEE80211_FHT_USEHT40) {
 1427                         if (!IEEE80211_IS_CHAN_HT40(chan)) {
 1428                                 /* NB: arbitrarily pick ht40+ over ht40- */
 1429                                 c = findhtchan(ic, chan, IEEE80211_CHAN_HT40U);
 1430                                 if (c == NULL)
 1431                                         c = findhtchan(ic, chan,
 1432                                                 IEEE80211_CHAN_HT40D);
 1433                                 if (c == NULL)
 1434                                         c = findhtchan(ic, chan,
 1435                                                 IEEE80211_CHAN_HT20);
 1436                                 if (c != NULL)
 1437                                         chan = c;
 1438                         }
 1439                 } else if (!IEEE80211_IS_CHAN_HT20(chan)) {
 1440                         c = findhtchan(ic, chan, IEEE80211_CHAN_HT20);
 1441                         if (c != NULL)
 1442                                 chan = c;
 1443                 }
 1444         } else if (IEEE80211_IS_CHAN_HT(chan)) {
 1445                 /* demote to legacy, HT use is disabled */
 1446                 c = ieee80211_find_channel(ic, chan->ic_freq,
 1447                     chan->ic_flags &~ IEEE80211_CHAN_HT);
 1448                 if (c != NULL)
 1449                         chan = c;
 1450         }
 1451         return chan;
 1452 }
 1453 
 1454 /*
 1455  * Setup HT-specific state for a legacy WDS peer.
 1456  */
 1457 void
 1458 ieee80211_ht_wds_init(struct ieee80211_node *ni)
 1459 {
 1460         struct ieee80211vap *vap = ni->ni_vap;
 1461         struct ieee80211_tx_ampdu *tap;
 1462         int tid;
 1463 
 1464         KASSERT(vap->iv_flags_ht & IEEE80211_FHT_HT, ("no HT requested"));
 1465 
 1466         /* XXX check scan cache in case peer has an ap and we have info */
 1467         /*
 1468          * If setup with a legacy channel; locate an HT channel.
 1469          * Otherwise if the inherited channel (from a companion
 1470          * AP) is suitable use it so we use the same location
 1471          * for the extension channel).
 1472          */
 1473         ni->ni_chan = ieee80211_ht_adjust_channel(ni->ni_ic,
 1474             ni->ni_chan, ieee80211_htchanflags(ni->ni_chan));
 1475 
 1476         ni->ni_htcap = 0;
 1477         if (vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20)
 1478                 ni->ni_htcap |= IEEE80211_HTCAP_SHORTGI20;
 1479         if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) {
 1480                 ni->ni_htcap |= IEEE80211_HTCAP_CHWIDTH40;
 1481                 ni->ni_chw = 40;
 1482                 if (IEEE80211_IS_CHAN_HT40U(ni->ni_chan))
 1483                         ni->ni_ht2ndchan = IEEE80211_HTINFO_2NDCHAN_ABOVE;
 1484                 else if (IEEE80211_IS_CHAN_HT40D(ni->ni_chan))
 1485                         ni->ni_ht2ndchan = IEEE80211_HTINFO_2NDCHAN_BELOW;
 1486                 if (vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40)
 1487                         ni->ni_htcap |= IEEE80211_HTCAP_SHORTGI40;
 1488         } else {
 1489                 ni->ni_chw = 20;
 1490                 ni->ni_ht2ndchan = IEEE80211_HTINFO_2NDCHAN_NONE;
 1491         }
 1492         ni->ni_htctlchan = ni->ni_chan->ic_ieee;
 1493         if (vap->iv_flags_ht & IEEE80211_FHT_RIFS)
 1494                 ni->ni_flags |= IEEE80211_NODE_RIFS;
 1495         /* XXX does it make sense to enable SMPS? */
 1496 
 1497         ni->ni_htopmode = 0;            /* XXX need protection state */
 1498         ni->ni_htstbc = 0;              /* XXX need info */
 1499 
 1500         for (tid = 0; tid < WME_NUM_TID; tid++) {
 1501                 tap = &ni->ni_tx_ampdu[tid];
 1502                 tap->txa_tid = tid;
 1503                 ieee80211_txampdu_init_pps(tap);
 1504         }
 1505         /* NB: AMPDU tx/rx governed by IEEE80211_FHT_AMPDU_{TX,RX} */
 1506         ni->ni_flags |= IEEE80211_NODE_HT | IEEE80211_NODE_AMPDU |
 1507             IEEE80211_NODE_AMSDU;
 1508 }
 1509 
 1510 /*
 1511  * Notify a VAP of a change in the HTINFO ie if it's a hostap VAP.
 1512  *
 1513  * This is to be called from the deferred HT protection update
 1514  * task once the flags are updated.
 1515  */
 1516 void
 1517 ieee80211_htinfo_notify(struct ieee80211vap *vap)
 1518 {
 1519 
 1520         IEEE80211_LOCK_ASSERT(vap->iv_ic);
 1521 
 1522         if (vap->iv_opmode != IEEE80211_M_HOSTAP)
 1523                 return;
 1524         if (vap->iv_state != IEEE80211_S_RUN ||
 1525             !IEEE80211_IS_CHAN_HT(vap->iv_bss->ni_chan))
 1526                 return;
 1527 
 1528         IEEE80211_NOTE(vap,
 1529             IEEE80211_MSG_ASSOC | IEEE80211_MSG_11N,
 1530             vap->iv_bss,
 1531             "HT bss occupancy change: %d sta, %d ht, "
 1532             "%d ht40%s, HT protmode now 0x%x"
 1533             , vap->iv_sta_assoc
 1534             , vap->iv_ht_sta_assoc
 1535             , vap->iv_ht40_sta_assoc
 1536             , (vap->iv_flags_ht & IEEE80211_FHT_NONHT_PR) ?
 1537                  ", non-HT sta present" : ""
 1538             , vap->iv_curhtprotmode);
 1539 
 1540         ieee80211_beacon_notify(vap, IEEE80211_BEACON_HTINFO);
 1541 }
 1542 
 1543 /*
 1544  * Calculate HT protection mode from current
 1545  * state and handle updates.
 1546  */
 1547 static void
 1548 htinfo_update(struct ieee80211vap *vap)
 1549 {
 1550         struct ieee80211com *ic = vap->iv_ic;
 1551         uint8_t protmode;
 1552 
 1553         if (vap->iv_sta_assoc != vap->iv_ht_sta_assoc) {
 1554                 protmode = IEEE80211_HTINFO_OPMODE_MIXED
 1555                          | IEEE80211_HTINFO_NONHT_PRESENT;
 1556         } else if (vap->iv_flags_ht & IEEE80211_FHT_NONHT_PR) {
 1557                 protmode = IEEE80211_HTINFO_OPMODE_PROTOPT
 1558                          | IEEE80211_HTINFO_NONHT_PRESENT;
 1559         } else if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
 1560             IEEE80211_IS_CHAN_HT40(ic->ic_bsschan) && 
 1561             vap->iv_sta_assoc != vap->iv_ht40_sta_assoc) {
 1562                 protmode = IEEE80211_HTINFO_OPMODE_HT20PR;
 1563         } else {
 1564                 protmode = IEEE80211_HTINFO_OPMODE_PURE;
 1565         }
 1566         if (protmode != vap->iv_curhtprotmode) {
 1567                 vap->iv_curhtprotmode = protmode;
 1568                 /* Update VAP with new protection mode */
 1569                 ieee80211_vap_update_ht_protmode(vap);
 1570         }
 1571 }
 1572 
 1573 /*
 1574  * Handle an HT station joining a BSS.
 1575  */
 1576 void
 1577 ieee80211_ht_node_join(struct ieee80211_node *ni)
 1578 {
 1579         struct ieee80211vap *vap = ni->ni_vap;
 1580 
 1581         IEEE80211_LOCK_ASSERT(vap->iv_ic);
 1582 
 1583         if (ni->ni_flags & IEEE80211_NODE_HT) {
 1584                 vap->iv_ht_sta_assoc++;
 1585                 if (ni->ni_chw == 40)
 1586                         vap->iv_ht40_sta_assoc++;
 1587         }
 1588         htinfo_update(vap);
 1589 }
 1590 
 1591 /*
 1592  * Handle an HT station leaving a BSS.
 1593  */
 1594 void
 1595 ieee80211_ht_node_leave(struct ieee80211_node *ni)
 1596 {
 1597         struct ieee80211vap *vap = ni->ni_vap;
 1598 
 1599         IEEE80211_LOCK_ASSERT(vap->iv_ic);
 1600 
 1601         if (ni->ni_flags & IEEE80211_NODE_HT) {
 1602                 vap->iv_ht_sta_assoc--;
 1603                 if (ni->ni_chw == 40)
 1604                         vap->iv_ht40_sta_assoc--;
 1605         }
 1606         htinfo_update(vap);
 1607 }
 1608 
 1609 /*
 1610  * Public version of htinfo_update; used for processing
 1611  * beacon frames from overlapping bss.
 1612  *
 1613  * Caller can specify either IEEE80211_HTINFO_OPMODE_MIXED
 1614  * (on receipt of a beacon that advertises MIXED) or
 1615  * IEEE80211_HTINFO_OPMODE_PROTOPT (on receipt of a beacon
 1616  * from an overlapping legacy bss).  We treat MIXED with
 1617  * a higher precedence than PROTOPT (i.e. we will not change
 1618  * change PROTOPT -> MIXED; only MIXED -> PROTOPT).  This
 1619  * corresponds to how we handle things in htinfo_update.
 1620  *
 1621  */
 1622 void
 1623 ieee80211_htprot_update(struct ieee80211vap *vap, int protmode)
 1624 {
 1625         struct ieee80211com *ic = vap->iv_ic;
 1626 #define OPMODE(x)       _IEEE80211_SHIFTMASK(x, IEEE80211_HTINFO_OPMODE)
 1627         IEEE80211_LOCK(ic);
 1628 
 1629         /* track non-HT station presence */
 1630         KASSERT(protmode & IEEE80211_HTINFO_NONHT_PRESENT,
 1631             ("protmode 0x%x", protmode));
 1632         vap->iv_flags_ht |= IEEE80211_FHT_NONHT_PR;
 1633         vap->iv_lastnonht = ticks;
 1634 
 1635         if (protmode != vap->iv_curhtprotmode &&
 1636             (OPMODE(vap->iv_curhtprotmode) != IEEE80211_HTINFO_OPMODE_MIXED ||
 1637              OPMODE(protmode) == IEEE80211_HTINFO_OPMODE_PROTOPT)) {
 1638                 vap->iv_curhtprotmode = protmode;
 1639                 /* Update VAP with new protection mode */
 1640                 ieee80211_vap_update_ht_protmode(vap);
 1641         }
 1642         IEEE80211_UNLOCK(ic);
 1643 #undef OPMODE
 1644 }
 1645 
 1646 /*
 1647  * Time out presence of an overlapping bss with non-HT
 1648  * stations.  When operating in hostap mode we listen for
 1649  * beacons from other stations and if we identify a non-HT
 1650  * station is present we update the opmode field of the
 1651  * HTINFO ie.  To identify when all non-HT stations are
 1652  * gone we time out this condition.
 1653  */
 1654 void
 1655 ieee80211_ht_timeout(struct ieee80211vap *vap)
 1656 {
 1657 
 1658         IEEE80211_LOCK_ASSERT(vap->iv_ic);
 1659 
 1660         if ((vap->iv_flags_ht & IEEE80211_FHT_NONHT_PR) &&
 1661             ieee80211_time_after(ticks, vap->iv_lastnonht + IEEE80211_NONHT_PRESENT_AGE)) {
 1662                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N,
 1663                     "%s", "time out non-HT STA present on channel");
 1664                 vap->iv_flags_ht &= ~IEEE80211_FHT_NONHT_PR;
 1665                 htinfo_update(vap);
 1666         }
 1667 }
 1668 
 1669 /*
 1670  * Process an 802.11n HT capabilities ie.
 1671  */
 1672 void
 1673 ieee80211_parse_htcap(struct ieee80211_node *ni, const uint8_t *ie)
 1674 {
 1675         if (ie[0] == IEEE80211_ELEMID_VENDOR) {
 1676                 /*
 1677                  * Station used Vendor OUI ie to associate;
 1678                  * mark the node so when we respond we'll use
 1679                  * the Vendor OUI's and not the standard ie's.
 1680                  */
 1681                 ni->ni_flags |= IEEE80211_NODE_HTCOMPAT;
 1682                 ie += 4;
 1683         } else
 1684                 ni->ni_flags &= ~IEEE80211_NODE_HTCOMPAT;
 1685 
 1686         ni->ni_htcap = le16dec(ie +
 1687                 __offsetof(struct ieee80211_ie_htcap, hc_cap));
 1688         ni->ni_htparam = ie[__offsetof(struct ieee80211_ie_htcap, hc_param)];
 1689 }
 1690 
 1691 static void
 1692 htinfo_parse(struct ieee80211_node *ni,
 1693         const struct ieee80211_ie_htinfo *htinfo)
 1694 {
 1695         uint16_t w;
 1696 
 1697         ni->ni_htctlchan = htinfo->hi_ctrlchannel;
 1698         ni->ni_ht2ndchan = _IEEE80211_SHIFTMASK(htinfo->hi_byte1,
 1699             IEEE80211_HTINFO_2NDCHAN);
 1700         w = le16dec(&htinfo->hi_byte2);
 1701         ni->ni_htopmode = _IEEE80211_SHIFTMASK(w, IEEE80211_HTINFO_OPMODE);
 1702         w = le16dec(&htinfo->hi_byte45);
 1703         ni->ni_htstbc = _IEEE80211_SHIFTMASK(w, IEEE80211_HTINFO_BASIC_STBCMCS);
 1704 }
 1705 
 1706 /*
 1707  * Parse an 802.11n HT info ie and save useful information
 1708  * to the node state.  Note this does not effect any state
 1709  * changes such as for channel width change.
 1710  */
 1711 void
 1712 ieee80211_parse_htinfo(struct ieee80211_node *ni, const uint8_t *ie)
 1713 {
 1714         if (ie[0] == IEEE80211_ELEMID_VENDOR)
 1715                 ie += 4;
 1716         htinfo_parse(ni, (const struct ieee80211_ie_htinfo *) ie);
 1717 }
 1718 
 1719 /*
 1720  * Handle 11n/11ac channel switch.
 1721  *
 1722  * Use the received HT/VHT ie's to identify the right channel to use.
 1723  * If we cannot locate it in the channel table then fallback to
 1724  * legacy operation.
 1725  *
 1726  * Note that we use this information to identify the node's
 1727  * channel only; the caller is responsible for insuring any
 1728  * required channel change is done (e.g. in sta mode when
 1729  * parsing the contents of a beacon frame).
 1730  */
 1731 static int
 1732 htinfo_update_chw(struct ieee80211_node *ni, int htflags, int vhtflags)
 1733 {
 1734         struct ieee80211com *ic = ni->ni_ic;
 1735         struct ieee80211_channel *c;
 1736         int chanflags;
 1737         int ret = 0;
 1738 
 1739         /*
 1740          * First step - do HT/VHT only channel lookup based on operating mode
 1741          * flags.  This involves masking out the VHT flags as well.
 1742          * Otherwise we end up doing the full channel walk each time
 1743          * we trigger this, which is expensive.
 1744          */
 1745         chanflags = (ni->ni_chan->ic_flags &~
 1746             (IEEE80211_CHAN_HT | IEEE80211_CHAN_VHT)) | htflags | vhtflags;
 1747 
 1748         if (chanflags == ni->ni_chan->ic_flags)
 1749                 goto done;
 1750 
 1751         /*
 1752          * If HT /or/ VHT flags have changed then check both.
 1753          * We need to start by picking a HT channel anyway.
 1754          */
 1755 
 1756         c = NULL;
 1757         chanflags = (ni->ni_chan->ic_flags &~
 1758             (IEEE80211_CHAN_HT | IEEE80211_CHAN_VHT)) | htflags;
 1759         /* XXX not right for ht40- */
 1760         c = ieee80211_find_channel(ic, ni->ni_chan->ic_freq, chanflags);
 1761         if (c == NULL && (htflags & IEEE80211_CHAN_HT40)) {
 1762                 /*
 1763                  * No HT40 channel entry in our table; fall back
 1764                  * to HT20 operation.  This should not happen.
 1765                  */
 1766                 c = findhtchan(ic, ni->ni_chan, IEEE80211_CHAN_HT20);
 1767 #if 0
 1768                 IEEE80211_NOTE(ni->ni_vap,
 1769                     IEEE80211_MSG_ASSOC | IEEE80211_MSG_11N, ni,
 1770                     "no HT40 channel (freq %u), falling back to HT20",
 1771                     ni->ni_chan->ic_freq);
 1772 #endif
 1773                 /* XXX stat */
 1774         }
 1775 
 1776         /* Nothing found - leave it alone; move onto VHT */
 1777         if (c == NULL)
 1778                 c = ni->ni_chan;
 1779 
 1780         /*
 1781          * If it's non-HT, then bail out now.
 1782          */
 1783         if (! IEEE80211_IS_CHAN_HT(c)) {
 1784                 IEEE80211_NOTE(ni->ni_vap,
 1785                     IEEE80211_MSG_ASSOC | IEEE80211_MSG_11N, ni,
 1786                     "not HT; skipping VHT check (%u/0x%x)",
 1787                     c->ic_freq, c->ic_flags);
 1788                 goto done;
 1789         }
 1790 
 1791         /*
 1792          * Next step - look at the current VHT flags and determine
 1793          * if we need to upgrade.  Mask out the VHT and HT flags since
 1794          * the vhtflags field will already have the correct HT
 1795          * flags to use.
 1796          */
 1797         if (IEEE80211_CONF_VHT(ic) && ni->ni_vhtcap != 0 && vhtflags != 0) {
 1798                 chanflags = (c->ic_flags
 1799                     &~ (IEEE80211_CHAN_HT | IEEE80211_CHAN_VHT))
 1800                     | vhtflags;
 1801                 IEEE80211_NOTE(ni->ni_vap,
 1802                     IEEE80211_MSG_ASSOC | IEEE80211_MSG_11N,
 1803                     ni,
 1804                     "%s: VHT; chanwidth=0x%02x; vhtflags=0x%08x",
 1805                     __func__, ni->ni_vht_chanwidth, vhtflags);
 1806 
 1807                 IEEE80211_NOTE(ni->ni_vap,
 1808                     IEEE80211_MSG_ASSOC | IEEE80211_MSG_11N,
 1809                     ni,
 1810                     "%s: VHT; trying lookup for %d/0x%08x",
 1811                     __func__, c->ic_freq, chanflags);
 1812                 c = ieee80211_find_channel(ic, c->ic_freq, chanflags);
 1813         }
 1814 
 1815         /* Finally, if it's changed */
 1816         if (c != NULL && c != ni->ni_chan) {
 1817                 IEEE80211_NOTE(ni->ni_vap,
 1818                     IEEE80211_MSG_ASSOC | IEEE80211_MSG_11N, ni,
 1819                     "switch station to %s%d channel %u/0x%x",
 1820                     IEEE80211_IS_CHAN_VHT(c) ? "VHT" : "HT",
 1821                     IEEE80211_IS_CHAN_VHT80(c) ? 80 :
 1822                       (IEEE80211_IS_CHAN_HT40(c) ? 40 : 20),
 1823                     c->ic_freq, c->ic_flags);
 1824                 ni->ni_chan = c;
 1825                 ret = 1;
 1826         }
 1827         /* NB: caller responsible for forcing any channel change */
 1828 
 1829 done:
 1830         /* update node's (11n) tx channel width */
 1831         ni->ni_chw = IEEE80211_IS_CHAN_HT40(ni->ni_chan)? 40 : 20;
 1832         return (ret);
 1833 }
 1834 
 1835 /*
 1836  * Update 11n MIMO PS state according to received htcap.
 1837  */
 1838 static __inline int
 1839 htcap_update_mimo_ps(struct ieee80211_node *ni)
 1840 {
 1841         uint16_t oflags = ni->ni_flags;
 1842 
 1843         switch (ni->ni_htcap & IEEE80211_HTCAP_SMPS) {
 1844         case IEEE80211_HTCAP_SMPS_DYNAMIC:
 1845                 ni->ni_flags |= IEEE80211_NODE_MIMO_PS;
 1846                 ni->ni_flags |= IEEE80211_NODE_MIMO_RTS;
 1847                 break;
 1848         case IEEE80211_HTCAP_SMPS_ENA:
 1849                 ni->ni_flags |= IEEE80211_NODE_MIMO_PS;
 1850                 ni->ni_flags &= ~IEEE80211_NODE_MIMO_RTS;
 1851                 break;
 1852         case IEEE80211_HTCAP_SMPS_OFF:
 1853         default:                /* disable on rx of reserved value */
 1854                 ni->ni_flags &= ~IEEE80211_NODE_MIMO_PS;
 1855                 ni->ni_flags &= ~IEEE80211_NODE_MIMO_RTS;
 1856                 break;
 1857         }
 1858         return (oflags ^ ni->ni_flags);
 1859 }
 1860 
 1861 /*
 1862  * Update short GI state according to received htcap
 1863  * and local settings.
 1864  */
 1865 static __inline void
 1866 htcap_update_shortgi(struct ieee80211_node *ni)
 1867 {
 1868         struct ieee80211vap *vap = ni->ni_vap;
 1869 
 1870         ni->ni_flags &= ~(IEEE80211_NODE_SGI20|IEEE80211_NODE_SGI40);
 1871         if ((ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) &&
 1872             (vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20))
 1873                 ni->ni_flags |= IEEE80211_NODE_SGI20;
 1874         if ((ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) &&
 1875             (vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40))
 1876                 ni->ni_flags |= IEEE80211_NODE_SGI40;
 1877 }
 1878 
 1879 /*
 1880  * Update LDPC state according to received htcap
 1881  * and local settings.
 1882  */
 1883 static __inline void
 1884 htcap_update_ldpc(struct ieee80211_node *ni)
 1885 {
 1886         struct ieee80211vap *vap = ni->ni_vap;
 1887 
 1888         if ((ni->ni_htcap & IEEE80211_HTCAP_LDPC) &&
 1889             (vap->iv_flags_ht & IEEE80211_FHT_LDPC_TX))
 1890                 ni->ni_flags |= IEEE80211_NODE_LDPC;
 1891 }
 1892 
 1893 /*
 1894  * Parse and update HT-related state extracted from
 1895  * the HT cap and info ie's.
 1896  *
 1897  * This is called from the STA management path and
 1898  * the ieee80211_node_join() path.  It will take into
 1899  * account the IEs discovered during scanning and
 1900  * adjust things accordingly.
 1901  */
 1902 void
 1903 ieee80211_ht_updateparams(struct ieee80211_node *ni,
 1904         const uint8_t *htcapie, const uint8_t *htinfoie)
 1905 {
 1906         struct ieee80211vap *vap = ni->ni_vap;
 1907         const struct ieee80211_ie_htinfo *htinfo;
 1908 
 1909         ieee80211_parse_htcap(ni, htcapie);
 1910         if (vap->iv_htcaps & IEEE80211_HTC_SMPS)
 1911                 htcap_update_mimo_ps(ni);
 1912         htcap_update_shortgi(ni);
 1913         htcap_update_ldpc(ni);
 1914 
 1915         if (htinfoie[0] == IEEE80211_ELEMID_VENDOR)
 1916                 htinfoie += 4;
 1917         htinfo = (const struct ieee80211_ie_htinfo *) htinfoie;
 1918         htinfo_parse(ni, htinfo);
 1919 
 1920         /*
 1921          * Defer the node channel change; we need to now
 1922          * update VHT parameters before we do it.
 1923          */
 1924 
 1925         if ((htinfo->hi_byte1 & IEEE80211_HTINFO_RIFSMODE_PERM) &&
 1926             (vap->iv_flags_ht & IEEE80211_FHT_RIFS))
 1927                 ni->ni_flags |= IEEE80211_NODE_RIFS;
 1928         else
 1929                 ni->ni_flags &= ~IEEE80211_NODE_RIFS;
 1930 }
 1931 
 1932 static uint32_t
 1933 ieee80211_vht_get_vhtflags(struct ieee80211_node *ni, uint32_t htflags)
 1934 {
 1935         struct ieee80211vap *vap = ni->ni_vap;
 1936         uint32_t vhtflags = 0;
 1937 
 1938         vhtflags = 0;
 1939         if (ni->ni_flags & IEEE80211_NODE_VHT && vap->iv_flags_vht & IEEE80211_FVHT_VHT) {
 1940                 if ((ni->ni_vht_chanwidth == IEEE80211_VHT_CHANWIDTH_160MHZ) &&
 1941                     /* XXX 2 means "160MHz and 80+80MHz", 1 means "160MHz" */
 1942                     (_IEEE80211_MASKSHIFT(vap->iv_vhtcaps,
 1943                      IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) >= 1) &&
 1944                     (vap->iv_flags_vht & IEEE80211_FVHT_USEVHT160)) {
 1945                         vhtflags = IEEE80211_CHAN_VHT160;
 1946                         /* Mirror the HT40 flags */
 1947                         if (htflags == IEEE80211_CHAN_HT40U) {
 1948                                 vhtflags |= IEEE80211_CHAN_HT40U;
 1949                         } else if (htflags == IEEE80211_CHAN_HT40D) {
 1950                                 vhtflags |= IEEE80211_CHAN_HT40D;
 1951                         }
 1952                 } else if ((ni->ni_vht_chanwidth == IEEE80211_VHT_CHANWIDTH_80P80MHZ) &&
 1953                     /* XXX 2 means "160MHz and 80+80MHz" */
 1954                     (_IEEE80211_MASKSHIFT(vap->iv_vhtcaps,
 1955                      IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK) == 2) &&
 1956                     (vap->iv_flags_vht & IEEE80211_FVHT_USEVHT80P80)) {
 1957                         vhtflags = IEEE80211_CHAN_VHT80P80;
 1958                         /* Mirror the HT40 flags */
 1959                         if (htflags == IEEE80211_CHAN_HT40U) {
 1960                                 vhtflags |= IEEE80211_CHAN_HT40U;
 1961                         } else if (htflags == IEEE80211_CHAN_HT40D) {
 1962                                 vhtflags |= IEEE80211_CHAN_HT40D;
 1963                         }
 1964                 } else if ((ni->ni_vht_chanwidth == IEEE80211_VHT_CHANWIDTH_80MHZ) &&
 1965                     (vap->iv_flags_vht & IEEE80211_FVHT_USEVHT80)) {
 1966                         vhtflags = IEEE80211_CHAN_VHT80;
 1967                         /* Mirror the HT40 flags */
 1968                         if (htflags == IEEE80211_CHAN_HT40U) {
 1969                                 vhtflags |= IEEE80211_CHAN_HT40U;
 1970                         } else if (htflags == IEEE80211_CHAN_HT40D) {
 1971                                 vhtflags |= IEEE80211_CHAN_HT40D;
 1972                         }
 1973                 } else if (ni->ni_vht_chanwidth == IEEE80211_VHT_CHANWIDTH_USE_HT) {
 1974                         /* Mirror the HT40 flags */
 1975                         /*
 1976                          * XXX TODO: if ht40 is disabled, but vht40 isn't
 1977                          * disabled then this logic will get very, very sad.
 1978                          * It's quite possible the only sane thing to do is
 1979                          * to not have vht40 as an option, and just obey
 1980                          * 'ht40' as that flag.
 1981                          */
 1982                         if ((htflags == IEEE80211_CHAN_HT40U) &&
 1983                             (vap->iv_flags_vht & IEEE80211_FVHT_USEVHT40)) {
 1984                                 vhtflags = IEEE80211_CHAN_VHT40U
 1985                                     | IEEE80211_CHAN_HT40U;
 1986                         } else if (htflags == IEEE80211_CHAN_HT40D &&
 1987                             (vap->iv_flags_vht & IEEE80211_FVHT_USEVHT40)) {
 1988                                 vhtflags = IEEE80211_CHAN_VHT40D
 1989                                     | IEEE80211_CHAN_HT40D;
 1990                         } else if (htflags == IEEE80211_CHAN_HT20) {
 1991                                 vhtflags = IEEE80211_CHAN_VHT20
 1992                                     | IEEE80211_CHAN_HT20;
 1993                         }
 1994                 } else {
 1995                         vhtflags = IEEE80211_CHAN_VHT20;
 1996                 }
 1997         }
 1998         return (vhtflags);
 1999 }
 2000 
 2001 /*
 2002  * Final part of updating the HT parameters.
 2003  *
 2004  * This is called from the STA management path and
 2005  * the ieee80211_node_join() path.  It will take into
 2006  * account the IEs discovered during scanning and
 2007  * adjust things accordingly.
 2008  *
 2009  * This is done after a call to ieee80211_ht_updateparams()
 2010  * because it (and the upcoming VHT version of updateparams)
 2011  * needs to ensure everything is parsed before htinfo_update_chw()
 2012  * is called - which will change the channel config for the
 2013  * node for us.
 2014  */
 2015 int
 2016 ieee80211_ht_updateparams_final(struct ieee80211_node *ni,
 2017         const uint8_t *htcapie, const uint8_t *htinfoie)
 2018 {
 2019         struct ieee80211vap *vap = ni->ni_vap;
 2020         const struct ieee80211_ie_htinfo *htinfo;
 2021         int htflags, vhtflags;
 2022         int ret = 0;
 2023 
 2024         htinfo = (const struct ieee80211_ie_htinfo *) htinfoie;
 2025 
 2026         htflags = (vap->iv_flags_ht & IEEE80211_FHT_HT) ?
 2027             IEEE80211_CHAN_HT20 : 0;
 2028 
 2029         /* NB: honor operating mode constraint */
 2030         if ((htinfo->hi_byte1 & IEEE80211_HTINFO_TXWIDTH_2040) &&
 2031             (vap->iv_flags_ht & IEEE80211_FHT_USEHT40)) {
 2032                 if (ni->ni_ht2ndchan == IEEE80211_HTINFO_2NDCHAN_ABOVE)
 2033                         htflags = IEEE80211_CHAN_HT40U;
 2034                 else if (ni->ni_ht2ndchan == IEEE80211_HTINFO_2NDCHAN_BELOW)
 2035                         htflags = IEEE80211_CHAN_HT40D;
 2036         }
 2037 
 2038         /*
 2039          * VHT flags - do much the same; check whether VHT is available
 2040          * and if so, what our ideal channel use would be based on our
 2041          * capabilities and the (pre-parsed) VHT info IE.
 2042          */
 2043         vhtflags = ieee80211_vht_get_vhtflags(ni, htflags);
 2044 
 2045         if (htinfo_update_chw(ni, htflags, vhtflags))
 2046                 ret = 1;
 2047 
 2048         return (ret);
 2049 }
 2050 
 2051 /*
 2052  * Parse and update HT-related state extracted from the HT cap ie
 2053  * for a station joining an HT BSS.
 2054  *
 2055  * This is called from the hostap path for each station.
 2056  */
 2057 void
 2058 ieee80211_ht_updatehtcap(struct ieee80211_node *ni, const uint8_t *htcapie)
 2059 {
 2060         struct ieee80211vap *vap = ni->ni_vap;
 2061 
 2062         ieee80211_parse_htcap(ni, htcapie);
 2063         if (vap->iv_htcaps & IEEE80211_HTC_SMPS)
 2064                 htcap_update_mimo_ps(ni);
 2065         htcap_update_shortgi(ni);
 2066         htcap_update_ldpc(ni);
 2067 }
 2068 
 2069 /*
 2070  * Called once HT and VHT capabilities are parsed in hostap mode -
 2071  * this will adjust the channel configuration of the given node
 2072  * based on the configuration and capabilities.
 2073  */
 2074 void
 2075 ieee80211_ht_updatehtcap_final(struct ieee80211_node *ni)
 2076 {
 2077         struct ieee80211vap *vap = ni->ni_vap;
 2078         int htflags;
 2079         int vhtflags;
 2080 
 2081         /* NB: honor operating mode constraint */
 2082         /* XXX 40 MHz intolerant */
 2083         htflags = (vap->iv_flags_ht & IEEE80211_FHT_HT) ?
 2084             IEEE80211_CHAN_HT20 : 0;
 2085         if ((ni->ni_htcap & IEEE80211_HTCAP_CHWIDTH40) &&
 2086             (vap->iv_flags_ht & IEEE80211_FHT_USEHT40)) {
 2087                 if (IEEE80211_IS_CHAN_HT40U(vap->iv_bss->ni_chan))
 2088                         htflags = IEEE80211_CHAN_HT40U;
 2089                 else if (IEEE80211_IS_CHAN_HT40D(vap->iv_bss->ni_chan))
 2090                         htflags = IEEE80211_CHAN_HT40D;
 2091         }
 2092         /*
 2093          * VHT flags - do much the same; check whether VHT is available
 2094          * and if so, what our ideal channel use would be based on our
 2095          * capabilities and the (pre-parsed) VHT info IE.
 2096          */
 2097         vhtflags = ieee80211_vht_get_vhtflags(ni, htflags);
 2098 
 2099         (void) htinfo_update_chw(ni, htflags, vhtflags);
 2100 }
 2101 
 2102 /*
 2103  * Install received HT rate set by parsing the HT cap ie.
 2104  */
 2105 int
 2106 ieee80211_setup_htrates(struct ieee80211_node *ni, const uint8_t *ie, int flags)
 2107 {
 2108         struct ieee80211com *ic = ni->ni_ic;
 2109         struct ieee80211vap *vap = ni->ni_vap;
 2110         const struct ieee80211_ie_htcap *htcap;
 2111         struct ieee80211_htrateset *rs;
 2112         int i, maxequalmcs, maxunequalmcs;
 2113 
 2114         maxequalmcs = ic->ic_txstream * 8 - 1;
 2115         maxunequalmcs = 0;
 2116         if (ic->ic_htcaps & IEEE80211_HTC_TXUNEQUAL) {
 2117                 if (ic->ic_txstream >= 2)
 2118                         maxunequalmcs = 38;
 2119                 if (ic->ic_txstream >= 3)
 2120                         maxunequalmcs = 52;
 2121                 if (ic->ic_txstream >= 4)
 2122                         maxunequalmcs = 76;
 2123         }
 2124 
 2125         rs = &ni->ni_htrates;
 2126         memset(rs, 0, sizeof(*rs));
 2127         if (ie != NULL) {
 2128                 if (ie[0] == IEEE80211_ELEMID_VENDOR)
 2129                         ie += 4;
 2130                 htcap = (const struct ieee80211_ie_htcap *) ie;
 2131                 for (i = 0; i < IEEE80211_HTRATE_MAXSIZE; i++) {
 2132                         if (isclr(htcap->hc_mcsset, i))
 2133                                 continue;
 2134                         if (rs->rs_nrates == IEEE80211_HTRATE_MAXSIZE) {
 2135                                 IEEE80211_NOTE(vap,
 2136                                     IEEE80211_MSG_XRATE | IEEE80211_MSG_11N, ni,
 2137                                     "WARNING, HT rate set too large; only "
 2138                                     "using %u rates", IEEE80211_HTRATE_MAXSIZE);
 2139                                 vap->iv_stats.is_rx_rstoobig++;
 2140                                 break;
 2141                         }
 2142                         if (i <= 31 && i > maxequalmcs)
 2143                                 continue;
 2144                         if (i == 32 &&
 2145                             (ic->ic_htcaps & IEEE80211_HTC_TXMCS32) == 0)
 2146                                 continue;
 2147                         if (i > 32 && i > maxunequalmcs)
 2148                                 continue;
 2149                         rs->rs_rates[rs->rs_nrates++] = i;
 2150                 }
 2151         }
 2152         return ieee80211_fix_rate(ni, (struct ieee80211_rateset *) rs, flags);
 2153 }
 2154 
 2155 /*
 2156  * Mark rates in a node's HT rate set as basic according
 2157  * to the information in the supplied HT info ie.
 2158  */
 2159 void
 2160 ieee80211_setup_basic_htrates(struct ieee80211_node *ni, const uint8_t *ie)
 2161 {
 2162         const struct ieee80211_ie_htinfo *htinfo;
 2163         struct ieee80211_htrateset *rs;
 2164         int i, j;
 2165 
 2166         if (ie[0] == IEEE80211_ELEMID_VENDOR)
 2167                 ie += 4;
 2168         htinfo = (const struct ieee80211_ie_htinfo *) ie;
 2169         rs = &ni->ni_htrates;
 2170         if (rs->rs_nrates == 0) {
 2171                 IEEE80211_NOTE(ni->ni_vap,
 2172                     IEEE80211_MSG_XRATE | IEEE80211_MSG_11N, ni,
 2173                     "%s", "WARNING, empty HT rate set");
 2174                 return;
 2175         }
 2176         for (i = 0; i < IEEE80211_HTRATE_MAXSIZE; i++) {
 2177                 if (isclr(htinfo->hi_basicmcsset, i))
 2178                         continue;
 2179                 for (j = 0; j < rs->rs_nrates; j++)
 2180                         if ((rs->rs_rates[j] & IEEE80211_RATE_VAL) == i)
 2181                                 rs->rs_rates[j] |= IEEE80211_RATE_BASIC;
 2182         }
 2183 }
 2184 
 2185 static void
 2186 ampdu_tx_setup(struct ieee80211_tx_ampdu *tap)
 2187 {
 2188         callout_init(&tap->txa_timer, 1);
 2189         tap->txa_flags |= IEEE80211_AGGR_SETUP;
 2190         tap->txa_lastsample = ticks;
 2191 }
 2192 
 2193 static void
 2194 ampdu_tx_stop(struct ieee80211_tx_ampdu *tap)
 2195 {
 2196         struct ieee80211_node *ni = tap->txa_ni;
 2197         struct ieee80211com *ic = ni->ni_ic;
 2198 
 2199         IEEE80211_NOTE(tap->txa_ni->ni_vap, IEEE80211_MSG_11N,
 2200             tap->txa_ni,
 2201             "%s: called",
 2202             __func__);
 2203 
 2204         KASSERT(tap->txa_flags & IEEE80211_AGGR_SETUP,
 2205             ("txa_flags 0x%x tid %d ac %d", tap->txa_flags, tap->txa_tid,
 2206             TID_TO_WME_AC(tap->txa_tid)));
 2207 
 2208         /*
 2209          * Stop BA stream if setup so driver has a chance
 2210          * to reclaim any resources it might have allocated.
 2211          */
 2212         ic->ic_addba_stop(ni, tap);
 2213         /*
 2214          * Stop any pending BAR transmit.
 2215          */
 2216         bar_stop_timer(tap);
 2217 
 2218         /*
 2219          * Reset packet estimate.
 2220          */
 2221         ieee80211_txampdu_init_pps(tap);
 2222 
 2223         /* NB: clearing NAK means we may re-send ADDBA */ 
 2224         tap->txa_flags &= ~(IEEE80211_AGGR_SETUP | IEEE80211_AGGR_NAK);
 2225 }
 2226 
 2227 /*
 2228  * ADDBA response timeout.
 2229  *
 2230  * If software aggregation and per-TID queue management was done here,
 2231  * that queue would be unpaused after the ADDBA timeout occurs.
 2232  */
 2233 static void
 2234 addba_timeout(void *arg)
 2235 {
 2236         struct ieee80211_tx_ampdu *tap = arg;
 2237         struct ieee80211_node *ni = tap->txa_ni;
 2238         struct ieee80211com *ic = ni->ni_ic;
 2239 
 2240         /* XXX ? */
 2241         tap->txa_flags &= ~IEEE80211_AGGR_XCHGPEND;
 2242         tap->txa_attempts++;
 2243         ic->ic_addba_response_timeout(ni, tap);
 2244 }
 2245 
 2246 static void
 2247 addba_start_timeout(struct ieee80211_tx_ampdu *tap)
 2248 {
 2249         /* XXX use CALLOUT_PENDING instead? */
 2250         callout_reset(&tap->txa_timer, ieee80211_addba_timeout,
 2251             addba_timeout, tap);
 2252         tap->txa_flags |= IEEE80211_AGGR_XCHGPEND;
 2253         tap->txa_nextrequest = ticks + ieee80211_addba_timeout;
 2254 }
 2255 
 2256 static void
 2257 addba_stop_timeout(struct ieee80211_tx_ampdu *tap)
 2258 {
 2259         /* XXX use CALLOUT_PENDING instead? */
 2260         if (tap->txa_flags & IEEE80211_AGGR_XCHGPEND) {
 2261                 callout_stop(&tap->txa_timer);
 2262                 tap->txa_flags &= ~IEEE80211_AGGR_XCHGPEND;
 2263         }
 2264 }
 2265 
 2266 static void
 2267 null_addba_response_timeout(struct ieee80211_node *ni,
 2268     struct ieee80211_tx_ampdu *tap)
 2269 {
 2270 }
 2271 
 2272 /*
 2273  * Default method for requesting A-MPDU tx aggregation.
 2274  * We setup the specified state block and start a timer
 2275  * to wait for an ADDBA response frame.
 2276  */
 2277 static int
 2278 ieee80211_addba_request(struct ieee80211_node *ni,
 2279         struct ieee80211_tx_ampdu *tap,
 2280         int dialogtoken, int baparamset, int batimeout)
 2281 {
 2282         int bufsiz;
 2283 
 2284         /* XXX locking */
 2285         tap->txa_token = dialogtoken;
 2286         tap->txa_flags |= IEEE80211_AGGR_IMMEDIATE;
 2287         bufsiz = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_BUFSIZ);
 2288         tap->txa_wnd = (bufsiz == 0) ?
 2289             IEEE80211_AGGR_BAWMAX : min(bufsiz, IEEE80211_AGGR_BAWMAX);
 2290         addba_start_timeout(tap);
 2291         return 1;
 2292 }
 2293 
 2294 /*
 2295  * Called by drivers that wish to request an ADDBA session be
 2296  * setup.  This brings it up and starts the request timer.
 2297  */
 2298 int
 2299 ieee80211_ampdu_tx_request_ext(struct ieee80211_node *ni, int tid)
 2300 {
 2301         struct ieee80211_tx_ampdu *tap;
 2302 
 2303         if (tid < 0 || tid > 15)
 2304                 return (0);
 2305         tap = &ni->ni_tx_ampdu[tid];
 2306 
 2307         /* XXX locking */
 2308         if ((tap->txa_flags & IEEE80211_AGGR_SETUP) == 0) {
 2309                 /* do deferred setup of state */
 2310                 ampdu_tx_setup(tap);
 2311         }
 2312         /* XXX hack for not doing proper locking */
 2313         tap->txa_flags &= ~IEEE80211_AGGR_NAK;
 2314         addba_start_timeout(tap);
 2315         return (1);
 2316 }
 2317 
 2318 /*
 2319  * Called by drivers that have marked a session as active.
 2320  */
 2321 int
 2322 ieee80211_ampdu_tx_request_active_ext(struct ieee80211_node *ni, int tid,
 2323     int status)
 2324 {
 2325         struct ieee80211_tx_ampdu *tap;
 2326 
 2327         if (tid < 0 || tid > 15)
 2328                 return (0);
 2329         tap = &ni->ni_tx_ampdu[tid];
 2330 
 2331         /* XXX locking */
 2332         addba_stop_timeout(tap);
 2333         if (status == 1) {
 2334                 tap->txa_flags |= IEEE80211_AGGR_RUNNING;
 2335                 tap->txa_attempts = 0;
 2336         } else {
 2337                 /* mark tid so we don't try again */
 2338                 tap->txa_flags |= IEEE80211_AGGR_NAK;
 2339         }
 2340         return (1);
 2341 }
 2342 
 2343 /*
 2344  * Default method for processing an A-MPDU tx aggregation
 2345  * response.  We shutdown any pending timer and update the
 2346  * state block according to the reply.
 2347  */
 2348 static int
 2349 ieee80211_addba_response(struct ieee80211_node *ni,
 2350         struct ieee80211_tx_ampdu *tap,
 2351         int status, int baparamset, int batimeout)
 2352 {
 2353         struct ieee80211vap *vap = ni->ni_vap;
 2354         int bufsiz;
 2355 
 2356         /* XXX locking */
 2357         addba_stop_timeout(tap);
 2358         if (status == IEEE80211_STATUS_SUCCESS) {
 2359                 bufsiz = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_BUFSIZ);
 2360                 /* XXX override our request? */
 2361                 tap->txa_wnd = (bufsiz == 0) ?
 2362                     IEEE80211_AGGR_BAWMAX : min(bufsiz, IEEE80211_AGGR_BAWMAX);
 2363 #ifdef __notyet__
 2364                 tid = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_TID);
 2365 #endif
 2366                 tap->txa_flags |= IEEE80211_AGGR_RUNNING;
 2367                 tap->txa_attempts = 0;
 2368                 /* TODO: this should be a vap flag */
 2369                 if ((vap->iv_htcaps & IEEE80211_HTC_TX_AMSDU_AMPDU) &&
 2370                     (ni->ni_flags & IEEE80211_NODE_AMSDU_TX) &&
 2371                     (_IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_AMSDU)))
 2372                         tap->txa_flags |= IEEE80211_AGGR_AMSDU;
 2373                 else
 2374                         tap->txa_flags &= ~IEEE80211_AGGR_AMSDU;
 2375         } else {
 2376                 /* mark tid so we don't try again */
 2377                 tap->txa_flags |= IEEE80211_AGGR_NAK;
 2378         }
 2379         return 1;
 2380 }
 2381 
 2382 /*
 2383  * Default method for stopping A-MPDU tx aggregation.
 2384  * Any timer is cleared and we drain any pending frames.
 2385  */
 2386 static void
 2387 ieee80211_addba_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
 2388 {
 2389         /* XXX locking */
 2390         addba_stop_timeout(tap);
 2391         if (tap->txa_flags & IEEE80211_AGGR_RUNNING) {
 2392                 /* XXX clear aggregation queue */
 2393                 tap->txa_flags &= ~(IEEE80211_AGGR_RUNNING | IEEE80211_AGGR_AMSDU);
 2394         }
 2395         tap->txa_attempts = 0;
 2396 }
 2397 
 2398 /*
 2399  * Process a received action frame using the default aggregation
 2400  * policy.  We intercept ADDBA-related frames and use them to
 2401  * update our aggregation state.  All other frames are passed up
 2402  * for processing by ieee80211_recv_action.
 2403  */
 2404 static int
 2405 ht_recv_action_ba_addba_request(struct ieee80211_node *ni,
 2406         const struct ieee80211_frame *wh,
 2407         const uint8_t *frm, const uint8_t *efrm)
 2408 {
 2409         struct ieee80211com *ic = ni->ni_ic;
 2410         struct ieee80211vap *vap = ni->ni_vap;
 2411         struct ieee80211_rx_ampdu *rap;
 2412         uint8_t dialogtoken;
 2413         uint16_t baparamset, batimeout, baseqctl;
 2414         uint16_t args[5];
 2415         int tid;
 2416 
 2417         dialogtoken = frm[2];
 2418         baparamset = le16dec(frm+3);
 2419         batimeout = le16dec(frm+5);
 2420         baseqctl = le16dec(frm+7);
 2421 
 2422         tid = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_TID);
 2423 
 2424         IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
 2425             "recv ADDBA request: dialogtoken %u baparamset 0x%x "
 2426             "(tid %d bufsiz %d) batimeout %d baseqctl %d:%d amsdu %d",
 2427             dialogtoken, baparamset,
 2428             tid, _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_BUFSIZ),
 2429             batimeout,
 2430             _IEEE80211_MASKSHIFT(baseqctl, IEEE80211_BASEQ_START),
 2431             _IEEE80211_MASKSHIFT(baseqctl, IEEE80211_BASEQ_FRAG),
 2432             _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_AMSDU));
 2433 
 2434         rap = &ni->ni_rx_ampdu[tid];
 2435 
 2436         /* Send ADDBA response */
 2437         args[0] = dialogtoken;
 2438         /*
 2439          * NB: We ack only if the sta associated with HT and
 2440          * the ap is configured to do AMPDU rx (the latter
 2441          * violates the 11n spec and is mostly for testing).
 2442          */
 2443         if ((ni->ni_flags & IEEE80211_NODE_AMPDU_RX) &&
 2444             (vap->iv_flags_ht & IEEE80211_FHT_AMPDU_RX)) {
 2445                 /* XXX TODO: handle ampdu_rx_start failure */
 2446                 ic->ic_ampdu_rx_start(ni, rap,
 2447                     baparamset, batimeout, baseqctl);
 2448 
 2449                 args[1] = IEEE80211_STATUS_SUCCESS;
 2450         } else {
 2451                 IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
 2452                     ni, "reject ADDBA request: %s",
 2453                     ni->ni_flags & IEEE80211_NODE_AMPDU_RX ?
 2454                        "administratively disabled" :
 2455                        "not negotiated for station");
 2456                 vap->iv_stats.is_addba_reject++;
 2457                 args[1] = IEEE80211_STATUS_UNSPECIFIED;
 2458         }
 2459         /* XXX honor rap flags? */
 2460         args[2] = IEEE80211_BAPS_POLICY_IMMEDIATE
 2461                 | _IEEE80211_SHIFTMASK(tid, IEEE80211_BAPS_TID)
 2462                 | _IEEE80211_SHIFTMASK(rap->rxa_wnd, IEEE80211_BAPS_BUFSIZ)
 2463                 ;
 2464 
 2465         /*
 2466          * TODO: we're out of iv_flags_ht fields; once
 2467          * this is extended we should make this configurable.
 2468          */
 2469         if ((baparamset & IEEE80211_BAPS_AMSDU) &&
 2470             (ni->ni_flags & IEEE80211_NODE_AMSDU_RX) &&
 2471             (vap->iv_htcaps & IEEE80211_HTC_RX_AMSDU_AMPDU))
 2472                 args[2] |= IEEE80211_BAPS_AMSDU;
 2473 
 2474         args[3] = 0;
 2475         args[4] = 0;
 2476         ic->ic_send_action(ni, IEEE80211_ACTION_CAT_BA,
 2477                 IEEE80211_ACTION_BA_ADDBA_RESPONSE, args);
 2478         return 0;
 2479 }
 2480 
 2481 static int
 2482 ht_recv_action_ba_addba_response(struct ieee80211_node *ni,
 2483         const struct ieee80211_frame *wh,
 2484         const uint8_t *frm, const uint8_t *efrm)
 2485 {
 2486         struct ieee80211com *ic = ni->ni_ic;
 2487         struct ieee80211vap *vap = ni->ni_vap;
 2488         struct ieee80211_tx_ampdu *tap;
 2489         uint8_t dialogtoken, policy;
 2490         uint16_t baparamset, batimeout, code;
 2491         int tid;
 2492 #ifdef IEEE80211_DEBUG
 2493         int amsdu, bufsiz;
 2494 #endif
 2495 
 2496         dialogtoken = frm[2];
 2497         code = le16dec(frm+3);
 2498         baparamset = le16dec(frm+5);
 2499         tid = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_TID);
 2500 #ifdef IEEE80211_DEBUG
 2501         bufsiz = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_BUFSIZ);
 2502         amsdu = !! _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_AMSDU);
 2503 #endif
 2504         policy = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_BAPS_POLICY);
 2505         batimeout = le16dec(frm+7);
 2506 
 2507         tap = &ni->ni_tx_ampdu[tid];
 2508         if ((tap->txa_flags & IEEE80211_AGGR_XCHGPEND) == 0) {
 2509                 IEEE80211_DISCARD_MAC(vap,
 2510                     IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
 2511                     ni->ni_macaddr, "ADDBA response",
 2512                     "no pending ADDBA, tid %d dialogtoken %u "
 2513                     "code %d", tid, dialogtoken, code);
 2514                 vap->iv_stats.is_addba_norequest++;
 2515                 return 0;
 2516         }
 2517         if (dialogtoken != tap->txa_token) {
 2518                 IEEE80211_DISCARD_MAC(vap,
 2519                     IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
 2520                     ni->ni_macaddr, "ADDBA response",
 2521                     "dialogtoken mismatch: waiting for %d, "
 2522                     "received %d, tid %d code %d",
 2523                     tap->txa_token, dialogtoken, tid, code);
 2524                 vap->iv_stats.is_addba_badtoken++;
 2525                 return 0;
 2526         }
 2527         /* NB: assumes IEEE80211_AGGR_IMMEDIATE is 1 */
 2528         if (policy != (tap->txa_flags & IEEE80211_AGGR_IMMEDIATE)) {
 2529                 IEEE80211_DISCARD_MAC(vap,
 2530                     IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
 2531                     ni->ni_macaddr, "ADDBA response",
 2532                     "policy mismatch: expecting %s, "
 2533                     "received %s, tid %d code %d",
 2534                     tap->txa_flags & IEEE80211_AGGR_IMMEDIATE,
 2535                     policy, tid, code);
 2536                 vap->iv_stats.is_addba_badpolicy++;
 2537                 return 0;
 2538         }
 2539 #if 0
 2540         /* XXX we take MIN in ieee80211_addba_response */
 2541         if (bufsiz > IEEE80211_AGGR_BAWMAX) {
 2542                 IEEE80211_DISCARD_MAC(vap,
 2543                     IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
 2544                     ni->ni_macaddr, "ADDBA response",
 2545                     "BA window too large: max %d, "
 2546                     "received %d, tid %d code %d",
 2547                     bufsiz, IEEE80211_AGGR_BAWMAX, tid, code);
 2548                 vap->iv_stats.is_addba_badbawinsize++;
 2549                 return 0;
 2550         }
 2551 #endif
 2552 
 2553         IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
 2554             "recv ADDBA response: dialogtoken %u code %d "
 2555             "baparamset 0x%x (tid %d bufsiz %d amsdu %d) batimeout %d",
 2556             dialogtoken, code, baparamset, tid,
 2557             bufsiz,
 2558             amsdu,
 2559             batimeout);
 2560         ic->ic_addba_response(ni, tap, code, baparamset, batimeout);
 2561         return 0;
 2562 }
 2563 
 2564 static int
 2565 ht_recv_action_ba_delba(struct ieee80211_node *ni,
 2566         const struct ieee80211_frame *wh,
 2567         const uint8_t *frm, const uint8_t *efrm)
 2568 {
 2569         struct ieee80211com *ic = ni->ni_ic;
 2570         struct ieee80211_rx_ampdu *rap;
 2571         struct ieee80211_tx_ampdu *tap;
 2572         uint16_t baparamset;
 2573 #ifdef IEEE80211_DEBUG
 2574         uint16_t code;
 2575 #endif
 2576         int tid;
 2577 
 2578         baparamset = le16dec(frm+2);
 2579 #ifdef IEEE80211_DEBUG
 2580         code = le16dec(frm+4);
 2581 #endif
 2582 
 2583         tid = _IEEE80211_MASKSHIFT(baparamset, IEEE80211_DELBAPS_TID);
 2584 
 2585         IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
 2586             "recv DELBA: baparamset 0x%x (tid %d initiator %d) "
 2587             "code %d", baparamset, tid,
 2588             _IEEE80211_MASKSHIFT(baparamset, IEEE80211_DELBAPS_INIT), code);
 2589 
 2590         if ((baparamset & IEEE80211_DELBAPS_INIT) == 0) {
 2591                 tap = &ni->ni_tx_ampdu[tid];
 2592                 ic->ic_addba_stop(ni, tap);
 2593         } else {
 2594                 rap = &ni->ni_rx_ampdu[tid];
 2595                 ic->ic_ampdu_rx_stop(ni, rap);
 2596         }
 2597         return 0;
 2598 }
 2599 
 2600 static int
 2601 ht_recv_action_ht_txchwidth(struct ieee80211_node *ni,
 2602         const struct ieee80211_frame *wh,
 2603         const uint8_t *frm, const uint8_t *efrm)
 2604 {
 2605         int chw;
 2606 
 2607         chw = (frm[2] == IEEE80211_A_HT_TXCHWIDTH_2040) ? 40 : 20;
 2608 
 2609         IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
 2610             "%s: HT txchwidth, width %d%s",
 2611             __func__, chw, ni->ni_chw != chw ? "*" : "");
 2612         if (chw != ni->ni_chw) {
 2613                 /* XXX does this need to change the ht40 station count? */
 2614                 ni->ni_chw = chw;
 2615                 /* XXX notify on change */
 2616         }
 2617         return 0;
 2618 }
 2619 
 2620 static int
 2621 ht_recv_action_ht_mimopwrsave(struct ieee80211_node *ni,
 2622         const struct ieee80211_frame *wh,
 2623         const uint8_t *frm, const uint8_t *efrm)
 2624 {
 2625         const struct ieee80211_action_ht_mimopowersave *mps =
 2626             (const struct ieee80211_action_ht_mimopowersave *) frm;
 2627 
 2628         /* XXX check iv_htcaps */
 2629         if (mps->am_control & IEEE80211_A_HT_MIMOPWRSAVE_ENA)
 2630                 ni->ni_flags |= IEEE80211_NODE_MIMO_PS;
 2631         else
 2632                 ni->ni_flags &= ~IEEE80211_NODE_MIMO_PS;
 2633         if (mps->am_control & IEEE80211_A_HT_MIMOPWRSAVE_MODE)
 2634                 ni->ni_flags |= IEEE80211_NODE_MIMO_RTS;
 2635         else
 2636                 ni->ni_flags &= ~IEEE80211_NODE_MIMO_RTS;
 2637         /* XXX notify on change */
 2638         IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
 2639             "%s: HT MIMO PS (%s%s)", __func__,
 2640             (ni->ni_flags & IEEE80211_NODE_MIMO_PS) ?  "on" : "off",
 2641             (ni->ni_flags & IEEE80211_NODE_MIMO_RTS) ?  "+rts" : ""
 2642         );
 2643         return 0;
 2644 }
 2645 
 2646 /*
 2647  * Transmit processing.
 2648  */
 2649 
 2650 /*
 2651  * Check if A-MPDU should be requested/enabled for a stream.
 2652  * We require a traffic rate above a per-AC threshold and we
 2653  * also handle backoff from previous failed attempts.
 2654  *
 2655  * Drivers may override this method to bring in information
 2656  * such as link state conditions in making the decision.
 2657  */
 2658 static int
 2659 ieee80211_ampdu_enable(struct ieee80211_node *ni,
 2660         struct ieee80211_tx_ampdu *tap)
 2661 {
 2662         struct ieee80211vap *vap = ni->ni_vap;
 2663 
 2664         if (tap->txa_avgpps <
 2665             vap->iv_ampdu_mintraffic[TID_TO_WME_AC(tap->txa_tid)])
 2666                 return 0;
 2667         /* XXX check rssi? */
 2668         if (tap->txa_attempts >= ieee80211_addba_maxtries &&
 2669             ieee80211_time_after(ticks, tap->txa_nextrequest)) {
 2670                 /*
 2671                  * Don't retry too often; txa_nextrequest is set
 2672                  * to the minimum interval we'll retry after
 2673                  * ieee80211_addba_maxtries failed attempts are made.
 2674                  */
 2675                 return 0;
 2676         }
 2677         IEEE80211_NOTE(vap, IEEE80211_MSG_11N, ni,
 2678             "enable AMPDU on tid %d (%s), avgpps %d pkts %d attempt %d",
 2679             tap->txa_tid, ieee80211_wme_acnames[TID_TO_WME_AC(tap->txa_tid)],
 2680             tap->txa_avgpps, tap->txa_pkts, tap->txa_attempts);
 2681         return 1;
 2682 }
 2683 
 2684 /*
 2685  * Request A-MPDU tx aggregation.  Setup local state and
 2686  * issue an ADDBA request.  BA use will only happen after
 2687  * the other end replies with ADDBA response.
 2688  */
 2689 int
 2690 ieee80211_ampdu_request(struct ieee80211_node *ni,
 2691         struct ieee80211_tx_ampdu *tap)
 2692 {
 2693         struct ieee80211com *ic = ni->ni_ic;
 2694         uint16_t args[5];
 2695         int tid, dialogtoken;
 2696         static int tokens = 0;  /* XXX */
 2697 
 2698         /* XXX locking */
 2699         if ((tap->txa_flags & IEEE80211_AGGR_SETUP) == 0) {
 2700                 /* do deferred setup of state */
 2701                 ampdu_tx_setup(tap);
 2702         }
 2703         /* XXX hack for not doing proper locking */
 2704         tap->txa_flags &= ~IEEE80211_AGGR_NAK;
 2705 
 2706         dialogtoken = (tokens+1) % 63;          /* XXX */
 2707         tid = tap->txa_tid;
 2708 
 2709         /*
 2710          * XXX TODO: This is racy with any other parallel TX going on. :(
 2711          */
 2712         tap->txa_start = ni->ni_txseqs[tid];
 2713 
 2714         args[0] = dialogtoken;
 2715         args[1] = 0;    /* NB: status code not used */
 2716         args[2] = IEEE80211_BAPS_POLICY_IMMEDIATE
 2717                 | _IEEE80211_SHIFTMASK(tid, IEEE80211_BAPS_TID)
 2718                 | _IEEE80211_SHIFTMASK(IEEE80211_AGGR_BAWMAX,
 2719                     IEEE80211_BAPS_BUFSIZ)
 2720                 ;
 2721 
 2722         /* XXX TODO: this should be a flag, not iv_htcaps */
 2723         if ((ni->ni_flags & IEEE80211_NODE_AMSDU_TX) &&
 2724             (ni->ni_vap->iv_htcaps & IEEE80211_HTC_TX_AMSDU_AMPDU))
 2725                 args[2] |= IEEE80211_BAPS_AMSDU;
 2726 
 2727         args[3] = 0;    /* batimeout */
 2728         /* NB: do first so there's no race against reply */
 2729         if (!ic->ic_addba_request(ni, tap, dialogtoken, args[2], args[3])) {
 2730                 /* unable to setup state, don't make request */
 2731                 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
 2732                     ni, "%s: could not setup BA stream for TID %d AC %d",
 2733                     __func__, tap->txa_tid, TID_TO_WME_AC(tap->txa_tid));
 2734                 /* defer next try so we don't slam the driver with requests */
 2735                 tap->txa_attempts = ieee80211_addba_maxtries;
 2736                 /* NB: check in case driver wants to override */
 2737                 if (tap->txa_nextrequest <= ticks)
 2738                         tap->txa_nextrequest = ticks + ieee80211_addba_backoff;
 2739                 return 0;
 2740         }
 2741         tokens = dialogtoken;                   /* allocate token */
 2742         /* NB: after calling ic_addba_request so driver can set txa_start */
 2743         args[4] = _IEEE80211_SHIFTMASK(tap->txa_start, IEEE80211_BASEQ_START)
 2744                 | _IEEE80211_SHIFTMASK(0, IEEE80211_BASEQ_FRAG)
 2745                 ;
 2746         return ic->ic_send_action(ni, IEEE80211_ACTION_CAT_BA,
 2747                 IEEE80211_ACTION_BA_ADDBA_REQUEST, args);
 2748 }
 2749 
 2750 /*
 2751  * Terminate an AMPDU tx stream.  State is reclaimed
 2752  * and the peer notified with a DelBA Action frame.
 2753  */
 2754 void
 2755 ieee80211_ampdu_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
 2756         int reason)
 2757 {
 2758         struct ieee80211com *ic = ni->ni_ic;
 2759         struct ieee80211vap *vap = ni->ni_vap;
 2760         uint16_t args[4];
 2761 
 2762         /* XXX locking */
 2763         tap->txa_flags &= ~IEEE80211_AGGR_BARPEND;
 2764         if (IEEE80211_AMPDU_RUNNING(tap)) {
 2765                 IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
 2766                     ni, "%s: stop BA stream for TID %d (reason: %d (%s))",
 2767                     __func__, tap->txa_tid, reason,
 2768                     ieee80211_reason_to_string(reason));
 2769                 vap->iv_stats.is_ampdu_stop++;
 2770 
 2771                 ic->ic_addba_stop(ni, tap);
 2772                 args[0] = tap->txa_tid;
 2773                 args[1] = IEEE80211_DELBAPS_INIT;
 2774                 args[2] = reason;                       /* XXX reason code */
 2775                 ic->ic_send_action(ni, IEEE80211_ACTION_CAT_BA,
 2776                         IEEE80211_ACTION_BA_DELBA, args);
 2777         } else {
 2778                 IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N,
 2779                     ni, "%s: BA stream for TID %d not running "
 2780                     "(reason: %d (%s))", __func__, tap->txa_tid, reason,
 2781                     ieee80211_reason_to_string(reason));
 2782                 vap->iv_stats.is_ampdu_stop_failed++;
 2783         }
 2784 }
 2785 
 2786 /* XXX */
 2787 static void bar_start_timer(struct ieee80211_tx_ampdu *tap);
 2788 
 2789 static void
 2790 bar_timeout(void *arg)
 2791 {
 2792         struct ieee80211_tx_ampdu *tap = arg;
 2793         struct ieee80211_node *ni = tap->txa_ni;
 2794 
 2795         KASSERT((tap->txa_flags & IEEE80211_AGGR_XCHGPEND) == 0,
 2796             ("bar/addba collision, flags 0x%x", tap->txa_flags));
 2797 
 2798         IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
 2799             ni, "%s: tid %u flags 0x%x attempts %d", __func__,
 2800             tap->txa_tid, tap->txa_flags, tap->txa_attempts);
 2801 
 2802         /* guard against race with bar_tx_complete */
 2803         if ((tap->txa_flags & IEEE80211_AGGR_BARPEND) == 0)
 2804                 return;
 2805         /* XXX ? */
 2806         if (tap->txa_attempts >= ieee80211_bar_maxtries) {
 2807                 struct ieee80211com *ic = ni->ni_ic;
 2808 
 2809                 ni->ni_vap->iv_stats.is_ampdu_bar_tx_fail++;
 2810                 /*
 2811                  * If (at least) the last BAR TX timeout was due to
 2812                  * an ieee80211_send_bar() failures, then we need
 2813                  * to make sure we notify the driver that a BAR
 2814                  * TX did occur and fail.  This gives the driver
 2815                  * a chance to undo any queue pause that may
 2816                  * have occurred.
 2817                  */
 2818                 ic->ic_bar_response(ni, tap, 1);
 2819                 ieee80211_ampdu_stop(ni, tap, IEEE80211_REASON_TIMEOUT);
 2820         } else {
 2821                 ni->ni_vap->iv_stats.is_ampdu_bar_tx_retry++;
 2822                 if (ieee80211_send_bar(ni, tap, tap->txa_seqpending) != 0) {
 2823                         IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
 2824                             ni, "%s: failed to TX, starting timer\n",
 2825                             __func__);
 2826                         /*
 2827                          * If ieee80211_send_bar() fails here, the
 2828                          * timer may have stopped and/or the pending
 2829                          * flag may be clear.  Because of this,
 2830                          * fake the BARPEND and reset the timer.
 2831                          * A retransmission attempt will then occur
 2832                          * during the next timeout.
 2833                          */
 2834                         /* XXX locking */
 2835                         tap->txa_flags |= IEEE80211_AGGR_BARPEND;
 2836                         bar_start_timer(tap);
 2837                 }
 2838         }
 2839 }
 2840 
 2841 static void
 2842 bar_start_timer(struct ieee80211_tx_ampdu *tap)
 2843 {
 2844         IEEE80211_NOTE(tap->txa_ni->ni_vap, IEEE80211_MSG_11N,
 2845             tap->txa_ni,
 2846             "%s: called",
 2847             __func__);
 2848         callout_reset(&tap->txa_timer, ieee80211_bar_timeout, bar_timeout, tap);
 2849 }
 2850 
 2851 static void
 2852 bar_stop_timer(struct ieee80211_tx_ampdu *tap)
 2853 {
 2854         IEEE80211_NOTE(tap->txa_ni->ni_vap, IEEE80211_MSG_11N,
 2855             tap->txa_ni,
 2856             "%s: called",
 2857             __func__);
 2858         callout_stop(&tap->txa_timer);
 2859 }
 2860 
 2861 static void
 2862 bar_tx_complete(struct ieee80211_node *ni, void *arg, int status)
 2863 {
 2864         struct ieee80211_tx_ampdu *tap = arg;
 2865 
 2866         IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
 2867             ni, "%s: tid %u flags 0x%x pending %d status %d",
 2868             __func__, tap->txa_tid, tap->txa_flags,
 2869             callout_pending(&tap->txa_timer), status);
 2870 
 2871         ni->ni_vap->iv_stats.is_ampdu_bar_tx++;
 2872         /* XXX locking */
 2873         if ((tap->txa_flags & IEEE80211_AGGR_BARPEND) &&
 2874             callout_pending(&tap->txa_timer)) {
 2875                 struct ieee80211com *ic = ni->ni_ic;
 2876 
 2877                 if (status == 0)                /* ACK'd */
 2878                         bar_stop_timer(tap);
 2879                 ic->ic_bar_response(ni, tap, status);
 2880                 /* NB: just let timer expire so we pace requests */
 2881         }
 2882 }
 2883 
 2884 static void
 2885 ieee80211_bar_response(struct ieee80211_node *ni,
 2886         struct ieee80211_tx_ampdu *tap, int status)
 2887 {
 2888 
 2889         IEEE80211_NOTE(tap->txa_ni->ni_vap, IEEE80211_MSG_11N,
 2890             tap->txa_ni,
 2891             "%s: called",
 2892             __func__);
 2893         if (status == 0) {              /* got ACK */
 2894                 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
 2895                     ni, "BAR moves BA win <%u:%u> (%u frames) txseq %u tid %u",
 2896                     tap->txa_start,
 2897                     IEEE80211_SEQ_ADD(tap->txa_start, tap->txa_wnd-1),
 2898                     tap->txa_qframes, tap->txa_seqpending,
 2899                     tap->txa_tid);
 2900 
 2901                 /* NB: timer already stopped in bar_tx_complete */
 2902                 tap->txa_start = tap->txa_seqpending;
 2903                 tap->txa_flags &= ~IEEE80211_AGGR_BARPEND;
 2904         }
 2905 }
 2906 
 2907 /*
 2908  * Transmit a BAR frame to the specified node.  The
 2909  * BAR contents are drawn from the supplied aggregation
 2910  * state associated with the node.
 2911  *
 2912  * NB: we only handle immediate ACK w/ compressed bitmap.
 2913  */
 2914 int
 2915 ieee80211_send_bar(struct ieee80211_node *ni,
 2916         struct ieee80211_tx_ampdu *tap, ieee80211_seq seq)
 2917 {
 2918 #define senderr(_x, _v) do { vap->iv_stats._v++; ret = _x; goto bad; } while (0)
 2919         struct ieee80211vap *vap = ni->ni_vap;
 2920         struct ieee80211com *ic = ni->ni_ic;
 2921         struct ieee80211_frame_bar *bar;
 2922         struct mbuf *m;
 2923         uint16_t barctl, barseqctl;
 2924         uint8_t *frm;
 2925         int tid, ret;
 2926 
 2927         IEEE80211_NOTE(tap->txa_ni->ni_vap, IEEE80211_MSG_11N,
 2928             tap->txa_ni,
 2929             "%s: called",
 2930             __func__);
 2931 
 2932         if ((tap->txa_flags & IEEE80211_AGGR_RUNNING) == 0) {
 2933                 /* no ADDBA response, should not happen */
 2934                 /* XXX stat+msg */
 2935                 return EINVAL;
 2936         }
 2937         /* XXX locking */
 2938         bar_stop_timer(tap);
 2939 
 2940         ieee80211_ref_node(ni);
 2941 
 2942         m = ieee80211_getmgtframe(&frm, ic->ic_headroom, sizeof(*bar));
 2943         if (m == NULL)
 2944                 senderr(ENOMEM, is_tx_nobuf);
 2945 
 2946         if (!ieee80211_add_callback(m, bar_tx_complete, tap)) {
 2947                 m_freem(m);
 2948                 senderr(ENOMEM, is_tx_nobuf);   /* XXX */
 2949                 /* NOTREACHED */
 2950         }
 2951 
 2952         bar = mtod(m, struct ieee80211_frame_bar *);
 2953         bar->i_fc[0] = IEEE80211_FC0_VERSION_0 |
 2954                 IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_BAR;
 2955         bar->i_fc[1] = 0;
 2956         IEEE80211_ADDR_COPY(bar->i_ra, ni->ni_macaddr);
 2957         IEEE80211_ADDR_COPY(bar->i_ta, vap->iv_myaddr);
 2958 
 2959         tid = tap->txa_tid;
 2960         barctl  = (tap->txa_flags & IEEE80211_AGGR_IMMEDIATE ?
 2961                         0 : IEEE80211_BAR_NOACK)
 2962                 | IEEE80211_BAR_COMP
 2963                 | _IEEE80211_SHIFTMASK(tid, IEEE80211_BAR_TID)
 2964                 ;
 2965         barseqctl = _IEEE80211_SHIFTMASK(seq, IEEE80211_BAR_SEQ_START);
 2966         /* NB: known to have proper alignment */
 2967         bar->i_ctl = htole16(barctl);
 2968         bar->i_seq = htole16(barseqctl);
 2969         m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame_bar);
 2970 
 2971         M_WME_SETAC(m, WME_AC_VO);
 2972 
 2973         IEEE80211_NODE_STAT(ni, tx_mgmt);       /* XXX tx_ctl? */
 2974 
 2975         /* XXX locking */
 2976         /* init/bump attempts counter */
 2977         if ((tap->txa_flags & IEEE80211_AGGR_BARPEND) == 0)
 2978                 tap->txa_attempts = 1;
 2979         else
 2980                 tap->txa_attempts++;
 2981         tap->txa_seqpending = seq;
 2982         tap->txa_flags |= IEEE80211_AGGR_BARPEND;
 2983 
 2984         IEEE80211_NOTE(vap, IEEE80211_MSG_DEBUG | IEEE80211_MSG_11N,
 2985             ni, "send BAR: tid %u ctl 0x%x start %u (attempt %d)",
 2986             tid, barctl, seq, tap->txa_attempts);
 2987 
 2988         /*
 2989          * ic_raw_xmit will free the node reference
 2990          * regardless of queue/TX success or failure.
 2991          */
 2992         IEEE80211_TX_LOCK(ic);
 2993         ret = ieee80211_raw_output(vap, ni, m, NULL);
 2994         IEEE80211_TX_UNLOCK(ic);
 2995         if (ret != 0) {
 2996                 IEEE80211_NOTE(vap, IEEE80211_MSG_DEBUG | IEEE80211_MSG_11N,
 2997                     ni, "send BAR: failed: (ret = %d)\n",
 2998                     ret);
 2999                 /* xmit failed, clear state flag */
 3000                 tap->txa_flags &= ~IEEE80211_AGGR_BARPEND;
 3001                 vap->iv_stats.is_ampdu_bar_tx_fail++;
 3002                 return ret;
 3003         }
 3004         /* XXX hack against tx complete happening before timer is started */
 3005         if (tap->txa_flags & IEEE80211_AGGR_BARPEND)
 3006                 bar_start_timer(tap);
 3007         return 0;
 3008 bad:
 3009         IEEE80211_NOTE(tap->txa_ni->ni_vap, IEEE80211_MSG_11N,
 3010             tap->txa_ni,
 3011             "%s: bad! ret=%d",
 3012             __func__, ret);
 3013         vap->iv_stats.is_ampdu_bar_tx_fail++;
 3014         ieee80211_free_node(ni);
 3015         return ret;
 3016 #undef senderr
 3017 }
 3018 
 3019 static int
 3020 ht_action_output(struct ieee80211_node *ni, struct mbuf *m)
 3021 {
 3022         struct ieee80211_bpf_params params;
 3023 
 3024         memset(&params, 0, sizeof(params));
 3025         params.ibp_pri = WME_AC_VO;
 3026         params.ibp_rate0 = ni->ni_txparms->mgmtrate;
 3027         /* NB: we know all frames are unicast */
 3028         params.ibp_try0 = ni->ni_txparms->maxretry;
 3029         params.ibp_power = ni->ni_txpower;
 3030         return ieee80211_mgmt_output(ni, m, IEEE80211_FC0_SUBTYPE_ACTION,
 3031              &params);
 3032 }
 3033 
 3034 #define ADDSHORT(frm, v) do {                   \
 3035         frm[0] = (v) & 0xff;                    \
 3036         frm[1] = (v) >> 8;                      \
 3037         frm += 2;                               \
 3038 } while (0)
 3039 
 3040 /*
 3041  * Send an action management frame.  The arguments are stuff
 3042  * into a frame without inspection; the caller is assumed to
 3043  * prepare them carefully (e.g. based on the aggregation state).
 3044  */
 3045 static int
 3046 ht_send_action_ba_addba(struct ieee80211_node *ni,
 3047         int category, int action, void *arg0)
 3048 {
 3049         struct ieee80211vap *vap = ni->ni_vap;
 3050         struct ieee80211com *ic = ni->ni_ic;
 3051         uint16_t *args = arg0;
 3052         struct mbuf *m;
 3053         uint8_t *frm;
 3054 
 3055         IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
 3056             "send ADDBA %s: dialogtoken %d status %d "
 3057             "baparamset 0x%x (tid %d amsdu %d) batimeout 0x%x baseqctl 0x%x",
 3058             (action == IEEE80211_ACTION_BA_ADDBA_REQUEST) ?
 3059                 "request" : "response", args[0], args[1], args[2],
 3060             _IEEE80211_MASKSHIFT(args[2], IEEE80211_BAPS_TID),
 3061             _IEEE80211_MASKSHIFT(args[2], IEEE80211_BAPS_AMSDU),
 3062             args[3], args[4]);
 3063 
 3064         IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
 3065             "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
 3066             ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
 3067         ieee80211_ref_node(ni);
 3068 
 3069         m = ieee80211_getmgtframe(&frm,
 3070             ic->ic_headroom + sizeof(struct ieee80211_frame),
 3071             sizeof(uint16_t)    /* action+category */
 3072             /* XXX may action payload */
 3073             + sizeof(struct ieee80211_action_ba_addbaresponse)
 3074         );
 3075         if (m != NULL) {
 3076                 *frm++ = category;
 3077                 *frm++ = action;
 3078                 *frm++ = args[0];               /* dialog token */
 3079                 if (action == IEEE80211_ACTION_BA_ADDBA_RESPONSE)
 3080                         ADDSHORT(frm, args[1]); /* status code */
 3081                 ADDSHORT(frm, args[2]);         /* baparamset */
 3082                 ADDSHORT(frm, args[3]);         /* batimeout */
 3083                 if (action == IEEE80211_ACTION_BA_ADDBA_REQUEST)
 3084                         ADDSHORT(frm, args[4]); /* baseqctl */
 3085                 m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
 3086                 return ht_action_output(ni, m);
 3087         } else {
 3088                 vap->iv_stats.is_tx_nobuf++;
 3089                 ieee80211_free_node(ni);
 3090                 return ENOMEM;
 3091         }
 3092 }
 3093 
 3094 static int
 3095 ht_send_action_ba_delba(struct ieee80211_node *ni,
 3096         int category, int action, void *arg0)
 3097 {
 3098         struct ieee80211vap *vap = ni->ni_vap;
 3099         struct ieee80211com *ic = ni->ni_ic;
 3100         uint16_t *args = arg0;
 3101         struct mbuf *m;
 3102         uint16_t baparamset;
 3103         uint8_t *frm;
 3104 
 3105         baparamset = _IEEE80211_SHIFTMASK(args[0], IEEE80211_DELBAPS_TID)
 3106                    | args[1]
 3107                    ;
 3108         IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
 3109             "send DELBA action: tid %d, initiator %d reason %d (%s)",
 3110             args[0], args[1], args[2], ieee80211_reason_to_string(args[2]));
 3111 
 3112         IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
 3113             "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
 3114             ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
 3115         ieee80211_ref_node(ni);
 3116 
 3117         m = ieee80211_getmgtframe(&frm,
 3118             ic->ic_headroom + sizeof(struct ieee80211_frame),
 3119             sizeof(uint16_t)    /* action+category */
 3120             /* XXX may action payload */
 3121             + sizeof(struct ieee80211_action_ba_addbaresponse)
 3122         );
 3123         if (m != NULL) {
 3124                 *frm++ = category;
 3125                 *frm++ = action;
 3126                 ADDSHORT(frm, baparamset);
 3127                 ADDSHORT(frm, args[2]);         /* reason code */
 3128                 m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
 3129                 return ht_action_output(ni, m);
 3130         } else {
 3131                 vap->iv_stats.is_tx_nobuf++;
 3132                 ieee80211_free_node(ni);
 3133                 return ENOMEM;
 3134         }
 3135 }
 3136 
 3137 static int
 3138 ht_send_action_ht_txchwidth(struct ieee80211_node *ni,
 3139         int category, int action, void *arg0)
 3140 {
 3141         struct ieee80211vap *vap = ni->ni_vap;
 3142         struct ieee80211com *ic = ni->ni_ic;
 3143         struct mbuf *m;
 3144         uint8_t *frm;
 3145 
 3146         IEEE80211_NOTE(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
 3147             "send HT txchwidth: width %d",
 3148             IEEE80211_IS_CHAN_HT40(ni->ni_chan) ? 40 : 20);
 3149 
 3150         IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
 3151             "ieee80211_ref_node (%s:%u) %p<%s> refcnt %d\n", __func__, __LINE__,
 3152             ni, ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)+1);
 3153         ieee80211_ref_node(ni);
 3154 
 3155         m = ieee80211_getmgtframe(&frm,
 3156             ic->ic_headroom + sizeof(struct ieee80211_frame),
 3157             sizeof(uint16_t)    /* action+category */
 3158             /* XXX may action payload */
 3159             + sizeof(struct ieee80211_action_ba_addbaresponse)
 3160         );
 3161         if (m != NULL) {
 3162                 *frm++ = category;
 3163                 *frm++ = action;
 3164                 *frm++ = IEEE80211_IS_CHAN_HT40(ni->ni_chan) ? 
 3165                         IEEE80211_A_HT_TXCHWIDTH_2040 :
 3166                         IEEE80211_A_HT_TXCHWIDTH_20;
 3167                 m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
 3168                 return ht_action_output(ni, m);
 3169         } else {
 3170                 vap->iv_stats.is_tx_nobuf++;
 3171                 ieee80211_free_node(ni);
 3172                 return ENOMEM;
 3173         }
 3174 }
 3175 #undef ADDSHORT
 3176 
 3177 /*
 3178  * Construct the MCS bit mask for inclusion in an HT capabilities
 3179  * information element.
 3180  */
 3181 static void
 3182 ieee80211_set_mcsset(struct ieee80211com *ic, uint8_t *frm)
 3183 {
 3184         int i;
 3185         uint8_t txparams;
 3186 
 3187         KASSERT((ic->ic_rxstream > 0 && ic->ic_rxstream <= 4),
 3188             ("ic_rxstream %d out of range", ic->ic_rxstream));
 3189         KASSERT((ic->ic_txstream > 0 && ic->ic_txstream <= 4),
 3190             ("ic_txstream %d out of range", ic->ic_txstream));
 3191 
 3192         for (i = 0; i < ic->ic_rxstream * 8; i++)
 3193                 setbit(frm, i);
 3194         if ((ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) &&
 3195             (ic->ic_htcaps & IEEE80211_HTC_RXMCS32))
 3196                 setbit(frm, 32);
 3197         if (ic->ic_htcaps & IEEE80211_HTC_RXUNEQUAL) {
 3198                 if (ic->ic_rxstream >= 2) {
 3199                         for (i = 33; i <= 38; i++)
 3200                                 setbit(frm, i);
 3201                 }
 3202                 if (ic->ic_rxstream >= 3) {
 3203                         for (i = 39; i <= 52; i++)
 3204                                 setbit(frm, i);
 3205                 }
 3206                 if (ic->ic_txstream >= 4) {
 3207                         for (i = 53; i <= 76; i++)
 3208                                 setbit(frm, i);
 3209                 }
 3210         }
 3211 
 3212         if (ic->ic_rxstream != ic->ic_txstream) {
 3213                 txparams = 0x1;                 /* TX MCS set defined */
 3214                 txparams |= 0x2;                /* TX RX MCS not equal */
 3215                 txparams |= (ic->ic_txstream - 1) << 2; /* num TX streams */
 3216                 if (ic->ic_htcaps & IEEE80211_HTC_TXUNEQUAL)
 3217                         txparams |= 0x16;       /* TX unequal modulation sup */
 3218         } else
 3219                 txparams = 0;
 3220         frm[12] = txparams;
 3221 }
 3222 
 3223 /*
 3224  * Add body of an HTCAP information element.
 3225  */
 3226 static uint8_t *
 3227 ieee80211_add_htcap_body(uint8_t *frm, struct ieee80211_node *ni)
 3228 {
 3229 #define ADDSHORT(frm, v) do {                   \
 3230         frm[0] = (v) & 0xff;                    \
 3231         frm[1] = (v) >> 8;                      \
 3232         frm += 2;                               \
 3233 } while (0)
 3234         struct ieee80211com *ic = ni->ni_ic;
 3235         struct ieee80211vap *vap = ni->ni_vap;
 3236         uint16_t caps, extcaps;
 3237         int rxmax, density;
 3238 
 3239         /* HT capabilities */
 3240         caps = vap->iv_htcaps & 0xffff;
 3241         /*
 3242          * Note channel width depends on whether we are operating as
 3243          * a sta or not.  When operating as a sta we are generating
 3244          * a request based on our desired configuration.  Otherwise
 3245          * we are operational and the channel attributes identify
 3246          * how we've been setup (which might be different if a fixed
 3247          * channel is specified).
 3248          */
 3249         if (vap->iv_opmode == IEEE80211_M_STA) {
 3250                 /* override 20/40 use based on config */
 3251                 if (vap->iv_flags_ht & IEEE80211_FHT_USEHT40)
 3252                         caps |= IEEE80211_HTCAP_CHWIDTH40;
 3253                 else
 3254                         caps &= ~IEEE80211_HTCAP_CHWIDTH40;
 3255 
 3256                 /* Start by using the advertised settings */
 3257                 rxmax = _IEEE80211_MASKSHIFT(ni->ni_htparam,
 3258                     IEEE80211_HTCAP_MAXRXAMPDU);
 3259                 density = _IEEE80211_MASKSHIFT(ni->ni_htparam,
 3260                     IEEE80211_HTCAP_MPDUDENSITY);
 3261 
 3262                 IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N,
 3263                     "%s: advertised rxmax=%d, density=%d, vap rxmax=%d, density=%d\n",
 3264                     __func__,
 3265                     rxmax,
 3266                     density,
 3267                     vap->iv_ampdu_rxmax,
 3268                     vap->iv_ampdu_density);
 3269 
 3270                 /* Cap at VAP rxmax */
 3271                 if (rxmax > vap->iv_ampdu_rxmax)
 3272                         rxmax = vap->iv_ampdu_rxmax;
 3273 
 3274                 /*
 3275                  * If the VAP ampdu density value greater, use that.
 3276                  *
 3277                  * (Larger density value == larger minimum gap between A-MPDU
 3278                  * subframes.)
 3279                  */
 3280                 if (vap->iv_ampdu_density > density)
 3281                         density = vap->iv_ampdu_density;
 3282 
 3283                 /*
 3284                  * NB: Hardware might support HT40 on some but not all
 3285                  * channels. We can't determine this earlier because only
 3286                  * after association the channel is upgraded to HT based
 3287                  * on the negotiated capabilities.
 3288                  */
 3289                 if (ni->ni_chan != IEEE80211_CHAN_ANYC &&
 3290                     findhtchan(ic, ni->ni_chan, IEEE80211_CHAN_HT40U) == NULL &&
 3291                     findhtchan(ic, ni->ni_chan, IEEE80211_CHAN_HT40D) == NULL)
 3292                         caps &= ~IEEE80211_HTCAP_CHWIDTH40;
 3293         } else {
 3294                 /* override 20/40 use based on current channel */
 3295                 if (IEEE80211_IS_CHAN_HT40(ni->ni_chan))
 3296                         caps |= IEEE80211_HTCAP_CHWIDTH40;
 3297                 else
 3298                         caps &= ~IEEE80211_HTCAP_CHWIDTH40;
 3299 
 3300                 /* XXX TODO should it start by using advertised settings? */
 3301                 rxmax = vap->iv_ampdu_rxmax;
 3302                 density = vap->iv_ampdu_density;
 3303         }
 3304 
 3305         /* adjust short GI based on channel and config */
 3306         if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20) == 0)
 3307                 caps &= ~IEEE80211_HTCAP_SHORTGI20;
 3308         if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40) == 0 ||
 3309             (caps & IEEE80211_HTCAP_CHWIDTH40) == 0)
 3310                 caps &= ~IEEE80211_HTCAP_SHORTGI40;
 3311 
 3312         /* adjust STBC based on receive capabilities */
 3313         if ((vap->iv_flags_ht & IEEE80211_FHT_STBC_RX) == 0)
 3314                 caps &= ~IEEE80211_HTCAP_RXSTBC;
 3315 
 3316         /* adjust LDPC based on receive capabilites */
 3317         if ((vap->iv_flags_ht & IEEE80211_FHT_LDPC_RX) == 0)
 3318                 caps &= ~IEEE80211_HTCAP_LDPC;
 3319 
 3320         ADDSHORT(frm, caps);
 3321 
 3322         /* HT parameters */
 3323         *frm = _IEEE80211_SHIFTMASK(rxmax, IEEE80211_HTCAP_MAXRXAMPDU)
 3324              | _IEEE80211_SHIFTMASK(density, IEEE80211_HTCAP_MPDUDENSITY)
 3325              ;
 3326         frm++;
 3327 
 3328         /* pre-zero remainder of ie */
 3329         memset(frm, 0, sizeof(struct ieee80211_ie_htcap) - 
 3330                 __offsetof(struct ieee80211_ie_htcap, hc_mcsset));
 3331 
 3332         /* supported MCS set */
 3333         /*
 3334          * XXX: For sta mode the rate set should be restricted based
 3335          * on the AP's capabilities, but ni_htrates isn't setup when
 3336          * we're called to form an AssocReq frame so for now we're
 3337          * restricted to the device capabilities.
 3338          */
 3339         ieee80211_set_mcsset(ni->ni_ic, frm);
 3340 
 3341         frm += __offsetof(struct ieee80211_ie_htcap, hc_extcap) -
 3342                 __offsetof(struct ieee80211_ie_htcap, hc_mcsset);
 3343 
 3344         /* HT extended capabilities */
 3345         extcaps = vap->iv_htextcaps & 0xffff;
 3346 
 3347         ADDSHORT(frm, extcaps);
 3348 
 3349         frm += sizeof(struct ieee80211_ie_htcap) -
 3350                 __offsetof(struct ieee80211_ie_htcap, hc_txbf);
 3351 
 3352         return frm;
 3353 #undef ADDSHORT
 3354 }
 3355 
 3356 /*
 3357  * Add 802.11n HT capabilities information element
 3358  */
 3359 uint8_t *
 3360 ieee80211_add_htcap(uint8_t *frm, struct ieee80211_node *ni)
 3361 {
 3362         frm[0] = IEEE80211_ELEMID_HTCAP;
 3363         frm[1] = sizeof(struct ieee80211_ie_htcap) - 2;
 3364         return ieee80211_add_htcap_body(frm + 2, ni);
 3365 }
 3366 
 3367 /*
 3368  * Non-associated probe request - add HT capabilities based on
 3369  * the current channel configuration.
 3370  */
 3371 static uint8_t *
 3372 ieee80211_add_htcap_body_ch(uint8_t *frm, struct ieee80211vap *vap,
 3373     struct ieee80211_channel *c)
 3374 {
 3375 #define ADDSHORT(frm, v) do {                   \
 3376         frm[0] = (v) & 0xff;                    \
 3377         frm[1] = (v) >> 8;                      \
 3378         frm += 2;                               \
 3379 } while (0)
 3380         struct ieee80211com *ic = vap->iv_ic;
 3381         uint16_t caps, extcaps;
 3382         int rxmax, density;
 3383 
 3384         /* HT capabilities */
 3385         caps = vap->iv_htcaps & 0xffff;
 3386 
 3387         /*
 3388          * We don't use this in STA mode; only in IBSS mode.
 3389          * So in IBSS mode we base our HTCAP flags on the
 3390          * given channel.
 3391          */
 3392 
 3393         /* override 20/40 use based on current channel */
 3394         if (IEEE80211_IS_CHAN_HT40(c))
 3395                 caps |= IEEE80211_HTCAP_CHWIDTH40;
 3396         else
 3397                 caps &= ~IEEE80211_HTCAP_CHWIDTH40;
 3398 
 3399         /* Use the currently configured values */
 3400         rxmax = vap->iv_ampdu_rxmax;
 3401         density = vap->iv_ampdu_density;
 3402 
 3403         /* adjust short GI based on channel and config */
 3404         if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20) == 0)
 3405                 caps &= ~IEEE80211_HTCAP_SHORTGI20;
 3406         if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40) == 0 ||
 3407             (caps & IEEE80211_HTCAP_CHWIDTH40) == 0)
 3408                 caps &= ~IEEE80211_HTCAP_SHORTGI40;
 3409         ADDSHORT(frm, caps);
 3410 
 3411         /* HT parameters */
 3412         *frm = _IEEE80211_SHIFTMASK(rxmax, IEEE80211_HTCAP_MAXRXAMPDU)
 3413              | _IEEE80211_SHIFTMASK(density, IEEE80211_HTCAP_MPDUDENSITY)
 3414              ;
 3415         frm++;
 3416 
 3417         /* pre-zero remainder of ie */
 3418         memset(frm, 0, sizeof(struct ieee80211_ie_htcap) - 
 3419                 __offsetof(struct ieee80211_ie_htcap, hc_mcsset));
 3420 
 3421         /* supported MCS set */
 3422         /*
 3423          * XXX: For sta mode the rate set should be restricted based
 3424          * on the AP's capabilities, but ni_htrates isn't setup when
 3425          * we're called to form an AssocReq frame so for now we're
 3426          * restricted to the device capabilities.
 3427          */
 3428         ieee80211_set_mcsset(ic, frm);
 3429 
 3430         frm += __offsetof(struct ieee80211_ie_htcap, hc_extcap) -
 3431                 __offsetof(struct ieee80211_ie_htcap, hc_mcsset);
 3432 
 3433         /* HT extended capabilities */
 3434         extcaps = vap->iv_htextcaps & 0xffff;
 3435 
 3436         ADDSHORT(frm, extcaps);
 3437 
 3438         frm += sizeof(struct ieee80211_ie_htcap) -
 3439                 __offsetof(struct ieee80211_ie_htcap, hc_txbf);
 3440 
 3441         return frm;
 3442 #undef ADDSHORT
 3443 }
 3444 
 3445 /*
 3446  * Add 802.11n HT capabilities information element
 3447  */
 3448 uint8_t *
 3449 ieee80211_add_htcap_ch(uint8_t *frm, struct ieee80211vap *vap,
 3450     struct ieee80211_channel *c)
 3451 {
 3452         frm[0] = IEEE80211_ELEMID_HTCAP;
 3453         frm[1] = sizeof(struct ieee80211_ie_htcap) - 2;
 3454         return ieee80211_add_htcap_body_ch(frm + 2, vap, c);
 3455 }
 3456 
 3457 /*
 3458  * Add Broadcom OUI wrapped standard HTCAP ie; this is
 3459  * used for compatibility w/ pre-draft implementations.
 3460  */
 3461 uint8_t *
 3462 ieee80211_add_htcap_vendor(uint8_t *frm, struct ieee80211_node *ni)
 3463 {
 3464         frm[0] = IEEE80211_ELEMID_VENDOR;
 3465         frm[1] = 4 + sizeof(struct ieee80211_ie_htcap) - 2;
 3466         frm[2] = (BCM_OUI >> 0) & 0xff;
 3467         frm[3] = (BCM_OUI >> 8) & 0xff;
 3468         frm[4] = (BCM_OUI >> 16) & 0xff;
 3469         frm[5] = BCM_OUI_HTCAP;
 3470         return ieee80211_add_htcap_body(frm + 6, ni);
 3471 }
 3472 
 3473 /*
 3474  * Construct the MCS bit mask of basic rates
 3475  * for inclusion in an HT information element.
 3476  */
 3477 static void
 3478 ieee80211_set_basic_htrates(uint8_t *frm, const struct ieee80211_htrateset *rs)
 3479 {
 3480         int i;
 3481 
 3482         for (i = 0; i < rs->rs_nrates; i++) {
 3483                 int r = rs->rs_rates[i] & IEEE80211_RATE_VAL;
 3484                 if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) &&
 3485                     r < IEEE80211_HTRATE_MAXSIZE) {
 3486                         /* NB: this assumes a particular implementation */
 3487                         setbit(frm, r);
 3488                 }
 3489         }
 3490 }
 3491 
 3492 /*
 3493  * Update the HTINFO ie for a beacon frame.
 3494  */
 3495 void
 3496 ieee80211_ht_update_beacon(struct ieee80211vap *vap,
 3497         struct ieee80211_beacon_offsets *bo)
 3498 {
 3499 #define PROTMODE        (IEEE80211_HTINFO_OPMODE|IEEE80211_HTINFO_NONHT_PRESENT)
 3500         struct ieee80211_node *ni;
 3501         const struct ieee80211_channel *bsschan;
 3502         struct ieee80211com *ic = vap->iv_ic;
 3503         struct ieee80211_ie_htinfo *ht =
 3504            (struct ieee80211_ie_htinfo *) bo->bo_htinfo;
 3505 
 3506         ni = ieee80211_ref_node(vap->iv_bss);
 3507         bsschan = ni->ni_chan;
 3508 
 3509         /* XXX only update on channel change */
 3510         ht->hi_ctrlchannel = ieee80211_chan2ieee(ic, bsschan);
 3511         if (vap->iv_flags_ht & IEEE80211_FHT_RIFS)
 3512                 ht->hi_byte1 = IEEE80211_HTINFO_RIFSMODE_PERM;
 3513         else
 3514                 ht->hi_byte1 = IEEE80211_HTINFO_RIFSMODE_PROH;
 3515         if (IEEE80211_IS_CHAN_HT40U(bsschan))
 3516                 ht->hi_byte1 |= IEEE80211_HTINFO_2NDCHAN_ABOVE;
 3517         else if (IEEE80211_IS_CHAN_HT40D(bsschan))
 3518                 ht->hi_byte1 |= IEEE80211_HTINFO_2NDCHAN_BELOW;
 3519         else
 3520                 ht->hi_byte1 |= IEEE80211_HTINFO_2NDCHAN_NONE;
 3521         if (IEEE80211_IS_CHAN_HT40(bsschan))
 3522                 ht->hi_byte1 |= IEEE80211_HTINFO_TXWIDTH_2040;
 3523 
 3524         /* protection mode */
 3525         /*
 3526          * XXX TODO: this uses the global flag, not the per-VAP flag.
 3527          * Eventually (once the protection modes are done per-channel
 3528          * rather than per-VAP) we can flip this over to be per-VAP but
 3529          * using the channel protection mode.
 3530          */
 3531         ht->hi_byte2 = (ht->hi_byte2 &~ PROTMODE) | ic->ic_curhtprotmode;
 3532 
 3533         ieee80211_free_node(ni);
 3534 
 3535         /* XXX propagate to vendor ie's */
 3536 #undef PROTMODE
 3537 }
 3538 
 3539 /*
 3540  * Add body of an HTINFO information element.
 3541  *
 3542  * NB: We don't use struct ieee80211_ie_htinfo because we can
 3543  * be called to fillin both a standard ie and a compat ie that
 3544  * has a vendor OUI at the front.
 3545  */
 3546 static uint8_t *
 3547 ieee80211_add_htinfo_body(uint8_t *frm, struct ieee80211_node *ni)
 3548 {
 3549         struct ieee80211vap *vap = ni->ni_vap;
 3550         struct ieee80211com *ic = ni->ni_ic;
 3551 
 3552         /* pre-zero remainder of ie */
 3553         memset(frm, 0, sizeof(struct ieee80211_ie_htinfo) - 2);
 3554 
 3555         /* primary/control channel center */
 3556         *frm++ = ieee80211_chan2ieee(ic, ni->ni_chan);
 3557 
 3558         if (vap->iv_flags_ht & IEEE80211_FHT_RIFS)
 3559                 frm[0] = IEEE80211_HTINFO_RIFSMODE_PERM;
 3560         else
 3561                 frm[0] = IEEE80211_HTINFO_RIFSMODE_PROH;
 3562         if (IEEE80211_IS_CHAN_HT40U(ni->ni_chan))
 3563                 frm[0] |= IEEE80211_HTINFO_2NDCHAN_ABOVE;
 3564         else if (IEEE80211_IS_CHAN_HT40D(ni->ni_chan))
 3565                 frm[0] |= IEEE80211_HTINFO_2NDCHAN_BELOW;
 3566         else
 3567                 frm[0] |= IEEE80211_HTINFO_2NDCHAN_NONE;
 3568         if (IEEE80211_IS_CHAN_HT40(ni->ni_chan))
 3569                 frm[0] |= IEEE80211_HTINFO_TXWIDTH_2040;
 3570 
 3571         /*
 3572          * Add current protection mode.  Unlike for beacons,
 3573          * this will respect the per-VAP flags.
 3574          */
 3575         frm[1] = vap->iv_curhtprotmode;
 3576 
 3577         frm += 5;
 3578 
 3579         /* basic MCS set */
 3580         ieee80211_set_basic_htrates(frm, &ni->ni_htrates);
 3581         frm += sizeof(struct ieee80211_ie_htinfo) -
 3582                 __offsetof(struct ieee80211_ie_htinfo, hi_basicmcsset);
 3583         return frm;
 3584 }
 3585 
 3586 /*
 3587  * Add 802.11n HT information element.
 3588  */
 3589 uint8_t *
 3590 ieee80211_add_htinfo(uint8_t *frm, struct ieee80211_node *ni)
 3591 {
 3592         frm[0] = IEEE80211_ELEMID_HTINFO;
 3593         frm[1] = sizeof(struct ieee80211_ie_htinfo) - 2;
 3594         return ieee80211_add_htinfo_body(frm + 2, ni);
 3595 }
 3596 
 3597 /*
 3598  * Add Broadcom OUI wrapped standard HTINFO ie; this is
 3599  * used for compatibility w/ pre-draft implementations.
 3600  */
 3601 uint8_t *
 3602 ieee80211_add_htinfo_vendor(uint8_t *frm, struct ieee80211_node *ni)
 3603 {
 3604         frm[0] = IEEE80211_ELEMID_VENDOR;
 3605         frm[1] = 4 + sizeof(struct ieee80211_ie_htinfo) - 2;
 3606         frm[2] = (BCM_OUI >> 0) & 0xff;
 3607         frm[3] = (BCM_OUI >> 8) & 0xff;
 3608         frm[4] = (BCM_OUI >> 16) & 0xff;
 3609         frm[5] = BCM_OUI_HTINFO;
 3610         return ieee80211_add_htinfo_body(frm + 6, ni);
 3611 }

Cache object: ba1ab8ff4fc659ceb5f43536248712dd


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.