diff options
Diffstat (limited to 'net/mac80211/status.c')
-rw-r--r-- | net/mac80211/status.c | 112 |
1 files changed, 77 insertions, 35 deletions
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index f3d710705e76..f97fa0a54cf6 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -228,6 +228,79 @@ static void ieee80211_set_bar_pending(struct sta_info *sta, u8 tid, u16 ssn) | |||
228 | tid_tx->bar_pending = true; | 228 | tid_tx->bar_pending = true; |
229 | } | 229 | } |
230 | 230 | ||
231 | static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info) | ||
232 | { | ||
233 | int len = sizeof(struct ieee80211_radiotap_header); | ||
234 | |||
235 | /* IEEE80211_RADIOTAP_RATE rate */ | ||
236 | if (info->status.rates[0].idx >= 0 && | ||
237 | !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) | ||
238 | len += 2; | ||
239 | |||
240 | /* IEEE80211_RADIOTAP_TX_FLAGS */ | ||
241 | len += 2; | ||
242 | |||
243 | /* IEEE80211_RADIOTAP_DATA_RETRIES */ | ||
244 | len += 1; | ||
245 | |||
246 | return len; | ||
247 | } | ||
248 | |||
249 | static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band | ||
250 | *sband, struct sk_buff *skb, | ||
251 | int retry_count, int rtap_len) | ||
252 | { | ||
253 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
254 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
255 | struct ieee80211_radiotap_header *rthdr; | ||
256 | unsigned char *pos; | ||
257 | __le16 txflags; | ||
258 | |||
259 | rthdr = (struct ieee80211_radiotap_header *) skb_push(skb, rtap_len); | ||
260 | |||
261 | memset(rthdr, 0, rtap_len); | ||
262 | rthdr->it_len = cpu_to_le16(rtap_len); | ||
263 | rthdr->it_present = | ||
264 | cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | | ||
265 | (1 << IEEE80211_RADIOTAP_DATA_RETRIES)); | ||
266 | pos = (unsigned char *)(rthdr + 1); | ||
267 | |||
268 | /* | ||
269 | * XXX: Once radiotap gets the bitmap reset thing the vendor | ||
270 | * extensions proposal contains, we can actually report | ||
271 | * the whole set of tries we did. | ||
272 | */ | ||
273 | |||
274 | /* IEEE80211_RADIOTAP_RATE */ | ||
275 | if (info->status.rates[0].idx >= 0 && | ||
276 | !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) { | ||
277 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); | ||
278 | *pos = sband->bitrates[info->status.rates[0].idx].bitrate / 5; | ||
279 | /* padding for tx flags */ | ||
280 | pos += 2; | ||
281 | } | ||
282 | |||
283 | /* IEEE80211_RADIOTAP_TX_FLAGS */ | ||
284 | txflags = 0; | ||
285 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | ||
286 | !is_multicast_ether_addr(hdr->addr1)) | ||
287 | txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); | ||
288 | |||
289 | if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | ||
290 | (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
291 | txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); | ||
292 | else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) | ||
293 | txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); | ||
294 | |||
295 | put_unaligned_le16(txflags, pos); | ||
296 | pos += 2; | ||
297 | |||
298 | /* IEEE80211_RADIOTAP_DATA_RETRIES */ | ||
299 | /* for now report the total retry_count */ | ||
300 | *pos = retry_count; | ||
301 | pos++; | ||
302 | } | ||
303 | |||
231 | /* | 304 | /* |
232 | * Use a static threshold for now, best value to be determined | 305 | * Use a static threshold for now, best value to be determined |
233 | * by testing ... | 306 | * by testing ... |
@@ -246,7 +319,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
246 | u16 frag, type; | 319 | u16 frag, type; |
247 | __le16 fc; | 320 | __le16 fc; |
248 | struct ieee80211_supported_band *sband; | 321 | struct ieee80211_supported_band *sband; |
249 | struct ieee80211_tx_status_rtap_hdr *rthdr; | ||
250 | struct ieee80211_sub_if_data *sdata; | 322 | struct ieee80211_sub_if_data *sdata; |
251 | struct net_device *prev_dev = NULL; | 323 | struct net_device *prev_dev = NULL; |
252 | struct sta_info *sta, *tmp; | 324 | struct sta_info *sta, *tmp; |
@@ -256,6 +328,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
256 | bool acked; | 328 | bool acked; |
257 | struct ieee80211_bar *bar; | 329 | struct ieee80211_bar *bar; |
258 | u16 tid; | 330 | u16 tid; |
331 | int rtap_len; | ||
259 | 332 | ||
260 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 333 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
261 | if (info->status.rates[i].idx < 0) { | 334 | if (info->status.rates[i].idx < 0) { |
@@ -460,44 +533,13 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
460 | } | 533 | } |
461 | 534 | ||
462 | /* send frame to monitor interfaces now */ | 535 | /* send frame to monitor interfaces now */ |
463 | 536 | rtap_len = ieee80211_tx_radiotap_len(info); | |
464 | if (skb_headroom(skb) < sizeof(*rthdr)) { | 537 | if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) { |
465 | printk(KERN_ERR "ieee80211_tx_status: headroom too small\n"); | 538 | printk(KERN_ERR "ieee80211_tx_status: headroom too small\n"); |
466 | dev_kfree_skb(skb); | 539 | dev_kfree_skb(skb); |
467 | return; | 540 | return; |
468 | } | 541 | } |
469 | 542 | ieee80211_add_tx_radiotap_header(sband, skb, retry_count, rtap_len); | |
470 | rthdr = (struct ieee80211_tx_status_rtap_hdr *) | ||
471 | skb_push(skb, sizeof(*rthdr)); | ||
472 | |||
473 | memset(rthdr, 0, sizeof(*rthdr)); | ||
474 | rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); | ||
475 | rthdr->hdr.it_present = | ||
476 | cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | | ||
477 | (1 << IEEE80211_RADIOTAP_DATA_RETRIES) | | ||
478 | (1 << IEEE80211_RADIOTAP_RATE)); | ||
479 | |||
480 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | ||
481 | !is_multicast_ether_addr(hdr->addr1)) | ||
482 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); | ||
483 | |||
484 | /* | ||
485 | * XXX: Once radiotap gets the bitmap reset thing the vendor | ||
486 | * extensions proposal contains, we can actually report | ||
487 | * the whole set of tries we did. | ||
488 | */ | ||
489 | if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | ||
490 | (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
491 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); | ||
492 | else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) | ||
493 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); | ||
494 | if (info->status.rates[0].idx >= 0 && | ||
495 | !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) | ||
496 | rthdr->rate = sband->bitrates[ | ||
497 | info->status.rates[0].idx].bitrate / 5; | ||
498 | |||
499 | /* for now report the total retry_count */ | ||
500 | rthdr->data_retries = retry_count; | ||
501 | 543 | ||
502 | /* XXX: is this sufficient for BPF? */ | 544 | /* XXX: is this sufficient for BPF? */ |
503 | skb_set_mac_header(skb, 0); | 545 | skb_set_mac_header(skb, 0); |