|
@@ -4813,6 +4813,102 @@ qdf_nbuf_update_radiotap_he_mu_other_flags(struct mon_rx_status *rx_status,
|
|
|
return rtap_len;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * qdf_nbuf_update_radiotap_usig_flags() - Update radiotap header with USIG data
|
|
|
+ * from rx_status
|
|
|
+ * @rx_status: Pointer to rx_status.
|
|
|
+ * @rtap_buf: buffer to which radiotap has to be updated
|
|
|
+ * @rtap_len: radiotap length
|
|
|
+ *
|
|
|
+ * API update Extra High Throughput (11be) fields in the radiotap header
|
|
|
+ *
|
|
|
+ * Return: length of rtap_len updated.
|
|
|
+ */
|
|
|
+static unsigned int
|
|
|
+qdf_nbuf_update_radiotap_usig_flags(struct mon_rx_status *rx_status,
|
|
|
+ int8_t *rtap_buf, uint32_t rtap_len)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * IEEE80211_RADIOTAP_USIG:
|
|
|
+ * u32, u32, u32
|
|
|
+ */
|
|
|
+ rtap_len = qdf_align(rtap_len, 4);
|
|
|
+
|
|
|
+ put_unaligned_le32(rx_status->usig_common, &rtap_buf[rtap_len]);
|
|
|
+ rtap_len += 4;
|
|
|
+
|
|
|
+ put_unaligned_le32(rx_status->usig_value, &rtap_buf[rtap_len]);
|
|
|
+ rtap_len += 4;
|
|
|
+
|
|
|
+ put_unaligned_le32(rx_status->usig_mask, &rtap_buf[rtap_len]);
|
|
|
+ rtap_len += 4;
|
|
|
+
|
|
|
+ qdf_rl_debug("U-SIG data %x %x %x",
|
|
|
+ rx_status->usig_common, rx_status->usig_value,
|
|
|
+ rx_status->usig_mask);
|
|
|
+
|
|
|
+ return rtap_len;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * qdf_nbuf_update_radiotap_eht_flags() - Update radiotap header with EHT data
|
|
|
+ * from rx_status
|
|
|
+ * @rx_status: Pointer to rx_status.
|
|
|
+ * @rtap_buf: buffer to which radiotap has to be updated
|
|
|
+ * @rtap_len: radiotap length
|
|
|
+ *
|
|
|
+ * API update Extra High Throughput (11be) fields in the radiotap header
|
|
|
+ *
|
|
|
+ * Return: length of rtap_len updated.
|
|
|
+ */
|
|
|
+static unsigned int
|
|
|
+qdf_nbuf_update_radiotap_eht_flags(struct mon_rx_status *rx_status,
|
|
|
+ int8_t *rtap_buf, uint32_t rtap_len)
|
|
|
+{
|
|
|
+ uint32_t user;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * IEEE80211_RADIOTAP_EHT:
|
|
|
+ * u32, u32, u32, u32, u32, u32, u32, u16, [u32, u32, u32]
|
|
|
+ */
|
|
|
+ rtap_len = qdf_align(rtap_len, 4);
|
|
|
+
|
|
|
+ put_unaligned_le32(rx_status->eht_known, &rtap_buf[rtap_len]);
|
|
|
+ rtap_len += 4;
|
|
|
+
|
|
|
+ put_unaligned_le32(rx_status->eht_data[0], &rtap_buf[rtap_len]);
|
|
|
+ rtap_len += 4;
|
|
|
+
|
|
|
+ put_unaligned_le32(rx_status->eht_data[1], &rtap_buf[rtap_len]);
|
|
|
+ rtap_len += 4;
|
|
|
+
|
|
|
+ put_unaligned_le32(rx_status->eht_data[2], &rtap_buf[rtap_len]);
|
|
|
+ rtap_len += 4;
|
|
|
+
|
|
|
+ put_unaligned_le32(rx_status->eht_data[3], &rtap_buf[rtap_len]);
|
|
|
+ rtap_len += 4;
|
|
|
+
|
|
|
+ put_unaligned_le32(rx_status->eht_data[4], &rtap_buf[rtap_len]);
|
|
|
+ rtap_len += 4;
|
|
|
+
|
|
|
+ put_unaligned_le32(rx_status->eht_data[5], &rtap_buf[rtap_len]);
|
|
|
+ rtap_len += 4;
|
|
|
+
|
|
|
+ for (user = 0; user < rx_status->num_eht_user_info_valid; user++) {
|
|
|
+ put_unaligned_le32(rx_status->eht_user_info[user],
|
|
|
+ &rtap_buf[rtap_len]);
|
|
|
+ rtap_len += 4;
|
|
|
+ }
|
|
|
+
|
|
|
+ qdf_rl_debug("EHT data %x %x %x %x %x %x %x",
|
|
|
+ rx_status->eht_known, rx_status->eht_data[0],
|
|
|
+ rx_status->eht_data[1], rx_status->eht_data[2],
|
|
|
+ rx_status->eht_data[3], rx_status->eht_data[4],
|
|
|
+ rx_status->eht_data[5]);
|
|
|
+
|
|
|
+ return rtap_len;
|
|
|
+}
|
|
|
+
|
|
|
#define IEEE80211_RADIOTAP_TX_STATUS 0
|
|
|
#define IEEE80211_RADIOTAP_RETRY_COUNT 1
|
|
|
#define IEEE80211_RADIOTAP_EXTENSION2 2
|
|
@@ -4879,25 +4975,32 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
|
|
|
uint8_t length = rtap_len;
|
|
|
struct qdf_radiotap_vendor_ns_ath *radiotap_vendor_ns_ath;
|
|
|
struct qdf_radiotap_ext2 *rtap_ext2;
|
|
|
- uint32_t *rtap_ext = NULL;
|
|
|
struct mon_rx_user_status *rx_user_status = rx_status->rx_user_status;
|
|
|
|
|
|
/* per user info */
|
|
|
+ qdf_le32_t *it_present;
|
|
|
+ uint32_t it_present_val;
|
|
|
+ bool radiotap_ext1_hdr_present = false;
|
|
|
+
|
|
|
+ it_present = &rthdr->it_present;
|
|
|
|
|
|
/* Adding Extended Header space */
|
|
|
- if (rx_status->add_rtap_ext) {
|
|
|
+ if (rx_status->add_rtap_ext || rx_status->add_rtap_ext2 ||
|
|
|
+ rx_status->usig_flags || rx_status->eht_flags) {
|
|
|
rtap_hdr_len += RADIOTAP_HEADER_EXT_LEN;
|
|
|
rtap_len = rtap_hdr_len;
|
|
|
+ radiotap_ext1_hdr_present = true;
|
|
|
}
|
|
|
+
|
|
|
length = rtap_len;
|
|
|
|
|
|
/* IEEE80211_RADIOTAP_TSFT __le64 microseconds*/
|
|
|
- rthdr->it_present = (1 << IEEE80211_RADIOTAP_TSFT);
|
|
|
+ it_present_val = (1 << IEEE80211_RADIOTAP_TSFT);
|
|
|
put_unaligned_le64(rx_status->tsft, &rtap_buf[rtap_len]);
|
|
|
rtap_len += 8;
|
|
|
|
|
|
/* IEEE80211_RADIOTAP_FLAGS u8 */
|
|
|
- rthdr->it_present |= (1 << IEEE80211_RADIOTAP_FLAGS);
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_FLAGS);
|
|
|
|
|
|
if (rx_status->rs_fcs_err)
|
|
|
rx_status->rtap_flags |= IEEE80211_RADIOTAP_F_BADFCS;
|
|
@@ -4908,14 +5011,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 |= (1 << IEEE80211_RADIOTAP_RATE);
|
|
|
+ it_present_val |= (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 |= (1 << IEEE80211_RADIOTAP_CHANNEL);
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_CHANNEL);
|
|
|
put_unaligned_le16(rx_status->chan_freq, &rtap_buf[rtap_len]);
|
|
|
rtap_len += 2;
|
|
|
/* Channel flags. */
|
|
@@ -4933,7 +5036,7 @@ 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 |= (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
|
|
|
/*
|
|
|
* rssi_comb is int dB, need to convert it to dBm.
|
|
|
* normalize value to noise floor of -96 dBm
|
|
@@ -4942,12 +5045,12 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
|
|
|
rtap_len += 1;
|
|
|
|
|
|
/* RX signal noise floor */
|
|
|
- rthdr->it_present |= (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE);
|
|
|
+ it_present_val |= (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 |= (1 << IEEE80211_RADIOTAP_ANTENNA);
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_ANTENNA);
|
|
|
rtap_buf[rtap_len] = rx_status->nr_ant;
|
|
|
rtap_len += 1;
|
|
|
|
|
@@ -4959,7 +5062,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 |= (1 << IEEE80211_RADIOTAP_MCS);
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_MCS);
|
|
|
rtap_buf[rtap_len] = IEEE80211_RADIOTAP_MCS_HAVE_BW |
|
|
|
IEEE80211_RADIOTAP_MCS_HAVE_MCS |
|
|
|
IEEE80211_RADIOTAP_MCS_HAVE_GI;
|
|
@@ -4984,7 +5087,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 |= (1 << IEEE80211_RADIOTAP_AMPDU_STATUS);
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_AMPDU_STATUS);
|
|
|
rtap_len = qdf_nbuf_update_radiotap_ampdu_flags(rx_status,
|
|
|
rtap_buf,
|
|
|
rtap_len);
|
|
@@ -4993,7 +5096,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 |= (1 << IEEE80211_RADIOTAP_VHT);
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_VHT);
|
|
|
rtap_len = qdf_nbuf_update_radiotap_vht_flags(rx_status,
|
|
|
rtap_buf,
|
|
|
rtap_len);
|
|
@@ -5007,7 +5110,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 |= (1 << IEEE80211_RADIOTAP_HE);
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_HE);
|
|
|
rtap_len = qdf_nbuf_update_radiotap_he_flags(rx_status,
|
|
|
rtap_buf,
|
|
|
rtap_len);
|
|
@@ -5021,7 +5124,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 |= (1 << IEEE80211_RADIOTAP_HE_MU);
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_HE_MU);
|
|
|
rtap_len = qdf_nbuf_update_radiotap_he_mu_flags(rx_status,
|
|
|
rtap_buf,
|
|
|
rtap_len);
|
|
@@ -5035,7 +5138,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 |= (1 << IEEE80211_RADIOTAP_HE_MU_OTHER);
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_HE_MU_OTHER);
|
|
|
rtap_len =
|
|
|
qdf_nbuf_update_radiotap_he_mu_other_flags(rx_status,
|
|
|
rtap_buf,
|
|
@@ -5051,7 +5154,7 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
|
|
|
/*
|
|
|
* Radiotap Vendor Namespace
|
|
|
*/
|
|
|
- rthdr->it_present |= (1 << IEEE80211_RADIOTAP_VENDOR_NAMESPACE);
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_VENDOR_NAMESPACE);
|
|
|
radiotap_vendor_ns_ath = (struct qdf_radiotap_vendor_ns_ath *)
|
|
|
(rtap_buf + rtap_len);
|
|
|
/*
|
|
@@ -5073,13 +5176,18 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
|
|
|
cpu_to_le32(rx_status->ppdu_timestamp);
|
|
|
rtap_len += sizeof(*radiotap_vendor_ns_ath);
|
|
|
|
|
|
+ /* Move to next it_present */
|
|
|
+ if (radiotap_ext1_hdr_present) {
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_EXT);
|
|
|
+ put_unaligned_le32(it_present_val, it_present);
|
|
|
+ it_present_val = 0;
|
|
|
+ it_present++;
|
|
|
+ }
|
|
|
+
|
|
|
/* Add Extension to Radiotap Header & corresponding data */
|
|
|
if (rx_status->add_rtap_ext) {
|
|
|
- rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_EXT);
|
|
|
- rtap_ext = (uint32_t *)&rthdr->it_present;
|
|
|
- rtap_ext++;
|
|
|
- *rtap_ext = cpu_to_le32(1 << IEEE80211_RADIOTAP_TX_STATUS);
|
|
|
- *rtap_ext |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RETRY_COUNT);
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_TX_STATUS);
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_RETRY_COUNT);
|
|
|
|
|
|
rtap_buf[rtap_len] = rx_status->tx_status;
|
|
|
rtap_len += 1;
|
|
@@ -5089,10 +5197,7 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
|
|
|
|
|
|
/* Add Extension2 to Radiotap Header */
|
|
|
if (rx_status->add_rtap_ext2) {
|
|
|
- rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_EXT);
|
|
|
- rtap_ext = (uint32_t *)&rthdr->it_present;
|
|
|
- rtap_ext++;
|
|
|
- *rtap_ext |= cpu_to_le32(1 << IEEE80211_RADIOTAP_EXTENSION2);
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_EXTENSION2);
|
|
|
|
|
|
rtap_ext2 = (struct qdf_radiotap_ext2 *)(rtap_buf + rtap_len);
|
|
|
rtap_ext2->ppdu_id = rx_status->ppdu_id;
|
|
@@ -5118,13 +5223,42 @@ unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
|
|
|
rtap_len += sizeof(*rtap_ext2);
|
|
|
}
|
|
|
|
|
|
+ if (rx_status->usig_flags) {
|
|
|
+ length = rtap_len;
|
|
|
+ /* IEEE80211_RADIOTAP_USIG */
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_EXT1_USIG);
|
|
|
+ rtap_len = qdf_nbuf_update_radiotap_usig_flags(rx_status,
|
|
|
+ rtap_buf,
|
|
|
+ rtap_len);
|
|
|
+
|
|
|
+ if ((rtap_len - length) > RADIOTAP_EHT_FLAGS_LEN) {
|
|
|
+ qdf_print("length is greater than RADIOTAP_EHT_FLAGS_LEN");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (rx_status->eht_flags) {
|
|
|
+ length = rtap_len;
|
|
|
+ /* IEEE80211_RADIOTAP_EHT */
|
|
|
+ it_present_val |= (1 << IEEE80211_RADIOTAP_EXT1_EHT);
|
|
|
+ rtap_len = qdf_nbuf_update_radiotap_eht_flags(rx_status,
|
|
|
+ rtap_buf,
|
|
|
+ rtap_len);
|
|
|
+
|
|
|
+ if ((rtap_len - length) > RADIOTAP_EHT_FLAGS_LEN) {
|
|
|
+ qdf_print("length is greater than RADIOTAP_EHT_FLAGS_LEN");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ put_unaligned_le32(it_present_val, it_present);
|
|
|
rthdr->it_len = cpu_to_le16(rtap_len);
|
|
|
- rthdr->it_present = cpu_to_le32(rthdr->it_present);
|
|
|
|
|
|
if (headroom_sz < rtap_len) {
|
|
|
qdf_debug("DEBUG: Not enough space to update radiotap");
|
|
|
return 0;
|
|
|
}
|
|
|
+
|
|
|
qdf_nbuf_push_head(nbuf, rtap_len);
|
|
|
qdf_mem_copy(qdf_nbuf_data(nbuf), rtap_buf, rtap_len);
|
|
|
return rtap_len;
|