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