1 /* 2 * RadioTap utility routines for WL and Apps 3 * This header file housing the define and function prototype use by 4 * both the wl driver, tools & Apps. 5 * 6 * Copyright (C) 2020, Broadcom. 7 * 8 * Unless you and Broadcom execute a separate written software license 9 * agreement governing use of this software, this software is licensed to you 10 * under the terms of the GNU General Public License version 2 (the "GPL"), 11 * available at http://www.broadcom.com/licenses/GPLv2.php, with the 12 * following added to such license: 13 * 14 * As a special exception, the copyright holders of this software give you 15 * permission to link this software with independent modules, and to copy and 16 * distribute the resulting executable under terms of your choice, provided that 17 * you also meet, for each linked independent module, the terms and conditions of 18 * the license of that module. An independent module is a module which is not 19 * derived from this software. The special exception does not apply to any 20 * modifications of the software. 21 * 22 * 23 * <<Broadcom-WL-IPTag/Dual:>> 24 */ 25 26 #ifndef _BCMWIFI_RADIOTAP_H_ 27 #define _BCMWIFI_RADIOTAP_H_ 28 29 #include <ieee80211_radiotap.h> 30 #include <siutils.h> 31 #include <monitor.h> 32 #include <802.11.h> 33 #include <802.11ax.h> 34 #include "bcmwifi_monitor.h" 35 #include <bcmwifi_rspec.h> 36 #include <bcmwifi_rates.h> 37 38 /* This marks the start of a packed structure section. */ 39 #include <packed_section_start.h> 40 /* 41 * RadioTap header specific implementation. Used by MacOS implementation only. 42 */ 43 BWL_PRE_PACKED_STRUCT struct wl_radiotap_hdr { 44 struct ieee80211_radiotap_header ieee_radiotap; 45 uint64 tsft; 46 uint8 flags; 47 union { 48 uint8 rate; 49 uint8 pad; 50 } u; 51 uint16 channel_freq; 52 uint16 channel_flags; 53 } BWL_POST_PACKED_STRUCT; 54 55 BWL_PRE_PACKED_STRUCT struct wl_radiotap_sna { 56 uint8 signal; 57 uint8 noise; 58 uint8 antenna; 59 } BWL_POST_PACKED_STRUCT; 60 61 BWL_PRE_PACKED_STRUCT struct wl_radiotap_xchan { 62 uint32 xchannel_flags; 63 uint16 xchannel_freq; 64 uint8 xchannel_channel; 65 uint8 xchannel_maxpower; 66 } BWL_POST_PACKED_STRUCT; 67 68 BWL_PRE_PACKED_STRUCT struct wl_radiotap_ampdu { 69 uint32 ref_num; 70 uint16 flags; 71 uint8 delimiter_crc; 72 uint8 reserved; 73 } BWL_POST_PACKED_STRUCT; 74 75 BWL_PRE_PACKED_STRUCT struct wl_htmcs { 76 uint8 mcs_known; 77 uint8 mcs_flags; 78 uint8 mcs_index; 79 uint8 pad; /* pad to 32 bit aligned */ 80 } BWL_POST_PACKED_STRUCT; 81 82 BWL_PRE_PACKED_STRUCT struct wl_vhtmcs { 83 uint16 vht_known; /* IEEE80211_RADIOTAP_VHT */ 84 uint8 vht_flags; 85 uint8 vht_bw; 86 uint8 vht_mcs_nss[4]; 87 uint8 vht_coding; 88 uint8 vht_group_id; 89 uint16 vht_partial_aid; 90 } BWL_POST_PACKED_STRUCT; 91 92 BWL_PRE_PACKED_STRUCT struct wl_radiotap_ht_tail { 93 struct wl_radiotap_xchan xc; 94 struct wl_radiotap_ampdu ampdu; 95 union { 96 struct wl_htmcs ht; 97 struct wl_vhtmcs vht; 98 } u; 99 } BWL_POST_PACKED_STRUCT; 100 101 typedef struct bsd_header_rx { 102 struct wl_radiotap_hdr hdr; 103 /* 104 * include extra space beyond wl_radiotap_ht size 105 * (larger of two structs in union): 106 * signal/noise/ant plus max of 3 pad for xchannel 107 * tail struct (xchannel and MCS info) 108 */ 109 uint8 pad[3]; 110 uint8 ht[sizeof(struct wl_radiotap_ht_tail)]; 111 } bsd_header_rx_t; 112 113 typedef struct radiotap_parse { 114 struct ieee80211_radiotap_header *hdr; 115 void *fields; 116 uint fields_len; 117 uint idx; 118 uint offset; 119 } radiotap_parse_t; 120 121 struct rtap_field { 122 uint len; 123 uint align; 124 }; 125 126 /* he radiotap - https://www.radiotap.org/fields/HE.html */ 127 #define HE_RADIOTAP_BSS_COLOR_SHIFT 0u 128 #define HE_RADIOTAP_BEAM_CHANGE_SHIFT 6u 129 #define HE_RADIOTAP_DL_UL_SHIFT 7u 130 #define HE_RADIOTAP_MCS_SHIFT 8u 131 #define HE_RADIOTAP_DCM_SHIFT 12u 132 #define HE_RADIOTAP_CODING_SHIFT 13u 133 #define HE_RADIOTAP_LDPC_SHIFT 14u 134 #define HE_RADIOTAP_STBC_SHIFT 15u 135 #define HE_RADIOTAP_SR_SHIFT 0u 136 #define HE_RADIOTAP_STAID_SHIFT 4u 137 #define HE_RADIOTAP_SR1_SHIFT 0u 138 #define HE_RADIOTAP_SR2_SHIFT 4u 139 #define HE_RADIOTAP_SR3_SHIFT 8u 140 #define HE_RADIOTAP_SR4_SHIFT 12u 141 #define HE_RADIOTAP_BW_SHIFT 0u 142 #define HE_RADIOTAP_RU_ALLOC_SHIFT 0u 143 #define HE_RADIOTAP_GI_SHIFT 4u 144 #define HE_RADIOTAP_LTF_SIZE_SHIFT 6u 145 #define HE_RADIOTAP_NUM_LTF_SHIFT 8u 146 #define HE_RADIOTAP_PADDING_SHIFT 12u 147 #define HE_RADIOTAP_TXBF_SHIFT 14u 148 #define HE_RADIOTAP_PE_SHIFT 15u 149 #define HE_RADIOTAP_NSTS_SHIFT 0u 150 #define HE_RADIOTAP_DOPPLER_SHIFT 4u 151 #define HE_RADIOTAP_TXOP_SHIFT 8u 152 #define HE_RADIOTAP_MIDAMBLE_SHIFT 15u 153 #define HE_RADIOTAP_DOPPLER_SET_NSTS_SHIFT 0u 154 #define HE_RADIOTAP_DOPPLER_NOTSET_NSTS_SHIFT 0u 155 156 /* he mu radiotap - https://www.radiotap.org/fields/HE-MU.html */ 157 #define HE_RADIOTAP_SIGB_MCS_SHIFT 0u 158 #define HE_RADIOTAP_SIGB_MCS_KNOWN_SHIFT 4u 159 #define HE_RADIOTAP_SIGB_DCM_SHIFT 5u 160 #define HE_RADIOTAP_SIGB_DCM_KNOWN_SHIFT 6u 161 #define HE_RADIOTAP_SIGB_COMP_KNOWN_SHIFT 14u 162 #define HE_RADIOTAP_SIGB_COMP_SHIFT 3u 163 #define HE_RADIOTAP_SIGB_SYMB_SHIFT 18u 164 #define HE_RADIOTAP_BW_SIGA_SHIFT 0u 165 #define HE_RADIOTAP_BW_SIGA_KNOWN_SHIFT 2u 166 #define HE_RADIOTAP_SIGB_SYM_MU_MIMO_USER_SHIFT 4u 167 #define HE_RADIOTAP_PRE_PUNCR_SIGA_SHIFT 8u 168 #define HE_RADIOTAP_PRE_PUNCR_SIGA_KNOWN_SHIFT 10u 169 170 #define WL_RADIOTAP_BRCM_SNS 0x01 171 #define WL_RADIOTAP_BRCM_MCS 0x00000001 172 #define WL_RADIOTAP_LEGACY_SNS 0x02 173 #define WL_RADIOTAP_LEGACY_VHT 0x00000001 174 #define WL_RADIOTAP_BRCM_PAD_SNS 0x3 175 176 #define IEEE80211_RADIOTAP_HTMOD_40 0x01 177 #define IEEE80211_RADIOTAP_HTMOD_SGI 0x02 178 #define IEEE80211_RADIOTAP_HTMOD_GF 0x04 179 #define IEEE80211_RADIOTAP_HTMOD_LDPC 0x08 180 #define IEEE80211_RADIOTAP_HTMOD_STBC_MASK 0x30 181 #define IEEE80211_RADIOTAP_HTMOD_STBC_SHIFT 4 182 183 /* Dyanmic bandwidth for VHT signaled in NONHT */ 184 #define WL_RADIOTAP_F_NONHT_VHT_DYN_BW 0x01 185 /* VHT BW is valid in NONHT */ 186 #define WL_RADIOTAP_F_NONHT_VHT_BW 0x02 187 188 typedef struct ieee80211_radiotap_header ieee80211_radiotap_header_t; 189 190 /* VHT information in non-HT frames; primarily VHT b/w signaling 191 * in frames received at legacy rates. 192 */ 193 BWL_PRE_PACKED_STRUCT struct wl_radiotap_nonht_vht { 194 uint8 len; /* length of the field excluding 'len' field */ 195 uint8 flags; 196 uint8 bw; 197 uint8 PAD; /* Add a pad so the next vendor entry, if any, will be 16 bit aligned */ 198 } BWL_POST_PACKED_STRUCT; 199 200 typedef struct wl_radiotap_nonht_vht wl_radiotap_nonht_vht_t; 201 202 BWL_PRE_PACKED_STRUCT struct wl_radiotap_basic { 203 uint32 tsft_l; 204 uint32 tsft_h; 205 uint8 flags; 206 uint8 rate; /* this field acts as a pad for non legacy packets */ 207 uint16 channel_freq; 208 uint16 channel_flags; 209 uint8 signal; 210 uint8 noise; 211 int8 antenna; 212 } BWL_POST_PACKED_STRUCT; 213 214 typedef struct wl_radiotap_basic wl_radiotap_basic_t; 215 216 /* radiotap standard - non-HT, non-VHT information with Broadcom vendor namespace extension 217 * that includes VHT information. 218 * Used with monitor type 3 when received by HT/Legacy PHY and received rate is legacy. 219 * Struct ieee80211_radiotap_header is of variable length due to possible 220 * extra it_present bitmap fields. 221 * It should not be included as a static length field here 222 */ 223 BWL_PRE_PACKED_STRUCT struct wl_radiotap_legacy { 224 wl_radiotap_basic_t basic; 225 uint8 PAD; 226 } BWL_POST_PACKED_STRUCT; 227 228 typedef struct wl_radiotap_legacy wl_radiotap_legacy_t; 229 230 #define WL_RADIOTAP_LEGACY_SKIP_LEN htol16(sizeof(struct wl_radiotap_legacy) - \ 231 OFFSETOF(struct wl_radiotap_legacy, nonht_vht)) 232 233 #define WL_RADIOTAP_NONHT_VHT_LEN (sizeof(wl_radiotap_nonht_vht_t) - 1) 234 235 /* Radiotap standard that includes HT information. This is for use with monitor type 3 236 * whenever frame is received by HT-PHY, and received rate is non-VHT. 237 * Struct ieee80211_radiotap_header is of variable length due to possible 238 * extra it_present bitmap fields. 239 * It should not be included as a static length field here 240 */ 241 BWL_PRE_PACKED_STRUCT struct wl_radiotap_ht { 242 wl_radiotap_basic_t basic; 243 uint8 PAD[3]; 244 uint32 xchannel_flags; 245 uint16 xchannel_freq; 246 uint8 xchannel_channel; 247 uint8 xchannel_maxpower; 248 uint8 mcs_known; 249 uint8 mcs_flags; 250 uint8 mcs_index; 251 uint8 PAD; 252 uint32 ampdu_ref_num; /* A-MPDU ID */ 253 uint16 ampdu_flags; /* A-MPDU flags */ 254 uint8 ampdu_delim_crc; /* Delimiter CRC if present in flags */ 255 uint8 ampdu_reserved; 256 } BWL_POST_PACKED_STRUCT; 257 258 typedef struct wl_radiotap_ht wl_radiotap_ht_t; 259 260 /* Radiotap standard that includes VHT information. 261 * This is for use with monitor type 3 whenever frame is 262 * received by HT-PHY (VHT-PHY), and received rate is VHT. 263 * Struct ieee80211_radiotap_header is of variable length due to possible 264 * extra it_present bitmap fields. 265 * It should not be included as a static length field here 266 */ 267 BWL_PRE_PACKED_STRUCT struct wl_radiotap_vht { 268 wl_radiotap_basic_t basic; 269 uint8 PAD[3]; 270 uint32 ampdu_ref_num; /* A-MPDU ID */ 271 uint16 ampdu_flags; /* A-MPDU flags */ 272 uint8 ampdu_delim_crc; /* Delimiter CRC if present in flags */ 273 uint8 ampdu_reserved; 274 uint16 vht_known; /* IEEE80211_RADIOTAP_VHT */ 275 uint8 vht_flags; /* IEEE80211_RADIOTAP_VHT */ 276 uint8 vht_bw; /* IEEE80211_RADIOTAP_VHT */ 277 uint8 vht_mcs_nss[4]; /* IEEE80211_RADIOTAP_VHT */ 278 uint8 vht_coding; /* IEEE80211_RADIOTAP_VHT */ 279 uint8 vht_group_id; /* IEEE80211_RADIOTAP_VHT */ 280 uint16 vht_partial_aid; /* IEEE80211_RADIOTAP_VHT */ 281 } BWL_POST_PACKED_STRUCT; 282 283 typedef struct wl_radiotap_vht wl_radiotap_vht_t; 284 285 /* Radiotap standard that includes HE information. */ 286 BWL_PRE_PACKED_STRUCT struct wl_radiotap_he { 287 wl_radiotap_basic_t basic; 288 uint8 PAD[3]; 289 uint32 ampdu_ref_num; /* A-MPDU ID */ 290 uint16 ampdu_flags; /* A-MPDU flags */ 291 uint8 ampdu_delim_crc; /* Delimiter CRC if present in flags */ 292 uint8 ampdu_reserved; 293 uint16 data1; 294 uint16 data2; 295 uint16 data3; 296 uint16 data4; 297 uint16 data5; 298 uint16 data6; 299 } BWL_POST_PACKED_STRUCT; 300 301 typedef struct wl_radiotap_he wl_radiotap_he_t; 302 303 BWL_PRE_PACKED_STRUCT struct radiotap_vendor_ns { 304 uint8 vend_oui[3]; 305 uint8 sns; 306 uint16 skip_len; 307 } BWL_POST_PACKED_STRUCT; 308 309 typedef struct radiotap_vendor_ns radiotap_vendor_ns_t; 310 311 #define WL_RADIOTAP_PRESENT_BASIC \ 312 ((1 << IEEE80211_RADIOTAP_TSFT) | \ 313 (1 << IEEE80211_RADIOTAP_FLAGS) | \ 314 (1 << IEEE80211_RADIOTAP_CHANNEL) | \ 315 (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \ 316 (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \ 317 (1 << IEEE80211_RADIOTAP_ANTENNA)) 318 319 #define WL_RADIOTAP_PRESENT_LEGACY \ 320 WL_RADIOTAP_PRESENT_BASIC | \ 321 (1 << IEEE80211_RADIOTAP_RATE) 322 323 #define WL_RADIOTAP_PRESENT_HT \ 324 WL_RADIOTAP_PRESENT_BASIC | \ 325 ((1 << IEEE80211_RADIOTAP_XCHANNEL) | \ 326 (1 << IEEE80211_RADIOTAP_MCS) | \ 327 (1 << IEEE80211_RADIOTAP_AMPDU)) 328 329 #define WL_RADIOTAP_PRESENT_VHT \ 330 WL_RADIOTAP_PRESENT_BASIC | \ 331 ((1 << IEEE80211_RADIOTAP_AMPDU) | \ 332 (1 << IEEE80211_RADIOTAP_VHT)) 333 334 #define WL_RADIOTAP_PRESENT_HE \ 335 WL_RADIOTAP_PRESENT_BASIC | \ 336 ((1 << IEEE80211_RADIOTAP_AMPDU) | \ 337 (1 << IEEE80211_RADIOTAP_HE)) 338 339 /* include/linux/if_arp.h 340 * #define ARPHRD_IEEE80211_PRISM 802 IEEE 802.11 + Prism2 header 341 * #define ARPHRD_IEEE80211_RADIOTAP 803 IEEE 802.11 + radiotap header 342 * include/net/ieee80211_radiotap.h 343 * radiotap structure 344 */ 345 346 #ifndef ARPHRD_IEEE80211_RADIOTAP 347 #define ARPHRD_IEEE80211_RADIOTAP 803 348 #endif 349 350 /* This marks the end of a packed structure section. */ 351 #include <packed_section_end.h> 352 353 extern void wl_rtapParseInit(radiotap_parse_t *rtap, uint8 *rtap_header); 354 extern ratespec_t wl_calcRspecFromRTap(uint8 *rtap_header); 355 extern bool wl_rtapFlags(uint8 *rtap_header, uint8* flags); 356 extern uint wl_radiotap_rx(struct dot11_header *mac_header, wl_rxsts_t *rxsts, 357 bsd_header_rx_t *bsd_header); 358 extern uint wl_radiotap_rx_legacy(struct dot11_header *mac_header, wl_rxsts_t *rxsts, 359 ieee80211_radiotap_header_t* rtap_hdr); 360 extern uint wl_radiotap_rx_ht(struct dot11_header *mac_header, wl_rxsts_t *rxsts, 361 ieee80211_radiotap_header_t* rtap_hdr); 362 extern uint wl_radiotap_rx_vht(struct dot11_header *mac_header, wl_rxsts_t *rxsts, 363 ieee80211_radiotap_header_t* rtap_hdr); 364 extern uint wl_radiotap_rx_he(struct dot11_header *mac_header, wl_rxsts_t *rxsts, 365 ieee80211_radiotap_header_t* rtap_hdr); 366 extern uint wl_radiotap_rx_eht(struct dot11_header *mac_header, wl_rxsts_t *rxsts, 367 ieee80211_radiotap_header_t *rtap_hdr); 368 369 /* Legacy phy radiotap header may include VHT bw signaling VS element */ 370 #define MAX_RADIOTAP_LEGACY_SIZE (sizeof(wl_radiotap_legacy_t) + \ 371 sizeof(radiotap_vendor_ns_t) + sizeof(wl_radiotap_nonht_vht_t)) 372 373 /* RadioTap header starts with a fixed struct ieee80211_radiotap_header, 374 * followed by variable fields for the 4 encodings supported, HE, VHT, HT, and Legacy 375 */ 376 #define MAX_RADIOTAP_SIZE (sizeof(struct ieee80211_radiotap_header) + \ 377 MAX(sizeof(wl_radiotap_he_t), \ 378 MAX(sizeof(wl_radiotap_vht_t), \ 379 MAX(sizeof(wl_radiotap_ht_t), MAX_RADIOTAP_LEGACY_SIZE)))) 380 #define MAX_MON_PKT_SIZE (4096 + MAX_RADIOTAP_SIZE) 381 382 #endif /* _BCMWIFI_RADIOTAP_H_ */ 383