aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/status.c
diff options
context:
space:
mode:
authorHelmut Schaa <helmut.schaa@googlemail.com>2011-10-11 12:08:54 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-10-14 14:48:14 -0400
commita2fe81667410723d941a688e1958a49d67ca3346 (patch)
tree4330d321d7a62f50f5ec7e7f14e4f258b721e7a7 /net/mac80211/status.c
parent7bd9897e1a07d97e6297f38f741e2d1851e243b8 (diff)
mac80211: Build TX radiotap header dynamically
Get rid of the ieee80211_tx_status_rtap_hdr struct and instead build the rtap header dynamically. This makes it easier to extend the rtap header generation in the future. Add ieee80211_tx_radiotap_len to calculate the expected size of the rtap header before generating it. Since we can't check if the rtap header fits into the requested headroom during compile time anymore add a WARN_ON_ONCE. Also move the actual rtap header generation into its own function. Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/status.c')
-rw-r--r--net/mac80211/status.c112
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
231static 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
249static 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);