1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2007-2009 Sam Leffler, Errno Consulting 5 * Copyright (c) 2007-2009 Intel Corporation 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * IEEE 802.11 TDMA mode support. 31 */ 32 #include "opt_inet.h" 33 #include "opt_tdma.h" 34 #include "opt_wlan.h" 35 36 #ifdef IEEE80211_SUPPORT_TDMA 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/mbuf.h> 41 #include <sys/malloc.h> 42 #include <sys/kernel.h> 43 44 #include <sys/socket.h> 45 #include <sys/sockio.h> 46 #include <sys/endian.h> 47 #include <sys/errno.h> 48 #include <sys/proc.h> 49 #include <sys/sysctl.h> 50 51 #include <net/if.h> 52 #include <net/if_media.h> 53 #include <net/if_llc.h> 54 #include <net/ethernet.h> 55 56 #include <net/bpf.h> 57 58 #include <net80211/ieee80211_var.h> 59 #include <net80211/ieee80211_tdma.h> 60 #include <net80211/ieee80211_input.h> 61 62 #ifndef TDMA_SLOTLEN_DEFAULT 63 #define TDMA_SLOTLEN_DEFAULT 10*1000 /* 10ms */ 64 #endif 65 #ifndef TDMA_SLOTCNT_DEFAULT 66 #define TDMA_SLOTCNT_DEFAULT 2 /* 2x (pt-to-pt) */ 67 #endif 68 #ifndef TDMA_BINTVAL_DEFAULT 69 #define TDMA_BINTVAL_DEFAULT 5 /* 5x ~= 100TU beacon intvl */ 70 #endif 71 #ifndef TDMA_TXRATE_11B_DEFAULT 72 #define TDMA_TXRATE_11B_DEFAULT 2*11 73 #endif 74 #ifndef TDMA_TXRATE_11G_DEFAULT 75 #define TDMA_TXRATE_11G_DEFAULT 2*24 76 #endif 77 #ifndef TDMA_TXRATE_11A_DEFAULT 78 #define TDMA_TXRATE_11A_DEFAULT 2*24 79 #endif 80 #ifndef TDMA_TXRATE_TURBO_DEFAULT 81 #define TDMA_TXRATE_TURBO_DEFAULT 2*24 82 #endif 83 #ifndef TDMA_TXRATE_HALF_DEFAULT 84 #define TDMA_TXRATE_HALF_DEFAULT 2*12 85 #endif 86 #ifndef TDMA_TXRATE_QUARTER_DEFAULT 87 #define TDMA_TXRATE_QUARTER_DEFAULT 2*6 88 #endif 89 #ifndef TDMA_TXRATE_11NA_DEFAULT 90 #define TDMA_TXRATE_11NA_DEFAULT (4 | IEEE80211_RATE_MCS) 91 #endif 92 #ifndef TDMA_TXRATE_11NG_DEFAULT 93 #define TDMA_TXRATE_11NG_DEFAULT (4 | IEEE80211_RATE_MCS) 94 #endif 95 96 #define TDMA_VERSION_VALID(_version) \ 97 (TDMA_VERSION_V2 <= (_version) && (_version) <= TDMA_VERSION) 98 #define TDMA_SLOTCNT_VALID(_slotcnt) \ 99 (2 <= (_slotcnt) && (_slotcnt) <= TDMA_MAXSLOTS) 100 /* XXX magic constants */ 101 #define TDMA_SLOTLEN_VALID(_slotlen) \ 102 (2*100 <= (_slotlen) && (unsigned)(_slotlen) <= 0xfffff) 103 /* XXX probably should set a max */ 104 #define TDMA_BINTVAL_VALID(_bintval) (1 <= (_bintval)) 105 106 /* 107 * This code is not prepared to handle more than 2 slots. 108 */ 109 CTASSERT(TDMA_MAXSLOTS == 2); 110 111 static void tdma_vdetach(struct ieee80211vap *vap); 112 static int tdma_newstate(struct ieee80211vap *, enum ieee80211_state, int); 113 static void tdma_beacon_miss(struct ieee80211vap *vap); 114 static void tdma_recv_mgmt(struct ieee80211_node *, struct mbuf *, 115 int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf); 116 static int tdma_update(struct ieee80211vap *vap, 117 const struct ieee80211_tdma_param *tdma, struct ieee80211_node *ni, 118 int pickslot); 119 static int tdma_process_params(struct ieee80211_node *ni, 120 const u_int8_t *ie, int rssi, int nf, const struct ieee80211_frame *wh); 121 122 static void 123 settxparms(struct ieee80211vap *vap, enum ieee80211_phymode mode, int rate) 124 { 125 if (isclr(vap->iv_ic->ic_modecaps, mode)) 126 return; 127 128 vap->iv_txparms[mode].ucastrate = rate; 129 vap->iv_txparms[mode].mcastrate = rate; 130 } 131 132 static void 133 setackpolicy(struct ieee80211com *ic, int noack) 134 { 135 struct ieee80211_wme_state *wme = &ic->ic_wme; 136 int ac; 137 138 for (ac = 0; ac < WME_NUM_AC; ac++) { 139 wme->wme_chanParams.cap_wmeParams[ac].wmep_noackPolicy = noack; 140 wme->wme_wmeChanParams.cap_wmeParams[ac].wmep_noackPolicy = noack; 141 } 142 } 143 144 void 145 ieee80211_tdma_vattach(struct ieee80211vap *vap) 146 { 147 struct ieee80211_tdma_state *ts; 148 149 KASSERT(vap->iv_caps & IEEE80211_C_TDMA, 150 ("not a tdma vap, caps 0x%x", vap->iv_caps)); 151 152 ts = (struct ieee80211_tdma_state *) IEEE80211_MALLOC( 153 sizeof(struct ieee80211_tdma_state), M_80211_VAP, 154 IEEE80211_M_NOWAIT | IEEE80211_M_ZERO); 155 if (ts == NULL) { 156 net80211_vap_printf(vap, 157 "%s: cannot allocate TDMA state block\n", __func__); 158 /* NB: fall back to adhdemo mode */ 159 vap->iv_caps &= ~IEEE80211_C_TDMA; 160 return; 161 } 162 /* NB: default configuration is passive so no beacons */ 163 ts->tdma_version = TDMA_VERSION; 164 ts->tdma_slotlen = TDMA_SLOTLEN_DEFAULT; 165 ts->tdma_slotcnt = TDMA_SLOTCNT_DEFAULT; 166 ts->tdma_bintval = TDMA_BINTVAL_DEFAULT; 167 ts->tdma_slot = 1; /* passive operation */ 168 169 /* setup default fixed rates */ 170 settxparms(vap, IEEE80211_MODE_11A, TDMA_TXRATE_11A_DEFAULT); 171 settxparms(vap, IEEE80211_MODE_11B, TDMA_TXRATE_11B_DEFAULT); 172 settxparms(vap, IEEE80211_MODE_11G, TDMA_TXRATE_11G_DEFAULT); 173 settxparms(vap, IEEE80211_MODE_TURBO_A, TDMA_TXRATE_TURBO_DEFAULT); 174 settxparms(vap, IEEE80211_MODE_TURBO_G, TDMA_TXRATE_TURBO_DEFAULT); 175 settxparms(vap, IEEE80211_MODE_STURBO_A, TDMA_TXRATE_TURBO_DEFAULT); 176 settxparms(vap, IEEE80211_MODE_11NA, TDMA_TXRATE_11NA_DEFAULT); 177 settxparms(vap, IEEE80211_MODE_11NG, TDMA_TXRATE_11NG_DEFAULT); 178 settxparms(vap, IEEE80211_MODE_HALF, TDMA_TXRATE_HALF_DEFAULT); 179 settxparms(vap, IEEE80211_MODE_QUARTER, TDMA_TXRATE_QUARTER_DEFAULT); 180 settxparms(vap, IEEE80211_MODE_VHT_2GHZ, TDMA_TXRATE_11NG_DEFAULT); 181 settxparms(vap, IEEE80211_MODE_VHT_5GHZ, TDMA_TXRATE_11NA_DEFAULT); 182 183 setackpolicy(vap->iv_ic, 1); /* disable ACK's */ 184 185 ts->tdma_opdetach = vap->iv_opdetach; 186 vap->iv_opdetach = tdma_vdetach; 187 ts->tdma_newstate = vap->iv_newstate; 188 vap->iv_newstate = tdma_newstate; 189 vap->iv_bmiss = tdma_beacon_miss; 190 ts->tdma_recv_mgmt = vap->iv_recv_mgmt; 191 vap->iv_recv_mgmt = tdma_recv_mgmt; 192 193 vap->iv_tdma = ts; 194 } 195 196 static void 197 tdma_vdetach(struct ieee80211vap *vap) 198 { 199 struct ieee80211_tdma_state *ts = vap->iv_tdma; 200 201 if (ts == NULL) { 202 /* NB: should not have touched any ic state */ 203 return; 204 } 205 ts->tdma_opdetach(vap); 206 IEEE80211_FREE(vap->iv_tdma, M_80211_VAP); 207 vap->iv_tdma = NULL; 208 209 setackpolicy(vap->iv_ic, 0); /* enable ACK's */ 210 } 211 212 static void 213 sta_leave(void *arg, struct ieee80211_node *ni) 214 { 215 struct ieee80211vap *vap = ni->ni_vap; 216 217 if (ni != vap->iv_bss) 218 ieee80211_node_leave(ni); 219 } 220 221 /* 222 * TDMA state machine handler. 223 */ 224 static int 225 tdma_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) 226 { 227 struct ieee80211_tdma_state *ts = vap->iv_tdma; 228 struct ieee80211com *ic = vap->iv_ic; 229 enum ieee80211_state ostate; 230 int status; 231 232 IEEE80211_LOCK_ASSERT(ic); 233 234 ostate = vap->iv_state; 235 IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE, "%s: %s -> %s (%d)\n", 236 __func__, ieee80211_state_name[ostate], 237 ieee80211_state_name[nstate], arg); 238 239 if (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) 240 callout_stop(&vap->iv_swbmiss); 241 if (nstate == IEEE80211_S_SCAN && 242 (ostate == IEEE80211_S_INIT || ostate == IEEE80211_S_RUN) && 243 ts->tdma_slot != 0) { 244 /* 245 * Override adhoc behaviour when operating as a slave; 246 * we need to scan even if the channel is locked. 247 */ 248 vap->iv_state = nstate; /* state transition */ 249 ieee80211_cancel_scan(vap); /* background scan */ 250 if (ostate == IEEE80211_S_RUN) { 251 /* purge station table; entries are stale */ 252 ieee80211_iterate_nodes_vap(&ic->ic_sta, vap, 253 sta_leave, NULL); 254 } 255 if (vap->iv_flags_ext & IEEE80211_FEXT_SCANREQ) { 256 ieee80211_check_scan(vap, 257 vap->iv_scanreq_flags, 258 vap->iv_scanreq_duration, 259 vap->iv_scanreq_mindwell, 260 vap->iv_scanreq_maxdwell, 261 vap->iv_scanreq_nssid, vap->iv_scanreq_ssid); 262 vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANREQ; 263 } else 264 ieee80211_check_scan_current(vap); 265 status = 0; 266 } else { 267 status = ts->tdma_newstate(vap, nstate, arg); 268 } 269 if (status == 0 && 270 nstate == IEEE80211_S_RUN && ostate != IEEE80211_S_RUN && 271 (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) && 272 ts->tdma_slot != 0 && 273 vap->iv_des_chan == IEEE80211_CHAN_ANYC) { 274 /* 275 * Start s/w beacon miss timer for slave devices w/o 276 * hardware support. Note we do this only if we're 277 * not locked to a channel (i.e. roam to follow the 278 * master). The 2x is a fudge for our doing this in 279 * software. 280 */ 281 vap->iv_swbmiss_period = IEEE80211_TU_TO_TICKS( 282 2 * vap->iv_bmissthreshold * ts->tdma_bintval * 283 ((ts->tdma_slotcnt * ts->tdma_slotlen) / 1024)); 284 vap->iv_swbmiss_count = 0; 285 callout_reset(&vap->iv_swbmiss, vap->iv_swbmiss_period, 286 ieee80211_swbmiss, vap); 287 } 288 return status; 289 } 290 291 static void 292 tdma_beacon_miss(struct ieee80211vap *vap) 293 { 294 struct ieee80211_tdma_state *ts = vap->iv_tdma; 295 296 IEEE80211_LOCK_ASSERT(vap->iv_ic); 297 298 KASSERT((vap->iv_ic->ic_flags & IEEE80211_F_SCAN) == 0, ("scanning")); 299 KASSERT(vap->iv_state == IEEE80211_S_RUN, 300 ("wrong state %d", vap->iv_state)); 301 302 IEEE80211_DPRINTF(vap, 303 IEEE80211_MSG_STATE | IEEE80211_MSG_TDMA | IEEE80211_MSG_DEBUG, 304 "beacon miss, mode %u state %s\n", 305 vap->iv_opmode, ieee80211_state_name[vap->iv_state]); 306 307 callout_stop(&vap->iv_swbmiss); 308 309 if (ts->tdma_peer != NULL) { /* XXX? can this be null? */ 310 ieee80211_notify_node_leave(vap->iv_bss); 311 ts->tdma_peer = NULL; 312 /* 313 * Treat beacon miss like an associate failure wrt the 314 * scan policy; this forces the entry in the scan cache 315 * to be ignored after several tries. 316 */ 317 ieee80211_scan_assoc_fail(vap, vap->iv_bss->ni_macaddr, 318 IEEE80211_STATUS_TIMEOUT); 319 } 320 #if 0 321 ts->tdma_inuse = 0; /* clear slot usage */ 322 #endif 323 ieee80211_new_state(vap, IEEE80211_S_SCAN, 0); 324 } 325 326 static void 327 tdma_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, 328 int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf) 329 { 330 struct ieee80211com *ic = ni->ni_ic; 331 struct ieee80211vap *vap = ni->ni_vap; 332 struct ieee80211_tdma_state *ts = vap->iv_tdma; 333 334 if (subtype == IEEE80211_FC0_SUBTYPE_BEACON && 335 (ic->ic_flags & IEEE80211_F_SCAN) == 0) { 336 struct ieee80211_frame *wh = mtod(m0, struct ieee80211_frame *); 337 struct ieee80211_scanparams scan; 338 339 /* XXX TODO: use rxstatus to determine off-channel beacons */ 340 if (ieee80211_parse_beacon(ni, m0, ic->ic_curchan, &scan) != 0) 341 return; 342 if (scan.tdma == NULL) { 343 /* 344 * TDMA stations must beacon a TDMA ie; ignore 345 * any other station. 346 * XXX detect overlapping bss and change channel 347 */ 348 IEEE80211_DISCARD(vap, 349 IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT, 350 wh, ieee80211_mgt_subtype_name(subtype), 351 "%s", "no TDMA ie"); 352 vap->iv_stats.is_rx_mgtdiscard++; 353 return; 354 } 355 if (ni == vap->iv_bss && 356 !IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr)) { 357 /* 358 * Fake up a node for this newly 359 * discovered member of the IBSS. 360 */ 361 ni = ieee80211_add_neighbor(vap, wh, &scan); 362 if (ni == NULL) { 363 /* NB: stat kept for alloc failure */ 364 return; 365 } 366 } 367 /* 368 * Check for state updates. 369 */ 370 if (IEEE80211_ADDR_EQ(wh->i_addr3, ni->ni_bssid)) { 371 /* 372 * Count frame now that we know it's to be processed. 373 */ 374 vap->iv_stats.is_rx_beacon++; 375 IEEE80211_NODE_STAT(ni, rx_beacons); 376 /* 377 * Record tsf of last beacon. NB: this must be 378 * done before calling tdma_process_params 379 * as deeper routines reference it. 380 */ 381 memcpy(&ni->ni_tstamp.data, scan.tstamp, 382 sizeof(ni->ni_tstamp.data)); 383 /* 384 * Count beacon frame for s/w bmiss handling. 385 */ 386 vap->iv_swbmiss_count++; 387 /* 388 * Process tdma ie. The contents are used to sync 389 * the slot timing, reconfigure the bss, etc. 390 */ 391 (void) tdma_process_params(ni, scan.tdma, rssi, nf, wh); 392 return; 393 } 394 /* 395 * NB: defer remaining work to the adhoc code; this causes 396 * 2x parsing of the frame but should happen infrequently 397 */ 398 } 399 ts->tdma_recv_mgmt(ni, m0, subtype, rxs, rssi, nf); 400 } 401 402 /* 403 * Update TDMA state on receipt of a beacon frame with 404 * a TDMA information element. The sender's identity 405 * is provided so we can track who our peer is. If pickslot 406 * is non-zero we scan the slot allocation state in the ie 407 * to locate a free slot for our use. 408 */ 409 static int 410 tdma_update(struct ieee80211vap *vap, const struct ieee80211_tdma_param *tdma, 411 struct ieee80211_node *ni, int pickslot) 412 { 413 struct ieee80211_tdma_state *ts = vap->iv_tdma; 414 int slot, slotlen, update; 415 416 KASSERT(vap->iv_caps & IEEE80211_C_TDMA, 417 ("not a tdma vap, caps 0x%x", vap->iv_caps)); 418 419 update = 0; 420 if (tdma->tdma_slotcnt != ts->tdma_slotcnt) { 421 if (!TDMA_SLOTCNT_VALID(tdma->tdma_slotcnt)) { 422 if (ppsratecheck(&ts->tdma_lastprint, &ts->tdma_fails, 1)) 423 net80211_vap_printf(vap, 424 "%s: bad slot cnt %u\n", __func__, 425 tdma->tdma_slotcnt); 426 return 0; 427 } 428 update |= TDMA_UPDATE_SLOTCNT; 429 } 430 slotlen = le16toh(tdma->tdma_slotlen) * 100; 431 if (slotlen != ts->tdma_slotlen) { 432 if (!TDMA_SLOTLEN_VALID(slotlen)) { 433 if (ppsratecheck(&ts->tdma_lastprint, &ts->tdma_fails, 1)) 434 net80211_vap_printf(vap, 435 "%s: bad slot len %u\n", __func__, slotlen); 436 return 0; 437 } 438 update |= TDMA_UPDATE_SLOTLEN; 439 } 440 if (tdma->tdma_bintval != ts->tdma_bintval) { 441 if (!TDMA_BINTVAL_VALID(tdma->tdma_bintval)) { 442 if (ppsratecheck(&ts->tdma_lastprint, &ts->tdma_fails, 1)) 443 net80211_vap_printf(vap, 444 "%s: bad beacon interval %u\n", __func__, 445 tdma->tdma_bintval); 446 return 0; 447 } 448 update |= TDMA_UPDATE_BINTVAL; 449 } 450 slot = ts->tdma_slot; 451 if (pickslot) { 452 /* 453 * Pick unoccupied slot. Note we never choose slot 0. 454 */ 455 for (slot = tdma->tdma_slotcnt-1; slot > 0; slot--) 456 if (isclr(tdma->tdma_inuse, slot)) 457 break; 458 if (slot <= 0) { 459 net80211_vap_printf(vap, 460 "%s: no free slot, slotcnt %u inuse: 0x%x\n", 461 __func__, tdma->tdma_slotcnt, 462 tdma->tdma_inuse[0]); 463 /* XXX need to do something better */ 464 return 0; 465 } 466 if (slot != ts->tdma_slot) 467 update |= TDMA_UPDATE_SLOT; 468 } 469 if (ni != ts->tdma_peer) { 470 /* update everything */ 471 update = TDMA_UPDATE_SLOT 472 | TDMA_UPDATE_SLOTCNT 473 | TDMA_UPDATE_SLOTLEN 474 | TDMA_UPDATE_BINTVAL; 475 } 476 477 if (update) { 478 /* 479 * New/changed parameters; update runtime state. 480 */ 481 /* XXX overwrites user parameters */ 482 if (update & TDMA_UPDATE_SLOTCNT) 483 ts->tdma_slotcnt = tdma->tdma_slotcnt; 484 if (update & TDMA_UPDATE_SLOTLEN) 485 ts->tdma_slotlen = slotlen; 486 if (update & TDMA_UPDATE_SLOT) 487 ts->tdma_slot = slot; 488 if (update & TDMA_UPDATE_BINTVAL) 489 ts->tdma_bintval = tdma->tdma_bintval; 490 /* mark beacon to be updated before next xmit */ 491 ieee80211_beacon_notify(vap, IEEE80211_BEACON_TDMA); 492 493 IEEE80211_DPRINTF(vap, IEEE80211_MSG_TDMA, 494 "%s: slot %u slotcnt %u slotlen %u us bintval %u\n", 495 __func__, ts->tdma_slot, ts->tdma_slotcnt, 496 ts->tdma_slotlen, ts->tdma_bintval); 497 } 498 /* 499 * Notify driver. Note we can be called before 500 * entering RUN state if we scanned and are 501 * joining an existing bss. In that case do not 502 * call the driver because not all necessary state 503 * has been setup. The next beacon will dtrt. 504 */ 505 if (vap->iv_state == IEEE80211_S_RUN) 506 vap->iv_ic->ic_tdma_update(ni, tdma, update); 507 /* 508 * Dispatch join event on first beacon from new master. 509 */ 510 if (ts->tdma_peer != ni) { 511 if (ts->tdma_peer != NULL) 512 ieee80211_notify_node_leave(vap->iv_bss); 513 ieee80211_notify_node_join(ni, 1); 514 /* NB: no reference, we just use the address */ 515 ts->tdma_peer = ni; 516 } 517 return 1; 518 } 519 520 /* 521 * Process received TDMA parameters. 522 */ 523 static int 524 tdma_process_params(struct ieee80211_node *ni, const u_int8_t *ie, 525 int rssi, int nf, const struct ieee80211_frame *wh) 526 { 527 struct ieee80211vap *vap = ni->ni_vap; 528 struct ieee80211_tdma_state *ts = vap->iv_tdma; 529 const struct ieee80211_tdma_param *tdma = 530 (const struct ieee80211_tdma_param *) ie; 531 u_int len = ie[1]; 532 533 KASSERT(vap->iv_caps & IEEE80211_C_TDMA, 534 ("not a tdma vap, caps 0x%x", vap->iv_caps)); 535 536 if (len < sizeof(*tdma) - 2) { 537 IEEE80211_DISCARD_IE(vap, 538 IEEE80211_MSG_ELEMID | IEEE80211_MSG_TDMA, 539 wh, "tdma", "too short, len %u", len); 540 return IEEE80211_REASON_IE_INVALID; 541 } 542 if (tdma->tdma_version != ts->tdma_version) { 543 IEEE80211_DISCARD_IE(vap, 544 IEEE80211_MSG_ELEMID | IEEE80211_MSG_TDMA, 545 wh, "tdma", "bad version %u (ours %u)", 546 tdma->tdma_version, ts->tdma_version); 547 return IEEE80211_REASON_IE_INVALID; 548 } 549 /* 550 * NB: ideally we'd check against tdma_slotcnt, but that 551 * would require extra effort so do this easy check that 552 * covers the work below; more stringent checks are done 553 * before we make more extensive use of the ie contents. 554 */ 555 if (tdma->tdma_slot >= TDMA_MAXSLOTS) { 556 IEEE80211_DISCARD_IE(vap, 557 IEEE80211_MSG_ELEMID | IEEE80211_MSG_TDMA, 558 wh, "tdma", "invalid slot %u", tdma->tdma_slot); 559 return IEEE80211_REASON_IE_INVALID; 560 } 561 /* 562 * Can reach here while scanning, update 563 * operational state only in RUN state. 564 */ 565 if (vap->iv_state == IEEE80211_S_RUN) { 566 if (tdma->tdma_slot != ts->tdma_slot && 567 isclr(ts->tdma_inuse, tdma->tdma_slot)) { 568 IEEE80211_NOTE(vap, IEEE80211_MSG_TDMA, ni, 569 "discovered in slot %u", tdma->tdma_slot); 570 setbit(ts->tdma_inuse, tdma->tdma_slot); 571 /* XXX dispatch event only when operating as master */ 572 if (ts->tdma_slot == 0) 573 ieee80211_notify_node_join(ni, 1); 574 } 575 setbit(ts->tdma_active, tdma->tdma_slot); 576 if (tdma->tdma_slot == ts->tdma_slot-1) { 577 /* 578 * Slave tsf synchronization to station 579 * just before us in the schedule. The driver 580 * is responsible for copying the timestamp 581 * of the received beacon into our beacon 582 * frame so the sender can calculate round 583 * trip time. We cannot do that here because 584 * we don't know how to update our beacon frame. 585 */ 586 (void) tdma_update(vap, tdma, ni, 0); 587 /* XXX reschedule swbmiss timer on parameter change */ 588 } else if (tdma->tdma_slot == ts->tdma_slot+1) { 589 uint64_t tstamp; 590 #if 0 591 uint32_t rstamp = (uint32_t) le64toh(rs->tsf); 592 int32_t rtt; 593 #endif 594 /* 595 * Use returned timstamp to calculate the 596 * roundtrip time. 597 */ 598 memcpy(&tstamp, tdma->tdma_tstamp, 8); 599 #if 0 600 /* XXX use only 15 bits of rstamp */ 601 rtt = rstamp - (le64toh(tstamp) & 0x7fff); 602 if (rtt < 0) 603 rtt += 0x7fff; 604 /* XXX hack to quiet normal use */ 605 IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOT1X, 606 "tdma rtt %5u [rstamp %5u tstamp %llu]\n", 607 rtt, rstamp, 608 (unsigned long long) le64toh(tstamp)); 609 #endif 610 } else if (tdma->tdma_slot == ts->tdma_slot && 611 le64toh(ni->ni_tstamp.tsf) > vap->iv_bss->ni_tstamp.tsf) { 612 /* 613 * Station using the same slot as us and has 614 * been around longer than us; we must move. 615 * Note this can happen if stations do not 616 * see each other while scanning. 617 */ 618 IEEE80211_DPRINTF(vap, IEEE80211_MSG_TDMA, 619 "slot %u collision rxtsf %llu tsf %llu\n", 620 tdma->tdma_slot, 621 (unsigned long long) le64toh(ni->ni_tstamp.tsf), 622 vap->iv_bss->ni_tstamp.tsf); 623 setbit(ts->tdma_inuse, tdma->tdma_slot); 624 625 (void) tdma_update(vap, tdma, ni, 1); 626 } 627 } 628 return 0; 629 } 630 631 int 632 ieee80211_tdma_getslot(struct ieee80211vap *vap) 633 { 634 struct ieee80211_tdma_state *ts = vap->iv_tdma; 635 636 KASSERT(vap->iv_caps & IEEE80211_C_TDMA, 637 ("not a tdma vap, caps 0x%x", vap->iv_caps)); 638 return ts->tdma_slot; 639 } 640 641 /* 642 * Parse a TDMA ie on station join and use it to setup node state. 643 */ 644 void 645 ieee80211_parse_tdma(struct ieee80211_node *ni, const uint8_t *ie) 646 { 647 struct ieee80211vap *vap = ni->ni_vap; 648 649 if (vap->iv_caps & IEEE80211_C_TDMA) { 650 const struct ieee80211_tdma_param *tdma = 651 (const struct ieee80211_tdma_param *)ie; 652 struct ieee80211_tdma_state *ts = vap->iv_tdma; 653 /* 654 * Adopt TDMA configuration when joining an 655 * existing network. 656 */ 657 setbit(ts->tdma_inuse, tdma->tdma_slot); 658 (void) tdma_update(vap, tdma, ni, 1); 659 /* 660 * Propagate capabilities based on the local 661 * configuration and the remote station's advertised 662 * capabilities. In particular this permits us to 663 * enable use of QoS to disable ACK's. 664 */ 665 if ((vap->iv_flags & IEEE80211_F_WME) && 666 ni->ni_ies.wme_ie != NULL) 667 ni->ni_flags |= IEEE80211_NODE_QOS; 668 } 669 } 670 671 #define TDMA_OUI_BYTES 0x00, 0x03, 0x7f 672 /* 673 * Add a TDMA parameters element to a frame. 674 */ 675 uint8_t * 676 ieee80211_add_tdma(uint8_t *frm, struct ieee80211vap *vap) 677 { 678 #define ADDSHORT(frm, v) do { \ 679 frm[0] = (v) & 0xff; \ 680 frm[1] = (v) >> 8; \ 681 frm += 2; \ 682 } while (0) 683 static const struct ieee80211_tdma_param param = { 684 .tdma_id = IEEE80211_ELEMID_VENDOR, 685 .tdma_len = sizeof(struct ieee80211_tdma_param) - 2, 686 .tdma_oui = { TDMA_OUI_BYTES }, 687 .tdma_type = TDMA_OUI_TYPE, 688 .tdma_subtype = TDMA_SUBTYPE_PARAM, 689 .tdma_version = TDMA_VERSION, 690 }; 691 const struct ieee80211_tdma_state *ts = vap->iv_tdma; 692 uint16_t slotlen; 693 694 KASSERT(vap->iv_caps & IEEE80211_C_TDMA, 695 ("not a tdma vap, caps 0x%x", vap->iv_caps)); 696 697 memcpy(frm, ¶m, sizeof(param)); 698 frm += __offsetof(struct ieee80211_tdma_param, tdma_slot); 699 *frm++ = ts->tdma_slot; 700 *frm++ = ts->tdma_slotcnt; 701 /* NB: convert units to fit in 16-bits */ 702 slotlen = ts->tdma_slotlen / 100; /* 100us units */ 703 ADDSHORT(frm, slotlen); 704 *frm++ = ts->tdma_bintval; 705 *frm++ = ts->tdma_inuse[0]; 706 frm += 10; /* pad+timestamp */ 707 return frm; 708 #undef ADDSHORT 709 } 710 #undef TDMA_OUI_BYTES 711 712 /* 713 * Update TDMA state at TBTT. 714 */ 715 void 716 ieee80211_tdma_update_beacon(struct ieee80211vap *vap, 717 struct ieee80211_beacon_offsets *bo) 718 { 719 struct ieee80211_tdma_state *ts = vap->iv_tdma; 720 721 KASSERT(vap->iv_caps & IEEE80211_C_TDMA, 722 ("not a tdma vap, caps 0x%x", vap->iv_caps)); 723 724 if (isset(bo->bo_flags, IEEE80211_BEACON_TDMA)) { 725 (void) ieee80211_add_tdma(bo->bo_tdma, vap); 726 clrbit(bo->bo_flags, IEEE80211_BEACON_TDMA); 727 } 728 if (ts->tdma_slot != 0) /* only on master */ 729 return; 730 if (ts->tdma_count <= 0) { 731 /* 732 * Time to update the mask of active/inuse stations. 733 * We track stations that we've received a beacon 734 * frame from and update this mask periodically. 735 * This allows us to miss a few beacons before marking 736 * a slot free for re-use. 737 */ 738 ts->tdma_inuse[0] = ts->tdma_active[0]; 739 ts->tdma_active[0] = 0x01; 740 /* update next time 'round */ 741 /* XXX use notify framework */ 742 setbit(bo->bo_flags, IEEE80211_BEACON_TDMA); 743 /* NB: use s/w beacon miss threshold; may be too high */ 744 ts->tdma_count = vap->iv_bmissthreshold-1; 745 } else 746 ts->tdma_count--; 747 } 748 749 static int 750 tdma_ioctl_get80211(struct ieee80211vap *vap, struct ieee80211req *ireq) 751 { 752 struct ieee80211_tdma_state *ts = vap->iv_tdma; 753 754 if ((vap->iv_caps & IEEE80211_C_TDMA) == 0) 755 return ENOSYS; 756 757 switch (ireq->i_type) { 758 case IEEE80211_IOC_TDMA_SLOT: 759 ireq->i_val = ts->tdma_slot; 760 break; 761 case IEEE80211_IOC_TDMA_SLOTCNT: 762 ireq->i_val = ts->tdma_slotcnt; 763 break; 764 case IEEE80211_IOC_TDMA_SLOTLEN: 765 ireq->i_val = ts->tdma_slotlen; 766 break; 767 case IEEE80211_IOC_TDMA_BINTERVAL: 768 ireq->i_val = ts->tdma_bintval; 769 break; 770 default: 771 return ENOSYS; 772 } 773 return 0; 774 } 775 IEEE80211_IOCTL_GET(tdma, tdma_ioctl_get80211); 776 777 static int 778 tdma_ioctl_set80211(struct ieee80211vap *vap, struct ieee80211req *ireq) 779 { 780 struct ieee80211_tdma_state *ts = vap->iv_tdma; 781 782 if ((vap->iv_caps & IEEE80211_C_TDMA) == 0) 783 return ENOSYS; 784 785 switch (ireq->i_type) { 786 case IEEE80211_IOC_TDMA_SLOT: 787 if (!(0 <= ireq->i_val && ireq->i_val <= ts->tdma_slotcnt)) 788 return EINVAL; 789 if (ireq->i_val != ts->tdma_slot) { 790 ts->tdma_slot = ireq->i_val; 791 goto restart; 792 } 793 break; 794 case IEEE80211_IOC_TDMA_SLOTCNT: 795 if (!TDMA_SLOTCNT_VALID(ireq->i_val)) 796 return EINVAL; 797 if (ireq->i_val != ts->tdma_slotcnt) { 798 ts->tdma_slotcnt = ireq->i_val; 799 goto restart; 800 } 801 break; 802 case IEEE80211_IOC_TDMA_SLOTLEN: 803 /* 804 * XXX 805 * 150 insures at least 1/8 TU 806 * 0xfffff is the max duration for bursting 807 * (implict by way of 16-bit data type for i_val) 808 */ 809 if (!TDMA_SLOTLEN_VALID(ireq->i_val)) 810 return EINVAL; 811 if (ireq->i_val != ts->tdma_slotlen) { 812 ts->tdma_slotlen = ireq->i_val; 813 goto restart; 814 } 815 break; 816 case IEEE80211_IOC_TDMA_BINTERVAL: 817 if (!TDMA_BINTVAL_VALID(ireq->i_val)) 818 return EINVAL; 819 if (ireq->i_val != ts->tdma_bintval) { 820 ts->tdma_bintval = ireq->i_val; 821 goto restart; 822 } 823 break; 824 default: 825 return ENOSYS; 826 } 827 return 0; 828 restart: 829 ieee80211_beacon_notify(vap, IEEE80211_BEACON_TDMA); 830 return ERESTART; 831 } 832 IEEE80211_IOCTL_SET(tdma, tdma_ioctl_set80211); 833 834 #endif /* IEEE80211_SUPPORT_TDMA */ 835