/* * RadioTap utility routines for WL and Apps * This header file housing the define and function prototype use by * both the wl driver, tools & Apps. * * Copyright (C) 2020, Broadcom. * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that * you also meet, for each linked independent module, the terms and conditions of * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. * * * <> */ #ifndef _BCMWIFI_RADIOTAP_H_ #define _BCMWIFI_RADIOTAP_H_ #include #include #include #include <802.11.h> #include <802.11ax.h> #include "bcmwifi_monitor.h" #include #include /* This marks the start of a packed structure section. */ #include /* * RadioTap header specific implementation. Used by MacOS implementation only. */ BWL_PRE_PACKED_STRUCT struct wl_radiotap_hdr { struct ieee80211_radiotap_header ieee_radiotap; uint64 tsft; uint8 flags; union { uint8 rate; uint8 pad; } u; uint16 channel_freq; uint16 channel_flags; } BWL_POST_PACKED_STRUCT; BWL_PRE_PACKED_STRUCT struct wl_radiotap_sna { uint8 signal; uint8 noise; uint8 antenna; } BWL_POST_PACKED_STRUCT; BWL_PRE_PACKED_STRUCT struct wl_radiotap_xchan { uint32 xchannel_flags; uint16 xchannel_freq; uint8 xchannel_channel; uint8 xchannel_maxpower; } BWL_POST_PACKED_STRUCT; BWL_PRE_PACKED_STRUCT struct wl_radiotap_ampdu { uint32 ref_num; uint16 flags; uint8 delimiter_crc; uint8 reserved; } BWL_POST_PACKED_STRUCT; BWL_PRE_PACKED_STRUCT struct wl_htmcs { uint8 mcs_known; uint8 mcs_flags; uint8 mcs_index; uint8 pad; /* pad to 32 bit aligned */ } BWL_POST_PACKED_STRUCT; BWL_PRE_PACKED_STRUCT struct wl_vhtmcs { uint16 vht_known; /* IEEE80211_RADIOTAP_VHT */ uint8 vht_flags; uint8 vht_bw; uint8 vht_mcs_nss[4]; uint8 vht_coding; uint8 vht_group_id; uint16 vht_partial_aid; } BWL_POST_PACKED_STRUCT; BWL_PRE_PACKED_STRUCT struct wl_radiotap_ht_tail { struct wl_radiotap_xchan xc; struct wl_radiotap_ampdu ampdu; union { struct wl_htmcs ht; struct wl_vhtmcs vht; } u; } BWL_POST_PACKED_STRUCT; typedef struct bsd_header_rx { struct wl_radiotap_hdr hdr; /* * include extra space beyond wl_radiotap_ht size * (larger of two structs in union): * signal/noise/ant plus max of 3 pad for xchannel * tail struct (xchannel and MCS info) */ uint8 pad[3]; uint8 ht[sizeof(struct wl_radiotap_ht_tail)]; } bsd_header_rx_t; typedef struct radiotap_parse { struct ieee80211_radiotap_header *hdr; void *fields; uint fields_len; uint idx; uint offset; } radiotap_parse_t; struct rtap_field { uint len; uint align; }; /* he radiotap - https://www.radiotap.org/fields/HE.html */ #define HE_RADIOTAP_BSS_COLOR_SHIFT 0u #define HE_RADIOTAP_BEAM_CHANGE_SHIFT 6u #define HE_RADIOTAP_DL_UL_SHIFT 7u #define HE_RADIOTAP_MCS_SHIFT 8u #define HE_RADIOTAP_DCM_SHIFT 12u #define HE_RADIOTAP_CODING_SHIFT 13u #define HE_RADIOTAP_LDPC_SHIFT 14u #define HE_RADIOTAP_STBC_SHIFT 15u #define HE_RADIOTAP_SR_SHIFT 0u #define HE_RADIOTAP_STAID_SHIFT 4u #define HE_RADIOTAP_SR1_SHIFT 0u #define HE_RADIOTAP_SR2_SHIFT 4u #define HE_RADIOTAP_SR3_SHIFT 8u #define HE_RADIOTAP_SR4_SHIFT 12u #define HE_RADIOTAP_BW_SHIFT 0u #define HE_RADIOTAP_RU_ALLOC_SHIFT 0u #define HE_RADIOTAP_GI_SHIFT 4u #define HE_RADIOTAP_LTF_SIZE_SHIFT 6u #define HE_RADIOTAP_NUM_LTF_SHIFT 8u #define HE_RADIOTAP_PADDING_SHIFT 12u #define HE_RADIOTAP_TXBF_SHIFT 14u #define HE_RADIOTAP_PE_SHIFT 15u #define HE_RADIOTAP_NSTS_SHIFT 0u #define HE_RADIOTAP_DOPPLER_SHIFT 4u #define HE_RADIOTAP_TXOP_SHIFT 8u #define HE_RADIOTAP_MIDAMBLE_SHIFT 15u #define HE_RADIOTAP_DOPPLER_SET_NSTS_SHIFT 0u #define HE_RADIOTAP_DOPPLER_NOTSET_NSTS_SHIFT 0u /* he mu radiotap - https://www.radiotap.org/fields/HE-MU.html */ #define HE_RADIOTAP_SIGB_MCS_SHIFT 0u #define HE_RADIOTAP_SIGB_MCS_KNOWN_SHIFT 4u #define HE_RADIOTAP_SIGB_DCM_SHIFT 5u #define HE_RADIOTAP_SIGB_DCM_KNOWN_SHIFT 6u #define HE_RADIOTAP_SIGB_COMP_KNOWN_SHIFT 14u #define HE_RADIOTAP_SIGB_COMP_SHIFT 3u #define HE_RADIOTAP_SIGB_SYMB_SHIFT 18u #define HE_RADIOTAP_BW_SIGA_SHIFT 0u #define HE_RADIOTAP_BW_SIGA_KNOWN_SHIFT 2u #define HE_RADIOTAP_SIGB_SYM_MU_MIMO_USER_SHIFT 4u #define HE_RADIOTAP_PRE_PUNCR_SIGA_SHIFT 8u #define HE_RADIOTAP_PRE_PUNCR_SIGA_KNOWN_SHIFT 10u #define WL_RADIOTAP_BRCM_SNS 0x01 #define WL_RADIOTAP_BRCM_MCS 0x00000001 #define WL_RADIOTAP_LEGACY_SNS 0x02 #define WL_RADIOTAP_LEGACY_VHT 0x00000001 #define WL_RADIOTAP_BRCM_PAD_SNS 0x3 #define IEEE80211_RADIOTAP_HTMOD_40 0x01 #define IEEE80211_RADIOTAP_HTMOD_SGI 0x02 #define IEEE80211_RADIOTAP_HTMOD_GF 0x04 #define IEEE80211_RADIOTAP_HTMOD_LDPC 0x08 #define IEEE80211_RADIOTAP_HTMOD_STBC_MASK 0x30 #define IEEE80211_RADIOTAP_HTMOD_STBC_SHIFT 4 /* Dyanmic bandwidth for VHT signaled in NONHT */ #define WL_RADIOTAP_F_NONHT_VHT_DYN_BW 0x01 /* VHT BW is valid in NONHT */ #define WL_RADIOTAP_F_NONHT_VHT_BW 0x02 typedef struct ieee80211_radiotap_header ieee80211_radiotap_header_t; /* VHT information in non-HT frames; primarily VHT b/w signaling * in frames received at legacy rates. */ BWL_PRE_PACKED_STRUCT struct wl_radiotap_nonht_vht { uint8 len; /* length of the field excluding 'len' field */ uint8 flags; uint8 bw; uint8 PAD; /* Add a pad so the next vendor entry, if any, will be 16 bit aligned */ } BWL_POST_PACKED_STRUCT; typedef struct wl_radiotap_nonht_vht wl_radiotap_nonht_vht_t; BWL_PRE_PACKED_STRUCT struct wl_radiotap_basic { uint32 tsft_l; uint32 tsft_h; uint8 flags; uint8 rate; /* this field acts as a pad for non legacy packets */ uint16 channel_freq; uint16 channel_flags; uint8 signal; uint8 noise; int8 antenna; } BWL_POST_PACKED_STRUCT; typedef struct wl_radiotap_basic wl_radiotap_basic_t; /* radiotap standard - non-HT, non-VHT information with Broadcom vendor namespace extension * that includes VHT information. * Used with monitor type 3 when received by HT/Legacy PHY and received rate is legacy. * Struct ieee80211_radiotap_header is of variable length due to possible * extra it_present bitmap fields. * It should not be included as a static length field here */ BWL_PRE_PACKED_STRUCT struct wl_radiotap_legacy { wl_radiotap_basic_t basic; uint8 PAD; } BWL_POST_PACKED_STRUCT; typedef struct wl_radiotap_legacy wl_radiotap_legacy_t; #define WL_RADIOTAP_LEGACY_SKIP_LEN htol16(sizeof(struct wl_radiotap_legacy) - \ OFFSETOF(struct wl_radiotap_legacy, nonht_vht)) #define WL_RADIOTAP_NONHT_VHT_LEN (sizeof(wl_radiotap_nonht_vht_t) - 1) /* Radiotap standard that includes HT information. This is for use with monitor type 3 * whenever frame is received by HT-PHY, and received rate is non-VHT. * Struct ieee80211_radiotap_header is of variable length due to possible * extra it_present bitmap fields. * It should not be included as a static length field here */ BWL_PRE_PACKED_STRUCT struct wl_radiotap_ht { wl_radiotap_basic_t basic; uint8 PAD[3]; uint32 xchannel_flags; uint16 xchannel_freq; uint8 xchannel_channel; uint8 xchannel_maxpower; uint8 mcs_known; uint8 mcs_flags; uint8 mcs_index; uint8 PAD; uint32 ampdu_ref_num; /* A-MPDU ID */ uint16 ampdu_flags; /* A-MPDU flags */ uint8 ampdu_delim_crc; /* Delimiter CRC if present in flags */ uint8 ampdu_reserved; } BWL_POST_PACKED_STRUCT; typedef struct wl_radiotap_ht wl_radiotap_ht_t; /* Radiotap standard that includes VHT information. * This is for use with monitor type 3 whenever frame is * received by HT-PHY (VHT-PHY), and received rate is VHT. * Struct ieee80211_radiotap_header is of variable length due to possible * extra it_present bitmap fields. * It should not be included as a static length field here */ BWL_PRE_PACKED_STRUCT struct wl_radiotap_vht { wl_radiotap_basic_t basic; uint8 PAD[3]; uint32 ampdu_ref_num; /* A-MPDU ID */ uint16 ampdu_flags; /* A-MPDU flags */ uint8 ampdu_delim_crc; /* Delimiter CRC if present in flags */ uint8 ampdu_reserved; uint16 vht_known; /* IEEE80211_RADIOTAP_VHT */ uint8 vht_flags; /* IEEE80211_RADIOTAP_VHT */ uint8 vht_bw; /* IEEE80211_RADIOTAP_VHT */ uint8 vht_mcs_nss[4]; /* IEEE80211_RADIOTAP_VHT */ uint8 vht_coding; /* IEEE80211_RADIOTAP_VHT */ uint8 vht_group_id; /* IEEE80211_RADIOTAP_VHT */ uint16 vht_partial_aid; /* IEEE80211_RADIOTAP_VHT */ } BWL_POST_PACKED_STRUCT; typedef struct wl_radiotap_vht wl_radiotap_vht_t; /* Radiotap standard that includes HE information. */ BWL_PRE_PACKED_STRUCT struct wl_radiotap_he { wl_radiotap_basic_t basic; uint8 PAD[3]; uint32 ampdu_ref_num; /* A-MPDU ID */ uint16 ampdu_flags; /* A-MPDU flags */ uint8 ampdu_delim_crc; /* Delimiter CRC if present in flags */ uint8 ampdu_reserved; uint16 data1; uint16 data2; uint16 data3; uint16 data4; uint16 data5; uint16 data6; } BWL_POST_PACKED_STRUCT; typedef struct wl_radiotap_he wl_radiotap_he_t; BWL_PRE_PACKED_STRUCT struct radiotap_vendor_ns { uint8 vend_oui[3]; uint8 sns; uint16 skip_len; } BWL_POST_PACKED_STRUCT; typedef struct radiotap_vendor_ns radiotap_vendor_ns_t; #define WL_RADIOTAP_PRESENT_BASIC \ ((1 << IEEE80211_RADIOTAP_TSFT) | \ (1 << IEEE80211_RADIOTAP_FLAGS) | \ (1 << IEEE80211_RADIOTAP_CHANNEL) | \ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \ (1 << IEEE80211_RADIOTAP_ANTENNA)) #define WL_RADIOTAP_PRESENT_LEGACY \ WL_RADIOTAP_PRESENT_BASIC | \ (1 << IEEE80211_RADIOTAP_RATE) #define WL_RADIOTAP_PRESENT_HT \ WL_RADIOTAP_PRESENT_BASIC | \ ((1 << IEEE80211_RADIOTAP_XCHANNEL) | \ (1 << IEEE80211_RADIOTAP_MCS) | \ (1 << IEEE80211_RADIOTAP_AMPDU)) #define WL_RADIOTAP_PRESENT_VHT \ WL_RADIOTAP_PRESENT_BASIC | \ ((1 << IEEE80211_RADIOTAP_AMPDU) | \ (1 << IEEE80211_RADIOTAP_VHT)) #define WL_RADIOTAP_PRESENT_HE \ WL_RADIOTAP_PRESENT_BASIC | \ ((1 << IEEE80211_RADIOTAP_AMPDU) | \ (1 << IEEE80211_RADIOTAP_HE)) /* include/linux/if_arp.h * #define ARPHRD_IEEE80211_PRISM 802 IEEE 802.11 + Prism2 header * #define ARPHRD_IEEE80211_RADIOTAP 803 IEEE 802.11 + radiotap header * include/net/ieee80211_radiotap.h * radiotap structure */ #ifndef ARPHRD_IEEE80211_RADIOTAP #define ARPHRD_IEEE80211_RADIOTAP 803 #endif /* This marks the end of a packed structure section. */ #include extern void wl_rtapParseInit(radiotap_parse_t *rtap, uint8 *rtap_header); extern ratespec_t wl_calcRspecFromRTap(uint8 *rtap_header); extern bool wl_rtapFlags(uint8 *rtap_header, uint8* flags); extern uint wl_radiotap_rx(struct dot11_header *mac_header, wl_rxsts_t *rxsts, bsd_header_rx_t *bsd_header); extern uint wl_radiotap_rx_legacy(struct dot11_header *mac_header, wl_rxsts_t *rxsts, ieee80211_radiotap_header_t* rtap_hdr); extern uint wl_radiotap_rx_ht(struct dot11_header *mac_header, wl_rxsts_t *rxsts, ieee80211_radiotap_header_t* rtap_hdr); extern uint wl_radiotap_rx_vht(struct dot11_header *mac_header, wl_rxsts_t *rxsts, ieee80211_radiotap_header_t* rtap_hdr); extern uint wl_radiotap_rx_he(struct dot11_header *mac_header, wl_rxsts_t *rxsts, ieee80211_radiotap_header_t* rtap_hdr); extern uint wl_radiotap_rx_eht(struct dot11_header *mac_header, wl_rxsts_t *rxsts, ieee80211_radiotap_header_t *rtap_hdr); /* Legacy phy radiotap header may include VHT bw signaling VS element */ #define MAX_RADIOTAP_LEGACY_SIZE (sizeof(wl_radiotap_legacy_t) + \ sizeof(radiotap_vendor_ns_t) + sizeof(wl_radiotap_nonht_vht_t)) /* RadioTap header starts with a fixed struct ieee80211_radiotap_header, * followed by variable fields for the 4 encodings supported, HE, VHT, HT, and Legacy */ #define MAX_RADIOTAP_SIZE (sizeof(struct ieee80211_radiotap_header) + \ MAX(sizeof(wl_radiotap_he_t), \ MAX(sizeof(wl_radiotap_vht_t), \ MAX(sizeof(wl_radiotap_ht_t), MAX_RADIOTAP_LEGACY_SIZE)))) #define MAX_MON_PKT_SIZE (4096 + MAX_RADIOTAP_SIZE) #endif /* _BCMWIFI_RADIOTAP_H_ */