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