qcacmn: Add new radiotap header fields

Add the following fields in Radiotap header:
Antenna noise (in dBM)
Vendor Namespace containing the following information
->L_SIG_A
->Device_ID
->L_SIG_B
->PPDU_START_TIMESTAMP

CRs-Fixed: 2285143
Change-Id: I977be73778ab27383f12214c73b56c9b80d9f02d
This commit is contained in:
Adil Saeed Musthafa 2018-07-17 20:49:31 -07:00 • committed by nshrivas
commit 61a21697f6
9 changed files with 187 additions and 45 deletions

View file

@ -156,6 +156,7 @@
* struct mon_rx_status - This will have monitor mode rx_status extracted from
* htt_rx_desc used later to update radiotap information.
* @tsft: Time Synchronization Function timer
* @ppdu_timestamp: Timestamp in the PPDU_START TLV
* @preamble_type: Preamble type in radio header
* @chan_freq: Capture channel frequency
* @chan_num: Capture channel number
@ -171,6 +172,8 @@
* @he_sig_A2_known: HE (11ax) sig A2 known field
* @he_sig_b_common: HE (11ax) sig B common field
* @he_sig_b_common_known: HE (11ax) sig B common known field
* @l_sig_a_info: L_SIG_A value coming in Rx descriptor
* @l_sig_b_info: L_SIG_B value coming in Rx descriptor
* @rate: Rate in terms 500Kbps
* @rtap_flags: Bit map of available fields in the radiotap
* @ant_signal_db: Rx packet RSSI
@ -207,9 +210,16 @@
* @he_data5: HE property of received frame
* @prev_ppdu_id: ppdu_id in previously received message
* @ppdu_id: Id of the PLCP protocol data unit
*
* The following variables are not coming from the TLVs.
* These variables are placeholders for passing information to update_radiotap
* function.
* @device_id: Device ID coming from sub-system (PCI, AHB etc..)
* @chan_noise_floor: Channel Noise Floor for the pdev
*/
struct mon_rx_status {
uint64_t tsft;
uint32_t ppdu_timestamp;
uint32_t preamble_type;
uint16_t chan_freq;
uint16_t chan_num;
@ -224,6 +234,8 @@ struct mon_rx_status {
uint16_t he_sig_A2_known;
uint16_t he_sig_b_common;
uint16_t he_sig_b_common_known;
uint32_t l_sig_a_info;
uint32_t l_sig_b_info;
uint8_t rate;
uint8_t rtap_flags;
uint8_t ant_signal_db;
@ -273,8 +285,41 @@ struct mon_rx_status {
uint32_t ppdu_len;
uint32_t prev_ppdu_id;
uint32_t ppdu_id;
uint32_t device_id;
int16_t chan_noise_floor;
};
/**
* struct qdf_radiotap_vendor_ns - Vendor Namespace header as per
* Radiotap spec: https://www.radiotap.org/fields/Vendor%20Namespace.html
* @oui: Vendor OUI
* @selector: sub_namespace selector
* @skip_length: How many bytes of Vendor Namespace data that follows
*/
struct qdf_radiotap_vendor_ns {
uint8_t oui[3];
uint8_t selector;
uint16_t skip_length;
} __attribute__((__packed__));
/**
* strcut qdf_radiotap_vendor_ns_ath - Combined QTI Vendor NS
* including the Radiotap specified Vendor Namespace header and
* QTI specific Vendor Namespace data
* @lsig: L_SIG_A (or L_SIG)
* @device_id: Device Identification
* @lsig_b: L_SIG_B
* @ppdu_start_timestamp: Timestamp from RX_PPDU_START TLV
*/
struct qdf_radiotap_vendor_ns_ath {
struct qdf_radiotap_vendor_ns hdr;
/* QTI specific data follows */
uint32_t lsig;
uint32_t device_id;
uint32_t lsig_b;
uint32_t ppdu_start_timestamp;
} __attribute__((__packed__));
/* Masks for HE SIG known fields in mon_rx_status structure */
#define QDF_MON_STATUS_HE_SIG_B_COMMON_KNOWN_RU0 0x00000001
#define QDF_MON_STATUS_HE_SIG_B_COMMON_KNOWN_RU1 0x00000002

View file

@ -3720,6 +3720,8 @@ static unsigned int qdf_nbuf_update_radiotap_vht_flags(
{
uint16_t vht_flags = 0;
rtap_len = qdf_align(rtap_len, 2);
/* IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16 */
vht_flags |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC |
IEEE80211_RADIOTAP_VHT_KNOWN_GI |
@ -3791,6 +3793,8 @@ qdf_nbuf_update_radiotap_he_flags(struct mon_rx_status *rx_status,
* IEEE80211_RADIOTAP_HE u16, u16, u16, u16, u16, u16
* Enable all "known" HE radiotap flags for now
*/
rtap_len = qdf_align(rtap_len, 2);
put_unaligned_le16(rx_status->he_data1, &rtap_buf[rtap_len]);
rtap_len += 2;
@ -3831,6 +3835,8 @@ static unsigned int
qdf_nbuf_update_radiotap_he_mu_flags(struct mon_rx_status *rx_status,
int8_t *rtap_buf, uint32_t rtap_len)
{
rtap_len = qdf_align(rtap_len, 2);
/*
* IEEE80211_RADIOTAP_HE_MU u16, u16, u8[4]
* Enable all "known" he-mu radiotap flags for now
@ -3875,6 +3881,8 @@ static unsigned int
qdf_nbuf_update_radiotap_he_mu_other_flags(struct mon_rx_status *rx_status,
int8_t *rtap_buf, uint32_t rtap_len)
{
rtap_len = qdf_align(rtap_len, 2);
/*
* IEEE80211_RADIOTAP_HE-MU-OTHER u16, u16, u8, u8
* Enable all "known" he-mu-other radiotap flags for now
@ -3897,21 +3905,24 @@ qdf_nbuf_update_radiotap_he_mu_other_flags(struct mon_rx_status *rx_status,
return rtap_len;
}
#define NORMALIZED_TO_NOISE_FLOOR (-96)
/* This is the length for radiotap, combined length
/**
* This is the length for radiotap, combined length
* (Mandatory part struct ieee80211_radiotap_header + RADIOTAP_HEADER_LEN)
* cannot be more than available headroom_sz.
* increase this when we add more radiotap elements.
* Number after '+' indicates maximum possible increase due to alignment
*/
#define RADIOTAP_VHT_FLAGS_LEN 12
#define RADIOTAP_HE_FLAGS_LEN 12
#define RADIOTAP_HE_MU_FLAGS_LEN 8
#define RADIOTAP_HE_MU_OTHER_FLAGS_LEN 18
#define RADIOTAP_FIXED_HEADER_LEN 16
#define RADIOTAP_VHT_FLAGS_LEN (12 + 1)
#define RADIOTAP_HE_FLAGS_LEN (12 + 1)
#define RADIOTAP_HE_MU_FLAGS_LEN (8 + 1)
#define RADIOTAP_HE_MU_OTHER_FLAGS_LEN (18 + 1)
#define RADIOTAP_FIXED_HEADER_LEN 17
#define RADIOTAP_HT_FLAGS_LEN 3
#define RADIOTAP_AMPDU_STATUS_LEN 8
#define RADIOTAP_AMPDU_STATUS_LEN (8 + 3)
#define RADIOTAP_VENDOR_NS_LEN \
(sizeof(struct qdf_radiotap_vendor_ns_ath) + 1)
#define RADIOTAP_HEADER_LEN (sizeof(struct ieee80211_radiotap_header) + \
RADIOTAP_FIXED_HEADER_LEN + \
RADIOTAP_HT_FLAGS_LEN + \
@ -3919,11 +3930,13 @@ qdf_nbuf_update_radiotap_he_mu_other_flags(struct mon_rx_status *rx_status,
RADIOTAP_AMPDU_STATUS_LEN + \
RADIOTAP_HE_FLAGS_LEN + \
RADIOTAP_HE_MU_FLAGS_LEN + \
RADIOTAP_HE_MU_OTHER_FLAGS_LEN)
RADIOTAP_HE_MU_OTHER_FLAGS_LEN + \
RADIOTAP_VENDOR_NS_LEN)
#define IEEE80211_RADIOTAP_HE 23
#define IEEE80211_RADIOTAP_HE_MU 24
#define IEEE80211_RADIOTAP_HE_MU_OTHER 25
uint8_t ATH_OUI[] = {0x00, 0x03, 0x7f}; /* Atheros OUI */
/**
* radiotap_num_to_freq() - Get frequency from chan number
@ -3975,6 +3988,8 @@ static unsigned int qdf_nbuf_update_radiotap_ampdu_flags(
uint16_t ampdu_flags = 0;
uint16_t ampdu_reserved_flags = 0;
rtap_len = qdf_align(rtap_len, 4);
put_unaligned_le32(ampdu_reference_num, &rtap_buf[rtap_len]);
rtap_len += 4;
put_unaligned_le16(ampdu_flags, &rtap_buf[rtap_len]);
@ -4002,14 +4017,15 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
uint32_t rtap_hdr_len = sizeof(struct ieee80211_radiotap_header);
uint32_t rtap_len = rtap_hdr_len;
uint8_t length = rtap_len;
struct qdf_radiotap_vendor_ns_ath *radiotap_vendor_ns_ath;
/* IEEE80211_RADIOTAP_TSFT __le64 microseconds*/
rthdr->it_present = cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT);
rthdr->it_present = (1 << IEEE80211_RADIOTAP_TSFT);
put_unaligned_le64(rx_status->tsft, &rtap_buf[rtap_len]);
rtap_len += 8;
/* IEEE80211_RADIOTAP_FLAGS u8 */
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_FLAGS);
rthdr->it_present |= (1 << IEEE80211_RADIOTAP_FLAGS);
if (rx_status->rs_fcs_err)
rx_status->rtap_flags |= IEEE80211_RADIOTAP_F_BADFCS;
@ -4020,14 +4036,14 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
/* IEEE80211_RADIOTAP_RATE u8 500kb/s */
if (!rx_status->ht_flags && !rx_status->vht_flags &&
!rx_status->he_flags) {
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
rthdr->it_present |= (1 << IEEE80211_RADIOTAP_RATE);
rtap_buf[rtap_len] = rx_status->rate;
} else
rtap_buf[rtap_len] = 0;
rtap_len += 1;
/* IEEE80211_RADIOTAP_CHANNEL 2 x __le16 MHz, bitmap */
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_CHANNEL);
rthdr->it_present |= (1 << IEEE80211_RADIOTAP_CHANNEL);
rx_status->chan_freq = radiotap_num_to_freq(rx_status->chan_num);
put_unaligned_le16(rx_status->chan_freq, &rtap_buf[rtap_len]);
rtap_len += 2;
@ -4046,17 +4062,21 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
/* IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from one milliwatt
* (dBm)
*/
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
rthdr->it_present |= (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
/*
* rssi_comb is int dB, need to convert it to dBm.
* normalize value to noise floor of -96 dBm
*/
rtap_buf[rtap_len] = rx_status->rssi_comb +
NORMALIZED_TO_NOISE_FLOOR;
rtap_buf[rtap_len] = rx_status->rssi_comb + rx_status->chan_noise_floor;
rtap_len += 1;
/* RX signal noise floor */
rthdr->it_present |= (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE);
rtap_buf[rtap_len] = (uint8_t)rx_status->chan_noise_floor;
rtap_len += 1;
/* IEEE80211_RADIOTAP_ANTENNA u8 antenna index */
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_ANTENNA);
rthdr->it_present |= (1 << IEEE80211_RADIOTAP_ANTENNA);
rtap_buf[rtap_len] = rx_status->nr_ant;
rtap_len += 1;
@ -4068,7 +4088,7 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
if (rx_status->ht_flags) {
length = rtap_len;
/* IEEE80211_RADIOTAP_VHT u8, u8, u8 */
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
rthdr->it_present |= (1 << IEEE80211_RADIOTAP_MCS);
rtap_buf[rtap_len] = IEEE80211_RADIOTAP_MCS_HAVE_BW |
IEEE80211_RADIOTAP_MCS_HAVE_MCS |
IEEE80211_RADIOTAP_MCS_HAVE_GI;
@ -4093,8 +4113,7 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
if (rx_status->rs_flags & IEEE80211_AMPDU_FLAG) {
/* IEEE80211_RADIOTAP_AMPDU_STATUS u32 u16 u8 u8 */
rthdr->it_present |=
cpu_to_le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS);
rthdr->it_present |= (1 << IEEE80211_RADIOTAP_AMPDU_STATUS);
rtap_len = qdf_nbuf_update_radiotap_ampdu_flags(rx_status,
rtap_buf,
rtap_len);
@ -4103,7 +4122,7 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
if (rx_status->vht_flags) {
length = rtap_len;
/* IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16 */
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
rthdr->it_present |= (1 << IEEE80211_RADIOTAP_VHT);
rtap_len = qdf_nbuf_update_radiotap_vht_flags(rx_status,
rtap_buf,
rtap_len);
@ -4117,7 +4136,7 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
if (rx_status->he_flags) {
length = rtap_len;
/* IEEE80211_RADIOTAP_HE */
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_HE);
rthdr->it_present |= (1 << IEEE80211_RADIOTAP_HE);
rtap_len = qdf_nbuf_update_radiotap_he_flags(rx_status,
rtap_buf,
rtap_len);
@ -4131,7 +4150,7 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
if (rx_status->he_mu_flags) {
length = rtap_len;
/* IEEE80211_RADIOTAP_HE-MU */
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_HE_MU);
rthdr->it_present |= (1 << IEEE80211_RADIOTAP_HE_MU);
rtap_len = qdf_nbuf_update_radiotap_he_mu_flags(rx_status,
rtap_buf,
rtap_len);
@ -4145,8 +4164,7 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
if (rx_status->he_mu_other_flags) {
length = rtap_len;
/* IEEE80211_RADIOTAP_HE-MU-OTHER */
rthdr->it_present |=
cpu_to_le32(1 << IEEE80211_RADIOTAP_HE_MU_OTHER);
rthdr->it_present |= (1 << IEEE80211_RADIOTAP_HE_MU_OTHER);
rtap_len =
qdf_nbuf_update_radiotap_he_mu_other_flags(rx_status,
rtap_buf,
@ -4158,7 +4176,34 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
}
}
rtap_len = qdf_align(rtap_len, 2);
/*
* Radiotap Vendor Namespace
*/
rthdr->it_present |= (1 << IEEE80211_RADIOTAP_VENDOR_NAMESPACE);
radiotap_vendor_ns_ath = (struct qdf_radiotap_vendor_ns_ath *)
(rtap_buf + rtap_len);
/*
* Copy Atheros OUI - 3 bytes (4th byte is 0)
*/
qdf_mem_copy(radiotap_vendor_ns_ath->hdr.oui, ATH_OUI, sizeof(ATH_OUI));
/*
* Name space selector = 0
* We only will have one namespace for now
*/
radiotap_vendor_ns_ath->hdr.selector = 0;
radiotap_vendor_ns_ath->hdr.skip_length = cpu_to_le16(
sizeof(*radiotap_vendor_ns_ath) -
sizeof(radiotap_vendor_ns_ath->hdr));
radiotap_vendor_ns_ath->device_id = cpu_to_le32(rx_status->device_id);
radiotap_vendor_ns_ath->lsig = cpu_to_le32(rx_status->l_sig_a_info);
radiotap_vendor_ns_ath->lsig_b = cpu_to_le32(rx_status->l_sig_b_info);
radiotap_vendor_ns_ath->ppdu_start_timestamp =
cpu_to_le32(rx_status->ppdu_timestamp);
rtap_len += sizeof(*radiotap_vendor_ns_ath);
rthdr->it_len = cpu_to_le16(rtap_len);
rthdr->it_present = cpu_to_le32(rthdr->it_present);
if (headroom_sz < rtap_len) {
qdf_err("ERROR: not enough space to update radiotap");