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