Skip to content

Commit

Permalink
mac80211: report some VHT radiotap infos for tx status
Browse files Browse the repository at this point in the history
The radiotap VHT info is 12 bytes (required to be aligned on 2) :
u16 known - IEEE80211_RADIOTAP_VHT_KNOWN_*
u8 flags - IEEE80211_RADIOTAP_VHT_FLAG_*
u8 bandwidth
u8 mcs_nss[4]
u8 coding
u8 group_id
u16 partial_aid

ATM mac80211 can handle IEEE80211_RADIOTAP_VHT_KNOWN_{GI,BANDWIDTH} and
mcs_nss[0] (i.e single user) in simple cases.
This is more a placeholder to let sniffers give more clues for VHT,
since we don't have yet the proper infrastructure/conventions
in mac80211 for complete feedback (e.g consider dynamic BW).

Signed-off-by: Karl Beldan <karl.beldan@rivierawaves.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Karl Beldan authored and Johannes Berg committed Aug 1, 2013
1 parent 9e2bc79 commit a824131
Showing 1 changed file with 63 additions and 13 deletions.
76 changes: 63 additions & 13 deletions net/mac80211/status.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,8 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info)

/* IEEE80211_RADIOTAP_RATE rate */
if (info->status.rates[0].idx >= 0 &&
!(info->status.rates[0].flags & IEEE80211_TX_RC_MCS))
!(info->status.rates[0].flags & (IEEE80211_TX_RC_MCS |
IEEE80211_TX_RC_VHT_MCS)))
len += 2;

/* IEEE80211_RADIOTAP_TX_FLAGS */
Expand All @@ -244,16 +245,21 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info)
/* IEEE80211_RADIOTAP_DATA_RETRIES */
len += 1;

/* IEEE80211_TX_RC_MCS */
if (info->status.rates[0].idx >= 0 &&
info->status.rates[0].flags & IEEE80211_TX_RC_MCS)
len += 3;
/* IEEE80211_RADIOTAP_MCS
* IEEE80211_RADIOTAP_VHT */
if (info->status.rates[0].idx >= 0) {
if (info->status.rates[0].flags & IEEE80211_TX_RC_MCS)
len += 3;
else if (info->status.rates[0].flags & IEEE80211_TX_RC_VHT_MCS)
len = ALIGN(len, 2) + 12;
}

return len;
}

static void
ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,
ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
struct ieee80211_supported_band *sband,
struct sk_buff *skb, int retry_count,
int rtap_len, int shift)
{
Expand All @@ -280,7 +286,8 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,

/* IEEE80211_RADIOTAP_RATE */
if (info->status.rates[0].idx >= 0 &&
!(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) {
!(info->status.rates[0].flags & (IEEE80211_TX_RC_MCS |
IEEE80211_TX_RC_VHT_MCS))) {
u16 rate;

rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
Expand Down Expand Up @@ -310,9 +317,12 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,
*pos = retry_count;
pos++;

/* IEEE80211_TX_RC_MCS */
if (info->status.rates[0].idx >= 0 &&
info->status.rates[0].flags & IEEE80211_TX_RC_MCS) {
if (info->status.rates[0].idx < 0)
return;

/* IEEE80211_RADIOTAP_MCS
* IEEE80211_RADIOTAP_VHT */
if (info->status.rates[0].flags & IEEE80211_TX_RC_MCS) {
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
pos[0] = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
IEEE80211_RADIOTAP_MCS_HAVE_GI |
Expand All @@ -325,8 +335,48 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,
pos[1] |= IEEE80211_RADIOTAP_MCS_FMT_GF;
pos[2] = info->status.rates[0].idx;
pos += 3;
}
} else if (info->status.rates[0].flags & IEEE80211_TX_RC_VHT_MCS) {
u16 known = local->hw.radiotap_vht_details &
(IEEE80211_RADIOTAP_VHT_KNOWN_GI |
IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH);

rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);

/* required alignment from rthdr */
pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2);

/* u16 known - IEEE80211_RADIOTAP_VHT_KNOWN_* */
put_unaligned_le16(known, pos);
pos += 2;

/* u8 flags - IEEE80211_RADIOTAP_VHT_FLAG_* */
if (info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
*pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
pos++;

/* u8 bandwidth */
if (info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
*pos = 1;
else if (info->status.rates[0].flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
*pos = 4;
else if (info->status.rates[0].flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
*pos = 11;
else /* IEEE80211_TX_RC_{20_MHZ_WIDTH,FIXME:DUP_DATA} */
*pos = 0;
pos++;

/* u8 mcs_nss[4] */
*pos = (ieee80211_rate_get_vht_mcs(&info->status.rates[0]) << 4) |
ieee80211_rate_get_vht_nss(&info->status.rates[0]);
pos += 4;

/* u8 coding */
pos++;
/* u8 group_id */
pos++;
/* u16 partial_aid */
pos += 2;
}
}

static void ieee80211_report_used_skb(struct ieee80211_local *local,
Expand Down Expand Up @@ -631,8 +681,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
dev_kfree_skb(skb);
return;
}
ieee80211_add_tx_radiotap_header(sband, skb, retry_count, rtap_len,
shift);
ieee80211_add_tx_radiotap_header(local, sband, skb, retry_count,
rtap_len, shift);

/* XXX: is this sufficient for BPF? */
skb_set_mac_header(skb, 0);
Expand Down

0 comments on commit a824131

Please sign in to comment.