Commit d1332e7b authored by Shaul Triebitz's avatar Shaul Triebitz Committed by Johannes Berg

mac80211: support radiotap L-SIG data

As before with HE, the data needs to be provided by the
driver in the skb head, since there's not enough space
in the skb CB.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarShaul Triebitz <shaul.triebitz@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 70e53669
...@@ -75,6 +75,7 @@ enum ieee80211_radiotap_presence { ...@@ -75,6 +75,7 @@ enum ieee80211_radiotap_presence {
IEEE80211_RADIOTAP_TIMESTAMP = 22, IEEE80211_RADIOTAP_TIMESTAMP = 22,
IEEE80211_RADIOTAP_HE = 23, IEEE80211_RADIOTAP_HE = 23,
IEEE80211_RADIOTAP_HE_MU = 24, IEEE80211_RADIOTAP_HE_MU = 24,
IEEE80211_RADIOTAP_LSIG = 27,
/* valid in every it_present bitmap, even vendor namespaces */ /* valid in every it_present bitmap, even vendor namespaces */
IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
...@@ -325,6 +326,20 @@ enum ieee80211_radiotap_he_mu_bits { ...@@ -325,6 +326,20 @@ enum ieee80211_radiotap_he_mu_bits {
IEEE80211_RADIOTAP_HE_MU_FLAGS2_CH2_CTR_26T_RU = 0x0800, IEEE80211_RADIOTAP_HE_MU_FLAGS2_CH2_CTR_26T_RU = 0x0800,
}; };
enum ieee80211_radiotap_lsig_data1 {
IEEE80211_RADIOTAP_LSIG_DATA1_RATE_KNOWN = 0x0001,
IEEE80211_RADIOTAP_LSIG_DATA1_LENGTH_KNOWN = 0x0002,
};
enum ieee80211_radiotap_lsig_data2 {
IEEE80211_RADIOTAP_LSIG_DATA2_RATE = 0x000f,
IEEE80211_RADIOTAP_LSIG_DATA2_LENGTH = 0xfff0,
};
struct ieee80211_radiotap_lsig {
__le16 data1, data2;
};
/** /**
* ieee80211_get_radiotap_len - get radiotap header length * ieee80211_get_radiotap_len - get radiotap header length
*/ */
......
...@@ -1141,6 +1141,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) ...@@ -1141,6 +1141,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* from the RX info data, so leave those zeroed when building this data) * from the RX info data, so leave those zeroed when building this data)
* @RX_FLAG_RADIOTAP_HE_MU: HE MU radiotap data is present * @RX_FLAG_RADIOTAP_HE_MU: HE MU radiotap data is present
* (&struct ieee80211_radiotap_he_mu) * (&struct ieee80211_radiotap_he_mu)
* @RX_FLAG_RADIOTAP_LSIG: L-SIG radiotap data is present
*/ */
enum mac80211_rx_flags { enum mac80211_rx_flags {
RX_FLAG_MMIC_ERROR = BIT(0), RX_FLAG_MMIC_ERROR = BIT(0),
...@@ -1171,6 +1172,7 @@ enum mac80211_rx_flags { ...@@ -1171,6 +1172,7 @@ enum mac80211_rx_flags {
RX_FLAG_AMPDU_EOF_BIT_KNOWN = BIT(25), RX_FLAG_AMPDU_EOF_BIT_KNOWN = BIT(25),
RX_FLAG_RADIOTAP_HE = BIT(26), RX_FLAG_RADIOTAP_HE = BIT(26),
RX_FLAG_RADIOTAP_HE_MU = BIT(27), RX_FLAG_RADIOTAP_HE_MU = BIT(27),
RX_FLAG_RADIOTAP_LSIG = BIT(28),
}; };
/** /**
......
...@@ -189,6 +189,12 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local, ...@@ -189,6 +189,12 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local,
BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he_mu) != 12); BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he_mu) != 12);
} }
if (status->flag & RX_FLAG_RADIOTAP_LSIG) {
len = ALIGN(len, 2);
len += 4;
BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_lsig) != 4);
}
if (status->chains) { if (status->chains) {
/* antenna and antenna signal fields */ /* antenna and antenna signal fields */
len += 2 * hweight8(status->chains); len += 2 * hweight8(status->chains);
...@@ -279,6 +285,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, ...@@ -279,6 +285,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
struct ieee80211_vendor_radiotap rtap = {}; struct ieee80211_vendor_radiotap rtap = {};
struct ieee80211_radiotap_he he = {}; struct ieee80211_radiotap_he he = {};
struct ieee80211_radiotap_he_mu he_mu = {}; struct ieee80211_radiotap_he_mu he_mu = {};
struct ieee80211_radiotap_lsig lsig = {};
if (status->flag & RX_FLAG_RADIOTAP_HE) { if (status->flag & RX_FLAG_RADIOTAP_HE) {
he = *(struct ieee80211_radiotap_he *)skb->data; he = *(struct ieee80211_radiotap_he *)skb->data;
...@@ -291,6 +298,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, ...@@ -291,6 +298,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
skb_pull(skb, sizeof(he_mu)); skb_pull(skb, sizeof(he_mu));
} }
if (status->flag & RX_FLAG_RADIOTAP_LSIG) {
lsig = *(struct ieee80211_radiotap_lsig *)skb->data;
skb_pull(skb, sizeof(lsig));
}
if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) { if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
rtap = *(struct ieee80211_vendor_radiotap *)skb->data; rtap = *(struct ieee80211_vendor_radiotap *)skb->data;
/* rtap.len and rtap.pad are undone immediately */ /* rtap.len and rtap.pad are undone immediately */
...@@ -630,6 +642,15 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, ...@@ -630,6 +642,15 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
pos += sizeof(he_mu); pos += sizeof(he_mu);
} }
if (status->flag & RX_FLAG_RADIOTAP_LSIG) {
/* ensure 2 byte alignment */
while ((pos - (u8 *)rthdr) & 1)
pos++;
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_LSIG);
memcpy(pos, &lsig, sizeof(lsig));
pos += sizeof(lsig);
}
for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) { for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) {
*pos++ = status->chain_signal[chain]; *pos++ = status->chain_signal[chain];
*pos++ = chain; *pos++ = chain;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment