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