aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/status.c
diff options
context:
space:
mode:
authorKarl Beldan <karl.beldan@rivierawaves.com>2013-07-27 05:47:04 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-08-01 04:49:04 -0400
commita824131017a2c3c8f275c6eb46740cfb8a43f7c5 (patch)
treef6d634a12d72cbd6dd7b5d38457b28a2604445cc /net/mac80211/status.c
parent9e2bc79bce58a1ce0005015c9351b3bcaaa02e5c (diff)
mac80211: report some VHT radiotap infos for tx status
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>
Diffstat (limited to 'net/mac80211/status.c')
-rw-r--r--net/mac80211/status.c76
1 files changed, 63 insertions, 13 deletions
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 8eabfd96ca36..368837fe3b80 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -235,7 +235,8 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info)
235 235
236 /* IEEE80211_RADIOTAP_RATE rate */ 236 /* IEEE80211_RADIOTAP_RATE rate */
237 if (info->status.rates[0].idx >= 0 && 237 if (info->status.rates[0].idx >= 0 &&
238 !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) 238 !(info->status.rates[0].flags & (IEEE80211_TX_RC_MCS |
239 IEEE80211_TX_RC_VHT_MCS)))
239 len += 2; 240 len += 2;
240 241
241 /* IEEE80211_RADIOTAP_TX_FLAGS */ 242 /* IEEE80211_RADIOTAP_TX_FLAGS */
@@ -244,16 +245,21 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info)
244 /* IEEE80211_RADIOTAP_DATA_RETRIES */ 245 /* IEEE80211_RADIOTAP_DATA_RETRIES */
245 len += 1; 246 len += 1;
246 247
247 /* IEEE80211_TX_RC_MCS */ 248 /* IEEE80211_RADIOTAP_MCS
248 if (info->status.rates[0].idx >= 0 && 249 * IEEE80211_RADIOTAP_VHT */
249 info->status.rates[0].flags & IEEE80211_TX_RC_MCS) 250 if (info->status.rates[0].idx >= 0) {
250 len += 3; 251 if (info->status.rates[0].flags & IEEE80211_TX_RC_MCS)
252 len += 3;
253 else if (info->status.rates[0].flags & IEEE80211_TX_RC_VHT_MCS)
254 len = ALIGN(len, 2) + 12;
255 }
251 256
252 return len; 257 return len;
253} 258}
254 259
255static void 260static void
256ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband, 261ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
262 struct ieee80211_supported_band *sband,
257 struct sk_buff *skb, int retry_count, 263 struct sk_buff *skb, int retry_count,
258 int rtap_len, int shift) 264 int rtap_len, int shift)
259{ 265{
@@ -280,7 +286,8 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,
280 286
281 /* IEEE80211_RADIOTAP_RATE */ 287 /* IEEE80211_RADIOTAP_RATE */
282 if (info->status.rates[0].idx >= 0 && 288 if (info->status.rates[0].idx >= 0 &&
283 !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) { 289 !(info->status.rates[0].flags & (IEEE80211_TX_RC_MCS |
290 IEEE80211_TX_RC_VHT_MCS))) {
284 u16 rate; 291 u16 rate;
285 292
286 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); 293 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
@@ -310,9 +317,12 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,
310 *pos = retry_count; 317 *pos = retry_count;
311 pos++; 318 pos++;
312 319
313 /* IEEE80211_TX_RC_MCS */ 320 if (info->status.rates[0].idx < 0)
314 if (info->status.rates[0].idx >= 0 && 321 return;
315 info->status.rates[0].flags & IEEE80211_TX_RC_MCS) { 322
323 /* IEEE80211_RADIOTAP_MCS
324 * IEEE80211_RADIOTAP_VHT */
325 if (info->status.rates[0].flags & IEEE80211_TX_RC_MCS) {
316 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS); 326 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
317 pos[0] = IEEE80211_RADIOTAP_MCS_HAVE_MCS | 327 pos[0] = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
318 IEEE80211_RADIOTAP_MCS_HAVE_GI | 328 IEEE80211_RADIOTAP_MCS_HAVE_GI |
@@ -325,8 +335,48 @@ ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband,
325 pos[1] |= IEEE80211_RADIOTAP_MCS_FMT_GF; 335 pos[1] |= IEEE80211_RADIOTAP_MCS_FMT_GF;
326 pos[2] = info->status.rates[0].idx; 336 pos[2] = info->status.rates[0].idx;
327 pos += 3; 337 pos += 3;
328 } 338 } else if (info->status.rates[0].flags & IEEE80211_TX_RC_VHT_MCS) {
339 u16 known = local->hw.radiotap_vht_details &
340 (IEEE80211_RADIOTAP_VHT_KNOWN_GI |
341 IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH);
342
343 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
344
345 /* required alignment from rthdr */
346 pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2);
329 347
348 /* u16 known - IEEE80211_RADIOTAP_VHT_KNOWN_* */
349 put_unaligned_le16(known, pos);
350 pos += 2;
351
352 /* u8 flags - IEEE80211_RADIOTAP_VHT_FLAG_* */
353 if (info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
354 *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
355 pos++;
356
357 /* u8 bandwidth */
358 if (info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
359 *pos = 1;
360 else if (info->status.rates[0].flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
361 *pos = 4;
362 else if (info->status.rates[0].flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
363 *pos = 11;
364 else /* IEEE80211_TX_RC_{20_MHZ_WIDTH,FIXME:DUP_DATA} */
365 *pos = 0;
366 pos++;
367
368 /* u8 mcs_nss[4] */
369 *pos = (ieee80211_rate_get_vht_mcs(&info->status.rates[0]) << 4) |
370 ieee80211_rate_get_vht_nss(&info->status.rates[0]);
371 pos += 4;
372
373 /* u8 coding */
374 pos++;
375 /* u8 group_id */
376 pos++;
377 /* u16 partial_aid */
378 pos += 2;
379 }
330} 380}
331 381
332static void ieee80211_report_used_skb(struct ieee80211_local *local, 382static void ieee80211_report_used_skb(struct ieee80211_local *local,
@@ -631,8 +681,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
631 dev_kfree_skb(skb); 681 dev_kfree_skb(skb);
632 return; 682 return;
633 } 683 }
634 ieee80211_add_tx_radiotap_header(sband, skb, retry_count, rtap_len, 684 ieee80211_add_tx_radiotap_header(local, sband, skb, retry_count,
635 shift); 685 rtap_len, shift);
636 686
637 /* XXX: is this sufficient for BPF? */ 687 /* XXX: is this sufficient for BPF? */
638 skb_set_mac_header(skb, 0); 688 skb_set_mac_header(skb, 0);