Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-ieee80211-radio.c
blob900e5e103cfe14f04916e0ff689ed9c31adb0ac0
1 /* packet-ieee80211-radio.c
2 * Routines for pseudo 802.11 header dissection and radio packet timing calculation
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * Copyright 2012 Parc Inc and Samsung Electronics
9 * Copyright 2015, 2016 & 2017 Cisco Inc
11 * Copied from README.developer
13 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include "config.h"
18 #include <epan/packet.h>
19 #include <epan/expert.h>
20 #include <wiretap/wtap.h>
21 #include <epan/prefs.h>
22 #include <epan/proto_data.h>
23 #include <epan/tap.h>
24 #include <epan/tfs.h>
25 #include <epan/unit_strings.h>
27 #include "packet-ieee80211.h"
28 #include "packet-ieee80211-radio.h"
29 #include "packet-ieee80211-radiotap-defs.h"
30 #include "math.h"
32 void proto_register_ieee80211_radio(void);
33 void proto_reg_handoff_ieee80211_radio(void);
35 static dissector_handle_t wlan_radio_handle;
36 static dissector_handle_t wlan_noqos_radio_handle;
37 static dissector_handle_t ieee80211_handle;
38 static dissector_handle_t ieee80211_noqos_handle;
40 static int proto_wlan_radio;
42 /* ************************************************************************* */
43 /* Header field info values for radio information */
44 /* ************************************************************************* */
45 static int hf_wlan_radio_phy;
46 static int hf_wlan_radio_11_fhss_hop_set;
47 static int hf_wlan_radio_11_fhss_hop_pattern;
48 static int hf_wlan_radio_11_fhss_hop_index;
49 static int hf_wlan_radio_11a_channel_type;
50 static int hf_wlan_radio_11a_turbo_type;
51 static int hf_wlan_radio_11g_mode;
52 static int hf_wlan_radio_11n_mcs_index;
53 static int hf_wlan_radio_11n_bandwidth;
54 static int hf_wlan_radio_11n_short_gi;
55 static int hf_wlan_radio_11n_greenfield;
56 static int hf_wlan_radio_11n_fec;
57 static int hf_wlan_radio_11n_stbc_streams;
58 static int hf_wlan_radio_11n_ness;
59 static int hf_wlan_radio_11ac_stbc;
60 static int hf_wlan_radio_11ac_txop_ps_not_allowed;
61 static int hf_wlan_radio_11ac_short_gi;
62 static int hf_wlan_radio_11ac_short_gi_nsym_disambig;
63 static int hf_wlan_radio_11ac_ldpc_extra_ofdm_symbol;
64 static int hf_wlan_radio_11ac_beamformed;
65 static int hf_wlan_radio_11ac_bandwidth;
66 static int hf_wlan_radio_11ac_user;
67 static int hf_wlan_radio_11ac_nsts;
68 static int hf_wlan_radio_11ac_mcs;
69 static int hf_wlan_radio_11ac_nss;
70 static int hf_wlan_radio_11ac_fec;
71 static int hf_wlan_radio_11ac_gid;
72 static int hf_wlan_radio_11ac_p_aid;
73 static int hf_wlan_radio_data_rate;
74 static int hf_wlan_radio_channel;
75 static int hf_wlan_radio_frequency;
76 static int hf_wlan_radio_short_preamble;
77 static int hf_wlan_radio_signal_percent;
78 static int hf_wlan_radio_signal_db;
79 static int hf_wlan_radio_signal_dbm;
80 static int hf_wlan_radio_noise_percent;
81 static int hf_wlan_radio_noise_db;
82 static int hf_wlan_radio_noise_dbm;
83 static int hf_wlan_radio_snr;
84 static int hf_wlan_radio_timestamp;
85 static int hf_wlan_last_part_of_a_mpdu;
86 static int hf_wlan_a_mpdu_delim_crc_error;
87 static int hf_wlan_a_mpdu_aggregate_id;
88 static int hf_wlan_radio_duration;
89 static int hf_wlan_radio_preamble;
90 static int hf_wlan_radio_aggregate;
91 static int hf_wlan_radio_aggregate_duration;
92 static int hf_wlan_radio_ifs;
93 static int hf_wlan_radio_start_tsf;
94 static int hf_wlan_radio_end_tsf;
95 static int hf_wlan_zero_length_psdu_type;
96 static int hf_wlan_radio_11be_user;
97 static int hf_wlan_radio_11be_sta_id;
98 static int hf_wlan_radio_11be_mcs;
99 static int hf_wlan_radio_11be_nsts;
102 static expert_field ei_wlan_radio_assumed_short_preamble;
103 static expert_field ei_wlan_radio_assumed_non_greenfield;
104 static expert_field ei_wlan_radio_assumed_no_stbc;
105 static expert_field ei_wlan_radio_assumed_no_extension_streams;
106 static expert_field ei_wlan_radio_assumed_bcc_fec;
107 static expert_field ei_wlan_radio_11be_num_users;
109 static int wlan_radio_tap;
110 static int wlan_radio_timeline_tap;
112 /* Settings */
113 static bool wlan_radio_always_short_preamble;
114 static bool wlan_radio_tsf_at_end = true;
115 static bool wlan_radio_timeline_enabled;
117 static const value_string phy_vals[] = {
118 { PHDR_802_11_PHY_11_FHSS, "802.11 FHSS" },
119 { PHDR_802_11_PHY_11_IR, "802.11 IR" },
120 { PHDR_802_11_PHY_11_DSSS, "802.11 DSSS" },
121 { PHDR_802_11_PHY_11B, "802.11b (HR/DSSS)" },
122 { PHDR_802_11_PHY_11A, "802.11a (OFDM)" },
123 { PHDR_802_11_PHY_11G, "802.11g (ERP)" },
124 { PHDR_802_11_PHY_11N, "802.11n (HT)" },
125 { PHDR_802_11_PHY_11AC, "802.11ac (VHT)" },
126 { PHDR_802_11_PHY_11AD, "802.11ad (DMG)" },
127 { PHDR_802_11_PHY_11AH, "802.11ah (S1G)" },
128 { PHDR_802_11_PHY_11AX, "802.11ax (HE)" },
129 { PHDR_802_11_PHY_11BE, "802.11be (EHT)" },
130 { 0, NULL }
133 static const value_string channel_type_11a_vals[] = {
134 { PHDR_802_11A_CHANNEL_TYPE_NORMAL, "Normal" },
135 { PHDR_802_11A_CHANNEL_TYPE_HALF_CLOCKED, "Half-clocked" },
136 { PHDR_802_11A_CHANNEL_TYPE_QUARTER_CLOCKED, "Quarter-clocked" },
137 { 0, NULL }
140 static const value_string turbo_type_11a_vals[] = {
141 { PHDR_802_11A_TURBO_TYPE_NORMAL, "Non-turbo" },
142 { PHDR_802_11A_TURBO_TYPE_TURBO, "Turbo" },
143 { PHDR_802_11A_TURBO_TYPE_DYNAMIC_TURBO, "Dynamic turbo" },
144 { PHDR_802_11A_TURBO_TYPE_STATIC_TURBO, "Static turbo" },
145 { 0, NULL }
148 static const value_string mode_11g_vals[] = {
149 { PHDR_802_11G_MODE_NORMAL, "None" },
150 { PHDR_802_11G_MODE_SUPER_G, "Super G" },
151 { 0, NULL }
154 static const value_string bandwidth_vals[] = {
155 { PHDR_802_11_BANDWIDTH_20_MHZ, "20 MHz" },
156 { PHDR_802_11_BANDWIDTH_40_MHZ, "40 MHz" },
157 { PHDR_802_11_BANDWIDTH_20_20L, "20 MHz + 20 MHz lower" },
158 { PHDR_802_11_BANDWIDTH_20_20U, "20 MHz + 20 MHz upper" },
159 { PHDR_802_11_BANDWIDTH_80_MHZ, "80 MHz" },
160 { PHDR_802_11_BANDWIDTH_40_40L, "40 MHz + 40 MHz lower" },
161 { PHDR_802_11_BANDWIDTH_40_40U, "40 MHz + 40 MHz upper" },
162 { PHDR_802_11_BANDWIDTH_20LL, "20 MHz, channel 1/4" },
163 { PHDR_802_11_BANDWIDTH_20LU, "20 MHz, channel 2/4" },
164 { PHDR_802_11_BANDWIDTH_20UL, "20 MHz, channel 3/4" },
165 { PHDR_802_11_BANDWIDTH_20UU, "20 MHz, channel 4/4" },
166 { PHDR_802_11_BANDWIDTH_160_MHZ, "160 MHz" },
167 { PHDR_802_11_BANDWIDTH_80_80L, "80 MHz + 80 MHz lower" },
168 { PHDR_802_11_BANDWIDTH_80_80U, "80 MHz + 80 MHz upper" },
169 { PHDR_802_11_BANDWIDTH_40LL, "40 MHz, channel 1/4" },
170 { PHDR_802_11_BANDWIDTH_40LU, "40 MHz, channel 2/4" },
171 { PHDR_802_11_BANDWIDTH_40UL, "40 MHz, channel 3/4" },
172 { PHDR_802_11_BANDWIDTH_40UU, "40 MHz, channel 4/4" },
173 { PHDR_802_11_BANDWIDTH_20LLL, "20 MHz, channel 1/8" },
174 { PHDR_802_11_BANDWIDTH_20LLU, "20 MHz, channel 2/8" },
175 { PHDR_802_11_BANDWIDTH_20LUL, "20 MHz, channel 3/8" },
176 { PHDR_802_11_BANDWIDTH_20LUU, "20 MHz, channel 4/8" },
177 { PHDR_802_11_BANDWIDTH_20ULL, "20 MHz, channel 5/8" },
178 { PHDR_802_11_BANDWIDTH_20ULU, "20 MHz, channel 6/8" },
179 { PHDR_802_11_BANDWIDTH_20UUL, "20 MHz, channel 7/8" },
180 { PHDR_802_11_BANDWIDTH_20UUU, "20 MHz, channel 8/8" },
181 { 0, NULL }
184 static const value_string fec_vals[] = {
185 { 0, "BEC" },
186 { 1, "LDPC" },
187 { 0, NULL }
190 static const value_string zero_length_psdu_vals[] = {
191 { 0, "sounding PPDU" },
192 { 1, "data not captured" },
193 { 255, "vendor-specific" },
194 { 0, NULL }
197 * Lookup for the MCS index (0-76)
198 * returning the number of data bits per symbol
199 * assumes 52 subcarriers (20MHz)
200 * symbols are 4us for long guard interval, 3.6us for short guard interval
201 * Note: MCS 32 is special - only valid for 40Mhz channel.
203 WS_DLL_PUBLIC_DEF const uint16_t ieee80211_ht_Dbps[MAX_MCS_INDEX+1] = {
204 /* MCS 0 - 1 stream */
205 26, 52, 78, 104, 156, 208, 234, 260,
207 /* MCS 8 - 2 stream */
208 52, 104, 156, 208, 312, 416, 468, 520,
210 /* MCS 16 - 3 stream */
211 78, 156, 234, 312, 468, 624, 702, 780,
213 /* MCS 24 - 4 stream */
214 104, 208, 312, 416, 624, 832, 936, 1040,
216 /* MCS 32 - 1 stream */
217 12, /* only valid for 40Mhz - 11a/g DUP mode */
219 /* MCS 33 - 2 stream */
220 156, 208, 260, 234, 312, 390,
222 /* MCS 39 - 3 stream */
223 208, 260, 260, 312, 364, 364, 416, 312, 390, 390, 468, 546, 546, 624,
225 /* MCS 53 - 4 stream */
226 260, 312, 364, 312, 364, 416, 468, 416, 468, 520, 520, 572,
227 390, 468, 546, 468, 546, 624, 702, 624, 702, 780, 780, 858
231 * Calculates data rate corresponding to a given 802.11n MCS index,
232 * bandwidth, and guard interval.
234 float ieee80211_htrate(int mcs_index, bool bandwidth, bool short_gi)
236 return (float)(ieee80211_ht_Dbps[mcs_index] * (bandwidth ? 108 : 52) / 52.0 / (short_gi ? 3.6 : 4.0));
239 static const uint8_t ieee80211_ht_streams[MAX_MCS_INDEX+1] = {
240 1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,
241 1,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,
242 4,4,4,4,4,4,4,4,4,4,4,4,4
245 static const uint8_t ieee80211_ht_Nes[MAX_MCS_INDEX+1] = {
246 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
247 1,1,1,1,1,2,2,2, 1,1,1,1,2,2,2,2,
249 1,1,1,1,1,1,
250 1,1,1,1,1,1,1,1,1,1,1,1,1,1,
251 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2
254 #define MAX_MCS_VHT_INDEX 9
257 * Maps a VHT bandwidth index to ieee80211_vhtinfo.rates index.
259 static const int ieee80211_vht_bw2rate_index[] = {
260 /* 20Mhz total */ 0,
261 /* 40Mhz total */ 1, 0, 0,
262 /* 80Mhz total */ 2, 1, 1, 0, 0, 0, 0,
263 /* 160Mhz total */ 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
266 struct mcs_info {
267 const char *modulation;
268 const char *coding_rate;
269 float data_bits_per_symbol; /* assuming 20MHz / 52 subcarriers */
272 #define EHT_MAX_MCS 14
273 static const struct mcs_info ieee80211_mcsinfo[EHT_MAX_MCS] = {
274 /* MCS 0 */
275 { "BPSK", "1/2", 26 },
276 /* MCS 1 */
277 { "QPSK", "1/2", 52 },
278 /* MCS 2 */
279 { "QPSK", "3/4", 78 },
280 /* MCS 3 */
281 { "16-QAM", "1/2", 104 },
282 /* MCS 4 */
283 { "16-QAM", "3/4", 156 },
284 /* MCS 5 */
285 { "64-QAM", "2/3", 208 },
286 /* MCS 6 */
287 { "64-QAM", "3/4", 234 },
288 /* MCS 7 */
289 { "64-QAM", "5/6", 260 },
290 /* MCS 8 */
291 { "256-QAM", "3/4", 312 },
292 /* MCS 9 */
293 { "256-QAM", "5/6", (float)(1040/3.0) },
294 /* MCS 10 */
295 { "1024-QAM", "3/4", 390 },
296 /* MCS 11 */
297 { "1024-QAM", "5/6", (float)(1300/3.0) },
298 /* MCS 12 */
299 { "4096-QAM", "3/4", 468 },
300 /* MCS 13 */
301 { "4096-QAM", "5/6", 520 }
304 /* map a bandwidth index to the number of data subcarriers */
305 static const unsigned subcarriers[4] = { 52, 108, 234, 468 };
307 #define MAX_VHT_NSS 8
309 struct mcs_vht_valid {
310 bool valid[4][MAX_VHT_NSS]; /* indexed by bandwidth and NSS-1 */
313 static const struct mcs_vht_valid ieee80211_vhtvalid[MAX_MCS_VHT_INDEX+1] = {
314 /* MCS 0 */
316 { /* 20 Mhz */ { true, true, true, true, true, true, true, true },
317 /* 40 Mhz */ { true, true, true, true, true, true, true, true },
318 /* 80 Mhz */ { true, true, true, true, true, true, true, true },
319 /* 160 Mhz */ { true, true, true, true, true, true, true, true },
322 /* MCS 1 */
324 { /* 20 Mhz */ { true, true, true, true, true, true, true, true },
325 /* 40 Mhz */ { true, true, true, true, true, true, true, true },
326 /* 80 Mhz */ { true, true, true, true, true, true, true, true },
327 /* 160 Mhz */ { true, true, true, true, true, true, true, true },
330 /* MCS 2 */
332 { /* 20 Mhz */ { true, true, true, true, true, true, true, true },
333 /* 40 Mhz */ { true, true, true, true, true, true, true, true },
334 /* 80 Mhz */ { true, true, true, true, true, true, true, true },
335 /* 160 Mhz */ { true, true, true, true, true, true, true, true },
338 /* MCS 3 */
340 { /* 20 Mhz */ { true, true, true, true, true, true, true, true },
341 /* 40 Mhz */ { true, true, true, true, true, true, true, true },
342 /* 80 Mhz */ { true, true, true, true, true, true, true, true },
343 /* 160 Mhz */ { true, true, true, true, true, true, true, true },
346 /* MCS 4 */
348 { /* 20 Mhz */ { true, true, true, true, true, true, true, true },
349 /* 40 Mhz */ { true, true, true, true, true, true, true, true },
350 /* 80 Mhz */ { true, true, true, true, true, true, true, true },
351 /* 160 Mhz */ { true, true, true, true, true, true, true, true },
354 /* MCS 5 */
356 { /* 20 Mhz */ { true, true, true, true, true, true, true, true },
357 /* 40 Mhz */ { true, true, true, true, true, true, true, true },
358 /* 80 Mhz */ { true, true, true, true, true, true, true, true },
359 /* 160 Mhz */ { true, true, true, true, true, true, true, true },
362 /* MCS 6 */
364 { /* 20 Mhz */ { true, true, true, true, true, true, true, true },
365 /* 40 Mhz */ { true, true, true, true, true, true, true, true },
366 /* 80 Mhz */ { true, true, false, true, true, true, false, true },
367 /* 160 Mhz */ { true, true, true, true, true, true, true, true },
370 /* MCS 7 */
372 { /* 20 Mhz */ { true, true, true, true, true, true, true, true },
373 /* 40 Mhz */ { true, true, true, true, true, true, true, true },
374 /* 80 Mhz */ { true, true, true, true, true, true, true, true },
375 /* 160 Mhz */ { true, true, true, true, true, true, true, true },
378 /* MCS 8 */
380 { /* 20 Mhz */ { true, true, true, true, true, true, true, true },
381 /* 40 Mhz */ { true, true, true, true, true, true, true, true },
382 /* 80 Mhz */ { true, true, true, true, true, true, true, true },
383 /* 160 Mhz */ { true, true, true, true, true, true, true, true },
386 /* MCS 9 */
388 { /* 20 Mhz */ { false, false, true, false, false, true, false, false },
389 /* 40 Mhz */ { true, true, true, true, true, true, true, true },
390 /* 80 Mhz */ { true, true, true, true, true, false, true, true },
391 /* 160 Mhz */ { true, true, false, true, true, true, true, true },
397 * Calculates data rate corresponding to a given 802.11ac MCS index,
398 * bandwidth, and guard interval.
400 static float ieee80211_vhtrate(int mcs_index, unsigned bandwidth_index, bool short_gi)
402 return (float)(ieee80211_mcsinfo[mcs_index].data_bits_per_symbol * subcarriers[bandwidth_index] / (short_gi ? 3.6 : 4.0) / 52.0);
406 * HE SU OFDM MCS rate table converted from http://mcsindex.com/
407 * indexed by (NSTS,MCS,BW,GI)
409 #define HE_MAX_NSTS 8
410 #define HE_MAX_MCS 12
411 #define HE_SU_MAX_BW 4
412 #define HE_MAX_GI 3
413 static float he_ofdm_tab[HE_MAX_NSTS][HE_MAX_MCS][HE_SU_MAX_BW][HE_MAX_GI] = {
415 {{ 8.6f, 8.1f, 7.3f},{ 17.2f, 16.3f, 14.6f},{ 36.0f, 34.0f, 30.6f},{ 72.1f, 68.1f, 61.3f}},
416 {{ 17.2f, 16.3f, 14.6f},{ 34.4f, 32.5f, 29.3f},{ 72.1f, 68.1f, 61.3f},{ 144.1f, 136.1f, 122.5f}},
417 {{ 25.8f, 24.4f, 21.9f},{ 51.6f, 48.8f, 43.9f},{ 108.1f, 102.1f, 91.9f},{ 216.2f, 204.2f, 183.8f}},
418 {{ 34.4f, 32.5f, 29.3f},{ 68.8f, 65.0f, 58.5f},{ 144.1f, 136.1f, 122.5f},{ 288.2f, 272.2f, 245.0f}},
419 {{ 51.6f, 48.8f, 43.9f},{ 103.2f, 97.5f, 87.8f},{ 216.2f, 204.2f, 183.8f},{ 432.4f, 408.3f, 367.5f}},
420 {{ 68.8f, 65.0f, 58.5f},{ 137.6f, 130.0f, 117.0f},{ 288.2f, 272.2f, 245.0f},{ 576.5f, 544.4f, 490.0f}},
421 {{ 77.4f, 73.1f, 65.8f},{ 154.9f, 146.3f, 131.6f},{ 324.3f, 306.3f, 275.6f},{ 648.5f, 612.5f, 551.3f}},
422 {{ 86.0f, 81.3f, 73.1f},{ 172.1f, 162.5f, 146.3f},{ 360.3f, 340.3f, 306.3f},{ 720.6f, 680.6f, 612.5f}},
423 {{ 103.2f, 97.5f, 87.8f},{ 206.5f, 195.0f, 175.5f},{ 432.4f, 408.3f, 367.5f},{ 864.7f, 816.7f, 735.0f}},
424 {{ 114.7f, 108.3f, 97.5f},{ 229.4f, 216.7f, 195.0f},{ 480.4f, 453.7f, 408.3f},{ 960.8f, 907.4f, 816.7f}},
425 {{ 129.0f, 121.9f, 109.7f},{ 258.1f, 243.8f, 219.4f},{ 540.4f, 510.4f, 459.4f},{ 1080.9f, 1020.8f, 918.8f}},
426 {{ 143.4f, 135.4f, 121.9f},{ 286.8f, 270.8f, 243.8f},{ 600.5f, 567.1f, 510.4f},{ 1201.0f, 1134.3f, 1020.8f}}
428 {{ 17.2f, 16.3f, 14.6f},{ 34.4f, 32.5f, 29.3f},{ 72.1f, 68.1f, 61.3f},{ 144.1f, 136.1f, 122.5f}},
429 {{ 34.4f, 32.5f, 29.3f},{ 68.8f, 65.0f, 58.5f},{ 144.1f, 136.1f, 122.5f},{ 288.2f, 272.2f, 245.0f}},
430 {{ 51.6f, 48.8f, 43.9f},{ 103.2f, 97.5f, 87.8f},{ 216.2f, 204.2f, 183.8f},{ 432.4f, 408.3f, 367.5f}},
431 {{ 68.8f, 65.0f, 58.5f},{ 137.6f, 130.0f, 117.0f},{ 288.2f, 272.2f, 245.0f},{ 576.5f, 544.4f, 490.0f}},
432 {{ 103.2f, 97.5f, 87.8f},{ 206.5f, 195.0f, 175.5f},{ 432.4f, 408.3f, 367.5f},{ 864.7f, 816.7f, 735.0f}},
433 {{ 137.6f, 130.0f, 117.0f},{ 275.3f, 260.0f, 234.0f},{ 576.5f, 544.4f, 490.0f},{ 1152.9f, 1088.9f, 980.0f}},
434 {{ 154.9f, 146.3f, 131.6f},{ 309.7f, 292.5f, 263.3f},{ 648.5f, 612.5f, 551.3f},{ 1297.1f, 1225.0f, 1102.5f}},
435 {{ 172.1f, 162.5f, 146.3f},{ 344.1f, 325.0f, 292.5f},{ 720.6f, 680.6f, 612.5f},{ 1441.2f, 1361.1f, 1225.0f}},
436 {{ 206.5f, 195.0f, 175.5f},{ 412.9f, 390.0f, 351.0f},{ 864.7f, 816.7f, 735.0f},{ 1729.4f, 1633.3f, 1470.0f}},
437 {{ 229.4f, 216.7f, 195.0f},{ 458.8f, 433.3f, 390.0f},{ 960.8f, 907.4f, 816.7f},{ 1921.6f, 1814.8f, 1633.3f}},
438 {{ 258.1f, 243.8f, 219.4f},{ 516.2f, 487.5f, 438.8f},{ 1080.9f, 1020.8f, 918.8f},{ 2161.8f, 2041.7f, 1837.5f}},
439 {{ 286.8f, 270.8f, 243.8f},{ 573.5f, 541.7f, 487.5f},{ 1201.0f, 1134.3f, 1020.8f},{ 2402.0f, 2268.5f, 2041.7f}}
441 {{ 25.8f, 24.4f, 21.9f},{ 51.6f, 48.8f, 43.9f},{ 108.1f, 102.1f, 91.9f},{ 216.2f, 204.2f, 183.8f}},
442 {{ 51.6f, 48.8f, 43.9f},{ 103.2f, 97.5f, 87.8f},{ 216.2f, 204.2f, 183.8f},{ 432.4f, 408.3f, 367.5f}},
443 {{ 77.4f, 73.1f, 65.8f},{ 154.9f, 146.3f, 131.6f},{ 324.3f, 306.3f, 275.6f},{ 648.5f, 612.5f, 551.3f}},
444 {{ 103.2f, 97.5f, 87.8f},{ 206.5f, 195.0f, 175.5f},{ 432.4f, 408.3f, 367.5f},{ 864.7f, 816.7f, 735.0f}},
445 {{ 154.9f, 146.3f, 131.6f},{ 309.7f, 292.5f, 263.3f},{ 648.5f, 612.5f, 551.3f},{ 1297.1f, 1225.0f, 1102.5f}},
446 {{ 206.5f, 195.0f, 175.5f},{ 412.9f, 390.0f, 351.0f},{ 864.7f, 816.7f, 735.0f},{ 1729.4f, 1633.3f, 1470.0f}},
447 {{ 232.3f, 219.4f, 197.4f},{ 464.6f, 438.8f, 394.9f},{ 972.8f, 918.8f, 826.9f},{ 1945.6f, 1837.5f, 1653.8f}},
448 {{ 258.1f, 243.8f, 219.4f},{ 516.2f, 487.5f, 438.8f},{ 1080.9f, 1020.8f, 918.8f},{ 2161.8f, 2041.7f, 1837.5f}},
449 {{ 309.7f, 292.5f, 263.3f},{ 619.4f, 585.0f, 526.5f},{ 1297.1f, 1225.0f, 1102.5f},{ 2594.1f, 2450.0f, 2205.0f}},
450 {{ 344.1f, 325.0f, 292.5f},{ 688.2f, 650.0f, 585.0f},{ 1441.2f, 1361.1f, 1225.0f},{ 2882.4f, 2722.2f, 2450.0f}},
451 {{ 387.1f, 365.6f, 329.1f},{ 774.3f, 731.3f, 658.1f},{ 1621.3f, 1531.3f, 1378.1f},{ 3242.6f, 3062.5f, 2756.3f}},
452 {{ 430.1f, 406.3f, 365.6f},{ 860.3f, 812.5f, 731.3f},{ 1801.5f, 1701.4f, 1531.3f},{ 3602.9f, 3402.8f, 3062.5f}}
454 {{ 34.4f, 32.5f, 29.3f},{ 68.8f, 65.0f, 58.5f},{ 144.1f, 136.1f, 122.5f},{ 288.2f, 272.2f, 245.0f}},
455 {{ 68.8f, 65.0f, 58.5f},{ 137.6f, 130.0f, 117.0f},{ 288.2f, 272.2f, 245.0f},{ 576.5f, 544.4f, 490.0f}},
456 {{ 103.2f, 97.5f, 87.8f},{ 206.5f, 195.0f, 175.5f},{ 432.4f, 408.3f, 367.5f},{ 864.7f, 816.7f, 735.0f}},
457 {{ 137.6f, 130.0f, 117.0f},{ 275.3f, 260.0f, 234.0f},{ 576.5f, 544.4f, 490.0f},{ 1152.9f, 1088.9f, 980.0f}},
458 {{ 206.5f, 195.0f, 175.5f},{ 412.9f, 390.0f, 351.0f},{ 864.7f, 816.7f, 735.0f},{ 1729.4f, 1633.3f, 1470.0f}},
459 {{ 275.3f, 260.0f, 234.0f},{ 550.6f, 520.0f, 468.0f},{ 1152.9f, 1088.9f, 980.0f},{ 2305.9f, 2177.8f, 1960.0f}},
460 {{ 309.7f, 292.5f, 263.3f},{ 619.4f, 585.0f, 526.5f},{ 1297.1f, 1225.0f, 1102.5f},{ 2594.1f, 2450.0f, 2205.0f}},
461 {{ 344.1f, 325.0f, 292.5f},{ 688.2f, 650.0f, 585.0f},{ 1441.2f, 1361.1f, 1225.0f},{ 2882.4f, 2722.2f, 2450.0f}},
462 {{ 412.9f, 390.0f, 351.0f},{ 825.9f, 780.0f, 702.0f},{ 1729.4f, 1633.3f, 1470.0f},{ 3458.8f, 3266.7f, 2940.0f}},
463 {{ 458.8f, 433.3f, 390.0f},{ 917.6f, 866.7f, 780.0f},{ 1921.6f, 1814.8f, 1633.3f},{ 3843.1f, 3629.6f, 3266.7f}},
464 {{ 516.2f, 487.5f, 438.8f},{ 1032.4f, 975.0f, 877.5f},{ 2161.8f, 2041.7f, 1837.5f},{ 4323.5f, 4083.3f, 3675.0f}},
465 {{ 573.5f, 541.7f, 487.5f},{ 1147.1f, 1083.3f, 975.0f},{ 2402.0f, 2268.5f, 2041.7f},{ 4803.9f, 4537.0f, 4083.3f}}
467 {{ 43.0f, 40.6f, 36.6f},{ 86.0f, 81.3f, 73.1f},{ 180.1f, 170.1f, 153.1f},{ 360.3f, 340.3f, 306.3f}},
468 {{ 86.0f, 81.3f, 73.1f},{ 172.1f, 162.5f, 146.3f},{ 360.3f, 340.3f, 306.3f},{ 720.6f, 680.6f, 612.5f}},
469 {{ 129.0f, 121.9f, 109.7f},{ 258.1f, 243.8f, 219.4f},{ 540.4f, 510.4f, 459.4f},{ 1080.9f, 1020.8f, 918.8f}},
470 {{ 172.1f, 162.5f, 146.3f},{ 344.1f, 325.0f, 292.5f},{ 720.6f, 680.6f, 612.5f},{ 1441.2f, 1361.1f, 1225.0f}},
471 {{ 258.1f, 243.8f, 219.4f},{ 516.2f, 487.5f, 438.8f},{ 1080.9f, 1020.8f, 918.8f},{ 2161.8f, 2041.7f, 1837.5f}},
472 {{ 344.1f, 325.0f, 292.5f},{ 688.2f, 650.0f, 585.0f},{ 1441.2f, 1361.1f, 1225.0f},{ 2882.4f, 2722.2f, 2450.0f}},
473 {{ 387.1f, 365.6f, 329.1f},{ 774.3f, 731.3f, 658.1f},{ 1621.3f, 1531.3f, 1378.1f},{ 3242.6f, 3062.5f, 2756.3f}},
474 {{ 430.1f, 406.3f, 365.6f},{ 860.3f, 812.5f, 731.3f},{ 1801.5f, 1701.4f, 1531.3f},{ 3602.9f, 3402.8f, 3062.5f}},
475 {{ 516.2f, 487.5f, 438.8f},{ 1032.4f, 975.0f, 877.5f},{ 2161.8f, 2041.7f, 1837.5f},{ 4323.5f, 4083.3f, 3675.0f}},
476 {{ 573.5f, 541.7f, 487.5f},{ 1147.1f, 1083.3f, 975.0f},{ 2402.0f, 2268.5f, 2041.7f},{ 4803.9f, 4537.0f, 4083.3f}},
477 {{ 645.2f, 609.4f, 548.4f},{ 1290.4f, 1218.8f, 1096.9f},{ 2702.2f, 2552.1f, 2296.9f},{ 5404.4f, 5104.2f, 4593.8f}},
478 {{ 716.9f, 677.1f, 609.4f},{ 1433.8f, 1354.2f, 1218.8f},{ 3002.5f, 2835.6f, 2552.1f},{ 6004.9f, 5671.3f, 5104.2f}}
480 {{ 51.6f, 48.8f, 43.9f},{ 103.2f, 97.5f, 87.8f},{ 216.2f, 204.2f, 183.8f},{ 432.4f, 408.3f, 367.5f}},
481 {{ 103.2f, 97.5f, 87.8f},{ 206.5f, 195.0f, 175.5f},{ 432.4f, 408.3f, 367.5f},{ 864.7f, 816.7f, 735.0f}},
482 {{ 154.9f, 146.3f, 131.6f},{ 309.7f, 292.5f, 263.3f},{ 648.5f, 612.5f, 551.3f},{ 1297.1f, 1225.0f, 1102.5f}},
483 {{ 206.5f, 195.0f, 175.5f},{ 412.9f, 390.0f, 351.0f},{ 864.7f, 816.7f, 735.0f},{ 1729.4f, 1633.3f, 1470.0f}},
484 {{ 309.7f, 292.5f, 263.3f},{ 619.4f, 585.0f, 526.5f},{ 1297.1f, 1225.0f, 1102.5f},{ 2594.1f, 2450.0f, 2205.0f}},
485 {{ 412.9f, 390.0f, 351.0f},{ 825.9f, 780.0f, 702.0f},{ 1729.4f, 1633.3f, 1470.0f},{ 3458.8f, 3266.7f, 2940.0f}},
486 {{ 464.6f, 438.8f, 394.9f},{ 929.1f, 877.5f, 789.8f},{ 1945.6f, 1837.5f, 1653.8f},{ 3891.2f, 3675.0f, 3307.5f}},
487 {{ 516.2f, 487.5f, 438.8f},{ 1032.4f, 975.0f, 877.5f},{ 2161.8f, 2041.7f, 1837.5f},{ 4323.5f, 4083.3f, 3675.0f}},
488 {{ 619.4f, 585.0f, 526.5f},{ 1238.8f, 1170.0f, 1053.0f},{ 2594.1f, 2450.0f, 2205.0f},{ 5188.2f, 4900.0f, 4410.0f}},
489 {{ 688.2f, 650.0f, 585.0f},{ 1376.5f, 1300.0f, 1170.0f},{ 2882.4f, 2722.2f, 2450.0f},{ 5764.7f, 5444.4f, 4900.0f}},
490 {{ 774.3f, 731.3f, 658.1f},{ 1548.5f, 1462.5f, 1316.3f},{ 3242.6f, 3062.5f, 2756.3f},{ 6485.3f, 6125.0f, 5512.5f}},
491 {{ 860.3f, 812.5f, 731.3f},{ 1720.6f, 1625.0f, 1462.5f},{ 3602.9f, 3402.8f, 3062.5f},{ 7205.9f, 6805.6f, 6125.0f}}
493 {{ 60.2f, 56.9f, 51.2f},{ 120.4f, 113.8f, 102.4f},{ 252.2f, 238.2f, 214.4f},{ 504.4f, 476.4f, 428.8f}},
494 {{ 120.4f, 113.8f, 102.4f},{ 240.9f, 227.5f, 204.8f},{ 504.4f, 476.4f, 428.8f},{ 1008.8f, 952.8f, 857.5f}},
495 {{ 180.7f, 170.6f, 153.6f},{ 361.3f, 341.3f, 307.1f},{ 756.6f, 714.6f, 643.1f},{ 1513.2f, 1429.2f, 1286.3f}},
496 {{ 240.9f, 227.5f, 204.8f},{ 481.8f, 455.0f, 409.5f},{ 1008.8f, 952.8f, 857.5f},{ 2017.6f, 1905.6f, 1715.0f}},
497 {{ 361.3f, 341.3f, 307.1f},{ 722.6f, 682.5f, 614.3f},{ 1513.2f, 1429.2f, 1286.3f},{ 3026.5f, 2858.3f, 2572.5f}},
498 {{ 481.8f, 455.0f, 409.5f},{ 963.5f, 910.0f, 819.0f},{ 2017.6f, 1905.6f, 1715.0f},{ 4035.3f, 3811.1f, 3430.0f}},
499 {{ 542.0f, 511.9f, 460.7f},{ 1084.0f, 1023.8f, 921.4f},{ 2269.9f, 2143.8f, 1929.4f},{ 4539.7f, 4287.5f, 3858.8f}},
500 {{ 602.2f, 568.8f, 511.9f},{ 1204.4f, 1137.5f, 1023.8f},{ 2522.1f, 2381.9f, 2143.8f},{ 5044.1f, 4763.9f, 4287.5f}},
501 {{ 722.6f, 682.5f, 614.3f},{ 1445.3f, 1365.0f, 1228.5f},{ 3026.5f, 2858.3f, 2572.5f},{ 6052.9f, 5716.7f, 5145.0f}},
502 {{ 802.9f, 758.3f, 682.5f},{ 1605.9f, 1516.7f, 1365.0f},{ 3362.7f, 3175.9f, 2858.3f},{ 6725.5f, 6351.9f, 5716.7f}},
503 {{ 903.3f, 853.1f, 767.8f},{ 1806.6f, 1706.3f, 1535.6f},{ 3783.1f, 3572.9f, 3215.6f},{ 7566.2f, 7145.8f, 6431.3f}},
504 {{ 1003.7f, 947.9f, 853.1f},{ 2007.4f, 1895.8f, 1706.3f},{ 4203.4f, 3969.9f, 3572.9f},{ 8406.9f, 7939.8f, 7145.8f}}
506 {{ 68.8f, 65.0f, 58.5f},{ 137.6f, 130.0f, 117.0f},{ 288.2f, 272.2f, 245.0f},{ 576.5f, 544.4f, 490.0f}},
507 {{ 137.6f, 130.0f, 117.0f},{ 275.3f, 260.0f, 234.0f},{ 576.5f, 544.4f, 490.0f},{ 1152.9f, 1088.9f, 980.0f}},
508 {{ 206.5f, 195.0f, 175.5f},{ 412.9f, 390.0f, 351.0f},{ 864.7f, 816.7f, 735.0f},{ 1729.4f, 1633.3f, 1470.0f}},
509 {{ 275.3f, 260.0f, 234.0f},{ 550.6f, 520.0f, 468.0f},{ 1152.9f, 1088.9f, 980.0f},{ 2305.9f, 2177.8f, 1960.0f}},
510 {{ 412.9f, 390.0f, 351.0f},{ 825.9f, 780.0f, 702.0f},{ 1729.4f, 1633.3f, 1470.0f},{ 3458.8f, 3266.7f, 2940.0f}},
511 {{ 550.6f, 520.0f, 468.0f},{ 1101.2f, 1040.0f, 936.0f},{ 2305.9f, 2177.8f, 1960.0f},{ 4611.8f, 4355.6f, 3920.0f}},
512 {{ 619.4f, 585.0f, 526.5f},{ 1238.8f, 1170.0f, 1053.0f},{ 2594.1f, 2450.0f, 2205.0f},{ 5188.2f, 4900.0f, 4410.0f}},
513 {{ 688.2f, 650.0f, 585.0f},{ 1376.5f, 1300.0f, 1170.0f},{ 2882.4f, 2722.2f, 2450.0f},{ 5764.7f, 5444.4f, 4900.0f}},
514 {{ 825.9f, 780.0f, 702.0f},{ 1651.8f, 1560.0f, 1404.0f},{ 3458.8f, 3266.7f, 2940.0f},{ 6917.6f, 6533.3f, 5880.0f}},
515 {{ 917.6f, 866.7f, 780.0f},{ 1835.3f, 1733.3f, 1560.0f},{ 3843.1f, 3629.6f, 3266.7f},{ 7686.3f, 7259.3f, 6533.3f}},
516 {{ 1032.4f, 975.0f, 877.5f},{ 2064.7f, 1950.0f, 1755.0f},{ 4323.5f, 4083.3f, 3675.0f},{ 8647.1f, 8166.7f, 7350.0f}},
517 {{ 1147.1f, 1083.3f, 975.0f},{ 2294.1f, 2166.7f, 1950.0f},{ 4803.9f, 4537.0f, 4083.3f},{ 9607.8f, 9074.1f, 8166.7f}}
522 * Calculates 802.11ax HE SU data rate corresponding to a given 802.11ax MCS index,
523 * bandwidth, and guard interval.
525 static float ieee80211_he_ofdm_rate(unsigned nsts, unsigned mcs, unsigned bw, unsigned gi)
527 float rate=0.0;
528 if ( ((nsts-1) < HE_MAX_NSTS) && (mcs < HE_MAX_MCS) && ( bw < HE_SU_MAX_BW) && ( gi < HE_MAX_GI ) ) {
529 rate = he_ofdm_tab[nsts-1][mcs][bw][gi];
531 return rate;
536 * HE MU OFDMA MCS rate table converted from http://mcsindex.com/
537 * indexed by (NSTS,MCS,RU,GI)
539 #define HE_MU_MAX_RU 6
540 static float he_mu_ofdma_tab[HE_MAX_NSTS][HE_MAX_MCS][HE_MU_MAX_RU][HE_MAX_GI] = {
542 {{ 0.9f, 0.8f, 0.8f},{ 1.8f, 1.7f, 1.5f},{ 3.8f, 3.5f, 3.2f},{ 8.6f, 8.1f, 7.3f},{ 17.2f, 16.3f, 14.6f},{ 36.0f, 34.0f, 30.6f}},
543 {{ 1.8f, 1.7f, 1.5f},{ 3.5f, 3.3f, 3.0f},{ 7.5f, 7.1f, 6.4f},{ 17.2f, 16.3f, 14.6f},{ 34.4f, 32.5f, 29.3f},{ 72.1f, 68.1f, 61.3f}},
544 {{ 2.6f, 2.5f, 2.3f},{ 5.3f, 5.0f, 4.5f},{ 11.3f, 10.6f, 9.6f},{ 25.8f, 24.4f, 21.9f},{ 51.6f, 48.8f, 43.9f},{ 108.1f, 102.1f, 91.9f}},
545 {{ 3.5f, 3.3f, 3.0f},{ 7.1f, 6.7f, 6.0f},{ 15.0f, 14.2f, 12.8f},{ 34.4f, 32.5f, 29.3f},{ 68.8f, 65.0f, 58.5f},{ 144.1f, 136.1f, 122.5f}},
546 {{ 5.3f, 5.0f, 4.5f},{ 10.6f, 10.0f, 9.0f},{ 22.5f, 21.3f, 19.1f},{ 51.6f, 48.8f, 43.9f},{ 103.2f, 97.5f, 87.8f},{ 216.2f, 204.2f, 183.8f}},
547 {{ 7.1f, 6.7f, 6.0f},{ 14.1f, 13.3f, 12.0f},{ 30.0f, 28.3f, 25.5f},{ 68.8f, 65.0f, 58.5f},{ 137.6f, 130.0f, 117.0f},{ 288.2f, 272.2f, 245.0f}},
548 {{ 7.9f, 7.5f, 6.8f},{ 15.9f, 15.0f, 13.5f},{ 33.8f, 31.9f, 28.7f},{ 77.4f, 73.1f, 65.8f},{ 154.9f, 146.3f, 131.6f},{ 324.3f, 306.3f, 275.6f}},
549 {{ 8.8f, 8.3f, 7.5f},{ 17.6f, 16.7f, 15.0f},{ 37.5f, 35.4f, 31.9f},{ 86.0f, 81.3f, 73.1f},{ 172.1f, 162.5f, 146.3f},{ 360.3f, 340.3f, 306.3f}},
550 {{ 10.6f, 10.0f, 9.0f},{ 21.2f, 20.0f, 18.0f},{ 45.0f, 42.5f, 38.3f},{ 103.2f, 97.5f, 87.8f},{ 206.5f, 195.0f, 175.5f},{ 432.4f, 408.3f, 367.5f}},
551 {{ 11.8f, 11.1f, 10.0f},{ 23.5f, 22.2f, 20.0f},{ 50.0f, 47.2f, 42.5f},{ 114.7f, 108.3f, 97.5f},{ 229.4f, 216.7f, 195.0f},{ 480.4f, 453.7f, 408.3f}},
552 {{ 13.2f, 12.5f, 11.3f},{ 26.5f, 25.0f, 22.5f},{ 56.3f, 53.1f, 47.8f},{ 129.0f, 121.9f, 109.7f},{ 258.1f, 243.8f, 219.4f},{ 540.4f, 510.4f, 459.4f}},
553 {{ 14.7f, 13.9f, 12.5f},{ 29.4f, 27.8f, 25.0f},{ 62.5f, 59.0f, 53.1f},{ 143.4f, 135.4f, 121.9f},{ 286.8f, 270.8f, 243.8f},{ 600.5f, 567.1f, 510.4f}}
555 {{ 1.8f, 1.7f, 1.5f},{ 3.5f, 3.3f, 3.0f},{ 7.5f, 7.1f, 6.4f},{ 17.2f, 16.3f, 14.6f},{ 34.4f, 32.5f, 29.3f},{ 72.1f, 68.1f, 61.3f}},
556 {{ 3.5f, 3.3f, 3.0f},{ 7.1f, 6.7f, 6.0f},{ 15.0f, 14.2f, 12.8f},{ 34.4f, 32.5f, 29.3f},{ 68.8f, 65.0f, 58.5f},{ 144.1f, 136.1f, 122.5f}},
557 {{ 5.3f, 5.0f, 4.5f},{ 10.6f, 10.0f, 9.0f},{ 22.5f, 21.3f, 19.1f},{ 51.6f, 48.8f, 43.9f},{ 103.2f, 97.5f, 87.8f},{ 216.2f, 204.2f, 183.8f}},
558 {{ 7.1f, 6.7f, 6.0f},{ 14.1f, 13.3f, 12.0f},{ 30.0f, 28.3f, 25.5f},{ 68.8f, 65.0f, 58.5f},{ 137.6f, 130.0f, 117.0f},{ 288.2f, 272.2f, 245.0f}},
559 {{ 10.6f, 10.0f, 9.0f},{ 21.2f, 20.0f, 18.0f},{ 45.0f, 42.5f, 38.3f},{ 103.2f, 97.5f, 87.8f},{ 206.5f, 195.0f, 175.5f},{ 432.4f, 408.3f, 367.5f}},
560 {{ 14.1f, 13.3f, 12.0f},{ 28.2f, 26.7f, 24.0f},{ 60.0f, 56.7f, 51.0f},{ 137.6f, 130.0f, 117.0f},{ 275.3f, 260.0f, 234.0f},{ 576.5f, 544.4f, 490.0f}},
561 {{ 15.9f, 15.0f, 13.5f},{ 31.8f, 30.0f, 27.0f},{ 67.5f, 63.8f, 57.4f},{ 154.9f, 146.3f, 131.6f},{ 309.7f, 292.5f, 263.3f},{ 648.5f, 612.5f, 551.3f}},
562 {{ 17.6f, 16.7f, 15.0f},{ 35.3f, 33.3f, 30.0f},{ 75.0f, 70.8f, 63.8f},{ 172.1f, 162.5f, 146.3f},{ 344.1f, 325.0f, 292.5f},{ 720.6f, 680.6f, 612.5f}},
563 {{ 21.2f, 20.0f, 18.0f},{ 42.4f, 40.0f, 36.0f},{ 90.0f, 85.0f, 76.5f},{ 206.5f, 195.0f, 175.5f},{ 412.9f, 390.0f, 351.0f},{ 864.7f, 816.7f, 735.0f}},
564 {{ 23.5f, 22.2f, 20.0f},{ 47.1f, 44.4f, 40.0f},{ 100.0f, 94.4f, 85.0f},{ 229.4f, 216.7f, 195.0f},{ 458.8f, 433.3f, 390.0f},{ 960.8f, 907.4f, 816.7f}},
565 {{ 26.5f, 25.0f, 22.5f},{ 52.9f, 50.0f, 45.0f},{ 112.5f, 106.3f, 95.6f},{ 258.1f, 243.8f, 219.4f},{ 516.2f, 487.5f, 438.8f},{ 1080.9f, 1020.8f, 918.8f}},
566 {{ 29.4f, 27.8f, 25.0f},{ 58.8f, 55.6f, 50.0f},{ 125.0f, 118.1f, 106.3f},{ 286.8f, 270.8f, 243.8f},{ 573.5f, 541.7f, 487.5f},{ 1201.0f, 1134.3f, 1020.8f}}
568 {{ 2.6f, 2.5f, 2.3f},{ 5.3f, 5.0f, 4.5f},{ 11.3f, 10.6f, 9.6f},{ 25.8f, 24.4f, 21.9f},{ 51.6f, 48.8f, 43.9f},{ 108.1f, 102.1f, 91.9f}},
569 {{ 5.3f, 5.0f, 4.5f},{ 10.6f, 10.0f, 9.0f},{ 22.5f, 21.3f, 19.1f},{ 51.6f, 48.8f, 43.9f},{ 103.2f, 97.5f, 87.8f},{ 216.2f, 204.2f, 183.8f}},
570 {{ 7.9f, 7.5f, 6.8f},{ 15.9f, 15.0f, 13.5f},{ 33.8f, 31.9f, 28.7f},{ 77.4f, 73.1f, 65.8f},{ 154.9f, 146.3f, 131.6f},{ 324.3f, 306.3f, 275.6f}},
571 {{ 10.6f, 10.0f, 9.0f},{ 21.2f, 20.0f, 18.0f},{ 45.0f, 42.5f, 38.3f},{ 103.2f, 97.5f, 87.8f},{ 206.5f, 195.0f, 175.5f},{ 432.4f, 408.3f, 367.5f}},
572 {{ 15.9f, 15.0f, 13.5f},{ 31.8f, 30.0f, 27.0f},{ 67.5f, 63.8f, 57.4f},{ 154.9f, 146.3f, 131.6f},{ 309.7f, 292.5f, 263.3f},{ 648.5f, 612.5f, 551.3f}},
573 {{ 21.2f, 20.0f, 18.0f},{ 42.4f, 40.0f, 36.0f},{ 90.0f, 85.0f, 76.5f},{ 206.5f, 195.0f, 175.5f},{ 412.9f, 390.0f, 351.0f},{ 864.7f, 816.7f, 735.0f}},
574 {{ 23.8f, 22.5f, 20.3f},{ 47.6f, 45.0f, 40.5f},{ 101.3f, 95.6f, 86.1f},{ 232.3f, 219.4f, 197.4f},{ 464.6f, 438.8f, 394.9f},{ 972.8f, 918.8f, 826.9f}},
575 {{ 26.5f, 25.0f, 22.5f},{ 52.9f, 50.0f, 45.0f},{ 112.5f, 106.3f, 95.6f},{ 258.1f, 243.8f, 219.4f},{ 516.2f, 487.5f, 438.8f},{ 1080.9f, 1020.8f, 918.8f}},
576 {{ 31.8f, 30.0f, 27.0f},{ 63.5f, 60.0f, 54.0f},{ 135.0f, 127.5f, 114.8f},{ 309.7f, 292.5f, 263.3f},{ 619.4f, 585.0f, 526.5f},{ 1297.1f, 1225.0f, 1102.5f}},
577 {{ 35.3f, 33.3f, 30.0f},{ 70.6f, 66.7f, 60.0f},{ 150.0f, 141.7f, 127.5f},{ 344.1f, 325.0f, 292.5f},{ 688.2f, 650.0f, 585.0f},{ 1441.2f, 1361.1f, 1225.0f}},
578 {{ 39.7f, 37.5f, 33.8f},{ 79.4f, 75.0f, 67.5f},{ 168.8f, 159.4f, 143.4f},{ 387.1f, 365.6f, 329.1f},{ 774.3f, 731.3f, 658.1f},{ 1621.3f, 1531.3f, 1378.1f}},
579 {{ 44.1f, 41.7f, 37.5f},{ 88.2f, 83.3f, 75.0f},{ 187.5f, 177.1f, 159.4f},{ 430.1f, 406.3f, 365.6f},{ 860.3f, 812.5f, 731.3f},{ 1801.5f, 1701.4f, 1531.3f}}
581 {{ 3.5f, 3.3f, 3.0f},{ 7.1f, 6.7f, 6.0f},{ 15.0f, 14.2f, 12.8f},{ 34.4f, 32.5f, 29.3f},{ 68.8f, 65.0f, 58.5f},{ 144.1f, 136.1f, 122.5f}},
582 {{ 7.1f, 6.7f, 6.0f},{ 14.1f, 13.3f, 12.0f},{ 30.0f, 28.3f, 25.5f},{ 68.8f, 65.0f, 58.5f},{ 137.6f, 130.0f, 117.0f},{ 288.2f, 272.2f, 245.0f}},
583 {{ 10.6f, 10.0f, 9.0f},{ 21.2f, 20.0f, 18.0f},{ 45.0f, 42.5f, 38.3f},{ 103.2f, 97.5f, 87.8f},{ 206.5f, 195.0f, 175.5f},{ 432.4f, 408.3f, 367.5f}},
584 {{ 14.1f, 13.3f, 12.0f},{ 28.2f, 26.7f, 24.0f},{ 60.0f, 56.7f, 51.0f},{ 137.6f, 130.0f, 117.0f},{ 275.3f, 260.0f, 234.0f},{ 576.5f, 544.4f, 490.0f}},
585 {{ 21.2f, 20.0f, 18.0f},{ 42.4f, 40.0f, 36.0f},{ 90.0f, 85.0f, 76.5f},{ 206.5f, 195.0f, 175.5f},{ 412.9f, 390.0f, 351.0f},{ 864.7f, 816.7f, 735.0f}},
586 {{ 28.2f, 26.7f, 24.0f},{ 56.5f, 53.3f, 48.0f},{ 120.0f, 113.3f, 102.0f},{ 275.3f, 260.0f, 234.0f},{ 550.6f, 520.0f, 468.0f},{ 1152.9f, 1088.9f, 980.0f}},
587 {{ 31.8f, 30.0f, 27.0f},{ 63.5f, 60.0f, 54.0f},{ 135.0f, 127.5f, 114.8f},{ 309.7f, 292.5f, 263.3f},{ 619.4f, 585.0f, 526.5f},{ 1297.1f, 1225.0f, 1102.5f}},
588 {{ 35.3f, 33.3f, 30.0f},{ 70.6f, 66.7f, 60.0f},{ 150.0f, 141.7f, 127.5f},{ 344.1f, 325.0f, 292.5f},{ 688.2f, 650.0f, 585.0f},{ 1441.2f, 1361.1f, 1225.0f}},
589 {{ 42.4f, 40.0f, 36.0f},{ 84.7f, 80.0f, 72.0f},{ 180.0f, 170.0f, 153.0f},{ 412.9f, 390.0f, 351.0f},{ 825.9f, 780.0f, 702.0f},{ 1729.4f, 1633.3f, 1470.0f}},
590 {{ 47.1f, 44.4f, 40.0f},{ 94.1f, 88.9f, 80.0f},{ 200.0f, 188.9f, 170.0f},{ 458.8f, 433.3f, 390.0f},{ 917.6f, 866.7f, 780.0f},{ 1921.6f, 1814.8f, 1633.3f}},
591 {{ 52.9f, 50.0f, 45.0f},{ 105.9f, 100.0f, 90.0f},{ 225.0f, 212.5f, 191.3f},{ 516.2f, 487.5f, 438.8f},{ 1032.4f, 975.0f, 877.5f},{ 2161.8f, 2041.7f, 1837.5f}},
592 {{ 58.8f, 55.6f, 50.0f},{ 117.6f, 111.1f, 100.0f},{ 250.0f, 236.1f, 212.5f},{ 573.5f, 541.7f, 487.5f},{ 1147.1f, 1083.3f, 975.0f},{ 2402.0f, 2268.5f, 2041.7f}}
594 {{ 4.4f, 4.2f, 3.8f},{ 8.8f, 8.3f, 7.5f},{ 18.8f, 17.7f, 15.9f},{ 43.0f, 40.6f, 36.6f},{ 86.0f, 81.3f, 73.1f},{ 180.1f, 170.1f, 153.1f}},
595 {{ 8.8f, 8.3f, 7.5f},{ 17.6f, 16.7f, 15.0f},{ 37.5f, 35.4f, 31.9f},{ 86.0f, 81.3f, 73.1f},{ 172.1f, 162.5f, 146.3f},{ 360.3f, 340.3f, 306.3f}},
596 {{ 13.2f, 12.5f, 11.3f},{ 26.5f, 25.0f, 22.5f},{ 56.3f, 53.1f, 47.8f},{ 129.0f, 121.9f, 109.7f},{ 258.1f, 243.8f, 219.4f},{ 540.4f, 510.4f, 459.4f}},
597 {{ 17.6f, 16.7f, 15.0f},{ 35.3f, 33.3f, 30.0f},{ 75.0f, 70.8f, 63.8f},{ 172.1f, 162.5f, 146.3f},{ 344.1f, 325.0f, 292.5f},{ 720.6f, 680.6f, 612.5f}},
598 {{ 26.5f, 25.0f, 22.5f},{ 52.9f, 50.0f, 45.0f},{ 112.5f, 106.3f, 95.6f},{ 258.1f, 243.8f, 219.4f},{ 516.2f, 487.5f, 438.8f},{ 1080.9f, 1020.8f, 918.8f}},
599 {{ 35.3f, 33.3f, 30.0f},{ 70.6f, 66.7f, 60.0f},{ 150.0f, 141.7f, 127.5f},{ 344.1f, 325.0f, 292.5f},{ 688.2f, 650.0f, 585.0f},{ 1441.2f, 1361.1f, 1225.0f}},
600 {{ 39.7f, 37.5f, 33.8f},{ 79.4f, 75.0f, 67.5f},{ 168.8f, 159.4f, 143.4f},{ 387.1f, 365.6f, 329.1f},{ 774.3f, 731.3f, 658.1f},{ 1621.3f, 1531.3f, 1378.1f}},
601 {{ 44.1f, 41.7f, 37.5f},{ 88.2f, 83.3f, 75.0f},{ 187.5f, 177.1f, 159.4f},{ 430.1f, 406.3f, 365.6f},{ 860.3f, 812.5f, 731.3f},{ 1801.5f, 1701.4f, 1531.3f}},
602 {{ 52.9f, 50.0f, 45.0f},{ 105.9f, 100.0f, 90.0f},{ 225.0f, 212.5f, 191.3f},{ 516.2f, 487.5f, 438.8f},{ 1032.4f, 975.0f, 877.5f},{ 2161.8f, 2041.7f, 1837.5f}},
603 {{ 58.8f, 55.6f, 50.0f},{ 117.6f, 111.1f, 100.0f},{ 250.0f, 236.1f, 212.5f},{ 573.5f, 541.7f, 487.5f},{ 1147.1f, 1083.3f, 975.0f},{ 2402.0f, 2268.5f, 2041.7f}},
604 {{ 66.2f, 62.5f, 56.3f},{ 132.4f, 125.0f, 112.5f},{ 281.3f, 265.6f, 239.1f},{ 645.2f, 609.4f, 548.4f},{ 1290.4f, 1218.8f, 1096.9f},{ 2702.2f, 2552.1f, 2296.9f}},
605 {{ 73.5f, 69.4f, 62.5f},{ 147.1f, 138.9f, 125.0f},{ 312.5f, 295.1f, 265.6f},{ 716.9f, 677.1f, 609.4f},{ 1433.8f, 1354.2f, 1218.8f},{ 3002.5f, 2835.6f, 2552.1f}}
607 {{ 5.3f, 5.0f, 4.5f},{ 10.6f, 10.0f, 9.0f},{ 22.5f, 21.3f, 19.1f},{ 51.6f, 48.8f, 43.9f},{ 103.2f, 97.5f, 87.8f},{ 216.2f, 204.2f, 183.8f}},
608 {{ 10.6f, 10.0f, 9.0f},{ 21.2f, 20.0f, 18.0f},{ 45.0f, 42.5f, 38.3f},{ 103.2f, 97.5f, 87.8f},{ 206.5f, 195.0f, 175.5f},{ 432.4f, 408.3f, 367.5f}},
609 {{ 15.9f, 15.0f, 13.5f},{ 31.8f, 30.0f, 27.0f},{ 67.5f, 63.8f, 57.4f},{ 154.9f, 146.3f, 131.6f},{ 309.7f, 292.5f, 263.3f},{ 648.5f, 612.5f, 551.3f}},
610 {{ 21.2f, 20.0f, 18.0f},{ 42.4f, 40.0f, 36.0f},{ 90.0f, 85.0f, 76.5f},{ 206.5f, 195.0f, 175.5f},{ 412.9f, 390.0f, 351.0f},{ 864.7f, 816.7f, 735.0f}},
611 {{ 31.8f, 30.0f, 27.0f},{ 63.5f, 60.0f, 54.0f},{ 135.0f, 127.5f, 114.8f},{ 309.7f, 292.5f, 263.3f},{ 619.4f, 585.0f, 526.5f},{ 1297.1f, 1225.0f, 1102.5f}},
612 {{ 42.4f, 40.0f, 36.0f},{ 84.7f, 80.0f, 72.0f},{ 180.0f, 170.0f, 153.0f},{ 412.9f, 390.0f, 351.0f},{ 825.9f, 780.0f, 702.0f},{ 1729.4f, 1633.3f, 1470.0f}},
613 {{ 47.6f, 45.0f, 40.5f},{ 95.3f, 90.0f, 81.0f},{ 202.5f, 191.3f, 172.1f},{ 464.6f, 438.8f, 394.9f},{ 929.1f, 877.5f, 789.8f},{ 1945.6f, 1837.5f, 1653.8f}},
614 {{ 52.9f, 50.0f, 45.0f},{ 105.9f, 100.0f, 90.0f},{ 225.0f, 212.5f, 191.3f},{ 516.2f, 487.5f, 438.8f},{ 1032.4f, 975.0f, 877.5f},{ 2161.8f, 2041.7f, 1837.5f}},
615 {{ 63.5f, 60.0f, 54.0f},{ 127.1f, 120.0f, 108.0f},{ 270.0f, 255.0f, 229.5f},{ 619.4f, 585.0f, 526.5f},{ 1238.8f, 1170.0f, 1053.0f},{ 2594.1f, 2450.0f, 2205.0f}},
616 {{ 70.6f, 66.7f, 60.0f},{ 141.2f, 133.3f, 120.0f},{ 300.0f, 283.3f, 255.0f},{ 688.2f, 650.0f, 585.0f},{ 1376.5f, 1300.0f, 1170.0f},{ 2882.4f, 2722.2f, 2450.0f}},
617 {{ 79.4f, 75.0f, 67.5f},{ 158.8f, 150.0f, 135.0f},{ 337.5f, 318.8f, 286.9f},{ 774.3f, 731.3f, 658.1f},{ 1548.5f, 1462.5f, 1316.3f},{ 3242.6f, 3062.5f, 2756.3f}},
618 {{ 88.2f, 83.3f, 75.0f},{ 176.5f, 166.7f, 150.0f},{ 375.0f, 354.2f, 318.8f},{ 860.3f, 812.5f, 731.3f},{ 1720.6f, 1625.0f, 1462.5f},{ 3602.9f, 3402.8f, 3062.5f}}
620 {{ 6.2f, 5.8f, 5.3f},{ 12.4f, 11.7f, 10.5f},{ 26.3f, 24.8f, 22.3f},{ 60.2f, 56.9f, 51.2f},{ 120.4f, 113.8f, 102.4f},{ 252.2f, 238.2f, 214.4f}},
621 {{ 12.4f, 11.7f, 10.5f},{ 24.7f, 23.3f, 21.0f},{ 52.5f, 49.6f, 44.6f},{ 120.4f, 113.8f, 102.4f},{ 240.9f, 227.5f, 204.8f},{ 504.4f, 476.4f, 428.8f}},
622 {{ 18.5f, 17.5f, 15.8f},{ 37.1f, 35.0f, 31.5f},{ 78.8f, 74.4f, 66.9f},{ 180.7f, 170.6f, 153.6f},{ 361.3f, 341.3f, 307.1f},{ 756.6f, 714.6f, 643.1f}},
623 {{ 24.7f, 23.3f, 21.0f},{ 49.4f, 46.7f, 42.0f},{ 105.0f, 99.2f, 89.3f},{ 240.9f, 227.5f, 204.8f},{ 481.8f, 455.0f, 409.5f},{ 1008.8f, 952.8f, 857.5f}},
624 {{ 37.1f, 35.0f, 31.5f},{ 74.1f, 70.0f, 63.0f},{ 157.5f, 148.8f, 133.9f},{ 361.3f, 341.3f, 307.1f},{ 722.6f, 682.5f, 614.3f},{ 1513.2f, 1429.2f, 1286.3f}},
625 {{ 49.4f, 46.7f, 42.0f},{ 98.8f, 93.3f, 84.0f},{ 210.0f, 198.3f, 178.5f},{ 481.8f, 455.0f, 409.5f},{ 963.5f, 910.0f, 819.0f},{ 2017.6f, 1905.6f, 1715.0f}},
626 {{ 55.6f, 52.5f, 47.3f},{ 111.2f, 105.0f, 94.5f},{ 236.3f, 223.1f, 200.8f},{ 542.0f, 511.9f, 460.7f},{ 1084.0f, 1023.8f, 921.4f},{ 2269.9f, 2143.8f, 1929.4f}},
627 {{ 61.8f, 58.3f, 52.5f},{ 123.5f, 116.7f, 105.0f},{ 262.5f, 247.9f, 223.1f},{ 602.2f, 568.8f, 511.9f},{ 1204.4f, 1137.5f, 1023.8f},{ 2522.1f, 2381.9f, 2143.8f}},
628 {{ 74.1f, 70.0f, 63.0f},{ 148.2f, 140.0f, 126.0f},{ 315.0f, 297.5f, 267.8f},{ 722.6f, 682.5f, 614.3f},{ 1445.3f, 1365.0f, 1228.5f},{ 3026.5f, 2858.3f, 2572.5f}},
629 {{ 82.4f, 77.8f, 70.0f},{ 164.7f, 155.6f, 140.0f},{ 350.0f, 330.6f, 297.5f},{ 802.9f, 758.3f, 682.5f},{ 1605.9f, 1516.7f, 1365.0f},{ 3362.7f, 3175.9f, 2858.3f}},
630 {{ 92.6f, 87.5f, 78.8f},{ 185.3f, 175.0f, 157.5f},{ 393.8f, 371.9f, 334.7f},{ 903.3f, 853.1f, 767.8f},{ 1806.6f, 1706.3f, 1535.6f},{ 3783.1f, 3572.9f, 3215.6f}},
631 {{ 102.9f, 97.2f, 87.5f},{ 205.9f, 194.4f, 175.0f},{ 437.5f, 413.2f, 371.9f},{ 1003.7f, 947.9f, 853.1f},{ 2007.4f, 1895.8f, 1706.3f},{ 4203.4f, 3969.9f, 3572.9f}}
633 {{ 7.1f, 6.7f, 6.0f},{ 14.1f, 13.3f, 12.0f},{ 30.0f, 28.3f, 25.5f},{ 68.8f, 65.0f, 58.5f},{ 137.6f, 130.0f, 117.0f},{ 288.2f, 272.2f, 245.0f}},
634 {{ 14.1f, 13.3f, 12.0f},{ 28.2f, 26.7f, 24.0f},{ 60.0f, 56.7f, 51.0f},{ 137.6f, 130.0f, 117.0f},{ 275.3f, 260.0f, 234.0f},{ 576.5f, 544.4f, 490.0f}},
635 {{ 21.2f, 20.0f, 18.0f},{ 42.4f, 40.0f, 36.0f},{ 90.0f, 85.0f, 76.5f},{ 206.5f, 195.0f, 175.5f},{ 412.9f, 390.0f, 351.0f},{ 864.7f, 816.7f, 735.0f}},
636 {{ 28.2f, 26.7f, 24.0f},{ 56.5f, 53.3f, 48.0f},{ 120.0f, 113.3f, 102.0f},{ 275.3f, 260.0f, 234.0f},{ 550.6f, 520.0f, 468.0f},{ 1152.9f, 1088.9f, 980.0f}},
637 {{ 42.4f, 40.0f, 36.0f},{ 84.7f, 80.0f, 72.0f},{ 180.0f, 170.0f, 153.0f},{ 412.9f, 390.0f, 351.0f},{ 825.9f, 780.0f, 702.0f},{ 1729.4f, 1633.3f, 1470.0f}},
638 {{ 56.5f, 53.3f, 48.0f},{ 112.9f, 106.7f, 96.0f},{ 240.0f, 226.7f, 204.0f},{ 550.6f, 520.0f, 468.0f},{ 1101.2f, 1040.0f, 936.0f},{ 2305.9f, 2177.8f, 1960.0f}},
639 {{ 63.5f, 60.0f, 54.0f},{ 127.1f, 120.0f, 108.0f},{ 270.0f, 255.0f, 229.5f},{ 619.4f, 585.0f, 526.5f},{ 1238.8f, 1170.0f, 1053.0f},{ 2594.1f, 2450.0f, 2205.0f}},
640 {{ 70.6f, 66.7f, 60.0f},{ 141.2f, 133.3f, 120.0f},{ 300.0f, 283.3f, 255.0f},{ 688.2f, 650.0f, 585.0f},{ 1376.5f, 1300.0f, 1170.0f},{ 2882.4f, 2722.2f, 2450.0f}},
641 {{ 84.7f, 80.0f, 72.0f},{ 169.4f, 160.0f, 144.0f},{ 360.0f, 340.0f, 306.0f},{ 825.9f, 780.0f, 702.0f},{ 1651.8f, 1560.0f, 1404.0f},{ 3458.8f, 3266.7f, 2940.0f}},
642 {{ 94.1f, 88.9f, 80.0f},{ 188.2f, 177.8f, 160.0f},{ 400.0f, 377.8f, 340.0f},{ 917.6f, 866.7f, 780.0f},{ 1835.3f, 1733.3f, 1560.0f},{ 3843.1f, 3629.6f, 3266.7f}},
643 {{ 105.9f, 100.0f, 90.0f},{ 211.8f, 200.0f, 180.0f},{ 450.0f, 425.0f, 382.5f},{ 1032.4f, 975.0f, 877.5f},{ 2064.7f, 1950.0f, 1755.0f},{ 4323.5f, 4083.3f, 3675.0f}},
644 {{ 117.6f, 111.1f, 100.0f},{ 235.3f, 222.2f, 200.0f},{ 500.0f, 472.2f, 425.0f},{ 1147.1f, 1083.3f, 975.0f},{ 2294.1f, 2166.7f, 1950.0f},{ 4803.9f, 4537.0f, 4083.3f}}
650 * Calculates 802.11ax HE SU data rate corresponding to a given 802.11ax MCS index,
651 * bandwidth, and guard interval.
653 static float ieee80211_he_mu_ofdma_rate(unsigned nsts, unsigned mcs, unsigned ru, unsigned gi)
655 float rate=0.0;
656 if ( ((nsts-1) < HE_MAX_NSTS) && (mcs < HE_MAX_MCS) && ( (ru-4) < HE_MU_MAX_RU) && ( gi < HE_MAX_GI ) ) {
657 rate = he_mu_ofdma_tab[nsts-1][mcs][ru-4][gi];
659 return rate;
663 * EHT MCS rate table converted from http://mcsindex.net
664 * indexed by (MCS,BW,GI)
665 * Covering only upto 4x996-tone-RU/320MHz, Additional RUs and Punctured modes not added yet.
666 * For higher # of spatial streams, the rate will be computed based on the 1SS rates below.
667 * The resultant error in rate computation remains within a maximum of +/- 0.5 Mbps from corresponding static table rates.
669 #define EHT_MAX_NSTS 8
670 #define EHT_MAX_BW IEEE80211_RADIOTAP_EHT_RU_4_TIMES_994 + 1
671 #define EHT_MAX_GI 3
672 static float eht_mcs_tab[EHT_MAX_MCS][EHT_MAX_BW][EHT_MAX_GI] = {
673 /* ru-26 | ru-52 | ru-106 | ru-242 / 20 MHz | ru-484 / 40 MHz | ru-996 / 80 MHz | 2 * ru-996 / 160 MHz | 4 * ru-996 / 320 MHz */
674 {{ 0.9f, 0.8f, 0.8f},{ 1.8f, 1.7f, 1.5f},{ 3.8f, 3.5f, 3.2f},{ 8.6f, 8.1f, 7.3f},{ 17.2f, 16.3f, 14.6f},{ 36.0f, 34.0f, 30.6f},{ 72.1f, 68.1f, 61.3f},{ 144.1f, 136.1f, 122.5f}},
675 {{ 1.8f, 1.7f, 1.5f},{ 3.5f, 3.3f, 3.0f},{ 7.5f, 7.1f, 6.4f},{ 17.2f, 16.3f, 14.6f},{ 34.4f, 32.5f, 29.3f},{ 72.1f, 68.1f, 61.3f},{ 144.1f, 136.1f, 122.5f},{ 288.2f, 272.2f, 245.0f}},
676 {{ 2.6f, 2.5f, 2.3f},{ 5.3f, 5.0f, 4.5f},{ 11.3f, 10.6f, 9.6f},{ 25.8f, 24.4f, 21.9f},{ 51.6f, 48.8f, 43.9f},{ 108.1f, 102.1f, 91.9f},{ 216.2f, 204.2f, 183.8f},{ 432.4f, 408.3f, 367.5f}},
677 {{ 3.5f, 3.3f, 3.0f},{ 7.1f, 6.7f, 6.0f},{ 15.0f, 14.2f, 12.8f},{ 34.4f, 32.5f, 29.3f},{ 68.8f, 65.0f, 58.5f},{ 144.1f, 136.1f, 122.5f},{ 288.2f, 272.2f, 245.0f},{ 576.5f, 544.4f, 490.0f}},
678 {{ 5.3f, 5.0f, 4.5f},{ 10.6f, 10.0f, 9.0f},{ 22.5f, 21.3f, 19.1f},{ 51.6f, 48.8f, 43.9f},{ 103.2f, 97.5f, 87.8f},{ 216.2f, 204.2f, 183.8f},{ 432.4f, 408.3f, 367.5f},{ 864.7f, 816.7f, 735.0f}},
679 {{ 7.1f, 6.7f, 6.0f},{ 14.1f, 13.3f, 12.0f},{ 30.0f, 28.3f, 25.5f},{ 68.8f, 65.0f, 58.5f},{ 137.6f, 130.0f, 117.0f},{ 288.2f, 272.2f, 245.0f},{ 576.5f, 544.4f, 490.0f},{ 1152.9f, 1088.9f, 980.0f}},
680 {{ 7.9f, 7.5f, 6.8f},{ 15.9f, 15.0f, 13.5f},{ 33.8f, 31.9f, 28.7f},{ 77.4f, 73.1f, 65.8f},{ 154.9f, 146.3f, 131.6f},{ 324.3f, 306.3f, 275.6f},{ 648.5f, 612.5f, 551.3f},{ 1297.1f, 1225.0f, 1102.5f}},
681 {{ 8.8f, 8.3f, 7.5f},{ 17.6f, 16.7f, 15.0f},{ 37.5f, 35.4f, 31.9f},{ 86.0f, 81.3f, 73.1f},{ 172.1f, 162.5f, 146.3f},{ 360.3f, 340.3f, 306.3f},{ 720.6f, 680.6f, 612.5f},{ 1441.2f, 1361.1f, 1225.0f}},
682 {{ 10.6f, 10.0f, 9.0f},{ 21.2f, 20.0f, 18.0f},{ 45.0f, 42.5f, 38.3f},{ 103.2f, 97.5f, 87.8f},{ 206.5f, 195.0f, 175.5f},{ 432.4f, 408.3f, 367.5f},{ 864.7f, 816.7f, 735.0f},{ 1729.4f, 1633.3f, 1470.0f}},
683 {{ 11.8f, 11.1f, 10.0f},{ 23.5f, 22.2f, 20.0f},{ 50.0f, 47.2f, 42.5f},{ 114.7f, 108.3f, 97.5f},{ 229.4f, 216.7f, 195.0f},{ 480.4f, 453.7f, 408.3f},{ 960.8f, 907.4f, 816.7f},{ 1921.6f, 1814.8f, 1633.3f}},
684 {{ 13.2f, 12.5f, 11.3f},{ 26.5f, 25.0f, 22.5f},{ 56.3f, 53.1f, 47.8f},{ 129.0f, 121.9f, 109.7f},{ 258.1f, 243.8f, 219.4f},{ 540.4f, 510.4f, 459.4f},{ 1080.9f, 1020.8f, 918.8f},{ 2161.8f, 2041.7f, 1837.5f}},
685 {{ 14.7f, 13.9f, 12.5f},{ 29.4f, 27.8f, 25.0f},{ 62.5f, 59.0f, 53.1f},{ 143.4f, 135.4f, 121.9f},{ 286.8f, 270.8f, 243.8f},{ 600.5f, 567.1f, 510.4f},{ 1201.0f, 1134.3f, 1020.8f},{ 2402.0f, 2268.5f, 2041.7f}},
686 {{ 15.9f, 15.0f, 13.5f},{ 31.8f, 30.0f, 27.0f},{ 67.5f, 63.8f, 57.4f},{ 154.9f, 146.3f, 131.6f},{ 309.7f, 292.5f, 263.3f},{ 648.5f, 612.5f, 551.3f},{ 1297.1f, 1225.0f, 1102.5f},{ 2594.1f, 2450.0f, 2205.0f}},
687 {{ 17.6f, 16.7f, 15.0f},{ 35.3f, 33.3f, 30.0f},{ 75.0f, 70.8f, 63.8f},{ 172.1f, 162.5f, 146.3f},{ 344.1f, 325.0f, 292.5f},{ 720.6f, 680.6f, 612.5f},{ 1441.2f, 1361.1f, 1225.0f},{ 2882.4f, 2722.2f, 2450.0f}}
692 * Calculates 802.11be EHT data rate corresponding to a given 802.11be MCS index,
693 * ru-size/bandwidth, guard interval and number of spatial streams.
695 static float ieee80211_eht_rate(unsigned nsts, unsigned mcs, unsigned bw, unsigned gi)
697 float rate=0.0;
698 if ( ((nsts-1) < EHT_MAX_NSTS) && (mcs < EHT_MAX_MCS) && (bw < EHT_MAX_BW) && (gi < EHT_MAX_GI) ) {
699 rate = eht_mcs_tab[mcs][bw][gi] * nsts;
701 return rate;
704 static int ett_wlan_radio;
705 static int ett_wlan_radio_11ac_user;
706 static int ett_wlan_radio_duration;
707 static int ett_wlan_radio_aggregate;
708 static int ett_wlan_radio_11be_user;
710 /* previous frame details, for aggregate detection */
711 struct previous_frame_info {
712 bool has_tsf_timestamp;
713 uint64_t tsf_timestamp;
714 unsigned phy;
715 union ieee_802_11_phy_info phy_info;
716 unsigned prev_length;
717 struct wlan_radio *radio_info;
720 static struct previous_frame_info previous_frame;
721 static struct aggregate *current_aggregate;
722 static wmem_list_t *agg_tracker_list;
724 static unsigned calculate_11n_duration(unsigned frame_length,
725 struct ieee_802_11n* info_n,
726 int stbc_streams)
728 unsigned bits;
729 unsigned bits_per_symbol;
730 unsigned Mstbc;
731 unsigned symbols;
733 /* data field calculation */
734 if (1) {
735 /* see ieee80211n-2009 20.3.11 (20-32) - for BCC FEC */
736 bits = 8 * frame_length + 16 + ieee80211_ht_Nes[info_n->mcs_index] * 6;
737 Mstbc = stbc_streams ? 2 : 1;
738 bits_per_symbol = ieee80211_ht_Dbps[info_n->mcs_index] *
739 (info_n->bandwidth == PHDR_802_11_BANDWIDTH_40_MHZ ? 2 : 1);
740 symbols = bits / (bits_per_symbol * Mstbc);
741 } else {
742 /* TODO: handle LDPC FEC, it changes the rounding */
744 /* round up to whole symbols */
745 if ((bits % (bits_per_symbol * Mstbc)) > 0)
746 symbols++;
748 symbols *= Mstbc;
749 return (symbols * (info_n->short_gi ? 36 : 40) + 5) / 10;
752 /* TODO: this is a crude quick hack, need proper calculation of bits/symbols/FEC/etc */
753 static unsigned calculate_11ac_duration(unsigned frame_length, float data_rate)
755 unsigned bits = 8 * frame_length + 16;
756 return (unsigned) (bits / data_rate);
759 static void adjust_agg_tsf(void *data, void *user_data)
761 struct wlan_radio *wlan_radio_info = (struct wlan_radio *)data;
762 uint64_t *ppdu_start = (uint64_t *)user_data;
764 wlan_radio_info->start_tsf += (*ppdu_start);
765 wlan_radio_info->end_tsf += (*ppdu_start);
766 if (wlan_radio_info->prior_aggregate_data == 0)
767 wlan_radio_info->ifs += (*ppdu_start);
771 * Dissect 802.11 pseudo-header containing radio information.
773 static void
774 dissect_wlan_radio_phdr(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, struct ieee_802_11_phdr *phdr)
776 proto_item *ti;
777 proto_tree *radio_tree;
778 float data_rate = 0.0f;
779 bool have_data_rate = false;
780 bool has_short_preamble = false;
781 bool short_preamble = true;
782 unsigned bandwidth = 0;
783 bool can_calculate_rate = false;
784 proto_item *p_item;
786 unsigned frame_length = tvb_reported_length(tvb); /* length of 802.11 frame data */
788 /* durations in microseconds */
789 unsigned preamble = 0, agg_preamble = 0; /* duration of plcp */
790 bool have_duration = false;
791 unsigned duration = 0; /* duration of whole frame (plcp + mac data + any trailing parts) */
792 unsigned prior_duration = 0; /* duration of previous part of aggregate */
794 struct wlan_radio *wlan_radio_info;
795 int phy = phdr->phy;
796 union ieee_802_11_phy_info *phy_info = &phdr->phy_info;
798 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Radio");
799 col_clear(pinfo->cinfo, COL_INFO);
801 /* Calculate the data rate, if we have the necessary data */
802 if (phdr->has_data_rate) {
803 data_rate = phdr->data_rate * 0.5f;
804 have_data_rate = true;
807 /* this is the first time we are looking at this frame during a
808 * capture dissection, so we know the dissection is done in
809 * frame order (subsequent dissections may be random access) */
810 if (!pinfo->fd->visited) {
811 wlan_radio_info = wmem_new0(wmem_file_scope(), struct wlan_radio);
812 p_add_proto_data(wmem_file_scope(), pinfo, proto_wlan_radio, 0, wlan_radio_info);
814 /* A-MPDU / aggregate detection
815 * Different generators need different detection algorithms
816 * One common pattern is to report all subframes in the aggregate with the same
817 * tsf, referenced to the start of the AMPDU (Broadcom). Another pattern is to
818 * report the tsf on the first subframe, then tsf=0 for the rest of the subframes
819 * (Intel).
820 * Another pattern is to report TSF = -1 for all frames but the last, and the
821 * last has the tsf referenced to the end of the PPDU. (QCA)
823 /* TODO: add code to work around problem with captures from Macbooks where
824 * aggregate subframes frames with FCS errors sometimes have incorrect
825 * PHY information.
827 if (pinfo->fd->num > 1 &&
828 (phdr->phy == PHDR_802_11_PHY_11N || phdr->phy == PHDR_802_11_PHY_11AC) &&
829 phdr->phy == previous_frame.phy &&
830 phdr->has_tsf_timestamp && previous_frame.has_tsf_timestamp &&
831 (phdr->tsf_timestamp == previous_frame.tsf_timestamp || /* find matching TSFs */
832 (!current_aggregate && previous_frame.tsf_timestamp && phdr->tsf_timestamp == 0) || /* Intel detect second frame */
833 (previous_frame.tsf_timestamp == UINT64_MAX) /* QCA, detect last frame */
834 )) {
835 /* we're in an aggregate */
836 if (!current_aggregate) {
837 /* this is the second frame in an aggregate
838 * where we first detect the aggregate */
839 current_aggregate = wmem_new0(wmem_file_scope(), struct aggregate);
840 current_aggregate->phy = previous_frame.phy;
841 current_aggregate->phy_info = previous_frame.phy_info;
843 /* go back to the first frame in the aggregate,
844 * and mark it as part of this aggregate */
845 if (previous_frame.radio_info != NULL)
846 previous_frame.radio_info->aggregate = current_aggregate;
848 wlan_radio_info->aggregate = current_aggregate;
850 /* accumulate the length of the prior subframes in the aggregate.
851 * Round up previous frame length (padding) */
852 if (previous_frame.prev_length % 4 != 0) {
853 previous_frame.prev_length = (previous_frame.prev_length | 3) + 1;
855 /* Also add the MPDU delimiter length */
856 previous_frame.prev_length += 4;
857 /* TODO: add padding to meet minimum subframe timing constraint */
858 wlan_radio_info->prior_aggregate_data = previous_frame.prev_length;
859 previous_frame.prev_length += frame_length;
861 /* work around macbook/QCA FCS error frame PHY rate bug here
862 * Some Macbook generators and some QCA generators erroneously report
863 * low PHY rates for some subframes within an aggregate that have FCS errors.
864 * All subframes must have the same PHY rate.
865 * Here we take the highest reported rate for the aggregate. */
866 switch (phdr->phy) {
867 case PHDR_802_11_PHY_11N:
869 struct ieee_802_11n *info_n = &phy_info->info_11n;
870 struct ieee_802_11n *agg_info_n = &current_aggregate->phy_info.info_11n;
872 if (info_n->has_mcs_index && agg_info_n->has_mcs_index &&
873 info_n->mcs_index > agg_info_n->mcs_index)
874 current_aggregate->phy_info = *phy_info;
876 break;
878 case PHDR_802_11_PHY_11AC:
880 struct ieee_802_11ac *info_ac = &phy_info->info_11ac;
881 struct ieee_802_11ac *agg_info_ac = &current_aggregate->phy_info.info_11ac;
883 if (info_ac->mcs[0] > agg_info_ac->mcs[0])
884 current_aggregate->phy_info = *phy_info;
886 break;
888 /* TODO record a warning if the PHY rate does not match the aggregate */
889 phy = current_aggregate->phy;
890 phy_info = &current_aggregate->phy_info;
891 } else {
892 current_aggregate = NULL;
893 previous_frame.prev_length = frame_length;
895 previous_frame.has_tsf_timestamp = phdr->has_tsf_timestamp;
896 previous_frame.tsf_timestamp = phdr->tsf_timestamp;
897 previous_frame.phy = phdr->phy;
898 previous_frame.phy_info = phdr->phy_info;
899 } else {
900 /* this frame has already been seen, so get its info structure */
901 wlan_radio_info = (struct wlan_radio *) p_get_proto_data(wmem_file_scope(), pinfo, proto_wlan_radio, 0);
903 if (wlan_radio_info && wlan_radio_info->aggregate) {
904 phy = wlan_radio_info->aggregate->phy;
905 phy_info = &wlan_radio_info->aggregate->phy_info;
909 ti = proto_tree_add_item(tree, proto_wlan_radio, tvb, 0, 0, ENC_NA);
910 radio_tree = proto_item_add_subtree (ti, ett_wlan_radio);
912 if (phy != PHDR_802_11_PHY_UNKNOWN) {
913 proto_tree_add_uint(radio_tree, hf_wlan_radio_phy, tvb, 0, 0, phy);
915 switch (phy) {
917 case PHDR_802_11_PHY_11_FHSS:
919 struct ieee_802_11_fhss *info_fhss = &phy_info->info_11_fhss;
921 if (info_fhss->has_hop_set) {
922 proto_tree_add_uint(radio_tree, hf_wlan_radio_11_fhss_hop_set, tvb, 0, 0,
923 info_fhss->hop_set);
925 if (info_fhss->has_hop_pattern) {
926 proto_tree_add_uint(radio_tree, hf_wlan_radio_11_fhss_hop_pattern, tvb, 0, 0,
927 info_fhss->hop_pattern);
929 if (info_fhss->has_hop_index) {
930 proto_tree_add_uint(radio_tree, hf_wlan_radio_11_fhss_hop_index, tvb, 0, 0,
931 info_fhss->hop_index);
933 break;
936 case PHDR_802_11_PHY_11B:
938 struct ieee_802_11b *info_b = &phy_info->info_11b;
940 has_short_preamble = info_b->has_short_preamble;
942 if (has_short_preamble) {
943 short_preamble = info_b->short_preamble;
944 proto_tree_add_boolean(radio_tree, hf_wlan_radio_short_preamble, tvb, 0, 0,
945 short_preamble);
947 break;
950 case PHDR_802_11_PHY_11A:
952 struct ieee_802_11a *info_a = &phy_info->info_11a;
954 if (info_a->has_channel_type) {
955 proto_tree_add_uint(radio_tree, hf_wlan_radio_11a_channel_type, tvb, 0, 0,
956 info_a->channel_type);
958 if (info_a->has_turbo_type) {
959 proto_tree_add_uint(radio_tree, hf_wlan_radio_11a_turbo_type, tvb, 0, 0,
960 info_a->turbo_type);
962 break;
965 case PHDR_802_11_PHY_11G:
967 struct ieee_802_11g *info_g = &phy_info->info_11g;
969 if (info_g->has_mode) {
970 proto_tree_add_uint(radio_tree, hf_wlan_radio_11g_mode, tvb, 0, 0,
971 info_g->mode);
973 break;
976 case PHDR_802_11_PHY_11N:
978 struct ieee_802_11n *info_n = &phy_info->info_11n;
979 unsigned bandwidth_40;
982 * If we have all the fields needed to look up the data rate,
983 * do so.
985 if (info_n->has_mcs_index &&
986 info_n->has_bandwidth &&
987 info_n->has_short_gi) {
988 bandwidth_40 = (info_n->bandwidth == PHDR_802_11_BANDWIDTH_40_MHZ) ? 1 : 0;
989 if (info_n->mcs_index < MAX_MCS_INDEX) {
990 data_rate = ieee80211_htrate(info_n->mcs_index, bandwidth_40, info_n->short_gi);
991 have_data_rate = true;
995 if (info_n->has_mcs_index) {
996 proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_mcs_index, tvb, 0, 0,
997 info_n->mcs_index);
1000 if (info_n->has_bandwidth) {
1001 proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_bandwidth, tvb, 0, 0,
1002 info_n->bandwidth);
1005 if (info_n->has_short_gi) {
1006 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11n_short_gi, tvb, 0, 0,
1007 info_n->short_gi);
1010 if (info_n->has_greenfield) {
1011 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11n_greenfield, tvb, 0, 0,
1012 info_n->greenfield);
1015 if (info_n->has_fec) {
1016 proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_fec, tvb, 0, 0,
1017 info_n->fec);
1020 if (info_n->has_stbc_streams) {
1021 proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_stbc_streams, tvb, 0, 0,
1022 info_n->stbc_streams);
1025 if (info_n->has_ness) {
1026 proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_ness, tvb, 0, 0,
1027 info_n->ness);
1030 break;
1032 case PHDR_802_11_PHY_11AC:
1034 struct ieee_802_11ac *info_ac = &phy_info->info_11ac;
1035 unsigned i;
1037 if (info_ac->has_short_gi) {
1038 can_calculate_rate = true; /* well, if we also have the bandwidth */
1039 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_short_gi, tvb, 0, 0, info_ac->short_gi);
1040 } else {
1041 can_calculate_rate = false; /* unknown GI length */
1044 if (info_ac->has_bandwidth) {
1045 proto_tree_add_uint(radio_tree, hf_wlan_radio_11ac_bandwidth, tvb, 0, 0, info_ac->bandwidth);
1046 if (info_ac->bandwidth < G_N_ELEMENTS(ieee80211_vht_bw2rate_index))
1047 bandwidth = ieee80211_vht_bw2rate_index[info_ac->bandwidth];
1048 else
1049 can_calculate_rate = false; /* unknown bandwidth */
1050 } else {
1051 can_calculate_rate = false; /* no bandwidth */
1054 if (info_ac->has_stbc) {
1055 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_stbc, tvb, 0, 0,
1056 info_ac->stbc);
1059 if (info_ac->has_txop_ps_not_allowed) {
1060 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_txop_ps_not_allowed, tvb, 0, 0,
1061 info_ac->txop_ps_not_allowed);
1064 if (info_ac->has_short_gi_nsym_disambig) {
1065 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_short_gi_nsym_disambig, tvb, 0, 0,
1066 info_ac->short_gi_nsym_disambig);
1069 if (info_ac->has_ldpc_extra_ofdm_symbol) {
1070 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_ldpc_extra_ofdm_symbol, tvb, 0, 0,
1071 info_ac->ldpc_extra_ofdm_symbol);
1074 if (info_ac->has_beamformed) {
1075 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_beamformed, tvb, 0, 0,
1076 info_ac->beamformed);
1079 for (i = 0; i < 4; i++) {
1081 if (info_ac->nss[i] != 0) {
1082 proto_item *it;
1083 proto_tree *user_tree;
1085 it = proto_tree_add_item(radio_tree, hf_wlan_radio_11ac_user, tvb, 0, 0, ENC_NA);
1086 proto_item_append_text(it, " %d: MCS %u", i, info_ac->mcs[i]);
1087 user_tree = proto_item_add_subtree(it, ett_wlan_radio_11ac_user);
1089 it = proto_tree_add_uint(user_tree, hf_wlan_radio_11ac_mcs, tvb, 0, 0,
1090 info_ac->mcs[i]);
1091 if (info_ac->mcs[i] > MAX_MCS_VHT_INDEX) {
1092 proto_item_append_text(it, " (invalid)");
1093 } else {
1094 proto_item_append_text(it, " (%s %s)",
1095 ieee80211_mcsinfo[info_ac->mcs[i]].modulation,
1096 ieee80211_mcsinfo[info_ac->mcs[i]].coding_rate);
1099 proto_tree_add_uint(user_tree, hf_wlan_radio_11ac_nss, tvb, 0, 0, info_ac->nss[i]);
1101 * If we don't know whether space-time block coding is being
1102 * used, we don't know the number of space-time streams.
1104 if (info_ac->has_stbc) {
1105 unsigned nsts;
1107 if (info_ac->stbc)
1108 nsts = 2 * info_ac->nss[i];
1109 else
1110 nsts = info_ac->nss[i];
1111 proto_tree_add_uint(user_tree, hf_wlan_radio_11ac_nsts, tvb, 0, 0,
1112 nsts);
1114 if (info_ac->has_fec) {
1115 proto_tree_add_uint(user_tree, hf_wlan_radio_11ac_fec, tvb, 0, 0,
1116 (info_ac->fec >> i) & 0x01);
1120 * If we can calculate the data rate for this user, do so.
1122 if (can_calculate_rate && info_ac->mcs[i] <= MAX_MCS_VHT_INDEX &&
1123 info_ac->nss[i] <= MAX_VHT_NSS &&
1124 ieee80211_vhtvalid[info_ac->mcs[i]].valid[bandwidth][info_ac->nss[i]-1]) {
1125 data_rate = ieee80211_vhtrate(info_ac->mcs[i], bandwidth, info_ac->short_gi) * info_ac->nss[i];
1126 if (data_rate != 0.0f) {
1127 have_data_rate = true;
1133 if (info_ac->has_group_id) {
1134 proto_tree_add_uint(radio_tree, hf_wlan_radio_11ac_gid, tvb, 0, 0, info_ac->group_id);
1137 if (info_ac->has_partial_aid) {
1138 proto_tree_add_uint(radio_tree, hf_wlan_radio_11ac_p_aid, tvb, 0, 0, info_ac->partial_aid);
1141 break;
1142 case PHDR_802_11_PHY_11AX:
1144 struct ieee_802_11ax *info_ax = &phy_info->info_11ax;
1145 if (info_ax->has_gi && info_ax->has_bwru && info_ax->has_mcs_index) {
1146 if (info_ax->bwru < HE_SU_MAX_BW) {
1147 data_rate = ieee80211_he_ofdm_rate(info_ax->nsts,info_ax->mcs,info_ax->bwru,info_ax->gi);
1148 } else {
1149 data_rate = ieee80211_he_mu_ofdma_rate(info_ax->nsts,info_ax->mcs,info_ax->bwru,info_ax->gi);
1151 if (data_rate != 0.0f) {
1152 have_data_rate = true;
1156 break;
1157 case PHDR_802_11_PHY_11BE:
1159 struct ieee_802_11be *info_11be = &phy_info->info_11be;
1160 int i;
1161 can_calculate_rate = true;
1162 /*for each user*/
1163 for (i = 0; i < info_11be->num_users; i++) {
1164 if (i >= PHDR_802_11BE_MAX_USERS) {
1165 expert_add_info(pinfo, radio_tree, &ei_wlan_radio_11be_num_users);
1166 break;
1168 unsigned nsts = info_11be->user[i].nsts;
1169 unsigned bw_idx = 0;
1170 /* Do we have all the fields needed to compute rate ?*/
1171 if (!info_11be->has_gi || !info_11be->user[i].nsts_known || !nsts)
1173 can_calculate_rate = false;
1175 if (!info_11be->has_bandwidth && (!info_11be->has_ru_mru_size ||
1176 info_11be->ru_mru_size > IEEE80211_RADIOTAP_EHT_RU_4_TIMES_994)) {
1177 can_calculate_rate = false;
1180 if (info_11be->has_bandwidth) {
1181 /* 20,40,80,160 and 320MHz overlap with mcs table index for ru-242 and above.
1182 * So add the offset.
1183 * Punctured modes not considered yet. */
1184 bw_idx = info_11be->bandwidth + IEEE80211_RADIOTAP_EHT_RU_242;
1185 } else {
1186 bw_idx = info_11be->ru_mru_size;
1188 proto_item *it;
1189 proto_tree *user_tree;
1191 it = proto_tree_add_item(radio_tree, hf_wlan_radio_11be_user, tvb, 0, 0, ENC_NA);
1192 proto_item_append_text(it, " %d: MCS %u", i, info_11be->user[i].mcs);
1193 user_tree = proto_item_add_subtree(it, ett_wlan_radio_11be_user);
1195 it = proto_tree_add_uint(user_tree, hf_wlan_radio_11be_mcs, tvb, 0, 0,
1196 info_11be->user[i].mcs);
1197 if (info_11be->user[i].mcs >= EHT_MAX_MCS) {
1198 proto_item_append_text(it, " (invalid)");
1199 } else {
1200 proto_item_append_text(it, " (%s %s)",
1201 ieee80211_mcsinfo[info_11be->user[i].mcs].modulation,
1202 ieee80211_mcsinfo[info_11be->user[i].mcs].coding_rate);
1205 proto_tree_add_uint(user_tree, hf_wlan_radio_11be_nsts, tvb, 0, 0, nsts);
1208 * If we can calculate the data rate for this user, do so.
1210 if (can_calculate_rate && info_11be->user[i].mcs < EHT_MAX_MCS &&
1211 nsts < EHT_MAX_NSTS) {
1212 data_rate = ieee80211_eht_rate(nsts, info_11be->user[i].mcs, bw_idx, info_11be->gi);
1213 if (data_rate != 0.0f) {
1214 //have_data_rate = true;
1215 proto_tree_add_float_format_value(user_tree, hf_wlan_radio_data_rate, tvb, 0, 0,
1216 data_rate,
1217 "%.1f Mb/s",
1218 data_rate);
1221 } // for (i = 0; i < info_11be->num_users; i++)
1222 } // case PHDR_802_11_PHY_11BE:
1223 break;
1227 if (have_data_rate) {
1228 col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%.1f", data_rate);
1229 proto_tree_add_float_format_value(radio_tree, hf_wlan_radio_data_rate, tvb, 0, 0,
1230 data_rate,
1231 "%.1f Mb/s",
1232 data_rate);
1235 if (phdr->has_channel) {
1236 col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u", phdr->channel);
1237 proto_tree_add_uint(radio_tree, hf_wlan_radio_channel, tvb, 0, 0, phdr->channel);
1240 if (phdr->has_frequency) {
1241 col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u MHz", phdr->frequency);
1242 proto_tree_add_uint(radio_tree, hf_wlan_radio_frequency, tvb, 0, 0, phdr->frequency);
1245 if (phdr->has_signal_percent) {
1246 col_add_fstr(pinfo->cinfo, COL_RSSI, "%u%%", phdr->signal_percent);
1247 proto_tree_add_uint(radio_tree, hf_wlan_radio_signal_percent, tvb, 0, 0, phdr->signal_percent);
1250 if (phdr->has_signal_db) {
1251 col_add_fstr(pinfo->cinfo, COL_RSSI, "%u dB", phdr->signal_db);
1252 proto_tree_add_uint(radio_tree, hf_wlan_radio_signal_db, tvb, 0, 0, phdr->signal_db);
1255 if (phdr->has_signal_dbm) {
1256 col_add_fstr(pinfo->cinfo, COL_RSSI, "%d dBm", phdr->signal_dbm);
1257 proto_tree_add_int(radio_tree, hf_wlan_radio_signal_dbm, tvb, 0, 0, phdr->signal_dbm);
1260 if (phdr->has_noise_percent) {
1261 proto_tree_add_uint(radio_tree, hf_wlan_radio_noise_percent, tvb, 0, 0, phdr->noise_percent);
1264 if (phdr->has_noise_db) {
1265 proto_tree_add_uint(radio_tree, hf_wlan_radio_noise_db, tvb, 0, 0, phdr->noise_db);
1268 if (phdr->has_noise_dbm) {
1269 proto_tree_add_int(radio_tree, hf_wlan_radio_noise_dbm, tvb, 0, 0, phdr->noise_dbm);
1272 if (phdr->has_signal_dbm && phdr->has_noise_dbm) {
1273 proto_tree_add_int(radio_tree, hf_wlan_radio_snr, tvb, 0, 0, phdr->signal_dbm - phdr->noise_dbm);
1276 * XXX - are the signal and noise in dB from a fixed reference point
1277 * guaranteed to use the *same* fixed reference point? If so, we could
1278 * calculate the SNR if they're both present, too.
1281 if (phdr->has_tsf_timestamp) {
1282 proto_tree_add_uint64(radio_tree, hf_wlan_radio_timestamp, tvb, 0, 0, phdr->tsf_timestamp);
1284 if (phdr->has_aggregate_info) {
1285 proto_tree_add_boolean(radio_tree, hf_wlan_last_part_of_a_mpdu, tvb, 0, 0, phdr->aggregate_flags);
1286 proto_tree_add_boolean(radio_tree, hf_wlan_a_mpdu_delim_crc_error, tvb, 0, 0, phdr->aggregate_flags);
1287 proto_tree_add_uint(radio_tree, hf_wlan_a_mpdu_aggregate_id, tvb, 0, 0, phdr->aggregate_id);
1290 /* make sure frame_length includes the FCS for accurate duration calculation */
1291 if (pinfo->pseudo_header->ieee_802_11.fcs_len == 0) {
1292 frame_length += 4;
1295 if (have_data_rate && data_rate > 0) {
1296 /* duration calculations */
1297 bool assumed_short_preamble = false;
1298 bool assumed_non_greenfield = false;
1299 bool assumed_no_stbc = false;
1300 bool assumed_no_extension_streams = false;
1301 bool assumed_bcc_fec = false;
1303 /* some generators report CCK frames as 'dynamic-cck-ofdm', which are converted
1304 * into the 11g PHY type, so we need to be smart and recognize which ones are
1305 * DSSS/CCK and which are OFDM. Use the data_rate to do this. */
1306 if (phy == PHDR_802_11_PHY_11G &&
1307 (data_rate == 1.0f || data_rate == 2.0f ||
1308 data_rate == 5.5f || data_rate == 11.0f ||
1309 data_rate == 22.0f || data_rate == 33.0f)) {
1310 phy = PHDR_802_11_PHY_11B;
1311 } else if (phy == PHDR_802_11_PHY_UNKNOWN &&
1312 (data_rate == 1.0f || data_rate == 2.0f ||
1313 data_rate == 5.5f || data_rate == 11.0f ||
1314 data_rate == 22.0f || data_rate == 33.0f)) {
1315 phy = PHDR_802_11_PHY_11B;
1316 } else if (phy == PHDR_802_11_PHY_UNKNOWN &&
1317 (data_rate == 6.0f || data_rate == 9.0f ||
1318 data_rate == 12.0f || data_rate == 18.0f ||
1319 data_rate == 24.0f || data_rate == 36.0f ||
1320 data_rate == 48.0f || data_rate == 54.0f)) {
1321 phy = PHDR_802_11_PHY_11A;
1323 switch (phy) {
1325 case PHDR_802_11_PHY_11_FHSS:
1326 /* TODO: preamble/duration calc for FHSS */
1327 break;
1329 case PHDR_802_11_PHY_11B:
1330 if (!has_short_preamble || wlan_radio_always_short_preamble) {
1331 assumed_short_preamble = true;
1332 short_preamble = true;
1334 preamble = short_preamble ? 72 + 24 : 144 + 48;
1336 /* calculation of frame duration
1337 * Things we need to know to calculate accurate duration
1338 * 802.11 / 802.11b (DSSS or CCK modulation)
1339 * - length of preamble
1340 * - rate
1342 /* round up to whole microseconds */
1343 have_duration = true;
1344 duration = (unsigned) ceil(preamble + frame_length * 8 / data_rate);
1345 break;
1347 case PHDR_802_11_PHY_11A:
1348 case PHDR_802_11_PHY_11G:
1350 /* OFDM rate */
1351 /* calculation of frame duration
1352 * Things we need to know to calculate accurate duration
1353 * 802.11a / 802.11g (OFDM modulation)
1354 * - rate
1357 /* preamble + signal */
1358 preamble = 16 + 4;
1360 /* 16 service bits, data and 6 tail bits */
1361 unsigned bits = 16 + 8 * frame_length + 6;
1362 unsigned symbols = (unsigned) ceil(bits / (data_rate * 4));
1364 have_duration = true;
1365 duration = preamble + symbols * 4;
1366 break;
1369 case PHDR_802_11_PHY_11N:
1371 struct ieee_802_11n *info_n = &phy_info->info_11n;
1373 /* We have all the fields required to calculate the duration */
1374 static const unsigned Nhtdltf[4] = {1, 2, 4, 4};
1375 static const unsigned Nhteltf[4] = {0, 1, 2, 4};
1376 unsigned Nsts;
1377 unsigned stbc_streams;
1378 unsigned ness;
1381 * If we don't have necessary fields, or if we have them but
1382 * they have invalid values, then bail.
1384 if (!info_n->has_mcs_index ||
1385 info_n->mcs_index > MAX_MCS_INDEX ||
1386 !info_n->has_bandwidth ||
1387 !info_n->has_short_gi)
1388 break;
1390 /* calculation of frame duration
1391 * Things we need to know to calculate accurate duration
1392 * 802.11n / HT
1393 * - whether frame preamble is mixed or greenfield, (assume mixed)
1394 * - guard interval, 800ns or 400ns
1395 * - bandwidth, 20Mhz or 40Mhz
1396 * - MCS index - used with previous 2 to calculate rate
1397 * - how many additional STBC streams are used (assume 0)
1398 * - how many optional extension spatial streams are used (assume 0)
1399 * - whether BCC or LDCP coding is used (assume BCC)
1402 /* preamble duration
1403 * see ieee802.11n-2009 Figure 20-1 - PPDU format
1404 * for HT-mixed format
1405 * L-STF 8us, L-LTF 8us, L-SIG 4us, HT-SIG 8us, HT_STF 4us
1406 * for HT-greenfield
1407 * HT-GF-STF 8us, HT-LTF1 8us, HT_SIG 8us
1409 if (info_n->has_greenfield) {
1410 preamble = info_n->greenfield ? 24 : 32;
1411 } else {
1412 preamble = 32;
1413 assumed_non_greenfield = true;
1416 if (info_n->has_stbc_streams) {
1417 stbc_streams = info_n->stbc_streams;
1418 } else {
1419 stbc_streams = 0;
1420 assumed_no_stbc = true;
1423 if (info_n->has_ness) {
1424 ness = info_n->ness;
1425 if (ness >= G_N_ELEMENTS(Nhteltf)) {
1426 /* Not valid */
1427 break;
1429 } else {
1430 ness = 0;
1431 assumed_no_extension_streams = true;
1434 /* calculate number of HT-LTF training symbols.
1435 * see ieee80211n-2009 20.3.9.4.6 table 20-11 */
1436 Nsts = ieee80211_ht_streams[info_n->mcs_index] + stbc_streams;
1437 if (Nsts == 0 || Nsts - 1 >= G_N_ELEMENTS(Nhtdltf)) {
1438 /* Not usable */
1439 break;
1441 preamble += 4 * (Nhtdltf[Nsts-1] + Nhteltf[ness]);
1443 if (info_n->has_stbc_streams) {
1444 stbc_streams = info_n->stbc_streams;
1445 } else {
1446 stbc_streams = 0;
1447 assumed_no_stbc = true;
1450 if (!info_n->has_ness) {
1451 assumed_no_extension_streams = true;
1454 if (!info_n->has_fec) {
1455 assumed_bcc_fec = true;
1458 /* data field calculation */
1459 if (wlan_radio_info && wlan_radio_info->aggregate) {
1460 agg_preamble = preamble;
1461 if (wlan_radio_info->prior_aggregate_data != 0) {
1462 preamble = 0;
1464 prior_duration = calculate_11n_duration(wlan_radio_info->prior_aggregate_data, info_n, stbc_streams);
1465 have_duration = true;
1466 duration = preamble +
1467 calculate_11n_duration(frame_length + wlan_radio_info->prior_aggregate_data, info_n, stbc_streams)
1468 - prior_duration;
1469 } else {
1470 have_duration = true;
1471 duration = preamble + calculate_11n_duration(frame_length, info_n, stbc_streams);
1473 break;
1476 case PHDR_802_11_PHY_11AC:
1478 struct ieee_802_11ac *info_ac = &phy_info->info_11ac;
1480 if (!info_ac->has_stbc) {
1481 assumed_no_stbc = true;
1483 preamble = 32 + 4 * info_ac->nss[0] * (info_ac->has_stbc ? info_ac->stbc+1 : 1);
1485 if (wlan_radio_info && wlan_radio_info->aggregate) {
1486 agg_preamble = preamble;
1487 if (wlan_radio_info->prior_aggregate_data != 0) {
1488 preamble = 0;
1490 prior_duration = calculate_11ac_duration(wlan_radio_info->prior_aggregate_data, data_rate);
1491 have_duration = true;
1492 duration = preamble +
1493 calculate_11ac_duration(wlan_radio_info->prior_aggregate_data + frame_length, data_rate)
1494 - prior_duration;
1495 } else {
1496 have_duration = true;
1497 duration = preamble + calculate_11ac_duration(frame_length, data_rate);
1499 break;
1503 if (!pinfo->fd->visited && have_duration && phdr->has_tsf_timestamp) {
1504 if (current_aggregate) {
1505 current_aggregate->duration = agg_preamble + prior_duration + duration;
1506 if (previous_frame.radio_info && previous_frame.radio_info->aggregate == current_aggregate)
1507 previous_frame.radio_info->nav = 0; // don't display NAV except for last frame in an aggregate
1509 if (phdr->tsf_timestamp == UINT64_MAX) {
1510 /* QCA aggregate, we don't know tsf yet */
1511 wlan_radio_info->start_tsf = prior_duration + (current_aggregate ? agg_preamble : 0);
1512 wlan_radio_info->end_tsf = prior_duration + duration + (current_aggregate ? agg_preamble : 0);
1513 if (agg_tracker_list == NULL) {
1514 agg_tracker_list = wmem_list_new(NULL);
1516 wmem_list_append(agg_tracker_list, wlan_radio_info);
1517 } else if (current_aggregate && wlan_radio_tsf_at_end && phdr->tsf_timestamp != UINT64_MAX) {
1518 /* QCA aggregate, last frame */
1519 wlan_radio_info->start_tsf = phdr->tsf_timestamp - duration;
1520 wlan_radio_info->end_tsf = phdr->tsf_timestamp;
1521 /* fix up the tsfs for the prior MPDUs */
1522 if (agg_tracker_list != NULL) {
1523 uint64_t ppdu_start = phdr->tsf_timestamp - (prior_duration + duration + agg_preamble);
1524 wmem_list_foreach(agg_tracker_list, adjust_agg_tsf, &ppdu_start);
1525 wmem_destroy_list(agg_tracker_list);
1526 agg_tracker_list = NULL;
1528 } else if (wlan_radio_tsf_at_end) {
1529 wlan_radio_info->start_tsf = phdr->tsf_timestamp - duration;
1530 wlan_radio_info->end_tsf = phdr->tsf_timestamp;
1531 } else {
1532 wlan_radio_info->start_tsf = phdr->tsf_timestamp + prior_duration - preamble;
1533 wlan_radio_info->end_tsf = phdr->tsf_timestamp + prior_duration + duration - preamble;
1535 if ((pinfo->fd->num > 1) && (previous_frame.radio_info != NULL)) {
1536 /* TODO handle intermediate packets without end_tsf correctly */
1537 wlan_radio_info->ifs = wlan_radio_info->start_tsf - previous_frame.radio_info->end_tsf;
1539 if (tvb_captured_length(tvb) >= 4) {
1541 * Duration/ID field.
1543 int nav = tvb_get_letohs(tvb, 2);
1544 if ((nav & 0x8000) == 0) {
1545 /* Duration */
1546 wlan_radio_info->nav = nav;
1549 if (phdr->has_signal_dbm) {
1550 wlan_radio_info->rssi = phdr->signal_dbm;
1551 if (current_aggregate)
1552 current_aggregate->rssi = phdr->signal_dbm;
1556 if (have_duration) {
1557 proto_item *item = proto_tree_add_uint(radio_tree, hf_wlan_radio_duration, tvb, 0, 0, duration);
1558 proto_tree *d_tree = proto_item_add_subtree(item, ett_wlan_radio_duration);
1559 proto_item_set_generated(item);
1561 if (assumed_short_preamble)
1562 expert_add_info(pinfo, item, &ei_wlan_radio_assumed_short_preamble);
1563 if (assumed_non_greenfield)
1564 expert_add_info(pinfo, item, &ei_wlan_radio_assumed_non_greenfield);
1565 if (assumed_no_stbc)
1566 expert_add_info(pinfo, item, &ei_wlan_radio_assumed_no_stbc);
1567 if (assumed_no_extension_streams)
1568 expert_add_info(pinfo, item, &ei_wlan_radio_assumed_no_extension_streams);
1569 if (assumed_bcc_fec)
1570 expert_add_info(pinfo, item, &ei_wlan_radio_assumed_bcc_fec);
1572 if (preamble) {
1573 p_item = proto_tree_add_uint(d_tree, hf_wlan_radio_preamble, tvb, 0, 0, preamble);
1574 proto_item_set_generated(p_item);
1576 if (wlan_radio_info) {
1577 if (wlan_radio_info->aggregate) {
1578 proto_tree *agg_tree;
1580 p_item = proto_tree_add_none_format(d_tree, hf_wlan_radio_aggregate, tvb, 0, 0,
1581 "This MPDU is part of an A-MPDU");
1582 agg_tree = proto_item_add_subtree(item, ett_wlan_radio_aggregate);
1583 proto_item_set_generated(p_item);
1584 if (wlan_radio_info->aggregate->duration) {
1585 proto_item *aitem = proto_tree_add_uint(agg_tree, hf_wlan_radio_aggregate_duration, tvb, 0, 0,
1586 wlan_radio_info->aggregate->duration);
1587 proto_item_set_generated(aitem);
1590 if (wlan_radio_info->ifs) {
1591 p_item = proto_tree_add_int64(d_tree, hf_wlan_radio_ifs, tvb, 0, 0, wlan_radio_info->ifs);
1592 proto_item_set_generated(p_item);
1593 /* TODO: warnings on unusual IFS values (too small or negative) */
1595 if (wlan_radio_info->start_tsf) {
1596 p_item = proto_tree_add_uint64(d_tree, hf_wlan_radio_start_tsf, tvb, 0, 0, wlan_radio_info->start_tsf);
1597 proto_item_set_generated(p_item);
1599 if (wlan_radio_info->end_tsf) {
1600 p_item = proto_tree_add_uint64(d_tree, hf_wlan_radio_end_tsf, tvb, 0, 0, wlan_radio_info->end_tsf);
1601 proto_item_set_generated(p_item);
1605 } /* if (have_data_rate) */
1606 if (phdr->has_zero_length_psdu_type)
1607 proto_tree_add_uint(radio_tree, hf_wlan_zero_length_psdu_type, tvb, 0, 0, phdr->zero_length_psdu_type);
1609 tap_queue_packet(wlan_radio_tap, pinfo, phdr);
1610 if (wlan_radio_timeline_enabled) {
1611 tap_queue_packet(wlan_radio_timeline_tap, pinfo, wlan_radio_info);
1614 if (!pinfo->fd->visited) {
1615 previous_frame.radio_info = wlan_radio_info;
1620 * Dissect 802.11 with a variable-length link-layer header and a pseudo-
1621 * header containing radio information.
1623 static int
1624 dissect_wlan_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void *data)
1626 struct ieee_802_11_phdr *phdr = (struct ieee_802_11_phdr *)data;
1628 dissect_wlan_radio_phdr(tvb, pinfo, tree, phdr);
1630 /* Is there anything there? A 0-length-psdu has no frame data. */
1631 if (phdr->has_zero_length_psdu_type)
1632 return tvb_captured_length(tvb);
1634 /* dissect the 802.11 packet next */
1635 return call_dissector_with_data(ieee80211_handle, tvb, pinfo, tree, data);
1639 * Dissect 802.11 with a variable-length link-layer header without qos elements and
1640 * a pseudo-header containing radio information.
1642 static int
1643 dissect_wlan_noqos_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void *data)
1645 struct ieee_802_11_phdr *phdr = (struct ieee_802_11_phdr *)data;
1647 dissect_wlan_radio_phdr(tvb, pinfo, tree, phdr);
1649 /* Is there anything there? A 0-length-psdu has no frame data. */
1650 if (phdr->has_zero_length_psdu_type)
1651 return tvb_captured_length(tvb);
1653 /* dissect the 802.11 packet next */
1654 return call_dissector_with_data(ieee80211_noqos_handle, tvb, pinfo, tree, data);
1657 static void
1658 setup_ieee80211_radio(void)
1660 /* start of a new dissection, initialize state variables */
1661 current_aggregate = NULL;
1662 agg_tracker_list = NULL;
1663 memset(&previous_frame, 0, sizeof(previous_frame));
1666 static void
1667 cleanup_ieee80211_radio(void)
1669 if (agg_tracker_list != NULL) {
1670 wmem_destroy_list(agg_tracker_list);
1671 agg_tracker_list = NULL;
1675 void proto_register_ieee80211_radio(void)
1677 static hf_register_info hf_wlan_radio[] = {
1678 {&hf_wlan_radio_phy,
1679 {"PHY type", "wlan_radio.phy", FT_UINT32, BASE_DEC, VALS(phy_vals), 0,
1680 NULL, HFILL }},
1682 {&hf_wlan_radio_11_fhss_hop_set,
1683 {"Hop set", "wlan_radio.fhss.hop_set", FT_UINT8, BASE_HEX, NULL, 0,
1684 NULL, HFILL }},
1686 {&hf_wlan_radio_11_fhss_hop_pattern,
1687 {"Hop pattern", "wlan_radio.fhss.hop_pattern", FT_UINT8, BASE_HEX, NULL, 0,
1688 NULL, HFILL }},
1690 {&hf_wlan_radio_11_fhss_hop_index,
1691 {"Hop index", "wlan_radio.fhss.hop_index", FT_UINT8, BASE_HEX, NULL, 0,
1692 NULL, HFILL }},
1694 {&hf_wlan_radio_11a_channel_type,
1695 {"Channel type", "wlan_radio.11a.channel_type", FT_UINT32, BASE_DEC, VALS(channel_type_11a_vals), 0,
1696 NULL, HFILL }},
1698 {&hf_wlan_radio_11a_turbo_type,
1699 {"Turbo type", "wlan_radio.11a.turbo_type", FT_UINT32, BASE_DEC, VALS(turbo_type_11a_vals), 0,
1700 NULL, HFILL }},
1702 {&hf_wlan_radio_11g_mode,
1703 {"Proprietary mode", "wlan_radio.11g.mode", FT_UINT32, BASE_DEC, VALS(mode_11g_vals), 0,
1704 NULL, HFILL }},
1706 {&hf_wlan_radio_11n_mcs_index,
1707 {"MCS index", "wlan_radio.11n.mcs_index", FT_UINT32, BASE_DEC, NULL, 0,
1708 "Modulation and Coding Scheme index", HFILL }},
1710 {&hf_wlan_radio_11n_bandwidth,
1711 {"Bandwidth", "wlan_radio.11n.bandwidth", FT_UINT32, BASE_DEC, VALS(bandwidth_vals), 0,
1712 NULL, HFILL }},
1714 {&hf_wlan_radio_11n_short_gi,
1715 {"Short GI", "wlan_radio.11n.short_gi", FT_BOOLEAN, BASE_NONE, NULL, 0,
1716 NULL, HFILL }},
1718 {&hf_wlan_radio_11n_greenfield,
1719 {"Greenfield", "wlan_radio.11n.greenfield", FT_BOOLEAN, BASE_NONE, NULL, 0,
1720 NULL, HFILL }},
1722 {&hf_wlan_radio_11n_fec,
1723 {"FEC", "wlan_radio.11n.fec", FT_UINT32, BASE_DEC, VALS(fec_vals), 0,
1724 NULL, HFILL }},
1726 {&hf_wlan_radio_11n_stbc_streams,
1727 {"Number of STBC streams", "wlan_radio.11n.stbc_streams", FT_UINT32, BASE_DEC, NULL, 0,
1728 NULL, HFILL }},
1730 {&hf_wlan_radio_11n_ness,
1731 {"Number of extension spatial streams", "wlan_radio.11n.ness", FT_UINT32, BASE_DEC, NULL, 0,
1732 NULL, HFILL }},
1734 {&hf_wlan_radio_11ac_stbc,
1735 {"STBC", "wlan_radio.11ac.stbc", FT_BOOLEAN, BASE_NONE, TFS(&tfs_on_off), 0x0,
1736 "Space Time Block Coding flag", HFILL }},
1738 {&hf_wlan_radio_11ac_txop_ps_not_allowed,
1739 {"TXOP_PS_NOT_ALLOWED", "wlan_radio_11ac.txop_ps_not_allowed", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1740 "Flag indicating whether STAs may doze during TXOP", HFILL }},
1742 {&hf_wlan_radio_11ac_short_gi,
1743 {"Short GI", "wlan_radio.11ac.short_gi", FT_BOOLEAN, BASE_NONE, NULL, 0,
1744 NULL, HFILL }},
1746 {&hf_wlan_radio_11ac_short_gi_nsym_disambig,
1747 {"Short GI Nsym disambiguation", "wlan_radio.11ac.short_gi_nsym_disambig", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1748 "Short Guard Interval Nsym disambiguation", HFILL }},
1750 {&hf_wlan_radio_11ac_ldpc_extra_ofdm_symbol,
1751 {"LDPC extra OFDM symbol", "wlan_radio.11ac.ldpc_extra_ofdm_symbol", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1752 NULL, HFILL }},
1754 {&hf_wlan_radio_11ac_beamformed,
1755 {"Beamformed", "wlan_radio.11ac.beamformed", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1756 NULL, HFILL }},
1758 {&hf_wlan_radio_11ac_bandwidth,
1759 {"Bandwidth", "wlan_radio.11ac.bandwidth", FT_UINT32, BASE_DEC, VALS(bandwidth_vals), 0,
1760 NULL, HFILL }},
1762 {&hf_wlan_radio_11ac_user,
1763 {"User", "wlan_radio.11ac.user", FT_NONE, BASE_NONE, NULL, 0x0,
1764 NULL, HFILL }},
1766 {&hf_wlan_radio_11ac_nsts,
1767 {"Space-time streams", "wlan_radio.11ac.nsts", FT_UINT32, BASE_DEC, NULL, 0x0,
1768 "Number of Space-time streams", HFILL }},
1770 {&hf_wlan_radio_11ac_mcs,
1771 {"MCS index", "wlan_radio.11ac.mcs", FT_UINT32, BASE_DEC, NULL, 0x0,
1772 "Modulation and Coding Scheme index", HFILL }},
1774 {&hf_wlan_radio_11ac_nss,
1775 {"Spatial streams", "wlan_radio.11ac.nss", FT_UINT32, BASE_DEC, NULL, 0x0,
1776 "Number of spatial streams", HFILL }},
1778 {&hf_wlan_radio_11ac_fec,
1779 {"FEC", "wlan_radio.11ac.fec", FT_UINT32, BASE_DEC, VALS(fec_vals), 0x0,
1780 "Type of FEC", HFILL }},
1782 {&hf_wlan_radio_11ac_gid,
1783 {"Group Id", "wlan_radio.11ac.gid", FT_UINT32, BASE_DEC, NULL, 0x0,
1784 NULL, HFILL }},
1786 {&hf_wlan_radio_11ac_p_aid,
1787 {"Partial AID", "wlan_radio.11ac.paid", FT_UINT16, BASE_DEC, NULL, 0x0,
1788 NULL, HFILL }},
1790 {&hf_wlan_radio_11be_user,
1791 {"User", "wlan_radio.11be.user", FT_NONE, BASE_NONE, NULL, 0x0,
1792 NULL, HFILL }},
1794 {&hf_wlan_radio_11be_sta_id,
1795 {"Sta ID", "wlan_radio.11be.sta_id", FT_UINT32, BASE_DEC, NULL, 0x0,
1796 "Station ID", HFILL }},
1798 {&hf_wlan_radio_11be_nsts,
1799 {"Space-time streams", "wlan_radio.11be.nsts", FT_UINT32, BASE_DEC, NULL, 0x0,
1800 "Number of Space-time streams", HFILL }},
1802 {&hf_wlan_radio_11be_mcs,
1803 {"MCS index", "wlan_radio.11be.mcs", FT_UINT32, BASE_DEC, NULL, 0x0,
1804 "Modulation and Coding Scheme index", HFILL }},
1806 {&hf_wlan_radio_data_rate,
1807 {"Data rate", "wlan_radio.data_rate", FT_FLOAT, BASE_NONE, NULL, 0,
1808 "Speed at which this frame was sent/received", HFILL }},
1810 {&hf_wlan_radio_channel,
1811 {"Channel", "wlan_radio.channel", FT_UINT32, BASE_DEC, NULL, 0,
1812 "802.11 channel number that this frame was sent/received on", HFILL }},
1814 {&hf_wlan_radio_frequency,
1815 {"Frequency", "wlan_radio.frequency", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_mhz), 0,
1816 "Center frequency of the 802.11 channel that this frame was sent/received on", HFILL }},
1818 {&hf_wlan_radio_short_preamble,
1819 {"Short preamble", "wlan_radio.short_preamble", FT_BOOLEAN, BASE_NONE, NULL, 0,
1820 NULL, HFILL }},
1822 {&hf_wlan_radio_signal_percent,
1823 {"Signal strength (percentage)", "wlan_radio.signal_percentage", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_percent), 0,
1824 "Signal strength, as percentage of maximum RSSI", HFILL }},
1826 {&hf_wlan_radio_signal_db,
1827 {"Signal strength (dB)", "wlan_radio.signal_db", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_decibels), 0,
1828 NULL, HFILL }},
1830 {&hf_wlan_radio_signal_dbm,
1831 {"Signal strength (dBm)", "wlan_radio.signal_dbm", FT_INT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_dbm), 0,
1832 NULL, HFILL }},
1834 {&hf_wlan_radio_noise_percent,
1835 {"Noise level (percentage)", "wlan_radio.noise_percentage", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_percent), 0,
1836 NULL, HFILL }},
1838 {&hf_wlan_radio_noise_db,
1839 {"Noise level (dB)", "wlan_radio.noise_db", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_decibels), 0,
1840 NULL, HFILL }},
1842 {&hf_wlan_radio_noise_dbm,
1843 {"Noise level (dBm)", "wlan_radio.noise_dbm", FT_INT8, BASE_DEC|BASE_UNIT_STRING, UNS(&units_dbm), 0,
1844 NULL, HFILL }},
1846 {&hf_wlan_radio_snr,
1847 {"Signal/noise ratio (dB)", "wlan_radio.snr", FT_INT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_decibels), 0,
1848 NULL, HFILL }},
1850 {&hf_wlan_radio_timestamp,
1851 {"TSF timestamp", "wlan_radio.timestamp", FT_UINT64, BASE_DEC, NULL, 0,
1852 "Timing Synchronization Function timestamp", HFILL }},
1854 {&hf_wlan_last_part_of_a_mpdu,
1855 {"Last part of an A-MPDU", "wlan_radio.last_part_of_an_ampdu", FT_BOOLEAN, 32, NULL, PHDR_802_11_LAST_PART_OF_A_MPDU,
1856 "This is the last part of an A-MPDU", HFILL }},
1858 {&hf_wlan_a_mpdu_delim_crc_error,
1859 {"A-MPDU delimiter CRC error", "wlan_radio.a_mpdu_delim_crc_error", FT_BOOLEAN, 32, NULL, PHDR_802_11_A_MPDU_DELIM_CRC_ERROR,
1860 NULL, HFILL }},
1862 {&hf_wlan_a_mpdu_aggregate_id,
1863 {"A-MPDU aggregate ID", "wlan_radio.a_mpdu_aggregate_id", FT_UINT32, BASE_DEC, NULL, 0,
1864 NULL, HFILL }},
1866 {&hf_wlan_radio_duration,
1867 {"Duration", "wlan_radio.duration", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_microseconds), 0,
1868 "Total duration of the frame in microseconds, including any preamble or plcp header. "
1869 "Calculated from the frame length, modulation and other phy data.", HFILL }},
1871 {&hf_wlan_radio_preamble,
1872 {"Preamble", "wlan_radio.preamble", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_microseconds), 0,
1873 "Duration of the PLCP or preamble in microseconds, calculated from PHY data", HFILL }},
1875 {&hf_wlan_radio_aggregate,
1876 {"A-MPDU", "wlan_radio.aggregate", FT_NONE, BASE_NONE, NULL, 0,
1877 "MPDU is part of an A-MPDU", HFILL }},
1879 {&hf_wlan_radio_ifs,
1880 {"IFS", "wlan_radio.ifs", FT_INT64, BASE_DEC|BASE_UNIT_STRING, UNS(&units_microseconds), 0,
1881 "Inter Frame Space before this frame in microseconds, calculated from PHY data", HFILL }},
1883 {&hf_wlan_radio_start_tsf,
1884 {"Start", "wlan_radio.start_tsf", FT_UINT64, BASE_DEC|BASE_UNIT_STRING, UNS(&units_microseconds), 0,
1885 "Calculated start time of the frame", HFILL }},
1887 {&hf_wlan_radio_end_tsf,
1888 {"End", "wlan_radio.end_tsf", FT_UINT64, BASE_DEC|BASE_UNIT_STRING, UNS(&units_microseconds), 0,
1889 "Calculated end time of the frame", HFILL }},
1891 {&hf_wlan_radio_aggregate_duration,
1892 {"Aggregate Duration", "wlan_radio.aggregate.duration", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_microseconds), 0,
1893 "Total duration of the aggregate in microseconds, including any preamble or plcp header and multiple MPDUs. "
1894 "Calculated from the total subframe lengths, modulation and other phy data, assumes no excess padding.", HFILL }},
1896 {&hf_wlan_zero_length_psdu_type,
1897 {"Zero-length PSDU Type", "wlan_radio.zero_len_psdu.type", FT_UINT8, BASE_HEX, VALS(zero_length_psdu_vals), 0x0,
1898 "Type of zero-length PSDU", HFILL}},
1901 static int *ett[] = {
1902 &ett_wlan_radio,
1903 &ett_wlan_radio_11ac_user,
1904 &ett_wlan_radio_duration,
1905 &ett_wlan_radio_aggregate,
1906 &ett_wlan_radio_11be_user,
1909 static ei_register_info ei[] = {
1910 { &ei_wlan_radio_assumed_short_preamble,
1911 { "wlan_radio.assumed.short_preamble", PI_ASSUMPTION, PI_WARN,
1912 "No preamble length information was available, assuming short preamble.", EXPFILL }},
1914 { &ei_wlan_radio_assumed_non_greenfield,
1915 { "wlan_radio.assumed.non_greenfield", PI_ASSUMPTION, PI_WARN,
1916 "No plcp type information was available, assuming non greenfield.", EXPFILL }},
1918 { &ei_wlan_radio_assumed_no_stbc,
1919 { "wlan_radio.assumed.no_stbc", PI_ASSUMPTION, PI_WARN,
1920 "No stbc information was available, assuming no stbc.", EXPFILL }},
1922 { &ei_wlan_radio_assumed_no_extension_streams,
1923 { "wlan_radio.assumed.no_extension_streams", PI_ASSUMPTION, PI_WARN,
1924 "No extension stream information was available, assuming no extension streams.", EXPFILL }},
1926 { &ei_wlan_radio_assumed_bcc_fec,
1927 { "wlan_radio.assumed.bcc_fec", PI_ASSUMPTION, PI_WARN,
1928 "No fec type information was available, assuming bcc fec.", EXPFILL }},
1930 { &ei_wlan_radio_11be_num_users,
1931 { "wlan_radio.11be_num_users", PI_MALFORMED, PI_WARN,
1932 "Number of users in the 802.11be header exceeds available slots.", EXPFILL }},
1935 module_t *wlan_radio_module;
1936 expert_module_t* expert_wlan_radio;
1938 proto_wlan_radio = proto_register_protocol("802.11 radio information", "802.11 Radio", "wlan_radio");
1939 proto_register_field_array(proto_wlan_radio, hf_wlan_radio, array_length(hf_wlan_radio));
1940 proto_register_subtree_array(ett, array_length(ett));
1942 expert_wlan_radio = expert_register_protocol(proto_wlan_radio);
1943 expert_register_field_array(expert_wlan_radio, ei, array_length(ei));
1945 wlan_radio_handle = register_dissector("wlan_radio", dissect_wlan_radio, proto_wlan_radio);
1946 wlan_noqos_radio_handle = register_dissector("wlan_noqos_radio", dissect_wlan_noqos_radio, proto_wlan_radio);
1948 wlan_radio_module = prefs_register_protocol(proto_wlan_radio, NULL);
1949 prefs_register_bool_preference(wlan_radio_module, "always_short_preamble",
1950 "802.11/11b preamble length is always short",
1951 "Some generators incorrectly indicate long preamble when the preamble was actually"
1952 "short. Always assume short preamble when calculating duration.",
1953 &wlan_radio_always_short_preamble);
1954 prefs_register_bool_preference(wlan_radio_module, "tsf_at_end",
1955 "TSF indicates the end of the PPDU",
1956 "Some generators timestamp the end of the PPDU rather than the start of the (A)MPDU.",
1957 &wlan_radio_tsf_at_end);
1958 prefs_register_bool_preference(wlan_radio_module, "timeline",
1959 "Enable Wireless Timeline (experimental)",
1960 "Enables an additional panel for navigating through packets",
1961 &wlan_radio_timeline_enabled);
1963 register_init_routine( setup_ieee80211_radio );
1964 register_cleanup_routine( cleanup_ieee80211_radio );
1966 wlan_radio_tap = register_tap("wlan_radio");
1967 wlan_radio_timeline_tap = register_tap("wlan_radio_timeline");
1970 void proto_reg_handoff_ieee80211_radio(void)
1972 /* Register handoff to radio-header dissectors */
1973 dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
1974 wlan_radio_handle);
1975 ieee80211_handle = find_dissector_add_dependency("wlan", proto_wlan_radio);
1976 ieee80211_noqos_handle = find_dissector_add_dependency("wlan_noqos", proto_wlan_radio);
1980 * Editor modelines
1982 * Local Variables:
1983 * c-basic-offset: 2
1984 * tab-width: 8
1985 * indent-tabs-mode: nil
1986 * End:
1988 * ex: set shiftwidth=2 tabstop=8 expandtab:
1989 * :indentSize=2:tabSize=8:noTabs=true: