/
ath9k_mac80211.patch
736 lines (704 loc) · 23.3 KB
/
ath9k_mac80211.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h
index 83029d6..47e9520 100644
--- a/drivers/net/wireless/ath/ath9k/ani.h
+++ b/drivers/net/wireless/ath/ath9k/ani.h
@@ -152,6 +152,9 @@ struct ar5416Stats {
u32 ast_ani_lneg_or_lzero;
u32 avgbrssi;
struct ath9k_mib_stats ast_mibstats;
+ u32 prev_ast_ani_ofdmerrs; /*_HOMESAW*/
+ u32 prev_ast_ani_cckerrs; /*_HOMESAW*/
+
};
#define ah_mibStats stats.ast_mibstats
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 93b45b4..e9345d6 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -27,6 +27,36 @@
#include "common.h"
#include "mci.h"
+#define _HOMESAW_
+#ifdef _HOMESAW_
+#include <net/ieee80211_radiotap.h>
+
+struct homesaw{
+ u_int32_t phyerr_;
+ u_int32_t cck_phyerr_;
+ u_int32_t ofdm_phyerr_;
+ u_int32_t time_buf_dur_;
+
+ u_int16_t caplen_ ;
+ int8_t rssi_ ;
+ s8 noise_ ;
+} __packed ;
+
+struct ath9k_radiotap {
+ struct ieee80211_radiotap_header hdr;
+ /* Vendor extension header */
+ u8 oui[3];
+ u8 sub_namespace;
+ __le16 skip_length;
+ //custom data structure
+ struct homesaw hs ;
+} __packed;
+
+#endif
+
+
+
+
/*
* Header for the ath9k.ko driver core *only* -- hw code nor any other driver
* should rely on this file or its contents.
@@ -230,6 +260,22 @@ struct ath_buf {
dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
bool bf_stale;
struct ath_buf_state bf_state;
+ /* _HOMESAW_ This is a clever way to modify the private/internal datastructure
+ of ath9k driver to temporarily save the enqueue timestamp of the frame
+ in the ath9k driver queue, so that one can later save the difference.
+ This is done because one can only use 40 bytes per skb, in the sk_buff
+ private data ; so we are limited by what we can communicate, but this is
+ a way around!
+ */
+#ifdef _HOMESAW_
+ u64 timestamp_temp; /*_HOMESAW_*/
+ u64 enqueue_time ; /*_HOMESAW_*/
+ u16 axq_ampdu_depth;
+ u16 axq_depth;
+ u8 axq_num;
+ u8 phy_f;
+#endif
+
};
struct ath_atx_tid {
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 356352a..8065217 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -164,6 +164,7 @@ struct ath_rx_stats {
u32 post_delim_crc_err;
u32 decrypt_busy_err;
u32 phy_err_stats[ATH9K_PHYERR_MAX];
+ u32 prev_phy_err ;/*_HOMESAW_ */
int8_t rs_rssi_ctl0;
int8_t rs_rssi_ctl1;
int8_t rs_rssi_ctl2;
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 67b862c..bd27f4e 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -434,10 +434,13 @@ void ath_rx_cleanup(struct ath_softc *sc)
u32 ath_calcrxfilter(struct ath_softc *sc)
{
u32 rfilt;
-
+ #ifndef _HOMESAW_
rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
| ATH9K_RX_FILTER_MCAST;
-
+ #else
+ rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
+ | ATH9K_RX_FILTER_MCAST| ATH9K_RX_FILTER_PHYERR ; //_HOMESAW_
+ #end
if (sc->rx.rxfilter & FIF_PROBE_REQ)
rfilt |= ATH9K_RX_FILTER_PROBEREQ;
@@ -1763,6 +1766,97 @@ div_comb_done:
antcomb->alt_recv_cnt = 0;
}
+
+#ifdef _HOMESAW_
+
+/*
+This function manipulates the sk_buff datastructure to append all
+the interesting information from the driver all the way to userland.
+One has to play with the 40 sacred private bytes in sk_buff to do this, in essence.
+*/
+void ath_rx_radiotap(struct ath_softc *sc,
+ struct sk_buff *skb,
+ struct ath_rx_status *rs,
+ u64 tsf)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ieee80211_rx_status *rxs = IEEE80211_SKB_RXCB(skb);
+ struct ieee80211_hw *hw = sc->hw;
+ struct ath9k_radiotap *rt;
+ struct ath_hw *ah = sc->sc_ah;
+ static phy_start=1;
+
+ int rt_len = sizeof(struct ath9k_radiotap) ; //ath9k_radiotap_len(sc, rs);
+
+ if (skb_headroom(skb) < rt_len &&
+ pskb_expand_head(skb, rt_len , 0, GFP_ATOMIC)) {
+ static int askb=0;
+ if(askb<3)
+ printk("not enugh in ath9k %d\n",askb++);
+ ath_dbg(common, ATH_DBG_QUEUE, "No free space for vendor radiotap\n");
+ goto fail;
+ }
+
+ rxs->flag |= RX_FLAG_HOMESAW_RADIOTAP;
+
+ rt = (struct ath9k_radiotap *)skb_push(skb, rt_len);
+ memset(rt, 0, rt_len);
+ rt->hdr.it_len = cpu_to_le16(rt_len);
+ if (rxs->flag & RX_FLAG_HOMESAW_FAILED_PHY){
+ static int kk=0;
+ if (kk<5)
+ printk("abhinav: phy errs came here %d\n",kk++);
+ }
+
+ rt->hs.time_buf_dur_=tsf-rxs->mactime ;
+ if (rt->hs.time_buf_dur_ <0){
+ rt->hs.time_buf_dur_ = rxs->mactime-tsf ;
+ }
+ static int avb2=0;
+ if(avb2<5){
+ printk("abhinav: recv_buff %llu\n", rt->hs.time_buf_dur_) ;
+ if ((unsigned long)rt % __alignof__(struct ath9k_radiotap) == 0)
+ printk("abhinav: in driver align; latest driver \n");
+ avb2++;
+ }
+ /* OUI */
+ rt->oui[0] = 0xb;
+ rt->oui[1] = 0xb;
+ rt->oui[2] = 0xb;
+ rt->sub_namespace = 1;
+ rt->skip_length =cpu_to_le16(sizeof(struct homesaw));
+ rt->hdr.it_present = BIT(0) ;
+ rxs->vendor_radiotap_len = sizeof(struct homesaw);
+ rt->hs.caplen_ = rs->rs_datalen ;
+ if(rs->rs_rssi != ATH9K_RSSI_BAD && !rs->rs_moreaggr)
+ rt->hs.rssi_ = rs->rs_rssi;
+ else
+ rt->hs.rssi_ = -127;
+
+ if (rs->rs_moreaggr)
+ rxs->flag |=RX_FLAG_HOMESAW_RX_AGGR ;
+
+ if (unlikely(phy_start)){
+ ah->stats.prev_ast_ani_ofdmerrs = ah->stats.ast_ani_ofdmerrs ;
+ ah->stats.prev_ast_ani_cckerrs = ah->stats.ast_ani_cckerrs ;
+ sc->debug.stats.rxstats.prev_phy_err= sc->debug.stats.rxstats.phy_err;
+ printk("abhinav: initializing phy errors \n");
+ phy_start=0;
+ }
+ rt->hs.ofdm_phyerr_ = ah->stats.ast_ani_ofdmerrs -ah->stats.prev_ast_ani_ofdmerrs ;
+ rt->hs.cck_phyerr_ = ah->stats.ast_ani_cckerrs -ah->stats.prev_ast_ani_cckerrs ;
+ rt->hs.phyerr_ = sc->debug.stats.rxstats.phy_err-sc->debug.stats.rxstats.prev_phy_err;
+ rt->hs.noise_ = ah->noise ;
+ ah->stats.prev_ast_ani_ofdmerrs =ah->stats.ast_ani_ofdmerrs ;
+ ah->stats.prev_ast_ani_cckerrs =ah->stats.ast_ani_cckerrs ;
+ sc->debug.stats.rxstats.prev_phy_err =sc->debug.stats.rxstats.phy_err;
+
+ fail:
+ return ;
+}
+#endif
+
+
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
{
struct ath_buf *bf;
@@ -1887,6 +1981,14 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
bf->bf_mpdu = NULL;
bf->bf_buf_addr = 0;
ath_err(common, "dma_mapping_error() on RX\n");
+#ifdef _HOMESAW_
+ ath_rx_radiotap(sc,skb,&rs,tsf);
+ if(rxs->flag & RX_FLAG_FAILED_FCS_CRC){
+ static int l=0;
+ if(l<3)
+ printk("abhinav : crc flag set before brk %d\n",l++);
+ }
+#endif
ieee80211_rx(hw, skb);
break;
}
@@ -1948,7 +2050,14 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3)
ath_ant_comb_scan(sc, &rs);
-
+#ifdef _HOMESAW_
+ ath_rx_radiotap(sc,skb,&rs,tsf);
+ if(rxs->flag & RX_FLAG_FAILED_FCS_CRC){
+ static int l_end=0;
+ if (l_end<3)
+ printk("abhinav : crc flag set at end %d\n",l_end++ );
+ }
+#endif
ieee80211_rx(hw, skb);
requeue_drop_frag:
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 55d077e..809e95f 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -315,6 +315,9 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
tbf->bf_buf_addr = bf->bf_buf_addr;
memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);
tbf->bf_state = bf->bf_state;
+ /*_HOMESAW_*/
+ tbf->timestamp_temp = bf->timestamp_temp;
+ tbf->enqueue_time = bf->enqueue_time;
return tbf;
}
@@ -1625,6 +1628,17 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
txq->axq_link = bf_last->bf_desc;
}
+ /*_HOMESAW_*/
+ /*The frame is pushed to the hardware; Enqueue timestamp stored
+ */
+ int a_d =-1, d=0;
+ u64 time_now = ath9k_hw_gettsf64(ah);
+ struct ath_buf *cur = bf;
+ while(cur) {
+ cur->enqueue_time = time_now;
+ cur = cur->bf_next ;
+ }
+
if (puttxbuf) {
TX_STAT_INC(txq->axq_qnum, puttxbuf);
ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
@@ -2037,8 +2051,10 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
struct ath_hw *ah = sc->sc_ah;
u8 i, tx_rateindex;
- if (txok)
- tx_info->status.ack_signal = ts->ts_rssi;
+
+ //if (txok) /*_HOMESAW_*/ commented out as we need space
+ //to get data out of driver to kernel
+ // tx_info->status.ack_signal = ts->ts_rssi;
tx_rateindex = ts->ts_rateindex;
WARN_ON(tx_rateindex >= hw->max_rates);
@@ -2089,6 +2105,23 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
{
int txok;
+ /*
+ abhinav's comment : This function seems like dequeue.
+ The depth of the transmit queue is decremented.
+ since ath_tx_status has all the retry counts information.
+ I calcaulate the total airtime for the frame by looping through
+ the retries, (1)the airtime for each transmision of the frame
+ (2) ACK time for
+ (3) SIFS between frames
+ (4) Last ACK
+ */
+ /*_HOMESAW_*/
+
+ u64 deq_tsf;
+ struct ath_hw *ah = sc->sc_ah;
+ deq_tsf =ath9k_hw_gettsf64(ah);
+ bf->timestamp_temp =deq_tsf ;
+
txq->axq_depth--;
txok = !(ts->ts_status & ATH9K_TXERR_MASK);
txq->axq_tx_inprogress = false;
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
index 7139254..3d2ea3c 100644
--- a/include/net/ieee80211_radiotap.h
+++ b/include/net/ieee80211_radiotap.h
@@ -205,6 +205,16 @@ enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_DATA_RETRIES = 17,
IEEE80211_RADIOTAP_MCS = 19,
+ //_HOMESAW_
+ IEEE80211_RADIOTAP_PHYERR_COUNT = 20, // For DMA counts; Check driver code for checking which flags were on
+ IEEE80211_RADIOTAP_CCK_PHYERR_COUNT = 21, // For CCK counts;
+ IEEE80211_RADIOTAP_OFDM_PHYERR_COUNT = 22, // For OFDM counts; Frames with OFDM endoding and were in error in physical layer
+ IEEE80211_RADIOTAP_TOTAL_TIME=23, // Time spend in hardware queue. Will give fine grained time information on Contention
+ IEEE80211_RADIOTAP_QUEUE_SIZES=24, // The size of the queues
+ IEEE80211_RADIOTAP_COLLECTION=25,
+ IEEE80211_RADIOTAP_CAPLEN = 26, //redundant information, this flag can be used for some other interesting information
+ IEEE80211_RADIOTAP_RSSI = 27,
+ IEEE80211_RADIOTAP_RATES_TRIED=28, // The order of rates and the number of retries on each while the device transmitted a payload
/* valid in every it_present bitmap, even vendor namespaces */
IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
@@ -237,6 +247,12 @@ enum ieee80211_radiotap_type {
* with fragmentation
*/
#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
+
+
+#define IEEE80211_RADIOTAP_F_HOMESAW_FAILED_PHY 0x20; /*frame has PHY ERR*/
+#define IEEE80211_RADIOTAP_F_HOMESAW_RX_AGG 0x10 /* received frame was aggregated frame */
+
+
#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
* 802.11 header and payload
* (to 32-bit boundary)
@@ -253,6 +269,8 @@ enum ieee80211_radiotap_type {
#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
#define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 /* don't expect an ack */
+#define IEEE80211_RADIOTAP_F_TX_AGG 0x40 /* _HOMESAW_ transmitted frame was aggregated or not.
+Understand the HT Minstrel algorithm to find out how this flag is set */
/* For IEEE80211_RADIOTAP_MCS */
#define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 48953e2..bc0e0d5 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -557,11 +557,22 @@ struct ieee80211_tx_info {
struct ieee80211_sta *sta;
} control;
struct {
- struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
- u8 ampdu_ack_len;
- int ack_signal;
- u8 ampdu_len;
- /* 15 bytes free */
+ struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
+ u8 ampdu_ack_len;
+ //int ack_signal;
+ /*
+ They are used to get the data frome the ath9k driver
+ to the kernel on the transmission side of frames.
+ */
+ u64 timestamp_tx; /*HOMESAW*/
+ u32 total_time; //difference between enqueueing and dequeueing in hardare queues
+ u16 ampdu_qsize; //The size of the 802.11 n ampdu. Its maximum size was 2 (as later verified by Felix)
+ u16 mpdu_qsize; //The size of mpdu (most of the frames are not aggregated)
+ u8 ath_qnum; // maps to 802.11 queues for traffic QoS
+ u8 tx_aggr_flag; // Flag to the mpdu received in userland was a part of AMPDU or not
+ u8 phy_flag;
+ u8 ampdu_len;
+ /* 15 bytes free ; not now ;) */
} status;
struct {
struct ieee80211_tx_rate driver_rates[
@@ -672,6 +683,11 @@ enum mac80211_rx_flags {
RX_FLAG_HT = 1<<9,
RX_FLAG_40MHZ = 1<<10,
RX_FLAG_SHORT_GI = 1<<11,
+ RX_FLAG_HOMESAW_RADIOTAP =1<<12,
+ RX_FLAG_HOMESAW_FAILED_PHY=1<<13, // for the CCK, OFDM and DMA failed CRC frame counts. They indicate the
+ // which were probably not even frames, but some fluctuation which was above the senstivity level of ath9k driver.
+ RX_FLAG_HOMESAW_RX_AGGR=1<<14, //received frame was aggregated or not
+
};
/**
@@ -703,6 +719,7 @@ struct ieee80211_rx_status {
int rate_idx;
int flag;
unsigned int rx_flags;
+ int vendor_radiotap_len ;//_HOMESAW_ // used in journey from ath9k driver to kernel
};
/**
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index ddddfbb..9ecd051 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -29,6 +29,37 @@
#include "tkip.h"
#include "wme.h"
+
+
+#ifndef _HOMESAW_
+//#define abhinav
+#define _HOMESAW_
+#endif
+
+#ifdef _HOMESAW_
+struct homesaw{
+ u_int32_t phyerr_; // capturing phy errrors which are DMAed from device to the kernel
+ u_int32_t cck_phyerr_; // PHY errors due in CCK encoding
+ u_int32_t ofdm_phyerr_; // PHY errors due in OFDM encoding
+ u_int32_t time_buf_dur_;// time difference between enqueuing and dequeuing in hardware buffer
+
+ u_int16_t caplen_ ; //capture length of
+ int8_t rssi_ ; // RSSI reported by the driver (measured in dBm)
+ s8 noise_ ; // Noise floor caliberated by the driver (measured in dBm)
+} __packed ;
+struct ath9k_radiotap {
+ struct ieee80211_radiotap_header hdr;
+
+ /* Vendor extension header */
+ u8 oui[3]; // added for tcpdump, Wireshark parser's don't break
+ u8 sub_namespace;
+ __le16 skip_length;
+ struct homesaw hs ; // header containing required information
+ //{put your additional field here properly padded per radiotap spec}
+
+} __packed;
+#endif
+
/*
* monitor mode reception
*
@@ -38,12 +69,33 @@
static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
struct sk_buff *skb)
{
+
+#ifdef _HOMESAW_
+ struct ath9k_radiotap* a9k_rthdr ;
+ struct ieee80211_radiotap_header *rthdr;
+ int len ;
+ static int db=0;
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+ if (status->flag & RX_FLAG_HOMESAW_RADIOTAP) {
+ rthdr = (struct ieee80211_radiotap_header *) skb->data;
+ a9k_rthdr = (struct ath9k_radiotap *) skb->data;
+ len= le16_to_cpu(rthdr->it_len) ;
+ if (likely(len > FCS_LEN))
+ __pskb_pull(skb,len);
+ }
+#endif
+
if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) {
if (likely(skb->len > FCS_LEN))
__pskb_trim(skb, skb->len - FCS_LEN);
else {
/* driver bug */
+#ifndef _HOMESAW_
WARN_ON(1);
+#else
+ printk("abhinav: driver bug exists! %d\n",db++);
+
+#end
dev_kfree_skb(skb);
skb = NULL;
}
@@ -88,8 +140,24 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local,
if (status->flag & RX_FLAG_HT) /* HT info */
len += 3;
-
+#ifdef _HOMESAW_
+ if (status->vendor_radiotap_len) {
+ static int al=0;
+ /* align standard part of vendor namespace */
+ len = ALIGN(len, 2);
+ /* allocate standard part of vendor namespace */
+ len += 6;
+ /* align vendor-defined part */
+ len +=sizeof(struct homesaw);
+ if (al<5)
+ printk("abhinav:eventual len = %d %d\n",len,al++);
+ }
+ return 58;
+#else
return len;
+#endif
+
+
}
/*
@@ -105,6 +173,38 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
{
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_radiotap_header *rthdr;
+ #ifdef _HOMESAW_
+ /*This part of code populates the actual radiotap header which is read
+ in userspace. It is populated from the header that was filled in driver
+ which is pealed off here and the memory reused for radiotap header */
+ struct ath9k_radiotap* a9k_rthdr ;
+ struct ath9k_radiotap *a9k_t;
+ struct ath9k_radiotap a9k ;
+ a9k_t = (struct ath9k_radiotap*) skb->data ;
+ memset(&a9k,0,sizeof(struct ath9k_radiotap));
+ a9k.hdr.it_present = a9k_t->hdr.it_present ;
+ a9k.oui[0]=a9k_t->oui[0]; //as per Radiotap spec. WireShark
+ a9k.oui[1]=a9k_t->oui[1]; // looks for this. Tcpdump parser is not so sophisticated,
+ a9k.oui[2]=a9k_t->oui[2]; // Tcpdump 4.1+ parser code is the same as Wirelshark
+ a9k.sub_namespace= a9k_t->sub_namespace;
+ a9k.skip_length =a9k_t->skip_length ;
+ a9k.hs.phyerr_ = a9k_t->hs.phyerr_ ;
+ a9k.hs.cck_phyerr_ = a9k_t->hs.cck_phyerr_ ;
+ a9k.hs.ofdm_phyerr_ = a9k_t->hs.ofdm_phyerr_ ;
+ a9k.hs.caplen_ = a9k_t->hs.caplen_ ;
+ a9k.hs.rssi_ = a9k_t->hs.rssi_ ;
+ a9k.hs.noise_ = a9k_t->hs.noise_ ;
+ a9k.hs.time_buf_dur_=a9k_t->hs.time_buf_dur_ ;
+ u16 len;
+
+ if (status->flag & RX_FLAG_HOMESAW_RADIOTAP) {
+ rthdr = (struct ieee80211_radiotap_header *) skb->data;
+ a9k_rthdr = (struct ath9k_radiotap *) skb->data;
+ len= le16_to_cpu(rthdr->it_len) ;
+ if (likely(len > FCS_LEN))
+ __pskb_pull(skb,len);
+ }
+ #endif
unsigned char *pos;
u16 rx_flags = 0;
@@ -116,7 +216,10 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
(1 << IEEE80211_RADIOTAP_CHANNEL) |
(1 << IEEE80211_RADIOTAP_ANTENNA) |
- (1 << IEEE80211_RADIOTAP_RX_FLAGS));
+ (1 << IEEE80211_RADIOTAP_RX_FLAGS) // for WireShark and Tcpdump parser
+ | (1 << IEEE80211_RADIOTAP_VENDOR_NAMESPACE)
+ | (1 << IEEE80211_RADIOTAP_EXT)
+ );
rthdr->it_len = cpu_to_le16(rtap_len);
pos = (unsigned char *)(rthdr+1);
@@ -181,7 +284,13 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
pos++;
}
-
+ /* IEEE80211_RADIOTAP_DBM_ANTNOISE */
+ #ifdef _HOMESAW_
+ rthdr->it_present |=
+ cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE);
+ *pos=a9k.hs.noise_;
+ pos++;
+ #endif
/* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */
/* IEEE80211_RADIOTAP_ANTENNA */
@@ -212,6 +321,52 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
pos++;
*pos++ = status->rate_idx;
}
+
+#ifdef _HOMESAW_
+
+ if (status->vendor_radiotap_len) {
+ /* ensure 2 byte alignment for the vendor field as required */
+ /* if ((pos - (u8 *)rthdr) & 1) {
+ *pos++ = 0;
+ static int k=0;
+ if (k<3){
+ printk("abhinav: allignment cared %d \n",k++);
+ }
+ */
+ *pos++ = a9k.oui[0];
+ *pos++ = a9k.oui[1];
+ *pos++ = a9k.oui[2];
+ *pos++ = a9k.sub_namespace;
+ put_unaligned_le16(a9k.skip_length, pos);
+ pos += 2;
+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_PHYERR_COUNT);
+ put_unaligned_le32(a9k.hs.phyerr_,pos);
+ pos +=4 ;
+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_CCK_PHYERR_COUNT);
+ put_unaligned_le32(a9k.hs.cck_phyerr_,pos);
+ pos +=4 ;
+ rthdr->it_present |= cpu_to_le32(1 <<IEEE80211_RADIOTAP_OFDM_PHYERR_COUNT);
+ put_unaligned_le32(a9k.hs.ofdm_phyerr_,pos);
+ pos +=4 ;
+ rthdr->it_present |= cpu_to_le32(1 <<IEEE80211_RADIOTAP_TOTAL_TIME);
+ put_unaligned_le32(a9k.hs.time_buf_dur_,pos);
+ pos +=4;
+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_CAPLEN);
+ put_unaligned_le16(a9k.hs.caplen_,pos) ;
+ pos +=2 ;
+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RSSI);
+ *pos = a9k.hs.rssi_ ;
+ pos++;
+ static int caleb=0;
+ if (caleb <5)
+ printk("abhinav: header %d %d\n",pos-(unsigned char*)rthdr,caleb++);
+ }
+
+#endif
+
+
+
+
}
/*
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index a9da6ee..29ba0aa 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -16,6 +16,7 @@
#include "mesh.h"
#include "led.h"
#include "wme.h"
+#define _HOMESAW_
void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
@@ -248,13 +249,27 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info)
if (info->status.rates[0].idx >= 0 &&
info->status.rates[0].flags & IEEE80211_TX_RC_MCS)
len += 3;
-
+#ifdef _HOMESAW_
+ len +=8;
+ len +=10;
+ len +=7;
+ static int gore=0;
+ if (gore <5) {
+ printk("abhinav:tx len=%d %d\n",len,gore++);
+ }
+ return 48;
+#endif
return len;
}
static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band
*sband, struct sk_buff *skb,
- int retry_count, int rtap_len)
+ int retry_count, int rtap_len
+#ifdef _HOMESAW_
+ , struct ieee80211_hw* hw
+#endif
+ )
+
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -322,6 +337,43 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band
pos[2] = info->status.rates[0].idx;
pos += 3;
}
+#ifdef _HOMESAW_
+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_TOTAL_TIME);
+ put_unaligned_le64(info->status.total_time,pos);
+ pos +=4;
+
+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_QUEUE_SIZES);
+ put_unaligned_le16(info->status.mpdu_qsize,pos);
+ pos +=2;
+ put_unaligned_le16(info->status.ampdu_qsize,pos);
+ pos +=2;
+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_COLLECTION);
+ *pos=info->status.phy_flag;
+ pos++;
+ *pos=info->status.ath_qnum;
+ pos++;
+ unsigned char * temp=pos ;
+ int i ;
+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATES_TRIED);
+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+ if (info->status.rates[i].idx < 0) {
+ break;
+ } else if (i >= hw->max_report_rates) {
+ /* the HW cannot have attempted that rate */
+ //info->status.rates[i].idx = -1;
+ //info->status.rates[i].count = 0;
+ break;
+ }
+ *pos= info->status.rates[i].idx;
+ pos++;
+ *pos= info->status.rates[i].count ;
+ pos++;
+ *pos= info->status.rates[i].flags;
+ pos++;
+ }
+ pos= temp+15;
+ *pos=0x9;
+#endif
}
@@ -585,12 +637,24 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
/* send frame to monitor interfaces now */
rtap_len = ieee80211_tx_radiotap_len(info);
+#ifndef _HOMESAW_
if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
printk(KERN_ERR "ieee80211_tx_status: headroom too small\n");
+#else
+ if(pskb_expand_head(skb, rtap_len, 0, GFP_ATOMIC)<0){
+ printk(KERN_ERR "ieee80211_tx_status: can't allocate headroom for HOMESAW\n");
+#endif
+
dev_kfree_skb(skb);
return;
}
- ieee80211_add_tx_radiotap_header(sband, skb, retry_count, rtap_len);
+ ieee80211_add_tx_radiotap_header(sband, skb, retry_count, rtap_len
+#ifdef _HOMESAW_
+ ,hw);
+#else
+ );
+#endif
+
/* XXX: is this sufficient for BPF? */
skb_set_mac_header(skb, 0);