Bug Summary

File:builds/wireshark/wireshark/epan/dissectors/packet-ieee80211-radio.c
Warning:line 1171, column 13
Value stored to 'bandwidth' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name packet-ieee80211-radio.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-18/lib/clang/18 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/epan -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-truncation -Wno-format-nonliteral -Wno-pointer-sign -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -dwarf-debug-flags /usr/lib/llvm-18/bin/clang -### --analyze -x c -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/epan -fvisibility=hidden -fexcess-precision=fast -fstrict-flex-arrays=3 -fstack-clash-protection -fcf-protection=full -D _GLIBCXX_ASSERTIONS -fstack-protector-strong -fno-delete-null-pointer-checks -fno-strict-overflow -fno-strict-aliasing -fexceptions -Wno-format-truncation -Wno-format-nonliteral -fdiagnostics-color=always -Wno-pointer-sign -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -std=gnu11 -fPIC /builds/wireshark/wireshark/epan/dissectors/packet-ieee80211-radio.c -o /builds/wireshark/wireshark/sbout/2025-07-05-100252-3847-1 -Xclang -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-07-05-100252-3847-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-ieee80211-radio.c
1/* packet-ieee80211-radio.c
2 * Routines for pseudo 802.11 header dissection and radio packet timing calculation
3 *
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
7 *
8 * Copyright 2012 Parc Inc and Samsung Electronics
9 * Copyright 2015, 2016 & 2017 Cisco Inc
10 *
11 * Copied from README.developer
12 *
13 * SPDX-License-Identifier: GPL-2.0-or-later
14 */
15
16#include "config.h"
17
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>
26
27#include "packet-ieee80211.h"
28#include "packet-ieee80211-radio.h"
29#include "packet-ieee80211-radiotap-defs.h"
30#include "math.h"
31
32void proto_register_ieee80211_radio(void);
33void proto_reg_handoff_ieee80211_radio(void);
34
35static dissector_handle_t wlan_radio_handle;
36static dissector_handle_t wlan_noqos_radio_handle;
37static dissector_handle_t ieee80211_handle;
38static dissector_handle_t ieee80211_noqos_handle;
39
40static int proto_wlan_radio;
41
42/* ************************************************************************* */
43/* Header field info values for radio information */
44/* ************************************************************************* */
45static int hf_wlan_radio_phy;
46static int hf_wlan_radio_11_fhss_hop_set;
47static int hf_wlan_radio_11_fhss_hop_pattern;
48static int hf_wlan_radio_11_fhss_hop_index;
49static int hf_wlan_radio_11a_channel_type;
50static int hf_wlan_radio_11a_turbo_type;
51static int hf_wlan_radio_11g_mode;
52static int hf_wlan_radio_11n_mcs_index;
53static int hf_wlan_radio_11n_bandwidth;
54static int hf_wlan_radio_11n_short_gi;
55static int hf_wlan_radio_11n_greenfield;
56static int hf_wlan_radio_11n_fec;
57static int hf_wlan_radio_11n_stbc_streams;
58static int hf_wlan_radio_11n_ness;
59static int hf_wlan_radio_11ac_stbc;
60static int hf_wlan_radio_11ac_txop_ps_not_allowed;
61static int hf_wlan_radio_11ac_short_gi;
62static int hf_wlan_radio_11ac_short_gi_nsym_disambig;
63static int hf_wlan_radio_11ac_ldpc_extra_ofdm_symbol;
64static int hf_wlan_radio_11ac_beamformed;
65static int hf_wlan_radio_11ac_bandwidth;
66static int hf_wlan_radio_11ac_user;
67static int hf_wlan_radio_11ac_nsts;
68static int hf_wlan_radio_11ac_mcs;
69static int hf_wlan_radio_11ac_nss;
70static int hf_wlan_radio_11ac_fec;
71static int hf_wlan_radio_11ac_gid;
72static int hf_wlan_radio_11ac_p_aid;
73static int hf_wlan_radio_11ax_mcs;
74static int hf_wlan_radio_11ax_bandwidth;
75static int hf_wlan_radio_11ax_short_gi;
76static int hf_wlan_radio_data_rate;
77static int hf_wlan_radio_channel;
78static int hf_wlan_radio_frequency;
79static int hf_wlan_radio_short_preamble;
80static int hf_wlan_radio_signal_percent;
81static int hf_wlan_radio_signal_db;
82static int hf_wlan_radio_signal_dbm;
83static int hf_wlan_radio_noise_percent;
84static int hf_wlan_radio_noise_db;
85static int hf_wlan_radio_noise_dbm;
86static int hf_wlan_radio_snr;
87static int hf_wlan_radio_timestamp;
88static int hf_wlan_last_part_of_a_mpdu;
89static int hf_wlan_a_mpdu_delim_crc_error;
90static int hf_wlan_a_mpdu_aggregate_id;
91static int hf_wlan_radio_duration;
92static int hf_wlan_radio_preamble;
93static int hf_wlan_radio_aggregate;
94static int hf_wlan_radio_aggregate_duration;
95static int hf_wlan_radio_ifs;
96static int hf_wlan_radio_start_tsf;
97static int hf_wlan_radio_end_tsf;
98static int hf_wlan_zero_length_psdu_type;
99static int hf_wlan_radio_11be_user;
100static int hf_wlan_radio_11be_sta_id;
101static int hf_wlan_radio_11be_mcs;
102static int hf_wlan_radio_11be_nsts;
103
104
105static expert_field ei_wlan_radio_assumed_short_preamble;
106static expert_field ei_wlan_radio_assumed_non_greenfield;
107static expert_field ei_wlan_radio_assumed_no_stbc;
108static expert_field ei_wlan_radio_assumed_no_extension_streams;
109static expert_field ei_wlan_radio_assumed_bcc_fec;
110static expert_field ei_wlan_radio_11be_num_users;
111
112static int wlan_radio_tap;
113static int wlan_radio_timeline_tap;
114
115/* Settings */
116static bool_Bool wlan_radio_always_short_preamble;
117static bool_Bool wlan_radio_tsf_at_end = true1;
118static bool_Bool wlan_radio_timeline_enabled;
119
120static const value_string phy_vals[] = {
121 { PHDR_802_11_PHY_11_FHSS1, "802.11 FHSS" },
122 { PHDR_802_11_PHY_11_IR2, "802.11 IR" },
123 { PHDR_802_11_PHY_11_DSSS3, "802.11 DSSS" },
124 { PHDR_802_11_PHY_11B4, "802.11b (HR/DSSS)" },
125 { PHDR_802_11_PHY_11A5, "802.11a (OFDM)" },
126 { PHDR_802_11_PHY_11G6, "802.11g (ERP)" },
127 { PHDR_802_11_PHY_11N7, "802.11n (HT)" },
128 { PHDR_802_11_PHY_11AC8, "802.11ac (VHT)" },
129 { PHDR_802_11_PHY_11AD9, "802.11ad (DMG)" },
130 { PHDR_802_11_PHY_11AH10, "802.11ah (S1G)" },
131 { PHDR_802_11_PHY_11AX11, "802.11ax (HE)" },
132 { PHDR_802_11_PHY_11BE12, "802.11be (EHT)" },
133 { 0, NULL((void*)0) }
134};
135
136static const value_string channel_type_11a_vals[] = {
137 { PHDR_802_11A_CHANNEL_TYPE_NORMAL0, "Normal" },
138 { PHDR_802_11A_CHANNEL_TYPE_HALF_CLOCKED1, "Half-clocked" },
139 { PHDR_802_11A_CHANNEL_TYPE_QUARTER_CLOCKED2, "Quarter-clocked" },
140 { 0, NULL((void*)0) }
141};
142
143static const value_string turbo_type_11a_vals[] = {
144 { PHDR_802_11A_TURBO_TYPE_NORMAL0, "Non-turbo" },
145 { PHDR_802_11A_TURBO_TYPE_TURBO1, "Turbo" },
146 { PHDR_802_11A_TURBO_TYPE_DYNAMIC_TURBO2, "Dynamic turbo" },
147 { PHDR_802_11A_TURBO_TYPE_STATIC_TURBO3, "Static turbo" },
148 { 0, NULL((void*)0) }
149};
150
151static const value_string mode_11g_vals[] = {
152 { PHDR_802_11G_MODE_NORMAL0, "None" },
153 { PHDR_802_11G_MODE_SUPER_G1, "Super G" },
154 { 0, NULL((void*)0) }
155};
156
157static const value_string bandwidth_vals[] = {
158 { PHDR_802_11_BANDWIDTH_20_MHZ0, "20 MHz" },
159 { PHDR_802_11_BANDWIDTH_40_MHZ1, "40 MHz" },
160 { PHDR_802_11_BANDWIDTH_20_20L2, "20 MHz + 20 MHz lower" },
161 { PHDR_802_11_BANDWIDTH_20_20U3, "20 MHz + 20 MHz upper" },
162 { PHDR_802_11_BANDWIDTH_80_MHZ4, "80 MHz" },
163 { PHDR_802_11_BANDWIDTH_40_40L5, "40 MHz + 40 MHz lower" },
164 { PHDR_802_11_BANDWIDTH_40_40U6, "40 MHz + 40 MHz upper" },
165 { PHDR_802_11_BANDWIDTH_20LL7, "20 MHz, channel 1/4" },
166 { PHDR_802_11_BANDWIDTH_20LU8, "20 MHz, channel 2/4" },
167 { PHDR_802_11_BANDWIDTH_20UL9, "20 MHz, channel 3/4" },
168 { PHDR_802_11_BANDWIDTH_20UU10, "20 MHz, channel 4/4" },
169 { PHDR_802_11_BANDWIDTH_160_MHZ11, "160 MHz" },
170 { PHDR_802_11_BANDWIDTH_80_80L12, "80 MHz + 80 MHz lower" },
171 { PHDR_802_11_BANDWIDTH_80_80U13, "80 MHz + 80 MHz upper" },
172 { PHDR_802_11_BANDWIDTH_40LL14, "40 MHz, channel 1/4" },
173 { PHDR_802_11_BANDWIDTH_40LU15, "40 MHz, channel 2/4" },
174 { PHDR_802_11_BANDWIDTH_40UL16, "40 MHz, channel 3/4" },
175 { PHDR_802_11_BANDWIDTH_40UU17, "40 MHz, channel 4/4" },
176 { PHDR_802_11_BANDWIDTH_20LLL18, "20 MHz, channel 1/8" },
177 { PHDR_802_11_BANDWIDTH_20LLU19, "20 MHz, channel 2/8" },
178 { PHDR_802_11_BANDWIDTH_20LUL20, "20 MHz, channel 3/8" },
179 { PHDR_802_11_BANDWIDTH_20LUU21, "20 MHz, channel 4/8" },
180 { PHDR_802_11_BANDWIDTH_20ULL22, "20 MHz, channel 5/8" },
181 { PHDR_802_11_BANDWIDTH_20ULU23, "20 MHz, channel 6/8" },
182 { PHDR_802_11_BANDWIDTH_20UUL24, "20 MHz, channel 7/8" },
183 { PHDR_802_11_BANDWIDTH_20UUU25, "20 MHz, channel 8/8" },
184 { 0, NULL((void*)0) }
185};
186
187static const value_string fec_vals[] = {
188 { 0, "BEC" },
189 { 1, "LDPC" },
190 { 0, NULL((void*)0) }
191};
192
193static const value_string zero_length_psdu_vals[] = {
194 { 0, "sounding PPDU" },
195 { 1, "data not captured" },
196 { 255, "vendor-specific" },
197 { 0, NULL((void*)0) }
198};
199/*
200 * Lookup for the MCS index (0-76)
201 * returning the number of data bits per symbol
202 * assumes 52 subcarriers (20MHz)
203 * symbols are 4us for long guard interval, 3.6us for short guard interval
204 * Note: MCS 32 is special - only valid for 40Mhz channel.
205 */
206WS_DLL_PUBLIC_DEF__attribute__ ((visibility ("default"))) const uint16_t ieee80211_ht_Dbps[MAX_MCS_INDEX76+1] = {
207 /* MCS 0 - 1 stream */
208 26, 52, 78, 104, 156, 208, 234, 260,
209
210 /* MCS 8 - 2 stream */
211 52, 104, 156, 208, 312, 416, 468, 520,
212
213 /* MCS 16 - 3 stream */
214 78, 156, 234, 312, 468, 624, 702, 780,
215
216 /* MCS 24 - 4 stream */
217 104, 208, 312, 416, 624, 832, 936, 1040,
218
219 /* MCS 32 - 1 stream */
220 12, /* only valid for 40Mhz - 11a/g DUP mode */
221
222 /* MCS 33 - 2 stream */
223 156, 208, 260, 234, 312, 390,
224
225 /* MCS 39 - 3 stream */
226 208, 260, 260, 312, 364, 364, 416, 312, 390, 390, 468, 546, 546, 624,
227
228 /* MCS 53 - 4 stream */
229 260, 312, 364, 312, 364, 416, 468, 416, 468, 520, 520, 572,
230 390, 468, 546, 468, 546, 624, 702, 624, 702, 780, 780, 858
231};
232
233/*
234 * Calculates data rate corresponding to a given 802.11n MCS index,
235 * bandwidth, and guard interval.
236 */
237float ieee80211_htrate(int mcs_index, bool_Bool bandwidth, bool_Bool short_gi)
238{
239 return (float)(ieee80211_ht_Dbps[mcs_index] * (bandwidth ? 108 : 52) / 52.0 / (short_gi ? 3.6 : 4.0));
240}
241
242static const uint8_t ieee80211_ht_streams[MAX_MCS_INDEX76+1] = {
243 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,
244 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,
245 4,4,4,4,4,4,4,4,4,4,4,4,4
246};
247
248static const uint8_t ieee80211_ht_Nes[MAX_MCS_INDEX76+1] = {
249 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,
250 1,1,1,1,1,2,2,2, 1,1,1,1,2,2,2,2,
251 1,
252 1,1,1,1,1,1,
253 1,1,1,1,1,1,1,1,1,1,1,1,1,1,
254 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2
255};
256
257#define MAX_MCS_VHT_INDEX9 9
258
259/*
260 * Maps a VHT bandwidth index to ieee80211_vhtinfo.rates index.
261 */
262static const int ieee80211_vht_bw2rate_index[] = {
263 /* 20Mhz total */ 0,
264 /* 40Mhz total */ 1, 0, 0,
265 /* 80Mhz total */ 2, 1, 1, 0, 0, 0, 0,
266 /* 160Mhz total */ 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0
267};
268
269struct mcs_info {
270 const char *modulation;
271 const char *coding_rate;
272 float data_bits_per_symbol; /* assuming 20MHz / 52 subcarriers */
273};
274
275#define EHT_MAX_MCS16 16
276static const struct mcs_info ieee80211_mcsinfo[EHT_MAX_MCS16] = {
277 /* MCS 0 */
278 { "BPSK", "1/2", 26 },
279 /* MCS 1 */
280 { "QPSK", "1/2", 52 },
281 /* MCS 2 */
282 { "QPSK", "3/4", 78 },
283 /* MCS 3 */
284 { "16-QAM", "1/2", 104 },
285 /* MCS 4 */
286 { "16-QAM", "3/4", 156 },
287 /* MCS 5 */
288 { "64-QAM", "2/3", 208 },
289 /* MCS 6 */
290 { "64-QAM", "3/4", 234 },
291 /* MCS 7 */
292 { "64-QAM", "5/6", 260 },
293 /* MCS 8 */
294 { "256-QAM", "3/4", 312 },
295 /* MCS 9 */
296 { "256-QAM", "5/6", (float)(1040/3.0) },
297 /* MCS 10 */
298 { "1024-QAM", "3/4", 390 },
299 /* MCS 11 */
300 { "1024-QAM", "5/6", (float)(1300/3.0) },
301 /* MCS 12 */
302 { "4096-QAM", "3/4", 468 },
303 /* MCS 13 */
304 { "4096-QAM", "5/6", 520 },
305 /* MCS 14 */
306 { "BPSK-DCM", "1/2", 6.5f },
307 /* MCS 15 */
308 { "BPSK-DCM", "1/2", 13 }
309};
310
311/* map a bandwidth index to the number of data subcarriers */
312static const unsigned subcarriers[4] = { 52, 108, 234, 468 };
313
314#define MAX_VHT_NSS8 8
315
316struct mcs_vht_valid {
317 bool_Bool valid[4][MAX_VHT_NSS8]; /* indexed by bandwidth and NSS-1 */
318};
319
320static const struct mcs_vht_valid ieee80211_vhtvalid[MAX_MCS_VHT_INDEX9+1] = {
321 /* MCS 0 */
322 {
323 { /* 20 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
324 /* 40 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
325 /* 80 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
326 /* 160 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
327 }
328 },
329 /* MCS 1 */
330 {
331 { /* 20 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
332 /* 40 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
333 /* 80 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
334 /* 160 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
335 }
336 },
337 /* MCS 2 */
338 {
339 { /* 20 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
340 /* 40 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
341 /* 80 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
342 /* 160 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
343 }
344 },
345 /* MCS 3 */
346 {
347 { /* 20 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
348 /* 40 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
349 /* 80 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
350 /* 160 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
351 }
352 },
353 /* MCS 4 */
354 {
355 { /* 20 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
356 /* 40 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
357 /* 80 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
358 /* 160 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
359 }
360 },
361 /* MCS 5 */
362 {
363 { /* 20 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
364 /* 40 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
365 /* 80 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
366 /* 160 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
367 }
368 },
369 /* MCS 6 */
370 {
371 { /* 20 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
372 /* 40 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
373 /* 80 Mhz */ { true1, true1, false0, true1, true1, true1, false0, true1 },
374 /* 160 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
375 }
376 },
377 /* MCS 7 */
378 {
379 { /* 20 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
380 /* 40 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
381 /* 80 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
382 /* 160 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
383 }
384 },
385 /* MCS 8 */
386 {
387 { /* 20 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
388 /* 40 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
389 /* 80 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
390 /* 160 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
391 }
392 },
393 /* MCS 9 */
394 {
395 { /* 20 Mhz */ { false0, false0, true1, false0, false0, true1, false0, false0 },
396 /* 40 Mhz */ { true1, true1, true1, true1, true1, true1, true1, true1 },
397 /* 80 Mhz */ { true1, true1, true1, true1, true1, false0, true1, true1 },
398 /* 160 Mhz */ { true1, true1, false0, true1, true1, true1, true1, true1 },
399 }
400 }
401};
402
403/*
404 * Calculates data rate corresponding to a given 802.11ac MCS index,
405 * bandwidth, and guard interval.
406 */
407static float ieee80211_vhtrate(int mcs_index, unsigned bandwidth_index, bool_Bool short_gi)
408{
409 return (float)(ieee80211_mcsinfo[mcs_index].data_bits_per_symbol * subcarriers[bandwidth_index] / (short_gi ? 3.6 : 4.0) / 52.0);
410}
411
412/*
413 * HE SU OFDM MCS rate table converted from http://mcsindex.com/
414 * indexed by (NSTS,MCS,BW,GI)
415 */
416#define HE_MAX_NSTS8 8
417#define HE_MAX_MCS12 12
418#define HE_SU_MAX_BW4 4
419#define HE_MAX_GI3 3
420static float he_ofdm_tab[HE_MAX_NSTS8][HE_MAX_MCS12][HE_SU_MAX_BW4][HE_MAX_GI3] = {
421 {
422 {{ 8.6f, 8.1f, 7.3f},{ 17.2f, 16.3f, 14.6f},{ 36.0f, 34.0f, 30.6f},{ 72.1f, 68.1f, 61.3f}},
423 {{ 17.2f, 16.3f, 14.6f},{ 34.4f, 32.5f, 29.3f},{ 72.1f, 68.1f, 61.3f},{ 144.1f, 136.1f, 122.5f}},
424 {{ 25.8f, 24.4f, 21.9f},{ 51.6f, 48.8f, 43.9f},{ 108.1f, 102.1f, 91.9f},{ 216.2f, 204.2f, 183.8f}},
425 {{ 34.4f, 32.5f, 29.3f},{ 68.8f, 65.0f, 58.5f},{ 144.1f, 136.1f, 122.5f},{ 288.2f, 272.2f, 245.0f}},
426 {{ 51.6f, 48.8f, 43.9f},{ 103.2f, 97.5f, 87.8f},{ 216.2f, 204.2f, 183.8f},{ 432.4f, 408.3f, 367.5f}},
427 {{ 68.8f, 65.0f, 58.5f},{ 137.6f, 130.0f, 117.0f},{ 288.2f, 272.2f, 245.0f},{ 576.5f, 544.4f, 490.0f}},
428 {{ 77.4f, 73.1f, 65.8f},{ 154.9f, 146.3f, 131.6f},{ 324.3f, 306.3f, 275.6f},{ 648.5f, 612.5f, 551.3f}},
429 {{ 86.0f, 81.3f, 73.1f},{ 172.1f, 162.5f, 146.3f},{ 360.3f, 340.3f, 306.3f},{ 720.6f, 680.6f, 612.5f}},
430 {{ 103.2f, 97.5f, 87.8f},{ 206.5f, 195.0f, 175.5f},{ 432.4f, 408.3f, 367.5f},{ 864.7f, 816.7f, 735.0f}},
431 {{ 114.7f, 108.3f, 97.5f},{ 229.4f, 216.7f, 195.0f},{ 480.4f, 453.7f, 408.3f},{ 960.8f, 907.4f, 816.7f}},
432 {{ 129.0f, 121.9f, 109.7f},{ 258.1f, 243.8f, 219.4f},{ 540.4f, 510.4f, 459.4f},{ 1080.9f, 1020.8f, 918.8f}},
433 {{ 143.4f, 135.4f, 121.9f},{ 286.8f, 270.8f, 243.8f},{ 600.5f, 567.1f, 510.4f},{ 1201.0f, 1134.3f, 1020.8f}}
434 },{
435 {{ 17.2f, 16.3f, 14.6f},{ 34.4f, 32.5f, 29.3f},{ 72.1f, 68.1f, 61.3f},{ 144.1f, 136.1f, 122.5f}},
436 {{ 34.4f, 32.5f, 29.3f},{ 68.8f, 65.0f, 58.5f},{ 144.1f, 136.1f, 122.5f},{ 288.2f, 272.2f, 245.0f}},
437 {{ 51.6f, 48.8f, 43.9f},{ 103.2f, 97.5f, 87.8f},{ 216.2f, 204.2f, 183.8f},{ 432.4f, 408.3f, 367.5f}},
438 {{ 68.8f, 65.0f, 58.5f},{ 137.6f, 130.0f, 117.0f},{ 288.2f, 272.2f, 245.0f},{ 576.5f, 544.4f, 490.0f}},
439 {{ 103.2f, 97.5f, 87.8f},{ 206.5f, 195.0f, 175.5f},{ 432.4f, 408.3f, 367.5f},{ 864.7f, 816.7f, 735.0f}},
440 {{ 137.6f, 130.0f, 117.0f},{ 275.3f, 260.0f, 234.0f},{ 576.5f, 544.4f, 490.0f},{ 1152.9f, 1088.9f, 980.0f}},
441 {{ 154.9f, 146.3f, 131.6f},{ 309.7f, 292.5f, 263.3f},{ 648.5f, 612.5f, 551.3f},{ 1297.1f, 1225.0f, 1102.5f}},
442 {{ 172.1f, 162.5f, 146.3f},{ 344.1f, 325.0f, 292.5f},{ 720.6f, 680.6f, 612.5f},{ 1441.2f, 1361.1f, 1225.0f}},
443 {{ 206.5f, 195.0f, 175.5f},{ 412.9f, 390.0f, 351.0f},{ 864.7f, 816.7f, 735.0f},{ 1729.4f, 1633.3f, 1470.0f}},
444 {{ 229.4f, 216.7f, 195.0f},{ 458.8f, 433.3f, 390.0f},{ 960.8f, 907.4f, 816.7f},{ 1921.6f, 1814.8f, 1633.3f}},
445 {{ 258.1f, 243.8f, 219.4f},{ 516.2f, 487.5f, 438.8f},{ 1080.9f, 1020.8f, 918.8f},{ 2161.8f, 2041.7f, 1837.5f}},
446 {{ 286.8f, 270.8f, 243.8f},{ 573.5f, 541.7f, 487.5f},{ 1201.0f, 1134.3f, 1020.8f},{ 2402.0f, 2268.5f, 2041.7f}}
447 },{
448 {{ 25.8f, 24.4f, 21.9f},{ 51.6f, 48.8f, 43.9f},{ 108.1f, 102.1f, 91.9f},{ 216.2f, 204.2f, 183.8f}},
449 {{ 51.6f, 48.8f, 43.9f},{ 103.2f, 97.5f, 87.8f},{ 216.2f, 204.2f, 183.8f},{ 432.4f, 408.3f, 367.5f}},
450 {{ 77.4f, 73.1f, 65.8f},{ 154.9f, 146.3f, 131.6f},{ 324.3f, 306.3f, 275.6f},{ 648.5f, 612.5f, 551.3f}},
451 {{ 103.2f, 97.5f, 87.8f},{ 206.5f, 195.0f, 175.5f},{ 432.4f, 408.3f, 367.5f},{ 864.7f, 816.7f, 735.0f}},
452 {{ 154.9f, 146.3f, 131.6f},{ 309.7f, 292.5f, 263.3f},{ 648.5f, 612.5f, 551.3f},{ 1297.1f, 1225.0f, 1102.5f}},
453 {{ 206.5f, 195.0f, 175.5f},{ 412.9f, 390.0f, 351.0f},{ 864.7f, 816.7f, 735.0f},{ 1729.4f, 1633.3f, 1470.0f}},
454 {{ 232.3f, 219.4f, 197.4f},{ 464.6f, 438.8f, 394.9f},{ 972.8f, 918.8f, 826.9f},{ 1945.6f, 1837.5f, 1653.8f}},
455 {{ 258.1f, 243.8f, 219.4f},{ 516.2f, 487.5f, 438.8f},{ 1080.9f, 1020.8f, 918.8f},{ 2161.8f, 2041.7f, 1837.5f}},
456 {{ 309.7f, 292.5f, 263.3f},{ 619.4f, 585.0f, 526.5f},{ 1297.1f, 1225.0f, 1102.5f},{ 2594.1f, 2450.0f, 2205.0f}},
457 {{ 344.1f, 325.0f, 292.5f},{ 688.2f, 650.0f, 585.0f},{ 1441.2f, 1361.1f, 1225.0f},{ 2882.4f, 2722.2f, 2450.0f}},
458 {{ 387.1f, 365.6f, 329.1f},{ 774.3f, 731.3f, 658.1f},{ 1621.3f, 1531.3f, 1378.1f},{ 3242.6f, 3062.5f, 2756.3f}},
459 {{ 430.1f, 406.3f, 365.6f},{ 860.3f, 812.5f, 731.3f},{ 1801.5f, 1701.4f, 1531.3f},{ 3602.9f, 3402.8f, 3062.5f}}
460 },{
461 {{ 34.4f, 32.5f, 29.3f},{ 68.8f, 65.0f, 58.5f},{ 144.1f, 136.1f, 122.5f},{ 288.2f, 272.2f, 245.0f}},
462 {{ 68.8f, 65.0f, 58.5f},{ 137.6f, 130.0f, 117.0f},{ 288.2f, 272.2f, 245.0f},{ 576.5f, 544.4f, 490.0f}},
463 {{ 103.2f, 97.5f, 87.8f},{ 206.5f, 195.0f, 175.5f},{ 432.4f, 408.3f, 367.5f},{ 864.7f, 816.7f, 735.0f}},
464 {{ 137.6f, 130.0f, 117.0f},{ 275.3f, 260.0f, 234.0f},{ 576.5f, 544.4f, 490.0f},{ 1152.9f, 1088.9f, 980.0f}},
465 {{ 206.5f, 195.0f, 175.5f},{ 412.9f, 390.0f, 351.0f},{ 864.7f, 816.7f, 735.0f},{ 1729.4f, 1633.3f, 1470.0f}},
466 {{ 275.3f, 260.0f, 234.0f},{ 550.6f, 520.0f, 468.0f},{ 1152.9f, 1088.9f, 980.0f},{ 2305.9f, 2177.8f, 1960.0f}},
467 {{ 309.7f, 292.5f, 263.3f},{ 619.4f, 585.0f, 526.5f},{ 1297.1f, 1225.0f, 1102.5f},{ 2594.1f, 2450.0f, 2205.0f}},
468 {{ 344.1f, 325.0f, 292.5f},{ 688.2f, 650.0f, 585.0f},{ 1441.2f, 1361.1f, 1225.0f},{ 2882.4f, 2722.2f, 2450.0f}},
469 {{ 412.9f, 390.0f, 351.0f},{ 825.9f, 780.0f, 702.0f},{ 1729.4f, 1633.3f, 1470.0f},{ 3458.8f, 3266.7f, 2940.0f}},
470 {{ 458.8f, 433.3f, 390.0f},{ 917.6f, 866.7f, 780.0f},{ 1921.6f, 1814.8f, 1633.3f},{ 3843.1f, 3629.6f, 3266.7f}},
471 {{ 516.2f, 487.5f, 438.8f},{ 1032.4f, 975.0f, 877.5f},{ 2161.8f, 2041.7f, 1837.5f},{ 4323.5f, 4083.3f, 3675.0f}},
472 {{ 573.5f, 541.7f, 487.5f},{ 1147.1f, 1083.3f, 975.0f},{ 2402.0f, 2268.5f, 2041.7f},{ 4803.9f, 4537.0f, 4083.3f}}
473 },{
474 {{ 43.0f, 40.6f, 36.6f},{ 86.0f, 81.3f, 73.1f},{ 180.1f, 170.1f, 153.1f},{ 360.3f, 340.3f, 306.3f}},
475 {{ 86.0f, 81.3f, 73.1f},{ 172.1f, 162.5f, 146.3f},{ 360.3f, 340.3f, 306.3f},{ 720.6f, 680.6f, 612.5f}},
476 {{ 129.0f, 121.9f, 109.7f},{ 258.1f, 243.8f, 219.4f},{ 540.4f, 510.4f, 459.4f},{ 1080.9f, 1020.8f, 918.8f}},
477 {{ 172.1f, 162.5f, 146.3f},{ 344.1f, 325.0f, 292.5f},{ 720.6f, 680.6f, 612.5f},{ 1441.2f, 1361.1f, 1225.0f}},
478 {{ 258.1f, 243.8f, 219.4f},{ 516.2f, 487.5f, 438.8f},{ 1080.9f, 1020.8f, 918.8f},{ 2161.8f, 2041.7f, 1837.5f}},
479 {{ 344.1f, 325.0f, 292.5f},{ 688.2f, 650.0f, 585.0f},{ 1441.2f, 1361.1f, 1225.0f},{ 2882.4f, 2722.2f, 2450.0f}},
480 {{ 387.1f, 365.6f, 329.1f},{ 774.3f, 731.3f, 658.1f},{ 1621.3f, 1531.3f, 1378.1f},{ 3242.6f, 3062.5f, 2756.3f}},
481 {{ 430.1f, 406.3f, 365.6f},{ 860.3f, 812.5f, 731.3f},{ 1801.5f, 1701.4f, 1531.3f},{ 3602.9f, 3402.8f, 3062.5f}},
482 {{ 516.2f, 487.5f, 438.8f},{ 1032.4f, 975.0f, 877.5f},{ 2161.8f, 2041.7f, 1837.5f},{ 4323.5f, 4083.3f, 3675.0f}},
483 {{ 573.5f, 541.7f, 487.5f},{ 1147.1f, 1083.3f, 975.0f},{ 2402.0f, 2268.5f, 2041.7f},{ 4803.9f, 4537.0f, 4083.3f}},
484 {{ 645.2f, 609.4f, 548.4f},{ 1290.4f, 1218.8f, 1096.9f},{ 2702.2f, 2552.1f, 2296.9f},{ 5404.4f, 5104.2f, 4593.8f}},
485 {{ 716.9f, 677.1f, 609.4f},{ 1433.8f, 1354.2f, 1218.8f},{ 3002.5f, 2835.6f, 2552.1f},{ 6004.9f, 5671.3f, 5104.2f}}
486 },{
487 {{ 51.6f, 48.8f, 43.9f},{ 103.2f, 97.5f, 87.8f},{ 216.2f, 204.2f, 183.8f},{ 432.4f, 408.3f, 367.5f}},
488 {{ 103.2f, 97.5f, 87.8f},{ 206.5f, 195.0f, 175.5f},{ 432.4f, 408.3f, 367.5f},{ 864.7f, 816.7f, 735.0f}},
489 {{ 154.9f, 146.3f, 131.6f},{ 309.7f, 292.5f, 263.3f},{ 648.5f, 612.5f, 551.3f},{ 1297.1f, 1225.0f, 1102.5f}},
490 {{ 206.5f, 195.0f, 175.5f},{ 412.9f, 390.0f, 351.0f},{ 864.7f, 816.7f, 735.0f},{ 1729.4f, 1633.3f, 1470.0f}},
491 {{ 309.7f, 292.5f, 263.3f},{ 619.4f, 585.0f, 526.5f},{ 1297.1f, 1225.0f, 1102.5f},{ 2594.1f, 2450.0f, 2205.0f}},
492 {{ 412.9f, 390.0f, 351.0f},{ 825.9f, 780.0f, 702.0f},{ 1729.4f, 1633.3f, 1470.0f},{ 3458.8f, 3266.7f, 2940.0f}},
493 {{ 464.6f, 438.8f, 394.9f},{ 929.1f, 877.5f, 789.8f},{ 1945.6f, 1837.5f, 1653.8f},{ 3891.2f, 3675.0f, 3307.5f}},
494 {{ 516.2f, 487.5f, 438.8f},{ 1032.4f, 975.0f, 877.5f},{ 2161.8f, 2041.7f, 1837.5f},{ 4323.5f, 4083.3f, 3675.0f}},
495 {{ 619.4f, 585.0f, 526.5f},{ 1238.8f, 1170.0f, 1053.0f},{ 2594.1f, 2450.0f, 2205.0f},{ 5188.2f, 4900.0f, 4410.0f}},
496 {{ 688.2f, 650.0f, 585.0f},{ 1376.5f, 1300.0f, 1170.0f},{ 2882.4f, 2722.2f, 2450.0f},{ 5764.7f, 5444.4f, 4900.0f}},
497 {{ 774.3f, 731.3f, 658.1f},{ 1548.5f, 1462.5f, 1316.3f},{ 3242.6f, 3062.5f, 2756.3f},{ 6485.3f, 6125.0f, 5512.5f}},
498 {{ 860.3f, 812.5f, 731.3f},{ 1720.6f, 1625.0f, 1462.5f},{ 3602.9f, 3402.8f, 3062.5f},{ 7205.9f, 6805.6f, 6125.0f}}
499 },{
500 {{ 60.2f, 56.9f, 51.2f},{ 120.4f, 113.8f, 102.4f},{ 252.2f, 238.2f, 214.4f},{ 504.4f, 476.4f, 428.8f}},
501 {{ 120.4f, 113.8f, 102.4f},{ 240.9f, 227.5f, 204.8f},{ 504.4f, 476.4f, 428.8f},{ 1008.8f, 952.8f, 857.5f}},
502 {{ 180.7f, 170.6f, 153.6f},{ 361.3f, 341.3f, 307.1f},{ 756.6f, 714.6f, 643.1f},{ 1513.2f, 1429.2f, 1286.3f}},
503 {{ 240.9f, 227.5f, 204.8f},{ 481.8f, 455.0f, 409.5f},{ 1008.8f, 952.8f, 857.5f},{ 2017.6f, 1905.6f, 1715.0f}},
504 {{ 361.3f, 341.3f, 307.1f},{ 722.6f, 682.5f, 614.3f},{ 1513.2f, 1429.2f, 1286.3f},{ 3026.5f, 2858.3f, 2572.5f}},
505 {{ 481.8f, 455.0f, 409.5f},{ 963.5f, 910.0f, 819.0f},{ 2017.6f, 1905.6f, 1715.0f},{ 4035.3f, 3811.1f, 3430.0f}},
506 {{ 542.0f, 511.9f, 460.7f},{ 1084.0f, 1023.8f, 921.4f},{ 2269.9f, 2143.8f, 1929.4f},{ 4539.7f, 4287.5f, 3858.8f}},
507 {{ 602.2f, 568.8f, 511.9f},{ 1204.4f, 1137.5f, 1023.8f},{ 2522.1f, 2381.9f, 2143.8f},{ 5044.1f, 4763.9f, 4287.5f}},
508 {{ 722.6f, 682.5f, 614.3f},{ 1445.3f, 1365.0f, 1228.5f},{ 3026.5f, 2858.3f, 2572.5f},{ 6052.9f, 5716.7f, 5145.0f}},
509 {{ 802.9f, 758.3f, 682.5f},{ 1605.9f, 1516.7f, 1365.0f},{ 3362.7f, 3175.9f, 2858.3f},{ 6725.5f, 6351.9f, 5716.7f}},
510 {{ 903.3f, 853.1f, 767.8f},{ 1806.6f, 1706.3f, 1535.6f},{ 3783.1f, 3572.9f, 3215.6f},{ 7566.2f, 7145.8f, 6431.3f}},
511 {{ 1003.7f, 947.9f, 853.1f},{ 2007.4f, 1895.8f, 1706.3f},{ 4203.4f, 3969.9f, 3572.9f},{ 8406.9f, 7939.8f, 7145.8f}}
512 },{
513 {{ 68.8f, 65.0f, 58.5f},{ 137.6f, 130.0f, 117.0f},{ 288.2f, 272.2f, 245.0f},{ 576.5f, 544.4f, 490.0f}},
514 {{ 137.6f, 130.0f, 117.0f},{ 275.3f, 260.0f, 234.0f},{ 576.5f, 544.4f, 490.0f},{ 1152.9f, 1088.9f, 980.0f}},
515 {{ 206.5f, 195.0f, 175.5f},{ 412.9f, 390.0f, 351.0f},{ 864.7f, 816.7f, 735.0f},{ 1729.4f, 1633.3f, 1470.0f}},
516 {{ 275.3f, 260.0f, 234.0f},{ 550.6f, 520.0f, 468.0f},{ 1152.9f, 1088.9f, 980.0f},{ 2305.9f, 2177.8f, 1960.0f}},
517 {{ 412.9f, 390.0f, 351.0f},{ 825.9f, 780.0f, 702.0f},{ 1729.4f, 1633.3f, 1470.0f},{ 3458.8f, 3266.7f, 2940.0f}},
518 {{ 550.6f, 520.0f, 468.0f},{ 1101.2f, 1040.0f, 936.0f},{ 2305.9f, 2177.8f, 1960.0f},{ 4611.8f, 4355.6f, 3920.0f}},
519 {{ 619.4f, 585.0f, 526.5f},{ 1238.8f, 1170.0f, 1053.0f},{ 2594.1f, 2450.0f, 2205.0f},{ 5188.2f, 4900.0f, 4410.0f}},
520 {{ 688.2f, 650.0f, 585.0f},{ 1376.5f, 1300.0f, 1170.0f},{ 2882.4f, 2722.2f, 2450.0f},{ 5764.7f, 5444.4f, 4900.0f}},
521 {{ 825.9f, 780.0f, 702.0f},{ 1651.8f, 1560.0f, 1404.0f},{ 3458.8f, 3266.7f, 2940.0f},{ 6917.6f, 6533.3f, 5880.0f}},
522 {{ 917.6f, 866.7f, 780.0f},{ 1835.3f, 1733.3f, 1560.0f},{ 3843.1f, 3629.6f, 3266.7f},{ 7686.3f, 7259.3f, 6533.3f}},
523 {{ 1032.4f, 975.0f, 877.5f},{ 2064.7f, 1950.0f, 1755.0f},{ 4323.5f, 4083.3f, 3675.0f},{ 8647.1f, 8166.7f, 7350.0f}},
524 {{ 1147.1f, 1083.3f, 975.0f},{ 2294.1f, 2166.7f, 1950.0f},{ 4803.9f, 4537.0f, 4083.3f},{ 9607.8f, 9074.1f, 8166.7f}}
525 }
526};
527
528/*
529 * Calculates 802.11ax HE SU data rate corresponding to a given 802.11ax MCS index,
530 * bandwidth, and guard interval.
531 */
532static float ieee80211_he_ofdm_rate(unsigned nsts, unsigned mcs, unsigned bw, unsigned gi)
533{
534 float rate=0.0;
535 if ( ((nsts-1) < HE_MAX_NSTS8) && (mcs < HE_MAX_MCS12) && ( bw < HE_SU_MAX_BW4) && ( gi < HE_MAX_GI3 ) ) {
536 rate = he_ofdm_tab[nsts-1][mcs][bw][gi];
537 }
538 return rate;
539}
540
541
542/*
543 * HE MU OFDMA MCS rate table converted from http://mcsindex.com/
544 * indexed by (NSTS,MCS,RU,GI)
545 */
546#define HE_MU_MAX_RU6 6
547static float he_mu_ofdma_tab[HE_MAX_NSTS8][HE_MAX_MCS12][HE_MU_MAX_RU6][HE_MAX_GI3] = {
548 {
549 {{ 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}},
550 {{ 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}},
551 {{ 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}},
552 {{ 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}},
553 {{ 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}},
554 {{ 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}},
555 {{ 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}},
556 {{ 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}},
557 {{ 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}},
558 {{ 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}},
559 {{ 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}},
560 {{ 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}}
561 },{
562 {{ 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}},
563 {{ 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}},
564 {{ 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}},
565 {{ 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}},
566 {{ 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}},
567 {{ 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}},
568 {{ 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}},
569 {{ 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}},
570 {{ 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}},
571 {{ 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}},
572 {{ 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}},
573 {{ 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}}
574 },{
575 {{ 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}},
576 {{ 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}},
577 {{ 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}},
578 {{ 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}},
579 {{ 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}},
580 {{ 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}},
581 {{ 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}},
582 {{ 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}},
583 {{ 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}},
584 {{ 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}},
585 {{ 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}},
586 {{ 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}}
587 },{
588 {{ 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}},
589 {{ 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}},
590 {{ 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}},
591 {{ 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}},
592 {{ 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}},
593 {{ 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}},
594 {{ 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}},
595 {{ 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}},
596 {{ 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}},
597 {{ 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}},
598 {{ 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}},
599 {{ 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}}
600 },{
601 {{ 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}},
602 {{ 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}},
603 {{ 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}},
604 {{ 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}},
605 {{ 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}},
606 {{ 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}},
607 {{ 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}},
608 {{ 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}},
609 {{ 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}},
610 {{ 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}},
611 {{ 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}},
612 {{ 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}}
613 },{
614 {{ 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}},
615 {{ 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}},
616 {{ 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}},
617 {{ 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}},
618 {{ 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}},
619 {{ 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}},
620 {{ 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}},
621 {{ 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}},
622 {{ 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}},
623 {{ 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}},
624 {{ 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}},
625 {{ 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}}
626 },{
627 {{ 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}},
628 {{ 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}},
629 {{ 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}},
630 {{ 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}},
631 {{ 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}},
632 {{ 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}},
633 {{ 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}},
634 {{ 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}},
635 {{ 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}},
636 {{ 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}},
637 {{ 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}},
638 {{ 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}}
639 },{
640 {{ 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}},
641 {{ 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}},
642 {{ 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}},
643 {{ 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}},
644 {{ 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}},
645 {{ 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}},
646 {{ 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}},
647 {{ 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}},
648 {{ 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}},
649 {{ 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}},
650 {{ 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}},
651 {{ 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}}
652 }
653
654};
655
656/*
657 * Calculates 802.11ax HE SU data rate corresponding to a given 802.11ax MCS index,
658 * bandwidth, and guard interval.
659 */
660static float ieee80211_he_mu_ofdma_rate(unsigned nsts, unsigned mcs, unsigned ru, unsigned gi)
661{
662 float rate=0.0;
663 if ( ((nsts-1) < HE_MAX_NSTS8) && (mcs < HE_MAX_MCS12) && ( (ru-4) < HE_MU_MAX_RU6) && ( gi < HE_MAX_GI3 ) ) {
664 rate = he_mu_ofdma_tab[nsts-1][mcs][ru-4][gi];
665 }
666 return rate;
667}
668
669/*
670 * EHT MCS rate table converted from http://mcsindex.net
671 * indexed by (MCS,BW,GI)
672 * Covering only upto 4x996-tone-RU/320MHz, Additional RUs and Punctured modes not added yet.
673 * For higher # of spatial streams, the rate will be computed based on the 1SS rates below.
674 * The resultant error in rate computation remains within a maximum of +/- 0.5 Mbps from corresponding static table rates.
675 */
676#define EHT_MAX_NSTS8 8
677#define EHT_MAX_BW0x7 + 1 IEEE80211_RADIOTAP_EHT_RU_4_TIMES_9940x7 + 1
678#define EHT_MAX_GI3 3
679static float eht_mcs_tab[EHT_MAX_MCS16][EHT_MAX_BW0x7 + 1][EHT_MAX_GI3] = {
680 /* 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 */
681 {{ 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}},
682 {{ 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}},
683 {{ 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}},
684 {{ 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}},
685 {{ 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}},
686 {{ 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}},
687 {{ 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}},
688 {{ 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}},
689 {{ 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}},
690 {{ 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}},
691 {{ 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}},
692 {{ 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}},
693 {{ 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}},
694 {{ 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}},
695 {{ 0.0f, 0.0f, 0.0f},{ 0.0f, 0.0f, 0.0f},{ 0.0f, 0.0f, 0.0f},{ 0.0f, 0.0f, 0.0f},{ 0.0f, 0.0f, 0.0f},{ 8.6f, 8.1f, 7.3f},{ 18.0f, 17.0f, 15.3f},{ 36.0f, 34.0f, 30.6f}},
696 {{ 0.4f, 0.4f, 0.4f},{ 0.9f, 0.8f, 0.8f},{ 1.8f, 1.7f, 1.6f},{ 4.3f, 4.0f, 3.6f},{ 8.6f, 8.1f, 7.3f},{ 18.0f, 17.0f, 15.3f},{ 36.0f, 34.0f, 30.6f},{ 72.1f, 68.1f, 61.3f}}
697};
698
699
700/*
701 * Calculates 802.11be EHT data rate corresponding to a given 802.11be MCS index,
702 * ru-size/bandwidth, guard interval and number of spatial streams.
703 */
704static float ieee80211_eht_rate(unsigned nsts, unsigned mcs, unsigned bw, unsigned gi)
705{
706 float rate=0.0;
707 if ( ((nsts-1) < EHT_MAX_NSTS8) && (mcs < EHT_MAX_MCS16) && (bw < EHT_MAX_BW0x7 + 1) && (gi < EHT_MAX_GI3) ) {
708 rate = eht_mcs_tab[mcs][bw][gi] * nsts;
709 }
710 return rate;
711}
712
713static int ett_wlan_radio;
714static int ett_wlan_radio_11ac_user;
715static int ett_wlan_radio_duration;
716static int ett_wlan_radio_aggregate;
717static int ett_wlan_radio_11be_user;
718
719/* previous frame details, for aggregate detection */
720struct previous_frame_info {
721 bool_Bool has_tsf_timestamp;
722 uint64_t tsf_timestamp;
723 unsigned phy;
724 union ieee_802_11_phy_info phy_info;
725 unsigned prev_length;
726 struct wlan_radio *radio_info;
727};
728
729static struct previous_frame_info previous_frame;
730static struct aggregate *current_aggregate;
731static wmem_list_t *agg_tracker_list;
732
733static unsigned calculate_11n_duration(unsigned frame_length,
734 struct ieee_802_11n* info_n,
735 int stbc_streams)
736{
737 unsigned bits;
738 unsigned bits_per_symbol;
739 unsigned Mstbc;
740 unsigned symbols;
741
742 /* data field calculation */
743 if (1) {
744 /* see ieee80211n-2009 20.3.11 (20-32) - for BCC FEC */
745 bits = 8 * frame_length + 16 + ieee80211_ht_Nes[info_n->mcs_index] * 6;
746 Mstbc = stbc_streams ? 2 : 1;
747 bits_per_symbol = ieee80211_ht_Dbps[info_n->mcs_index] *
748 (info_n->bandwidth == PHDR_802_11_BANDWIDTH_40_MHZ1 ? 2 : 1);
749 symbols = bits / (bits_per_symbol * Mstbc);
750 } else {
751 /* TODO: handle LDPC FEC, it changes the rounding */
752 }
753 /* round up to whole symbols */
754 if ((bits % (bits_per_symbol * Mstbc)) > 0)
755 symbols++;
756
757 symbols *= Mstbc;
758 return (symbols * (info_n->short_gi ? 36 : 40) + 5) / 10;
759}
760
761/* TODO: this is a crude quick hack, need proper calculation of bits/symbols/FEC/etc */
762static unsigned calculate_11ac_duration(unsigned frame_length, float data_rate)
763{
764 unsigned bits = 8 * frame_length + 16;
765 return (unsigned) (bits / data_rate);
766}
767
768static void adjust_agg_tsf(void *data, void *user_data)
769{
770 struct wlan_radio *wlan_radio_info = (struct wlan_radio *)data;
771 uint64_t *ppdu_start = (uint64_t *)user_data;
772
773 wlan_radio_info->start_tsf += (*ppdu_start);
774 wlan_radio_info->end_tsf += (*ppdu_start);
775 if (wlan_radio_info->prior_aggregate_data == 0)
776 wlan_radio_info->ifs += (*ppdu_start);
777}
778
779/*
780 * Dissect 802.11 pseudo-header containing radio information.
781 */
782static void
783dissect_wlan_radio_phdr(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, struct ieee_802_11_phdr *phdr)
784{
785 proto_item *ti;
786 proto_tree *radio_tree;
787 float data_rate = 0.0f;
788 bool_Bool have_data_rate = false0;
789 bool_Bool has_short_preamble = false0;
790 bool_Bool short_preamble = true1;
791 unsigned bandwidth = 0;
792 bool_Bool can_calculate_rate = false0;
793 proto_item *p_item;
794
795 unsigned frame_length = tvb_reported_length(tvb); /* length of 802.11 frame data */
796
797 /* durations in microseconds */
798 unsigned preamble = 0, agg_preamble = 0; /* duration of plcp */
799 bool_Bool have_duration = false0;
800 unsigned duration = 0; /* duration of whole frame (plcp + mac data + any trailing parts) */
801 unsigned prior_duration = 0; /* duration of previous part of aggregate */
802
803 struct wlan_radio *wlan_radio_info;
804 int phy = phdr->phy;
805 union ieee_802_11_phy_info *phy_info = &phdr->phy_info;
806
807 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Radio");
808 col_clear(pinfo->cinfo, COL_INFO);
809
810 /* Calculate the data rate, if we have the necessary data */
811 if (phdr->has_data_rate) {
812 data_rate = phdr->data_rate * 0.5f;
813 have_data_rate = true1;
814 }
815
816 /* this is the first time we are looking at this frame during a
817 * capture dissection, so we know the dissection is done in
818 * frame order (subsequent dissections may be random access) */
819 if (!pinfo->fd->visited) {
820 wlan_radio_info = wmem_new0(wmem_file_scope(), struct wlan_radio)((struct wlan_radio*)wmem_alloc0((wmem_file_scope()), sizeof(
struct wlan_radio)))
;
821 p_add_proto_data(wmem_file_scope(), pinfo, proto_wlan_radio, 0, wlan_radio_info);
822
823 /* A-MPDU / aggregate detection
824 * Different generators need different detection algorithms
825 * One common pattern is to report all subframes in the aggregate with the same
826 * tsf, referenced to the start of the AMPDU (Broadcom). Another pattern is to
827 * report the tsf on the first subframe, then tsf=0 for the rest of the subframes
828 * (Intel).
829 * Another pattern is to report TSF = -1 for all frames but the last, and the
830 * last has the tsf referenced to the end of the PPDU. (QCA)
831 */
832 /* TODO: add code to work around problem with captures from Macbooks where
833 * aggregate subframes frames with FCS errors sometimes have incorrect
834 * PHY information.
835 */
836 if (pinfo->fd->num > 1 &&
837 (phdr->phy == PHDR_802_11_PHY_11N7 || phdr->phy == PHDR_802_11_PHY_11AC8) &&
838 phdr->phy == previous_frame.phy &&
839 phdr->has_tsf_timestamp && previous_frame.has_tsf_timestamp &&
840 (phdr->tsf_timestamp == previous_frame.tsf_timestamp || /* find matching TSFs */
841 (!current_aggregate && previous_frame.tsf_timestamp && phdr->tsf_timestamp == 0) || /* Intel detect second frame */
842 (previous_frame.tsf_timestamp == UINT64_MAX(18446744073709551615UL)) /* QCA, detect last frame */
843 )) {
844 /* we're in an aggregate */
845 if (!current_aggregate) {
846 /* this is the second frame in an aggregate
847 * where we first detect the aggregate */
848 current_aggregate = wmem_new0(wmem_file_scope(), struct aggregate)((struct aggregate*)wmem_alloc0((wmem_file_scope()), sizeof(struct
aggregate)))
;
849 current_aggregate->phy = previous_frame.phy;
850 current_aggregate->phy_info = previous_frame.phy_info;
851
852 /* go back to the first frame in the aggregate,
853 * and mark it as part of this aggregate */
854 if (previous_frame.radio_info != NULL((void*)0))
855 previous_frame.radio_info->aggregate = current_aggregate;
856 }
857 wlan_radio_info->aggregate = current_aggregate;
858
859 /* accumulate the length of the prior subframes in the aggregate.
860 * Round up previous frame length (padding) */
861 if (previous_frame.prev_length % 4 != 0) {
862 previous_frame.prev_length = (previous_frame.prev_length | 3) + 1;
863 }
864 /* Also add the MPDU delimiter length */
865 previous_frame.prev_length += 4;
866 /* TODO: add padding to meet minimum subframe timing constraint */
867 wlan_radio_info->prior_aggregate_data = previous_frame.prev_length;
868 previous_frame.prev_length += frame_length;
869
870 /* work around macbook/QCA FCS error frame PHY rate bug here
871 * Some Macbook generators and some QCA generators erroneously report
872 * low PHY rates for some subframes within an aggregate that have FCS errors.
873 * All subframes must have the same PHY rate.
874 * Here we take the highest reported rate for the aggregate. */
875 switch (phdr->phy) {
876 case PHDR_802_11_PHY_11N7:
877 {
878 struct ieee_802_11n *info_n = &phy_info->info_11n;
879 struct ieee_802_11n *agg_info_n = &current_aggregate->phy_info.info_11n;
880
881 if (info_n->has_mcs_index && agg_info_n->has_mcs_index &&
882 info_n->mcs_index > agg_info_n->mcs_index)
883 current_aggregate->phy_info = *phy_info;
884 }
885 break;
886
887 case PHDR_802_11_PHY_11AC8:
888 {
889 struct ieee_802_11ac *info_ac = &phy_info->info_11ac;
890 struct ieee_802_11ac *agg_info_ac = &current_aggregate->phy_info.info_11ac;
891
892 if (info_ac->mcs[0] > agg_info_ac->mcs[0])
893 current_aggregate->phy_info = *phy_info;
894 }
895 break;
896 }
897 /* TODO record a warning if the PHY rate does not match the aggregate */
898 phy = current_aggregate->phy;
899 phy_info = &current_aggregate->phy_info;
900 } else {
901 current_aggregate = NULL((void*)0);
902 previous_frame.prev_length = frame_length;
903 }
904 previous_frame.has_tsf_timestamp = phdr->has_tsf_timestamp;
905 previous_frame.tsf_timestamp = phdr->tsf_timestamp;
906 previous_frame.phy = phdr->phy;
907 previous_frame.phy_info = phdr->phy_info;
908 } else {
909 /* this frame has already been seen, so get its info structure */
910 wlan_radio_info = (struct wlan_radio *) p_get_proto_data(wmem_file_scope(), pinfo, proto_wlan_radio, 0);
911
912 if (wlan_radio_info && wlan_radio_info->aggregate) {
913 phy = wlan_radio_info->aggregate->phy;
914 phy_info = &wlan_radio_info->aggregate->phy_info;
915 }
916 }
917
918 ti = proto_tree_add_item(tree, proto_wlan_radio, tvb, 0, 0, ENC_NA0x00000000);
919 radio_tree = proto_item_add_subtree (ti, ett_wlan_radio);
920
921 if (phy != PHDR_802_11_PHY_UNKNOWN0) {
922 proto_tree_add_uint(radio_tree, hf_wlan_radio_phy, tvb, 0, 0, phy);
923
924 switch (phy) {
925
926 case PHDR_802_11_PHY_11_FHSS1:
927 {
928 struct ieee_802_11_fhss *info_fhss = &phy_info->info_11_fhss;
929
930 if (info_fhss->has_hop_set) {
931 proto_tree_add_uint(radio_tree, hf_wlan_radio_11_fhss_hop_set, tvb, 0, 0,
932 info_fhss->hop_set);
933 }
934 if (info_fhss->has_hop_pattern) {
935 proto_tree_add_uint(radio_tree, hf_wlan_radio_11_fhss_hop_pattern, tvb, 0, 0,
936 info_fhss->hop_pattern);
937 }
938 if (info_fhss->has_hop_index) {
939 proto_tree_add_uint(radio_tree, hf_wlan_radio_11_fhss_hop_index, tvb, 0, 0,
940 info_fhss->hop_index);
941 }
942 break;
943 }
944
945 case PHDR_802_11_PHY_11B4:
946 {
947 struct ieee_802_11b *info_b = &phy_info->info_11b;
948
949 has_short_preamble = info_b->has_short_preamble;
950
951 if (has_short_preamble) {
952 short_preamble = info_b->short_preamble;
953 proto_tree_add_boolean(radio_tree, hf_wlan_radio_short_preamble, tvb, 0, 0,
954 short_preamble);
955 }
956 break;
957 }
958
959 case PHDR_802_11_PHY_11A5:
960 {
961 struct ieee_802_11a *info_a = &phy_info->info_11a;
962
963 if (info_a->has_channel_type) {
964 proto_tree_add_uint(radio_tree, hf_wlan_radio_11a_channel_type, tvb, 0, 0,
965 info_a->channel_type);
966 }
967 if (info_a->has_turbo_type) {
968 proto_tree_add_uint(radio_tree, hf_wlan_radio_11a_turbo_type, tvb, 0, 0,
969 info_a->turbo_type);
970 }
971 break;
972 }
973
974 case PHDR_802_11_PHY_11G6:
975 {
976 struct ieee_802_11g *info_g = &phy_info->info_11g;
977
978 if (info_g->has_mode) {
979 proto_tree_add_uint(radio_tree, hf_wlan_radio_11g_mode, tvb, 0, 0,
980 info_g->mode);
981 }
982 break;
983 }
984
985 case PHDR_802_11_PHY_11N7:
986 {
987 struct ieee_802_11n *info_n = &phy_info->info_11n;
988 unsigned bandwidth_40;
989
990 /*
991 * If we have all the fields needed to look up the data rate,
992 * do so.
993 */
994 if (info_n->has_mcs_index &&
995 info_n->has_bandwidth &&
996 info_n->has_short_gi) {
997 bandwidth_40 = (info_n->bandwidth == PHDR_802_11_BANDWIDTH_40_MHZ1) ? 1 : 0;
998 if (info_n->mcs_index < MAX_MCS_INDEX76) {
999 data_rate = ieee80211_htrate(info_n->mcs_index, bandwidth_40, info_n->short_gi);
1000 have_data_rate = true1;
1001 }
1002 }
1003
1004 if (info_n->has_mcs_index) {
1005 proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_mcs_index, tvb, 0, 0,
1006 info_n->mcs_index);
1007 }
1008
1009 if (info_n->has_bandwidth) {
1010 proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_bandwidth, tvb, 0, 0,
1011 info_n->bandwidth);
1012 }
1013
1014 if (info_n->has_short_gi) {
1015 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11n_short_gi, tvb, 0, 0,
1016 info_n->short_gi);
1017 }
1018
1019 if (info_n->has_greenfield) {
1020 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11n_greenfield, tvb, 0, 0,
1021 info_n->greenfield);
1022 }
1023
1024 if (info_n->has_fec) {
1025 proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_fec, tvb, 0, 0,
1026 info_n->fec);
1027 }
1028
1029 if (info_n->has_stbc_streams) {
1030 proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_stbc_streams, tvb, 0, 0,
1031 info_n->stbc_streams);
1032 }
1033
1034 if (info_n->has_ness) {
1035 proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_ness, tvb, 0, 0,
1036 info_n->ness);
1037 }
1038 }
1039 break;
1040
1041 case PHDR_802_11_PHY_11AC8:
1042 {
1043 struct ieee_802_11ac *info_ac = &phy_info->info_11ac;
1044 unsigned i;
1045
1046 if (info_ac->has_short_gi) {
1047 can_calculate_rate = true1; /* well, if we also have the bandwidth */
1048 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_short_gi, tvb, 0, 0, info_ac->short_gi);
1049 } else {
1050 can_calculate_rate = false0; /* unknown GI length */
1051 }
1052
1053 if (info_ac->has_bandwidth) {
1054 proto_tree_add_uint(radio_tree, hf_wlan_radio_11ac_bandwidth, tvb, 0, 0, info_ac->bandwidth);
1055 if (info_ac->bandwidth < G_N_ELEMENTS(ieee80211_vht_bw2rate_index)(sizeof (ieee80211_vht_bw2rate_index) / sizeof ((ieee80211_vht_bw2rate_index
)[0]))
)
1056 bandwidth = ieee80211_vht_bw2rate_index[info_ac->bandwidth];
1057 else
1058 can_calculate_rate = false0; /* unknown bandwidth */
1059 } else {
1060 can_calculate_rate = false0; /* no bandwidth */
1061 }
1062
1063 if (info_ac->has_stbc) {
1064 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_stbc, tvb, 0, 0,
1065 info_ac->stbc);
1066 }
1067
1068 if (info_ac->has_txop_ps_not_allowed) {
1069 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_txop_ps_not_allowed, tvb, 0, 0,
1070 info_ac->txop_ps_not_allowed);
1071 }
1072
1073 if (info_ac->has_short_gi_nsym_disambig) {
1074 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_short_gi_nsym_disambig, tvb, 0, 0,
1075 info_ac->short_gi_nsym_disambig);
1076 }
1077
1078 if (info_ac->has_ldpc_extra_ofdm_symbol) {
1079 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_ldpc_extra_ofdm_symbol, tvb, 0, 0,
1080 info_ac->ldpc_extra_ofdm_symbol);
1081 }
1082
1083 if (info_ac->has_beamformed) {
1084 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_beamformed, tvb, 0, 0,
1085 info_ac->beamformed);
1086 }
1087
1088 for (i = 0; i < 4; i++) {
1089
1090 if (info_ac->nss[i] != 0) {
1091 proto_item *it;
1092 proto_tree *user_tree;
1093
1094 it = proto_tree_add_item(radio_tree, hf_wlan_radio_11ac_user, tvb, 0, 0, ENC_NA0x00000000);
1095 proto_item_append_text(it, " %d: MCS %u", i, info_ac->mcs[i]);
1096 user_tree = proto_item_add_subtree(it, ett_wlan_radio_11ac_user);
1097
1098 it = proto_tree_add_uint(user_tree, hf_wlan_radio_11ac_mcs, tvb, 0, 0,
1099 info_ac->mcs[i]);
1100 if (info_ac->mcs[i] > MAX_MCS_VHT_INDEX9) {
1101 proto_item_append_text(it, " (invalid)");
1102 } else {
1103 proto_item_append_text(it, " (%s %s)",
1104 ieee80211_mcsinfo[info_ac->mcs[i]].modulation,
1105 ieee80211_mcsinfo[info_ac->mcs[i]].coding_rate);
1106 }
1107
1108 proto_tree_add_uint(user_tree, hf_wlan_radio_11ac_nss, tvb, 0, 0, info_ac->nss[i]);
1109 /*
1110 * If we don't know whether space-time block coding is being
1111 * used, we don't know the number of space-time streams.
1112 */
1113 if (info_ac->has_stbc) {
1114 unsigned nsts;
1115
1116 if (info_ac->stbc)
1117 nsts = 2 * info_ac->nss[i];
1118 else
1119 nsts = info_ac->nss[i];
1120 proto_tree_add_uint(user_tree, hf_wlan_radio_11ac_nsts, tvb, 0, 0,
1121 nsts);
1122 }
1123 if (info_ac->has_fec) {
1124 proto_tree_add_uint(user_tree, hf_wlan_radio_11ac_fec, tvb, 0, 0,
1125 (info_ac->fec >> i) & 0x01);
1126 }
1127
1128 /*
1129 * If we can calculate the data rate for this user, do so.
1130 */
1131 if (can_calculate_rate && info_ac->mcs[i] <= MAX_MCS_VHT_INDEX9 &&
1132 info_ac->nss[i] <= MAX_VHT_NSS8 &&
1133 ieee80211_vhtvalid[info_ac->mcs[i]].valid[bandwidth][info_ac->nss[i]-1]) {
1134 data_rate = ieee80211_vhtrate(info_ac->mcs[i], bandwidth, info_ac->short_gi) * info_ac->nss[i];
1135 if (data_rate != 0.0f) {
1136 have_data_rate = true1;
1137 }
1138 }
1139 }
1140 }
1141
1142 if (info_ac->has_group_id) {
1143 proto_tree_add_uint(radio_tree, hf_wlan_radio_11ac_gid, tvb, 0, 0, info_ac->group_id);
1144 }
1145
1146 if (info_ac->has_partial_aid) {
1147 proto_tree_add_uint(radio_tree, hf_wlan_radio_11ac_p_aid, tvb, 0, 0, info_ac->partial_aid);
1148 }
1149 }
1150 break;
1151 case PHDR_802_11_PHY_11AX11:
1152 {
1153 struct ieee_802_11ax *info_ax = &phy_info->info_11ax;
1154 if (info_ax->has_gi && info_ax->has_bwru && info_ax->has_mcs_index) {
1155 if (info_ax->bwru < HE_SU_MAX_BW4) {
1156 data_rate = ieee80211_he_ofdm_rate(info_ax->nsts,info_ax->mcs,info_ax->bwru,info_ax->gi);
1157 } else {
1158 data_rate = ieee80211_he_mu_ofdma_rate(info_ax->nsts,info_ax->mcs,info_ax->bwru,info_ax->gi);
1159 }
1160 if (data_rate != 0.0f) {
1161 have_data_rate = true1;
1162 }
1163 }
1164 if (info_ax->has_gi) {
1165 proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ax_short_gi, tvb, 0, 0, info_ax->gi);
1166 }
1167
1168 if (info_ax->has_bwru) {
1169 proto_tree_add_uint(radio_tree, hf_wlan_radio_11ax_bandwidth, tvb, 0, 0, info_ax->bwru);
1170 if (info_ax->bwru < G_N_ELEMENTS(ieee80211_vht_bw2rate_index)(sizeof (ieee80211_vht_bw2rate_index) / sizeof ((ieee80211_vht_bw2rate_index
)[0]))
)
1171 bandwidth = ieee80211_vht_bw2rate_index[info_ax->bwru];
Value stored to 'bandwidth' is never read
1172 }
1173
1174 if (info_ax->has_mcs_index) {
1175 proto_tree_add_uint(radio_tree, hf_wlan_radio_11ax_mcs, tvb, 0, 0, info_ax->mcs);
1176 }
1177 }
1178 break;
1179 case PHDR_802_11_PHY_11BE12:
1180 {
1181 struct ieee_802_11be *info_11be = &phy_info->info_11be;
1182 int i;
1183 can_calculate_rate = true1;
1184 /*for each user*/
1185 for (i = 0; i < info_11be->num_users; i++) {
1186 if (i >= PHDR_802_11BE_MAX_USERS4) {
1187 expert_add_info(pinfo, radio_tree, &ei_wlan_radio_11be_num_users);
1188 break;
1189 }
1190 unsigned nsts = info_11be->user[i].nsts;
1191 unsigned bw_idx = 0;
1192 /* Do we have all the fields needed to compute rate ?*/
1193 if (!info_11be->has_gi || !info_11be->user[i].nsts_known || !nsts)
1194 {
1195 can_calculate_rate = false0;
1196 }
1197 if (!info_11be->has_bandwidth && (!info_11be->has_ru_mru_size ||
1198 info_11be->ru_mru_size > IEEE80211_RADIOTAP_EHT_RU_4_TIMES_9940x7)) {
1199 can_calculate_rate = false0;
1200 }
1201
1202 if (info_11be->has_bandwidth) {
1203 /* 20,40,80,160 and 320MHz overlap with mcs table index for ru-242 and above.
1204 * So add the offset.
1205 * Punctured modes not considered yet. */
1206 if (info_11be->bandwidth == IEEE80211_RADIOTAP_USIG_BW_320_20x5) {
1207 /* The overlap works for 320MHz-1 but not for 320MHz-2. As the workaround,
1208 * use the same index for 320MHz-1 and 320MHz-2 */
1209 bw_idx = IEEE80211_RADIOTAP_USIG_BW_320_10x4 + IEEE80211_RADIOTAP_EHT_RU_2420x3;
1210 } else {
1211 bw_idx = info_11be->bandwidth + IEEE80211_RADIOTAP_EHT_RU_2420x3;
1212 }
1213 } else {
1214 bw_idx = info_11be->ru_mru_size;
1215 }
1216
1217 /* Handle specificities of MCS 14 & 15 */
1218 if (nsts != 1 && (info_11be->user[i].mcs == 14 ||
1219 info_11be->user[i].mcs == 15)) {
1220 can_calculate_rate = false0;
1221 }
1222
1223 proto_item *it;
1224 proto_tree *user_tree;
1225
1226 it = proto_tree_add_item(radio_tree, hf_wlan_radio_11be_user, tvb, 0, 0, ENC_NA0x00000000);
1227 proto_item_append_text(it, " %d: MCS %u", i, info_11be->user[i].mcs);
1228 user_tree = proto_item_add_subtree(it, ett_wlan_radio_11be_user);
1229
1230 it = proto_tree_add_uint(user_tree, hf_wlan_radio_11be_mcs, tvb, 0, 0,
1231 info_11be->user[i].mcs);
1232 if (info_11be->user[i].mcs >= EHT_MAX_MCS16) {
1233 proto_item_append_text(it, " (invalid)");
1234 } else {
1235 proto_item_append_text(it, " (%s %s)",
1236 ieee80211_mcsinfo[info_11be->user[i].mcs].modulation,
1237 ieee80211_mcsinfo[info_11be->user[i].mcs].coding_rate);
1238 }
1239
1240 proto_tree_add_uint(user_tree, hf_wlan_radio_11be_nsts, tvb, 0, 0, nsts);
1241
1242 /*
1243 * If we can calculate the data rate for this user, do so.
1244 */
1245 if (can_calculate_rate && info_11be->user[i].mcs < EHT_MAX_MCS16 &&
1246 nsts < EHT_MAX_NSTS8) {
1247 data_rate = ieee80211_eht_rate(nsts, info_11be->user[i].mcs, bw_idx, info_11be->gi);
1248 if (data_rate != 0.0f) {
1249 //have_data_rate = true;
1250 proto_tree_add_float_format_value(user_tree, hf_wlan_radio_data_rate, tvb, 0, 0,
1251 data_rate,
1252 "%.1f Mb/s",
1253 data_rate);
1254 }
1255 }
1256 } // for (i = 0; i < info_11be->num_users; i++)
1257 } // case PHDR_802_11_PHY_11BE:
1258 break;
1259 }
1260 }
1261
1262 if (have_data_rate) {
1263 col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%.1f", data_rate);
1264 proto_tree_add_float_format_value(radio_tree, hf_wlan_radio_data_rate, tvb, 0, 0,
1265 data_rate,
1266 "%.1f Mb/s",
1267 data_rate);
1268 }
1269
1270 if (phdr->has_channel) {
1271 col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u", phdr->channel);
1272 proto_tree_add_uint(radio_tree, hf_wlan_radio_channel, tvb, 0, 0, phdr->channel);
1273 }
1274
1275 if (phdr->has_frequency) {
1276 col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u MHz", phdr->frequency);
1277 proto_tree_add_uint(radio_tree, hf_wlan_radio_frequency, tvb, 0, 0, phdr->frequency);
1278 }
1279
1280 if (phdr->has_signal_percent) {
1281 col_add_fstr(pinfo->cinfo, COL_RSSI, "%u%%", phdr->signal_percent);
1282 proto_tree_add_uint(radio_tree, hf_wlan_radio_signal_percent, tvb, 0, 0, phdr->signal_percent);
1283 }
1284
1285 if (phdr->has_signal_db) {
1286 col_add_fstr(pinfo->cinfo, COL_RSSI, "%u dB", phdr->signal_db);
1287 proto_tree_add_uint(radio_tree, hf_wlan_radio_signal_db, tvb, 0, 0, phdr->signal_db);
1288 }
1289
1290 if (phdr->has_signal_dbm) {
1291 col_add_fstr(pinfo->cinfo, COL_RSSI, "%d dBm", phdr->signal_dbm);
1292 proto_tree_add_int(radio_tree, hf_wlan_radio_signal_dbm, tvb, 0, 0, phdr->signal_dbm);
1293 }
1294
1295 if (phdr->has_noise_percent) {
1296 proto_tree_add_uint(radio_tree, hf_wlan_radio_noise_percent, tvb, 0, 0, phdr->noise_percent);
1297 }
1298
1299 if (phdr->has_noise_db) {
1300 proto_tree_add_uint(radio_tree, hf_wlan_radio_noise_db, tvb, 0, 0, phdr->noise_db);
1301 }
1302
1303 if (phdr->has_noise_dbm) {
1304 proto_tree_add_int(radio_tree, hf_wlan_radio_noise_dbm, tvb, 0, 0, phdr->noise_dbm);
1305 }
1306
1307 if (phdr->has_signal_dbm && phdr->has_noise_dbm) {
1308 proto_tree_add_int(radio_tree, hf_wlan_radio_snr, tvb, 0, 0, phdr->signal_dbm - phdr->noise_dbm);
1309 }
1310 /*
1311 * XXX - are the signal and noise in dB from a fixed reference point
1312 * guaranteed to use the *same* fixed reference point? If so, we could
1313 * calculate the SNR if they're both present, too.
1314 */
1315
1316 if (phdr->has_tsf_timestamp) {
1317 proto_tree_add_uint64(radio_tree, hf_wlan_radio_timestamp, tvb, 0, 0, phdr->tsf_timestamp);
1318 }
1319 if (phdr->has_aggregate_info) {
1320 proto_tree_add_boolean(radio_tree, hf_wlan_last_part_of_a_mpdu, tvb, 0, 0, phdr->aggregate_flags);
1321 proto_tree_add_boolean(radio_tree, hf_wlan_a_mpdu_delim_crc_error, tvb, 0, 0, phdr->aggregate_flags);
1322 proto_tree_add_uint(radio_tree, hf_wlan_a_mpdu_aggregate_id, tvb, 0, 0, phdr->aggregate_id);
1323 }
1324
1325 /* make sure frame_length includes the FCS for accurate duration calculation */
1326 if (pinfo->pseudo_header->ieee_802_11.fcs_len == 0) {
1327 frame_length += 4;
1328 }
1329
1330 if (have_data_rate && data_rate > 0) {
1331 /* duration calculations */
1332 bool_Bool assumed_short_preamble = false0;
1333 bool_Bool assumed_non_greenfield = false0;
1334 bool_Bool assumed_no_stbc = false0;
1335 bool_Bool assumed_no_extension_streams = false0;
1336 bool_Bool assumed_bcc_fec = false0;
1337
1338 /* some generators report CCK frames as 'dynamic-cck-ofdm', which are converted
1339 * into the 11g PHY type, so we need to be smart and recognize which ones are
1340 * DSSS/CCK and which are OFDM. Use the data_rate to do this. */
1341 if (phy == PHDR_802_11_PHY_11G6 &&
1342 (data_rate == 1.0f || data_rate == 2.0f ||
1343 data_rate == 5.5f || data_rate == 11.0f ||
1344 data_rate == 22.0f || data_rate == 33.0f)) {
1345 phy = PHDR_802_11_PHY_11B4;
1346 } else if (phy == PHDR_802_11_PHY_UNKNOWN0 &&
1347 (data_rate == 1.0f || data_rate == 2.0f ||
1348 data_rate == 5.5f || data_rate == 11.0f ||
1349 data_rate == 22.0f || data_rate == 33.0f)) {
1350 phy = PHDR_802_11_PHY_11B4;
1351 } else if (phy == PHDR_802_11_PHY_UNKNOWN0 &&
1352 (data_rate == 6.0f || data_rate == 9.0f ||
1353 data_rate == 12.0f || data_rate == 18.0f ||
1354 data_rate == 24.0f || data_rate == 36.0f ||
1355 data_rate == 48.0f || data_rate == 54.0f)) {
1356 phy = PHDR_802_11_PHY_11A5;
1357 }
1358 switch (phy) {
1359
1360 case PHDR_802_11_PHY_11_FHSS1:
1361 /* TODO: preamble/duration calc for FHSS */
1362 break;
1363
1364 case PHDR_802_11_PHY_11B4:
1365 if (!has_short_preamble || wlan_radio_always_short_preamble) {
1366 assumed_short_preamble = true1;
1367 short_preamble = true1;
1368 }
1369 preamble = short_preamble ? 72 + 24 : 144 + 48;
1370
1371 /* calculation of frame duration
1372 * Things we need to know to calculate accurate duration
1373 * 802.11 / 802.11b (DSSS or CCK modulation)
1374 * - length of preamble
1375 * - rate
1376 */
1377 /* round up to whole microseconds */
1378 have_duration = true1;
1379 duration = (unsigned) ceil(preamble + frame_length * 8 / data_rate);
1380 break;
1381
1382 case PHDR_802_11_PHY_11A5:
1383 case PHDR_802_11_PHY_11G6:
1384 {
1385 /* OFDM rate */
1386 /* calculation of frame duration
1387 * Things we need to know to calculate accurate duration
1388 * 802.11a / 802.11g (OFDM modulation)
1389 * - rate
1390 */
1391
1392 /* preamble + signal */
1393 preamble = 16 + 4;
1394
1395 /* 16 service bits, data and 6 tail bits */
1396 unsigned bits = 16 + 8 * frame_length + 6;
1397 unsigned symbols = (unsigned) ceil(bits / (data_rate * 4));
1398
1399 have_duration = true1;
1400 duration = preamble + symbols * 4;
1401 break;
1402 }
1403
1404 case PHDR_802_11_PHY_11N7:
1405 {
1406 struct ieee_802_11n *info_n = &phy_info->info_11n;
1407
1408 /* We have all the fields required to calculate the duration */
1409 static const unsigned Nhtdltf[4] = {1, 2, 4, 4};
1410 static const unsigned Nhteltf[4] = {0, 1, 2, 4};
1411 unsigned Nsts;
1412 unsigned stbc_streams;
1413 unsigned ness;
1414
1415 /*
1416 * If we don't have necessary fields, or if we have them but
1417 * they have invalid values, then bail.
1418 */
1419 if (!info_n->has_mcs_index ||
1420 info_n->mcs_index > MAX_MCS_INDEX76 ||
1421 !info_n->has_bandwidth ||
1422 !info_n->has_short_gi)
1423 break;
1424
1425 /* calculation of frame duration
1426 * Things we need to know to calculate accurate duration
1427 * 802.11n / HT
1428 * - whether frame preamble is mixed or greenfield, (assume mixed)
1429 * - guard interval, 800ns or 400ns
1430 * - bandwidth, 20Mhz or 40Mhz
1431 * - MCS index - used with previous 2 to calculate rate
1432 * - how many additional STBC streams are used (assume 0)
1433 * - how many optional extension spatial streams are used (assume 0)
1434 * - whether BCC or LDCP coding is used (assume BCC)
1435 */
1436
1437 /* preamble duration
1438 * see ieee802.11n-2009 Figure 20-1 - PPDU format
1439 * for HT-mixed format
1440 * L-STF 8us, L-LTF 8us, L-SIG 4us, HT-SIG 8us, HT_STF 4us
1441 * for HT-greenfield
1442 * HT-GF-STF 8us, HT-LTF1 8us, HT_SIG 8us
1443 */
1444 if (info_n->has_greenfield) {
1445 preamble = info_n->greenfield ? 24 : 32;
1446 } else {
1447 preamble = 32;
1448 assumed_non_greenfield = true1;
1449 }
1450
1451 if (info_n->has_stbc_streams) {
1452 stbc_streams = info_n->stbc_streams;
1453 } else {
1454 stbc_streams = 0;
1455 assumed_no_stbc = true1;
1456 }
1457
1458 if (info_n->has_ness) {
1459 ness = info_n->ness;
1460 if (ness >= G_N_ELEMENTS(Nhteltf)(sizeof (Nhteltf) / sizeof ((Nhteltf)[0]))) {
1461 /* Not valid */
1462 break;
1463 }
1464 } else {
1465 ness = 0;
1466 assumed_no_extension_streams = true1;
1467 }
1468
1469 /* calculate number of HT-LTF training symbols.
1470 * see ieee80211n-2009 20.3.9.4.6 table 20-11 */
1471 Nsts = ieee80211_ht_streams[info_n->mcs_index] + stbc_streams;
1472 if (Nsts == 0 || Nsts - 1 >= G_N_ELEMENTS(Nhtdltf)(sizeof (Nhtdltf) / sizeof ((Nhtdltf)[0]))) {
1473 /* Not usable */
1474 break;
1475 }
1476 preamble += 4 * (Nhtdltf[Nsts-1] + Nhteltf[ness]);
1477
1478 if (info_n->has_stbc_streams) {
1479 stbc_streams = info_n->stbc_streams;
1480 } else {
1481 stbc_streams = 0;
1482 assumed_no_stbc = true1;
1483 }
1484
1485 if (!info_n->has_ness) {
1486 assumed_no_extension_streams = true1;
1487 }
1488
1489 if (!info_n->has_fec) {
1490 assumed_bcc_fec = true1;
1491 }
1492
1493 /* data field calculation */
1494 if (wlan_radio_info && wlan_radio_info->aggregate) {
1495 agg_preamble = preamble;
1496 if (wlan_radio_info->prior_aggregate_data != 0) {
1497 preamble = 0;
1498 }
1499 prior_duration = calculate_11n_duration(wlan_radio_info->prior_aggregate_data, info_n, stbc_streams);
1500 have_duration = true1;
1501 duration = preamble +
1502 calculate_11n_duration(frame_length + wlan_radio_info->prior_aggregate_data, info_n, stbc_streams)
1503 - prior_duration;
1504 } else {
1505 have_duration = true1;
1506 duration = preamble + calculate_11n_duration(frame_length, info_n, stbc_streams);
1507 }
1508 break;
1509 }
1510
1511 case PHDR_802_11_PHY_11AC8:
1512 {
1513 struct ieee_802_11ac *info_ac = &phy_info->info_11ac;
1514
1515 if (!info_ac->has_stbc) {
1516 assumed_no_stbc = true1;
1517 }
1518 preamble = 32 + 4 * info_ac->nss[0] * (info_ac->has_stbc ? info_ac->stbc+1 : 1);
1519
1520 if (wlan_radio_info && wlan_radio_info->aggregate) {
1521 agg_preamble = preamble;
1522 if (wlan_radio_info->prior_aggregate_data != 0) {
1523 preamble = 0;
1524 }
1525 prior_duration = calculate_11ac_duration(wlan_radio_info->prior_aggregate_data, data_rate);
1526 have_duration = true1;
1527 duration = preamble +
1528 calculate_11ac_duration(wlan_radio_info->prior_aggregate_data + frame_length, data_rate)
1529 - prior_duration;
1530 } else {
1531 have_duration = true1;
1532 duration = preamble + calculate_11ac_duration(frame_length, data_rate);
1533 }
1534 break;
1535 }
1536 }
1537
1538 if (!pinfo->fd->visited && have_duration && phdr->has_tsf_timestamp) {
1539 if (current_aggregate) {
1540 current_aggregate->duration = agg_preamble + prior_duration + duration;
1541 if (previous_frame.radio_info && previous_frame.radio_info->aggregate == current_aggregate)
1542 previous_frame.radio_info->nav = 0; // don't display NAV except for last frame in an aggregate
1543 }
1544 if (phdr->tsf_timestamp == UINT64_MAX(18446744073709551615UL)) {
1545 /* QCA aggregate, we don't know tsf yet */
1546 wlan_radio_info->start_tsf = prior_duration + (current_aggregate ? agg_preamble : 0);
1547 wlan_radio_info->end_tsf = prior_duration + duration + (current_aggregate ? agg_preamble : 0);
1548 if (agg_tracker_list == NULL((void*)0)) {
1549 agg_tracker_list = wmem_list_new(NULL((void*)0));
1550 }
1551 wmem_list_append(agg_tracker_list, wlan_radio_info);
1552 } else if (current_aggregate && wlan_radio_tsf_at_end && phdr->tsf_timestamp != UINT64_MAX(18446744073709551615UL)) {
1553 /* QCA aggregate, last frame */
1554 wlan_radio_info->start_tsf = phdr->tsf_timestamp - duration;
1555 wlan_radio_info->end_tsf = phdr->tsf_timestamp;
1556 /* fix up the tsfs for the prior MPDUs */
1557 if (agg_tracker_list != NULL((void*)0)) {
1558 uint64_t ppdu_start = phdr->tsf_timestamp - (prior_duration + duration + agg_preamble);
1559 wmem_list_foreach(agg_tracker_list, adjust_agg_tsf, &ppdu_start);
1560 wmem_destroy_list(agg_tracker_list);
1561 agg_tracker_list = NULL((void*)0);
1562 };
1563 } else if (wlan_radio_tsf_at_end) {
1564 wlan_radio_info->start_tsf = phdr->tsf_timestamp - duration;
1565 wlan_radio_info->end_tsf = phdr->tsf_timestamp;
1566 } else {
1567 wlan_radio_info->start_tsf = phdr->tsf_timestamp + prior_duration - preamble;
1568 wlan_radio_info->end_tsf = phdr->tsf_timestamp + prior_duration + duration - preamble;
1569 }
1570 if ((pinfo->fd->num > 1) && (previous_frame.radio_info != NULL((void*)0))) {
1571 /* TODO handle intermediate packets without end_tsf correctly */
1572 wlan_radio_info->ifs = wlan_radio_info->start_tsf - previous_frame.radio_info->end_tsf;
1573 }
1574 if (tvb_captured_length(tvb) >= 4) {
1575 /*
1576 * Duration/ID field.
1577 */
1578 int nav = tvb_get_letohs(tvb, 2);
1579 if ((nav & 0x8000) == 0) {
1580 /* Duration */
1581 wlan_radio_info->nav = nav;
1582 }
1583 }
1584 if (phdr->has_signal_dbm) {
1585 wlan_radio_info->rssi = phdr->signal_dbm;
1586 if (current_aggregate)
1587 current_aggregate->rssi = phdr->signal_dbm;
1588 }
1589 }
1590
1591 if (have_duration) {
1592 proto_item *item = proto_tree_add_uint(radio_tree, hf_wlan_radio_duration, tvb, 0, 0, duration);
1593 proto_tree *d_tree = proto_item_add_subtree(item, ett_wlan_radio_duration);
1594 proto_item_set_generated(item);
1595
1596 if (assumed_short_preamble)
1597 expert_add_info(pinfo, item, &ei_wlan_radio_assumed_short_preamble);
1598 if (assumed_non_greenfield)
1599 expert_add_info(pinfo, item, &ei_wlan_radio_assumed_non_greenfield);
1600 if (assumed_no_stbc)
1601 expert_add_info(pinfo, item, &ei_wlan_radio_assumed_no_stbc);
1602 if (assumed_no_extension_streams)
1603 expert_add_info(pinfo, item, &ei_wlan_radio_assumed_no_extension_streams);
1604 if (assumed_bcc_fec)
1605 expert_add_info(pinfo, item, &ei_wlan_radio_assumed_bcc_fec);
1606
1607 if (preamble) {
1608 p_item = proto_tree_add_uint(d_tree, hf_wlan_radio_preamble, tvb, 0, 0, preamble);
1609 proto_item_set_generated(p_item);
1610 }
1611 if (wlan_radio_info) {
1612 if (wlan_radio_info->aggregate) {
1613 proto_tree *agg_tree;
1614
1615 p_item = proto_tree_add_none_format(d_tree, hf_wlan_radio_aggregate, tvb, 0, 0,
1616 "This MPDU is part of an A-MPDU");
1617 agg_tree = proto_item_add_subtree(item, ett_wlan_radio_aggregate);
1618 proto_item_set_generated(p_item);
1619 if (wlan_radio_info->aggregate->duration) {
1620 proto_item *aitem = proto_tree_add_uint(agg_tree, hf_wlan_radio_aggregate_duration, tvb, 0, 0,
1621 wlan_radio_info->aggregate->duration);
1622 proto_item_set_generated(aitem);
1623 }
1624 }
1625 if (wlan_radio_info->ifs) {
1626 p_item = proto_tree_add_int64(d_tree, hf_wlan_radio_ifs, tvb, 0, 0, wlan_radio_info->ifs);
1627 proto_item_set_generated(p_item);
1628 /* TODO: warnings on unusual IFS values (too small or negative) */
1629 }
1630 if (wlan_radio_info->start_tsf) {
1631 p_item = proto_tree_add_uint64(d_tree, hf_wlan_radio_start_tsf, tvb, 0, 0, wlan_radio_info->start_tsf);
1632 proto_item_set_generated(p_item);
1633 }
1634 if (wlan_radio_info->end_tsf) {
1635 p_item = proto_tree_add_uint64(d_tree, hf_wlan_radio_end_tsf, tvb, 0, 0, wlan_radio_info->end_tsf);
1636 proto_item_set_generated(p_item);
1637 }
1638 }
1639 }
1640 } /* if (have_data_rate) */
1641 if (phdr->has_zero_length_psdu_type)
1642 proto_tree_add_uint(radio_tree, hf_wlan_zero_length_psdu_type, tvb, 0, 0, phdr->zero_length_psdu_type);
1643
1644 tap_queue_packet(wlan_radio_tap, pinfo, phdr);
1645 if (wlan_radio_timeline_enabled) {
1646 tap_queue_packet(wlan_radio_timeline_tap, pinfo, wlan_radio_info);
1647 }
1648
1649 if (!pinfo->fd->visited) {
1650 previous_frame.radio_info = wlan_radio_info;
1651 }
1652}
1653
1654/*
1655 * Dissect 802.11 with a variable-length link-layer header and a pseudo-
1656 * header containing radio information.
1657 */
1658static int
1659dissect_wlan_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void *data)
1660{
1661 struct ieee_802_11_phdr *phdr = (struct ieee_802_11_phdr *)data;
1662
1663 dissect_wlan_radio_phdr(tvb, pinfo, tree, phdr);
1664
1665 /* Is there anything there? A 0-length-psdu has no frame data. */
1666 if (phdr->has_zero_length_psdu_type)
1667 return tvb_captured_length(tvb);
1668
1669 /* dissect the 802.11 packet next */
1670 return call_dissector_with_data(ieee80211_handle, tvb, pinfo, tree, data);
1671}
1672
1673/*
1674 * Dissect 802.11 with a variable-length link-layer header without qos elements and
1675 * a pseudo-header containing radio information.
1676 */
1677static int
1678dissect_wlan_noqos_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void *data)
1679{
1680 struct ieee_802_11_phdr *phdr = (struct ieee_802_11_phdr *)data;
1681
1682 dissect_wlan_radio_phdr(tvb, pinfo, tree, phdr);
1683
1684 /* Is there anything there? A 0-length-psdu has no frame data. */
1685 if (phdr->has_zero_length_psdu_type)
1686 return tvb_captured_length(tvb);
1687
1688 /* dissect the 802.11 packet next */
1689 return call_dissector_with_data(ieee80211_noqos_handle, tvb, pinfo, tree, data);
1690}
1691
1692static void
1693setup_ieee80211_radio(void)
1694{
1695 /* start of a new dissection, initialize state variables */
1696 current_aggregate = NULL((void*)0);
1697 agg_tracker_list = NULL((void*)0);
1698 memset(&previous_frame, 0, sizeof(previous_frame));
1699}
1700
1701static void
1702cleanup_ieee80211_radio(void)
1703{
1704 if (agg_tracker_list != NULL((void*)0)) {
1705 wmem_destroy_list(agg_tracker_list);
1706 agg_tracker_list = NULL((void*)0);
1707 }
1708}
1709
1710void proto_register_ieee80211_radio(void)
1711{
1712 static hf_register_info hf_wlan_radio[] = {
1713 {&hf_wlan_radio_phy,
1714 {"PHY type", "wlan_radio.phy", FT_UINT32, BASE_DEC, VALS(phy_vals)((0 ? (const struct _value_string*)0 : ((phy_vals)))), 0,
1715 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1716
1717 {&hf_wlan_radio_11_fhss_hop_set,
1718 {"Hop set", "wlan_radio.fhss.hop_set", FT_UINT8, BASE_HEX, NULL((void*)0), 0,
1719 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1720
1721 {&hf_wlan_radio_11_fhss_hop_pattern,
1722 {"Hop pattern", "wlan_radio.fhss.hop_pattern", FT_UINT8, BASE_HEX, NULL((void*)0), 0,
1723 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1724
1725 {&hf_wlan_radio_11_fhss_hop_index,
1726 {"Hop index", "wlan_radio.fhss.hop_index", FT_UINT8, BASE_HEX, NULL((void*)0), 0,
1727 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1728
1729 {&hf_wlan_radio_11a_channel_type,
1730 {"Channel type", "wlan_radio.11a.channel_type", FT_UINT32, BASE_DEC, VALS(channel_type_11a_vals)((0 ? (const struct _value_string*)0 : ((channel_type_11a_vals
))))
, 0,
1731 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1732
1733 {&hf_wlan_radio_11a_turbo_type,
1734 {"Turbo type", "wlan_radio.11a.turbo_type", FT_UINT32, BASE_DEC, VALS(turbo_type_11a_vals)((0 ? (const struct _value_string*)0 : ((turbo_type_11a_vals)
)))
, 0,
1735 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1736
1737 {&hf_wlan_radio_11g_mode,
1738 {"Proprietary mode", "wlan_radio.11g.mode", FT_UINT32, BASE_DEC, VALS(mode_11g_vals)((0 ? (const struct _value_string*)0 : ((mode_11g_vals)))), 0,
1739 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1740
1741 {&hf_wlan_radio_11n_mcs_index,
1742 {"MCS index", "wlan_radio.11n.mcs_index", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
1743 "Modulation and Coding Scheme index", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1744
1745 {&hf_wlan_radio_11n_bandwidth,
1746 {"Bandwidth", "wlan_radio.11n.bandwidth", FT_UINT32, BASE_DEC, VALS(bandwidth_vals)((0 ? (const struct _value_string*)0 : ((bandwidth_vals)))), 0,
1747 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1748
1749 {&hf_wlan_radio_11n_short_gi,
1750 {"Short GI", "wlan_radio.11n.short_gi", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0,
1751 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1752
1753 {&hf_wlan_radio_11n_greenfield,
1754 {"Greenfield", "wlan_radio.11n.greenfield", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0,
1755 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1756
1757 {&hf_wlan_radio_11n_fec,
1758 {"FEC", "wlan_radio.11n.fec", FT_UINT32, BASE_DEC, VALS(fec_vals)((0 ? (const struct _value_string*)0 : ((fec_vals)))), 0,
1759 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1760
1761 {&hf_wlan_radio_11n_stbc_streams,
1762 {"Number of STBC streams", "wlan_radio.11n.stbc_streams", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
1763 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1764
1765 {&hf_wlan_radio_11n_ness,
1766 {"Number of extension spatial streams", "wlan_radio.11n.ness", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
1767 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1768
1769 {&hf_wlan_radio_11ac_stbc,
1770 {"STBC", "wlan_radio.11ac.stbc", FT_BOOLEAN, BASE_NONE, TFS(&tfs_on_off)((0 ? (const struct true_false_string*)0 : ((&tfs_on_off)
)))
, 0x0,
1771 "Space Time Block Coding flag", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1772
1773 {&hf_wlan_radio_11ac_txop_ps_not_allowed,
1774 {"TXOP_PS_NOT_ALLOWED", "wlan_radio_11ac.txop_ps_not_allowed", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
1775 "Flag indicating whether STAs may doze during TXOP", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1776
1777 {&hf_wlan_radio_11ac_short_gi,
1778 {"Short GI", "wlan_radio.11ac.short_gi", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0,
1779 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1780
1781 {&hf_wlan_radio_11ac_short_gi_nsym_disambig,
1782 {"Short GI Nsym disambiguation", "wlan_radio.11ac.short_gi_nsym_disambig", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
1783 "Short Guard Interval Nsym disambiguation", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1784
1785 {&hf_wlan_radio_11ac_ldpc_extra_ofdm_symbol,
1786 {"LDPC extra OFDM symbol", "wlan_radio.11ac.ldpc_extra_ofdm_symbol", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
1787 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1788
1789 {&hf_wlan_radio_11ac_beamformed,
1790 {"Beamformed", "wlan_radio.11ac.beamformed", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
1791 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1792
1793 {&hf_wlan_radio_11ac_bandwidth,
1794 {"Bandwidth", "wlan_radio.11ac.bandwidth", FT_UINT32, BASE_DEC, VALS(bandwidth_vals)((0 ? (const struct _value_string*)0 : ((bandwidth_vals)))), 0,
1795 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1796
1797 {&hf_wlan_radio_11ac_user,
1798 {"User", "wlan_radio.11ac.user", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
1799 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1800
1801 {&hf_wlan_radio_11ac_nsts,
1802 {"Space-time streams", "wlan_radio.11ac.nsts", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
1803 "Number of Space-time streams", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1804
1805 {&hf_wlan_radio_11ac_mcs,
1806 {"MCS index", "wlan_radio.11ac.mcs", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
1807 "Modulation and Coding Scheme index", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1808
1809 {&hf_wlan_radio_11ac_nss,
1810 {"Spatial streams", "wlan_radio.11ac.nss", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
1811 "Number of spatial streams", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1812
1813 {&hf_wlan_radio_11ac_fec,
1814 {"FEC", "wlan_radio.11ac.fec", FT_UINT32, BASE_DEC, VALS(fec_vals)((0 ? (const struct _value_string*)0 : ((fec_vals)))), 0x0,
1815 "Type of FEC", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1816
1817 {&hf_wlan_radio_11ac_gid,
1818 {"Group Id", "wlan_radio.11ac.gid", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
1819 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1820
1821 {&hf_wlan_radio_11ac_p_aid,
1822 {"Partial AID", "wlan_radio.11ac.paid", FT_UINT16, BASE_DEC, NULL((void*)0), 0x0,
1823 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1824
1825 { &hf_wlan_radio_11ax_mcs,
1826 {"MCS index", "wlan_radio.11ax.mcs", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
1827 "Modulation and Coding Scheme index", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1828
1829 { &hf_wlan_radio_11ax_bandwidth,
1830 {"Bandwidth", "wlan_radio.11ax.bandwidth", FT_UINT32, BASE_DEC, VALS(bandwidth_vals)((0 ? (const struct _value_string*)0 : ((bandwidth_vals)))), 0,
1831 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1832
1833 { &hf_wlan_radio_11ax_short_gi,
1834 {"Short GI", "wlan_radio.11ax.short_gi", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0,
1835 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1836
1837 {&hf_wlan_radio_11be_user,
1838 {"User", "wlan_radio.11be.user", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
1839 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1840
1841 {&hf_wlan_radio_11be_sta_id,
1842 {"Sta ID", "wlan_radio.11be.sta_id", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
1843 "Station ID", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1844
1845 {&hf_wlan_radio_11be_nsts,
1846 {"Space-time streams", "wlan_radio.11be.nsts", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
1847 "Number of Space-time streams", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1848
1849 {&hf_wlan_radio_11be_mcs,
1850 {"MCS index", "wlan_radio.11be.mcs", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
1851 "Modulation and Coding Scheme index", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1852
1853 {&hf_wlan_radio_data_rate,
1854 {"Data rate", "wlan_radio.data_rate", FT_FLOAT, BASE_NONE, NULL((void*)0), 0,
1855 "Speed at which this frame was sent/received", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1856
1857 {&hf_wlan_radio_channel,
1858 {"Channel", "wlan_radio.channel", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
1859 "802.11 channel number that this frame was sent/received on", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1860
1861 {&hf_wlan_radio_frequency,
1862 {"Frequency", "wlan_radio.frequency", FT_UINT16, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_mhz)((0 ? (const struct unit_name_string*)0 : ((&units_mhz)))
)
, 0,
1863 "Center frequency of the 802.11 channel that this frame was sent/received on", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1864
1865 {&hf_wlan_radio_short_preamble,
1866 {"Short preamble", "wlan_radio.short_preamble", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0,
1867 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1868
1869 {&hf_wlan_radio_signal_percent,
1870 {"Signal strength (percentage)", "wlan_radio.signal_percentage", FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_percent)((0 ? (const struct unit_name_string*)0 : ((&units_percent
))))
, 0,
1871 "Signal strength, as percentage of maximum RSSI", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1872
1873 {&hf_wlan_radio_signal_db,
1874 {"Signal strength (dB)", "wlan_radio.signal_db", FT_UINT8, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_decibels)((0 ? (const struct unit_name_string*)0 : ((&units_decibels
))))
, 0,
1875 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1876
1877 {&hf_wlan_radio_signal_dbm,
1878 {"Signal strength (dBm)", "wlan_radio.signal_dbm", FT_INT8, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_dbm)((0 ? (const struct unit_name_string*)0 : ((&units_dbm)))
)
, 0,
1879 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1880
1881 {&hf_wlan_radio_noise_percent,
1882 {"Noise level (percentage)", "wlan_radio.noise_percentage", FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_percent)((0 ? (const struct unit_name_string*)0 : ((&units_percent
))))
, 0,
1883 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1884
1885 {&hf_wlan_radio_noise_db,
1886 {"Noise level (dB)", "wlan_radio.noise_db", FT_UINT8, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_decibels)((0 ? (const struct unit_name_string*)0 : ((&units_decibels
))))
, 0,
1887 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1888
1889 {&hf_wlan_radio_noise_dbm,
1890 {"Noise level (dBm)", "wlan_radio.noise_dbm", FT_INT8, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_dbm)((0 ? (const struct unit_name_string*)0 : ((&units_dbm)))
)
, 0,
1891 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1892
1893 {&hf_wlan_radio_snr,
1894 {"Signal/noise ratio (dB)", "wlan_radio.snr", FT_INT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_decibels)((0 ? (const struct unit_name_string*)0 : ((&units_decibels
))))
, 0,
1895 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1896
1897 {&hf_wlan_radio_timestamp,
1898 {"TSF timestamp", "wlan_radio.timestamp", FT_UINT64, BASE_DEC, NULL((void*)0), 0,
1899 "Timing Synchronization Function timestamp", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1900
1901 {&hf_wlan_last_part_of_a_mpdu,
1902 {"Last part of an A-MPDU", "wlan_radio.last_part_of_an_ampdu", FT_BOOLEAN, 32, NULL((void*)0), PHDR_802_11_LAST_PART_OF_A_MPDU0x00000001,
1903 "This is the last part of an A-MPDU", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1904
1905 {&hf_wlan_a_mpdu_delim_crc_error,
1906 {"A-MPDU delimiter CRC error", "wlan_radio.a_mpdu_delim_crc_error", FT_BOOLEAN, 32, NULL((void*)0), PHDR_802_11_A_MPDU_DELIM_CRC_ERROR0x00000002,
1907 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1908
1909 {&hf_wlan_a_mpdu_aggregate_id,
1910 {"A-MPDU aggregate ID", "wlan_radio.a_mpdu_aggregate_id", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
1911 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1912
1913 {&hf_wlan_radio_duration,
1914 {"Duration", "wlan_radio.duration", FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_microseconds)((0 ? (const struct unit_name_string*)0 : ((&units_microseconds
))))
, 0,
1915 "Total duration of the frame in microseconds, including any preamble or plcp header. "
1916 "Calculated from the frame length, modulation and other phy data.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1917
1918 {&hf_wlan_radio_preamble,
1919 {"Preamble", "wlan_radio.preamble", FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_microseconds)((0 ? (const struct unit_name_string*)0 : ((&units_microseconds
))))
, 0,
1920 "Duration of the PLCP or preamble in microseconds, calculated from PHY data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1921
1922 {&hf_wlan_radio_aggregate,
1923 {"A-MPDU", "wlan_radio.aggregate", FT_NONE, BASE_NONE, NULL((void*)0), 0,
1924 "MPDU is part of an A-MPDU", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1925
1926 {&hf_wlan_radio_ifs,
1927 {"IFS", "wlan_radio.ifs", FT_INT64, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_microseconds)((0 ? (const struct unit_name_string*)0 : ((&units_microseconds
))))
, 0,
1928 "Inter Frame Space before this frame in microseconds, calculated from PHY data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1929
1930 {&hf_wlan_radio_start_tsf,
1931 {"Start", "wlan_radio.start_tsf", FT_UINT64, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_microseconds)((0 ? (const struct unit_name_string*)0 : ((&units_microseconds
))))
, 0,
1932 "Calculated start time of the frame", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1933
1934 {&hf_wlan_radio_end_tsf,
1935 {"End", "wlan_radio.end_tsf", FT_UINT64, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_microseconds)((0 ? (const struct unit_name_string*)0 : ((&units_microseconds
))))
, 0,
1936 "Calculated end time of the frame", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1937
1938 {&hf_wlan_radio_aggregate_duration,
1939 {"Aggregate Duration", "wlan_radio.aggregate.duration", FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_microseconds)((0 ? (const struct unit_name_string*)0 : ((&units_microseconds
))))
, 0,
1940 "Total duration of the aggregate in microseconds, including any preamble or plcp header and multiple MPDUs. "
1941 "Calculated from the total subframe lengths, modulation and other phy data, assumes no excess padding.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
1942
1943 {&hf_wlan_zero_length_psdu_type,
1944 {"Zero-length PSDU Type", "wlan_radio.zero_len_psdu.type", FT_UINT8, BASE_HEX, VALS(zero_length_psdu_vals)((0 ? (const struct _value_string*)0 : ((zero_length_psdu_vals
))))
, 0x0,
1945 "Type of zero-length PSDU", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},
1946 };
1947
1948 static int *ett[] = {
1949 &ett_wlan_radio,
1950 &ett_wlan_radio_11ac_user,
1951 &ett_wlan_radio_duration,
1952 &ett_wlan_radio_aggregate,
1953 &ett_wlan_radio_11be_user,
1954 };
1955
1956 static ei_register_info ei[] = {
1957 { &ei_wlan_radio_assumed_short_preamble,
1958 { "wlan_radio.assumed.short_preamble", PI_ASSUMPTION0x0d000000, PI_WARN0x00600000,
1959 "No preamble length information was available, assuming short preamble.", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},
1960
1961 { &ei_wlan_radio_assumed_non_greenfield,
1962 { "wlan_radio.assumed.non_greenfield", PI_ASSUMPTION0x0d000000, PI_WARN0x00600000,
1963 "No plcp type information was available, assuming non greenfield.", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},
1964
1965 { &ei_wlan_radio_assumed_no_stbc,
1966 { "wlan_radio.assumed.no_stbc", PI_ASSUMPTION0x0d000000, PI_WARN0x00600000,
1967 "No stbc information was available, assuming no stbc.", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},
1968
1969 { &ei_wlan_radio_assumed_no_extension_streams,
1970 { "wlan_radio.assumed.no_extension_streams", PI_ASSUMPTION0x0d000000, PI_WARN0x00600000,
1971 "No extension stream information was available, assuming no extension streams.", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},
1972
1973 { &ei_wlan_radio_assumed_bcc_fec,
1974 { "wlan_radio.assumed.bcc_fec", PI_ASSUMPTION0x0d000000, PI_WARN0x00600000,
1975 "No fec type information was available, assuming bcc fec.", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},
1976
1977 { &ei_wlan_radio_11be_num_users,
1978 { "wlan_radio.11be_num_users", PI_MALFORMED0x07000000, PI_WARN0x00600000,
1979 "Number of users in the 802.11be header exceeds available slots.", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE
, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void
*)0)}}
}},
1980 };
1981
1982 module_t *wlan_radio_module;
1983 expert_module_t* expert_wlan_radio;
1984
1985 proto_wlan_radio = proto_register_protocol("802.11 radio information", "802.11 Radio", "wlan_radio");
1986 proto_register_field_array(proto_wlan_radio, hf_wlan_radio, array_length(hf_wlan_radio)(sizeof (hf_wlan_radio) / sizeof (hf_wlan_radio)[0]));
1987 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
1988
1989 expert_wlan_radio = expert_register_protocol(proto_wlan_radio);
1990 expert_register_field_array(expert_wlan_radio, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
1991
1992 wlan_radio_handle = register_dissector("wlan_radio", dissect_wlan_radio, proto_wlan_radio);
1993 wlan_noqos_radio_handle = register_dissector("wlan_noqos_radio", dissect_wlan_noqos_radio, proto_wlan_radio);
1994
1995 wlan_radio_module = prefs_register_protocol(proto_wlan_radio, NULL((void*)0));
1996 prefs_register_bool_preference(wlan_radio_module, "always_short_preamble",
1997 "802.11/11b preamble length is always short",
1998 "Some generators incorrectly indicate long preamble when the preamble was actually"
1999 "short. Always assume short preamble when calculating duration.",
2000 &wlan_radio_always_short_preamble);
2001 prefs_register_bool_preference(wlan_radio_module, "tsf_at_end",
2002 "TSF indicates the end of the PPDU",
2003 "Some generators timestamp the end of the PPDU rather than the start of the (A)MPDU.",
2004 &wlan_radio_tsf_at_end);
2005 prefs_register_bool_preference(wlan_radio_module, "timeline",
2006 "Enable Wireless Timeline (experimental)",
2007 "Enables an additional panel for navigating through packets",
2008 &wlan_radio_timeline_enabled);
2009
2010 register_init_routine( setup_ieee80211_radio );
2011 register_cleanup_routine( cleanup_ieee80211_radio );
2012
2013 wlan_radio_tap = register_tap("wlan_radio");
2014 wlan_radio_timeline_tap = register_tap("wlan_radio_timeline");
2015}
2016
2017void proto_reg_handoff_ieee80211_radio(void)
2018{
2019 /* Register handoff to radio-header dissectors */
2020 dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE_802_11_WITH_RADIO22,
2021 wlan_radio_handle);
2022 ieee80211_handle = find_dissector_add_dependency("wlan", proto_wlan_radio);
2023 ieee80211_noqos_handle = find_dissector_add_dependency("wlan_noqos", proto_wlan_radio);
2024}
2025
2026/*
2027 * Editor modelines
2028 *
2029 * Local Variables:
2030 * c-basic-offset: 2
2031 * tab-width: 8
2032 * indent-tabs-mode: nil
2033 * End:
2034 *
2035 * ex: set shiftwidth=2 tabstop=8 expandtab:
2036 * :indentSize=2:tabSize=8:noTabs=true:
2037 */