Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/net80211/ieee80211_phy.c
39475 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
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
/*
30
* IEEE 802.11 PHY-related support.
31
*/
32
33
#include "opt_inet.h"
34
35
#include <sys/param.h>
36
#include <sys/kernel.h>
37
#include <sys/systm.h>
38
#include <sys/malloc.h>
39
40
#include <sys/socket.h>
41
42
#include <net/if.h>
43
#include <net/if_media.h>
44
45
#include <net/ethernet.h>
46
#include <net/route.h>
47
48
#include <net80211/ieee80211_var.h>
49
#include <net80211/ieee80211_phy.h>
50
51
#ifdef notyet
52
struct ieee80211_ds_plcp_hdr {
53
uint8_t i_signal;
54
uint8_t i_service;
55
uint16_t i_length;
56
uint16_t i_crc;
57
} __packed;
58
59
#endif /* notyet */
60
61
/* shorthands to compact tables for readability */
62
#define OFDM IEEE80211_T_OFDM
63
#define CCK IEEE80211_T_CCK
64
#define TURBO IEEE80211_T_TURBO
65
#define HALF IEEE80211_T_OFDM_HALF
66
#define QUART IEEE80211_T_OFDM_QUARTER
67
#define HT IEEE80211_T_HT
68
/* XXX the 11n and the basic rate flag are unfortunately overlapping. Grr. */
69
#define N(r) (IEEE80211_RATE_MCS | r)
70
#define PBCC (IEEE80211_T_OFDM_QUARTER+1) /* XXX */
71
#define B(r) (IEEE80211_RATE_BASIC | r)
72
#define Mb(x) (x*1000)
73
74
static struct ieee80211_rate_table ieee80211_11b_table = {
75
.rateCount = 4, /* XXX no PBCC */
76
.info = {
77
/* short ctrl */
78
/* Preamble dot11Rate Rate */
79
[0] = { .phy = CCK, 1000, 0x00, B(2), 0 },/* 1 Mb */
80
[1] = { .phy = CCK, 2000, 0x04, B(4), 1 },/* 2 Mb */
81
[2] = { .phy = CCK, 5500, 0x04, B(11), 1 },/* 5.5 Mb */
82
[3] = { .phy = CCK, 11000, 0x04, B(22), 1 },/* 11 Mb */
83
[4] = { .phy = PBCC, 22000, 0x04, 44, 3 } /* 22 Mb */
84
},
85
};
86
87
static struct ieee80211_rate_table ieee80211_11g_table = {
88
.rateCount = 12,
89
.info = {
90
/* short ctrl */
91
/* Preamble dot11Rate Rate */
92
[0] = { .phy = CCK, 1000, 0x00, B(2), 0 },
93
[1] = { .phy = CCK, 2000, 0x04, B(4), 1 },
94
[2] = { .phy = CCK, 5500, 0x04, B(11), 2 },
95
[3] = { .phy = CCK, 11000, 0x04, B(22), 3 },
96
[4] = { .phy = OFDM, 6000, 0x00, 12, 4 },
97
[5] = { .phy = OFDM, 9000, 0x00, 18, 4 },
98
[6] = { .phy = OFDM, 12000, 0x00, 24, 6 },
99
[7] = { .phy = OFDM, 18000, 0x00, 36, 6 },
100
[8] = { .phy = OFDM, 24000, 0x00, 48, 8 },
101
[9] = { .phy = OFDM, 36000, 0x00, 72, 8 },
102
[10] = { .phy = OFDM, 48000, 0x00, 96, 8 },
103
[11] = { .phy = OFDM, 54000, 0x00, 108, 8 }
104
},
105
};
106
107
static struct ieee80211_rate_table ieee80211_11a_table = {
108
.rateCount = 8,
109
.info = {
110
/* short ctrl */
111
/* Preamble dot11Rate Rate */
112
[0] = { .phy = OFDM, 6000, 0x00, B(12), 0 },
113
[1] = { .phy = OFDM, 9000, 0x00, 18, 0 },
114
[2] = { .phy = OFDM, 12000, 0x00, B(24), 2 },
115
[3] = { .phy = OFDM, 18000, 0x00, 36, 2 },
116
[4] = { .phy = OFDM, 24000, 0x00, B(48), 4 },
117
[5] = { .phy = OFDM, 36000, 0x00, 72, 4 },
118
[6] = { .phy = OFDM, 48000, 0x00, 96, 4 },
119
[7] = { .phy = OFDM, 54000, 0x00, 108, 4 }
120
},
121
};
122
123
static struct ieee80211_rate_table ieee80211_half_table = {
124
.rateCount = 8,
125
.info = {
126
/* short ctrl */
127
/* Preamble dot11Rate Rate */
128
[0] = { .phy = HALF, 3000, 0x00, B(6), 0 },
129
[1] = { .phy = HALF, 4500, 0x00, 9, 0 },
130
[2] = { .phy = HALF, 6000, 0x00, B(12), 2 },
131
[3] = { .phy = HALF, 9000, 0x00, 18, 2 },
132
[4] = { .phy = HALF, 12000, 0x00, B(24), 4 },
133
[5] = { .phy = HALF, 18000, 0x00, 36, 4 },
134
[6] = { .phy = HALF, 24000, 0x00, 48, 4 },
135
[7] = { .phy = HALF, 27000, 0x00, 54, 4 }
136
},
137
};
138
139
static struct ieee80211_rate_table ieee80211_quarter_table = {
140
.rateCount = 8,
141
.info = {
142
/* short ctrl */
143
/* Preamble dot11Rate Rate */
144
[0] = { .phy = QUART, 1500, 0x00, B(3), 0 },
145
[1] = { .phy = QUART, 2250, 0x00, 4, 0 },
146
[2] = { .phy = QUART, 3000, 0x00, B(9), 2 },
147
[3] = { .phy = QUART, 4500, 0x00, 9, 2 },
148
[4] = { .phy = QUART, 6000, 0x00, B(12), 4 },
149
[5] = { .phy = QUART, 9000, 0x00, 18, 4 },
150
[6] = { .phy = QUART, 12000, 0x00, 24, 4 },
151
[7] = { .phy = QUART, 13500, 0x00, 27, 4 }
152
},
153
};
154
155
static struct ieee80211_rate_table ieee80211_turbog_table = {
156
.rateCount = 7,
157
.info = {
158
/* short ctrl */
159
/* Preamble dot11Rate Rate */
160
[0] = { .phy = TURBO, 12000, 0x00, B(12), 0 },
161
[1] = { .phy = TURBO, 24000, 0x00, B(24), 1 },
162
[2] = { .phy = TURBO, 36000, 0x00, 36, 1 },
163
[3] = { .phy = TURBO, 48000, 0x00, B(48), 3 },
164
[4] = { .phy = TURBO, 72000, 0x00, 72, 3 },
165
[5] = { .phy = TURBO, 96000, 0x00, 96, 3 },
166
[6] = { .phy = TURBO, 108000, 0x00, 108, 3 }
167
},
168
};
169
170
static struct ieee80211_rate_table ieee80211_turboa_table = {
171
.rateCount = 8,
172
.info = {
173
/* short ctrl */
174
/* Preamble dot11Rate Rate */
175
[0] = { .phy = TURBO, 12000, 0x00, B(12), 0 },
176
[1] = { .phy = TURBO, 18000, 0x00, 18, 0 },
177
[2] = { .phy = TURBO, 24000, 0x00, B(24), 2 },
178
[3] = { .phy = TURBO, 36000, 0x00, 36, 2 },
179
[4] = { .phy = TURBO, 48000, 0x00, B(48), 4 },
180
[5] = { .phy = TURBO, 72000, 0x00, 72, 4 },
181
[6] = { .phy = TURBO, 96000, 0x00, 96, 4 },
182
[7] = { .phy = TURBO, 108000, 0x00, 108, 4 }
183
},
184
};
185
186
static struct ieee80211_rate_table ieee80211_11ng_table = {
187
.rateCount = 36,
188
.info = {
189
/* short ctrl */
190
/* Preamble dot11Rate Rate */
191
[0] = { .phy = CCK, 1000, 0x00, B(2), 0 },
192
[1] = { .phy = CCK, 2000, 0x04, B(4), 1 },
193
[2] = { .phy = CCK, 5500, 0x04, B(11), 2 },
194
[3] = { .phy = CCK, 11000, 0x04, B(22), 3 },
195
[4] = { .phy = OFDM, 6000, 0x00, 12, 4 },
196
[5] = { .phy = OFDM, 9000, 0x00, 18, 4 },
197
[6] = { .phy = OFDM, 12000, 0x00, 24, 6 },
198
[7] = { .phy = OFDM, 18000, 0x00, 36, 6 },
199
[8] = { .phy = OFDM, 24000, 0x00, 48, 8 },
200
[9] = { .phy = OFDM, 36000, 0x00, 72, 8 },
201
[10] = { .phy = OFDM, 48000, 0x00, 96, 8 },
202
[11] = { .phy = OFDM, 54000, 0x00, 108, 8 },
203
204
[12] = { .phy = HT, 6500, 0x00, N(0), 4 },
205
[13] = { .phy = HT, 13000, 0x00, N(1), 6 },
206
[14] = { .phy = HT, 19500, 0x00, N(2), 6 },
207
[15] = { .phy = HT, 26000, 0x00, N(3), 8 },
208
[16] = { .phy = HT, 39000, 0x00, N(4), 8 },
209
[17] = { .phy = HT, 52000, 0x00, N(5), 8 },
210
[18] = { .phy = HT, 58500, 0x00, N(6), 8 },
211
[19] = { .phy = HT, 65000, 0x00, N(7), 8 },
212
213
[20] = { .phy = HT, 13000, 0x00, N(8), 4 },
214
[21] = { .phy = HT, 26000, 0x00, N(9), 6 },
215
[22] = { .phy = HT, 39000, 0x00, N(10), 6 },
216
[23] = { .phy = HT, 52000, 0x00, N(11), 8 },
217
[24] = { .phy = HT, 78000, 0x00, N(12), 8 },
218
[25] = { .phy = HT, 104000, 0x00, N(13), 8 },
219
[26] = { .phy = HT, 117000, 0x00, N(14), 8 },
220
[27] = { .phy = HT, 130000, 0x00, N(15), 8 },
221
222
[28] = { .phy = HT, 19500, 0x00, N(16), 4 },
223
[29] = { .phy = HT, 39000, 0x00, N(17), 6 },
224
[30] = { .phy = HT, 58500, 0x00, N(18), 6 },
225
[31] = { .phy = HT, 78000, 0x00, N(19), 8 },
226
[32] = { .phy = HT, 117000, 0x00, N(20), 8 },
227
[33] = { .phy = HT, 156000, 0x00, N(21), 8 },
228
[34] = { .phy = HT, 175500, 0x00, N(22), 8 },
229
[35] = { .phy = HT, 195000, 0x00, N(23), 8 },
230
231
},
232
};
233
234
static struct ieee80211_rate_table ieee80211_11na_table = {
235
.rateCount = 32,
236
.info = {
237
/* short ctrl */
238
/* Preamble dot11Rate Rate */
239
[0] = { .phy = OFDM, 6000, 0x00, B(12), 0 },
240
[1] = { .phy = OFDM, 9000, 0x00, 18, 0 },
241
[2] = { .phy = OFDM, 12000, 0x00, B(24), 2 },
242
[3] = { .phy = OFDM, 18000, 0x00, 36, 2 },
243
[4] = { .phy = OFDM, 24000, 0x00, B(48), 4 },
244
[5] = { .phy = OFDM, 36000, 0x00, 72, 4 },
245
[6] = { .phy = OFDM, 48000, 0x00, 96, 4 },
246
[7] = { .phy = OFDM, 54000, 0x00, 108, 4 },
247
248
[8] = { .phy = HT, 6500, 0x00, N(0), 0 },
249
[9] = { .phy = HT, 13000, 0x00, N(1), 2 },
250
[10] = { .phy = HT, 19500, 0x00, N(2), 2 },
251
[11] = { .phy = HT, 26000, 0x00, N(3), 4 },
252
[12] = { .phy = HT, 39000, 0x00, N(4), 4 },
253
[13] = { .phy = HT, 52000, 0x00, N(5), 4 },
254
[14] = { .phy = HT, 58500, 0x00, N(6), 4 },
255
[15] = { .phy = HT, 65000, 0x00, N(7), 4 },
256
257
[16] = { .phy = HT, 13000, 0x00, N(8), 0 },
258
[17] = { .phy = HT, 26000, 0x00, N(9), 2 },
259
[18] = { .phy = HT, 39000, 0x00, N(10), 2 },
260
[19] = { .phy = HT, 52000, 0x00, N(11), 4 },
261
[20] = { .phy = HT, 78000, 0x00, N(12), 4 },
262
[21] = { .phy = HT, 104000, 0x00, N(13), 4 },
263
[22] = { .phy = HT, 117000, 0x00, N(14), 4 },
264
[23] = { .phy = HT, 130000, 0x00, N(15), 4 },
265
266
[24] = { .phy = HT, 19500, 0x00, N(16), 0 },
267
[25] = { .phy = HT, 39000, 0x00, N(17), 2 },
268
[26] = { .phy = HT, 58500, 0x00, N(18), 2 },
269
[27] = { .phy = HT, 78000, 0x00, N(19), 4 },
270
[28] = { .phy = HT, 117000, 0x00, N(20), 4 },
271
[29] = { .phy = HT, 156000, 0x00, N(21), 4 },
272
[30] = { .phy = HT, 175500, 0x00, N(22), 4 },
273
[31] = { .phy = HT, 195000, 0x00, N(23), 4 },
274
275
},
276
};
277
278
#undef Mb
279
#undef B
280
#undef OFDM
281
#undef HALF
282
#undef QUART
283
#undef CCK
284
#undef TURBO
285
#undef XR
286
#undef HT
287
#undef N
288
289
/*
290
* Setup a rate table's reverse lookup table and fill in
291
* ack durations. The reverse lookup tables are assumed
292
* to be initialized to zero (or at least the first entry).
293
* We use this as a key that indicates whether or not
294
* we've previously setup the reverse lookup table.
295
*
296
* XXX not reentrant, but shouldn't matter
297
*/
298
static void
299
ieee80211_setup_ratetable(struct ieee80211_rate_table *rt)
300
{
301
#define WLAN_CTRL_FRAME_SIZE \
302
(sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN)
303
304
int i;
305
306
for (i = 0; i < nitems(rt->rateCodeToIndex); i++)
307
rt->rateCodeToIndex[i] = (uint8_t) -1;
308
for (i = 0; i < rt->rateCount; i++) {
309
uint8_t code = rt->info[i].dot11Rate;
310
uint8_t cix = rt->info[i].ctlRateIndex;
311
uint8_t ctl_rate = rt->info[cix].dot11Rate;
312
313
/*
314
* Map without the basic rate bit.
315
*
316
* It's up to the caller to ensure that the basic
317
* rate bit is stripped here.
318
*
319
* For HT, use the MCS rate bit.
320
*/
321
code &= IEEE80211_RATE_VAL;
322
if (rt->info[i].phy == IEEE80211_T_HT) {
323
code |= IEEE80211_RATE_MCS;
324
}
325
326
/* XXX assume the control rate is non-MCS? */
327
ctl_rate &= IEEE80211_RATE_VAL;
328
rt->rateCodeToIndex[code] = i;
329
330
/*
331
* XXX for 11g the control rate to use for 5.5 and 11 Mb/s
332
* depends on whether they are marked as basic rates;
333
* the static tables are setup with an 11b-compatible
334
* 2Mb/s rate which will work but is suboptimal
335
*
336
* NB: Control rate is always less than or equal to the
337
* current rate, so control rate's reverse lookup entry
338
* has been installed and following call is safe.
339
*/
340
rt->info[i].lpAckDuration = ieee80211_compute_duration(rt,
341
WLAN_CTRL_FRAME_SIZE, ctl_rate, 0);
342
rt->info[i].spAckDuration = ieee80211_compute_duration(rt,
343
WLAN_CTRL_FRAME_SIZE, ctl_rate, IEEE80211_F_SHPREAMBLE);
344
}
345
346
#undef WLAN_CTRL_FRAME_SIZE
347
}
348
349
/* Setup all rate tables */
350
static void
351
ieee80211_phy_init(void)
352
{
353
static struct ieee80211_rate_table * const ratetables[] = {
354
&ieee80211_half_table,
355
&ieee80211_quarter_table,
356
&ieee80211_11na_table,
357
&ieee80211_11ng_table,
358
&ieee80211_turbog_table,
359
&ieee80211_turboa_table,
360
&ieee80211_11a_table,
361
&ieee80211_11g_table,
362
&ieee80211_11b_table
363
};
364
int i;
365
366
for (i = 0; i < nitems(ratetables); ++i)
367
ieee80211_setup_ratetable(ratetables[i]);
368
369
}
370
SYSINIT(wlan_phy, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_phy_init, NULL);
371
372
const struct ieee80211_rate_table *
373
ieee80211_get_ratetable(struct ieee80211_channel *c)
374
{
375
const struct ieee80211_rate_table *rt;
376
377
/* XXX HT */
378
if (IEEE80211_IS_CHAN_HALF(c))
379
rt = &ieee80211_half_table;
380
else if (IEEE80211_IS_CHAN_QUARTER(c))
381
rt = &ieee80211_quarter_table;
382
else if (IEEE80211_IS_CHAN_HTA(c))
383
rt = &ieee80211_11na_table;
384
else if (IEEE80211_IS_CHAN_HTG(c))
385
rt = &ieee80211_11ng_table;
386
else if (IEEE80211_IS_CHAN_108G(c))
387
rt = &ieee80211_turbog_table;
388
else if (IEEE80211_IS_CHAN_ST(c))
389
rt = &ieee80211_turboa_table;
390
else if (IEEE80211_IS_CHAN_TURBO(c))
391
rt = &ieee80211_turboa_table;
392
else if (IEEE80211_IS_CHAN_A(c))
393
rt = &ieee80211_11a_table;
394
else if (IEEE80211_IS_CHAN_ANYG(c))
395
rt = &ieee80211_11g_table;
396
else if (IEEE80211_IS_CHAN_B(c))
397
rt = &ieee80211_11b_table;
398
else {
399
/* NB: should not get here */
400
panic("%s: no rate table for channel; freq %u flags 0x%x\n",
401
__func__, c->ic_freq, c->ic_flags);
402
}
403
return rt;
404
}
405
406
/*
407
* Convert PLCP signal/rate field to 802.11 rate (.5Mbits/s)
408
*
409
* Note we do no parameter checking; this routine is mainly
410
* used to derive an 802.11 rate for constructing radiotap
411
* header data for rx frames.
412
*
413
* XXX might be a candidate for inline
414
*/
415
uint8_t
416
ieee80211_plcp2rate(uint8_t plcp, enum ieee80211_phytype type)
417
{
418
if (type == IEEE80211_T_OFDM) {
419
static const uint8_t ofdm_plcp2rate[16] = {
420
[0xb] = 12,
421
[0xf] = 18,
422
[0xa] = 24,
423
[0xe] = 36,
424
[0x9] = 48,
425
[0xd] = 72,
426
[0x8] = 96,
427
[0xc] = 108
428
};
429
return ofdm_plcp2rate[plcp & 0xf];
430
}
431
if (type == IEEE80211_T_CCK) {
432
static const uint8_t cck_plcp2rate[16] = {
433
[0xa] = 2, /* 0x0a */
434
[0x4] = 4, /* 0x14 */
435
[0x7] = 11, /* 0x37 */
436
[0xe] = 22, /* 0x6e */
437
[0xc] = 44, /* 0xdc , actually PBCC */
438
};
439
return cck_plcp2rate[plcp & 0xf];
440
}
441
return 0;
442
}
443
444
/*
445
* Covert 802.11 rate to PLCP signal.
446
*/
447
uint8_t
448
ieee80211_rate2plcp(int rate, enum ieee80211_phytype type)
449
{
450
/* XXX ignore type for now since rates are unique */
451
switch (rate) {
452
/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
453
case 12: return 0xb;
454
case 18: return 0xf;
455
case 24: return 0xa;
456
case 36: return 0xe;
457
case 48: return 0x9;
458
case 72: return 0xd;
459
case 96: return 0x8;
460
case 108: return 0xc;
461
/* CCK rates (IEEE Std 802.11b-1999 page 15, subclause 18.2.3.3) */
462
case 2: return 10;
463
case 4: return 20;
464
case 11: return 55;
465
case 22: return 110;
466
/* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */
467
case 44: return 220;
468
}
469
return 0; /* XXX unsupported/unknown rate */
470
}
471
472
#define CCK_SIFS_TIME 10
473
#define CCK_PREAMBLE_BITS 144
474
#define CCK_PLCP_BITS 48
475
476
#define OFDM_SIFS_TIME 16
477
#define OFDM_PREAMBLE_TIME 20
478
#define OFDM_PLCP_BITS 22
479
#define OFDM_SYMBOL_TIME 4
480
481
#define OFDM_HALF_SIFS_TIME 32
482
#define OFDM_HALF_PREAMBLE_TIME 40
483
#define OFDM_HALF_PLCP_BITS 22
484
#define OFDM_HALF_SYMBOL_TIME 8
485
486
#define OFDM_QUARTER_SIFS_TIME 64
487
#define OFDM_QUARTER_PREAMBLE_TIME 80
488
#define OFDM_QUARTER_PLCP_BITS 22
489
#define OFDM_QUARTER_SYMBOL_TIME 16
490
491
#define TURBO_SIFS_TIME 8
492
#define TURBO_PREAMBLE_TIME 14
493
#define TURBO_PLCP_BITS 22
494
#define TURBO_SYMBOL_TIME 4
495
496
/*
497
* Compute the time to transmit a frame of length frameLen bytes
498
* using the specified rate, phy, and short preamble setting.
499
* SIFS is included.
500
*/
501
uint16_t
502
ieee80211_compute_duration(const struct ieee80211_rate_table *rt,
503
uint32_t frameLen, uint16_t rate, int isShortPreamble)
504
{
505
uint8_t rix = rt->rateCodeToIndex[rate];
506
uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
507
uint32_t kbps;
508
509
KASSERT(rix != (uint8_t)-1, ("rate %d has no info", rate));
510
kbps = rt->info[rix].rateKbps;
511
if (kbps == 0) /* XXX bandaid for channel changes */
512
return 0;
513
514
switch (rt->info[rix].phy) {
515
case IEEE80211_T_CCK:
516
phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
517
if (isShortPreamble && rt->info[rix].shortPreamble)
518
phyTime >>= 1;
519
numBits = frameLen << 3;
520
txTime = CCK_SIFS_TIME + phyTime
521
+ ((numBits * 1000)/kbps);
522
break;
523
case IEEE80211_T_OFDM:
524
bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
525
KASSERT(bitsPerSymbol != 0, ("full rate bps"));
526
527
numBits = OFDM_PLCP_BITS + (frameLen << 3);
528
numSymbols = howmany(numBits, bitsPerSymbol);
529
txTime = OFDM_SIFS_TIME
530
+ OFDM_PREAMBLE_TIME
531
+ (numSymbols * OFDM_SYMBOL_TIME);
532
break;
533
case IEEE80211_T_OFDM_HALF:
534
bitsPerSymbol = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000;
535
KASSERT(bitsPerSymbol != 0, ("1/4 rate bps"));
536
537
numBits = OFDM_PLCP_BITS + (frameLen << 3);
538
numSymbols = howmany(numBits, bitsPerSymbol);
539
txTime = OFDM_HALF_SIFS_TIME
540
+ OFDM_HALF_PREAMBLE_TIME
541
+ (numSymbols * OFDM_HALF_SYMBOL_TIME);
542
break;
543
case IEEE80211_T_OFDM_QUARTER:
544
bitsPerSymbol = (kbps * OFDM_QUARTER_SYMBOL_TIME) / 1000;
545
KASSERT(bitsPerSymbol != 0, ("1/2 rate bps"));
546
547
numBits = OFDM_PLCP_BITS + (frameLen << 3);
548
numSymbols = howmany(numBits, bitsPerSymbol);
549
txTime = OFDM_QUARTER_SIFS_TIME
550
+ OFDM_QUARTER_PREAMBLE_TIME
551
+ (numSymbols * OFDM_QUARTER_SYMBOL_TIME);
552
break;
553
case IEEE80211_T_TURBO:
554
/* we still save OFDM rates in kbps - so double them */
555
bitsPerSymbol = ((kbps << 1) * TURBO_SYMBOL_TIME) / 1000;
556
KASSERT(bitsPerSymbol != 0, ("turbo bps"));
557
558
numBits = TURBO_PLCP_BITS + (frameLen << 3);
559
numSymbols = howmany(numBits, bitsPerSymbol);
560
txTime = TURBO_SIFS_TIME + TURBO_PREAMBLE_TIME
561
+ (numSymbols * TURBO_SYMBOL_TIME);
562
break;
563
default:
564
panic("%s: unknown phy %u (rate %u)\n", __func__,
565
rt->info[rix].phy, rate);
566
}
567
return txTime;
568
}
569
570
static const uint16_t ht20_bps[32] = {
571
26, 52, 78, 104, 156, 208, 234, 260,
572
52, 104, 156, 208, 312, 416, 468, 520,
573
78, 156, 234, 312, 468, 624, 702, 780,
574
104, 208, 312, 416, 624, 832, 936, 1040
575
};
576
static const uint16_t ht40_bps[32] = {
577
54, 108, 162, 216, 324, 432, 486, 540,
578
108, 216, 324, 432, 648, 864, 972, 1080,
579
162, 324, 486, 648, 972, 1296, 1458, 1620,
580
216, 432, 648, 864, 1296, 1728, 1944, 2160
581
};
582
583
#define OFDM_PLCP_BITS 22
584
#define HT_L_STF 8
585
#define HT_L_LTF 8
586
#define HT_L_SIG 4
587
#define HT_SIG 8
588
#define HT_STF 4
589
#define HT_LTF(n) ((n) * 4)
590
591
/*
592
* Calculate the transmit duration of an 11n frame.
593
*/
594
uint32_t
595
ieee80211_compute_duration_ht(uint32_t frameLen, uint16_t rate,
596
int streams, int isht40, int isShortGI)
597
{
598
uint32_t bitsPerSymbol, numBits, numSymbols, txTime;
599
600
KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate));
601
KASSERT((rate &~ IEEE80211_RATE_MCS) < 31, ("bad mcs 0x%x", rate));
602
603
if (isht40)
604
bitsPerSymbol = ht40_bps[rate & 0x1f];
605
else
606
bitsPerSymbol = ht20_bps[rate & 0x1f];
607
numBits = OFDM_PLCP_BITS + (frameLen << 3);
608
numSymbols = howmany(numBits, bitsPerSymbol);
609
if (isShortGI)
610
txTime = ((numSymbols * 18) + 4) / 5; /* 3.6us */
611
else
612
txTime = numSymbols * 4; /* 4us */
613
return txTime + HT_L_STF + HT_L_LTF +
614
HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
615
}
616
617
#undef HT_LTF
618
#undef HT_STF
619
#undef HT_SIG
620
#undef HT_L_SIG
621
#undef HT_L_LTF
622
#undef HT_L_STF
623
#undef OFDM_PLCP_BITS
624
625
626
/*
627
* A bitmask of allowable rates for each spatial stream
628
* and bandwidth.
629
*
630
* This is based on 802.11-2020 21.5 (Parameters for VHT-MCSs.)
631
*
632
* Not all MCS rate / channel widths are valid, as there needs
633
* to be an integer number of symbols and the number of tones
634
* available for each channel bandwidth doesn't result in
635
* an integer value.
636
*/
637
static uint16_t ieee80211_vht_mcs_allowed_list_20[] = {
638
0x01ff, 0x01ff, 0x03ff, 0x01ff, 0x01ff, 0x03ff, 0x01ff, 0x01ff,
639
};
640
641
static uint16_t ieee80211_vht_mcs_allowed_list_40[] = {
642
0x03ff, 0x03ff, 0x03ff, 0x03ff, 0x03ff, 0x03ff, 0x03ff, 0x03ff,
643
};
644
645
static uint16_t ieee80211_vht_mcs_allowed_list_80[] = {
646
0x03ff, 0x03ff, 0x03bf, 0x03ff, 0x03ff, 0x01ff, 0x03bf, 0x03ff,
647
};
648
649
static uint16_t ieee80211_vht_mcs_allowed_list_160[] = {
650
0x03ff, 0x03ff, 0x01ff, 0x03ff, 0x03ff, 0x03ff, 0x03ff, 0x03ff,
651
};
652
653
/**
654
* @brief Fetch the allowable MCS mask for the given channel bandwidth and NSS
655
*
656
* Return a bitmask of valid MCS rates from 0..9 given a channel bandwith
657
* and number of spatial streams.
658
*
659
* See 802.11-2020 21.5 (Parameters for VHT-MCSs) for more details.
660
*
661
* @param bw channel bandwidth, via enum net80211_sta_rx_bw
662
* @param nss number of spatial streams, 1..8
663
* @returns bitmask of valid MCS rates from 0..9
664
*/
665
uint16_t
666
ieee80211_phy_vht_get_mcs_mask(enum net80211_sta_rx_bw bw, uint8_t nss)
667
{
668
if (nss == 0 || nss > 8)
669
return (0);
670
671
switch (bw) {
672
case NET80211_STA_RX_BW_20:
673
return (ieee80211_vht_mcs_allowed_list_20[nss - 1]);
674
case NET80211_STA_RX_BW_40:
675
return (ieee80211_vht_mcs_allowed_list_40[nss - 1]);
676
case NET80211_STA_RX_BW_80:
677
return (ieee80211_vht_mcs_allowed_list_80[nss - 1]);
678
case NET80211_STA_RX_BW_160:
679
return (ieee80211_vht_mcs_allowed_list_160[nss - 1]);
680
case NET80211_STA_RX_BW_320:
681
/* invalid for VHT */
682
return (0);
683
}
684
}
685
686
/**
687
* @brief Check if the given NSS/MCS combination is valid for the given channel
688
* bandwidth
689
*
690
* See 802.11-2020 21.5 (Parameters for VHT-MCSs) for more details.
691
*
692
* @param bw channel bandwidth, via enum net80211_sta_rx_bw
693
* @param nss number of spatial streams, 1..8
694
* @param mcs MCS rate, 0..9
695
* @retval true if the NSS / MCS / bandwidth combination is valid
696
* @retval false if the NSS / MCS / bandwidth combination is not valid
697
*/
698
bool
699
ieee80211_phy_vht_validate_mcs(enum net80211_sta_rx_bw bw, uint8_t nss,
700
uint8_t mcs)
701
{
702
uint16_t mask;
703
704
mask = ieee80211_phy_vht_get_mcs_mask(bw, nss);
705
if (mask == 0)
706
return (false);
707
708
return ((mask & (1 << mcs)) != 0);
709
}
710
711
struct mcs_entry {
712
int n_sym; /* Number of bits per symbol */
713
int cod_n; /* Coding rate numerator */
714
int cod_d; /* Coding rate denominator */
715
};
716
717
/*
718
* These parameters are taken from 802.11-2020 Table 21-29
719
* (VHT-MCSs for Mandatory 20 MHZ, Nss=1).
720
*
721
* n_sym corresponds to "Nbpscs", cod_n/cod_d corresponds to
722
* "R".
723
*/
724
static struct mcs_entry mcs_entries[] = {
725
{ 1, 1, 2 }, /* MCS0 */
726
{ 2, 1, 2 },
727
{ 2, 3, 4 },
728
{ 4, 1, 2 },
729
{ 4, 3, 4 },
730
{ 6, 2, 3 },
731
{ 6, 3, 4 },
732
{ 6, 5, 6 },
733
{ 8, 3, 4 },
734
{ 8, 5, 6 }, /* MCS9 */
735
};
736
737
/**
738
* @brief Calculate the bitrate of the given VHT MCS rate.
739
*
740
* @param bw Channel bandwidth (enum net80211_sta_rx_bw)
741
* @param nss Number of spatial streams, 1..8
742
* @param mcs MCS, 0..9
743
* @param is_shortgi True if short guard-interval (400nS)
744
* false otherwise (800nS)
745
*
746
* @returns The bitrate in kbit/sec.
747
*/
748
uint32_t
749
ieee80211_phy_vht_get_mcs_kbit(enum net80211_sta_rx_bw bw,
750
uint8_t nss, uint8_t mcs, bool is_shortgi)
751
{
752
uint32_t sym_len, n_carriers;
753
754
/* Validate MCS 0..9, NSS 1..8 */
755
if (mcs > 9)
756
return (0);
757
if (nss == 0 || nss > 8)
758
return (0);
759
760
/*
761
* Short-GI - 3.6uS symbol time, long-GI - 4.0uS symbol time
762
*
763
* See 802.11-2020 Table 21-5 (Timing-related constraints.)
764
*/
765
if (is_shortgi)
766
sym_len = 36;
767
else
768
sym_len = 40;
769
770
/*
771
* Calculate the number of carriers for the given channel bandwidth
772
*
773
* See 802.11-2020 Table 21-5 (Timing-related constraints.)
774
*/
775
switch (bw) {
776
case NET80211_STA_RX_BW_20:
777
n_carriers = 52;
778
break;
779
case NET80211_STA_RX_BW_40:
780
n_carriers = 108;
781
break;
782
case NET80211_STA_RX_BW_80:
783
n_carriers = 234;
784
break;
785
case NET80211_STA_RX_BW_160:
786
n_carriers = 468;
787
break;
788
default:
789
return (0);
790
}
791
792
return ((n_carriers * mcs_entries[mcs].n_sym * mcs_entries[mcs].cod_n *
793
nss * 10000) / (mcs_entries[mcs].cod_d * sym_len));
794
}
795
796