aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-07-05 05:34:31 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-08-20 07:53:22 -0400
commit4c29867790131c281ef96af507d85e3e5f829408 (patch)
tree9278b0314ba0108b5e9a8ab7db3c9120022be84e
parent48613ece3d6a2613caa376f51477435cc080f3cd (diff)
mac80211: support A-MPDU status reporting
Support getting A-MPDU status information from the drivers and reporting it to userspace via radiotap in the standard fields. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/mac80211.h53
-rw-r--r--net/mac80211/rx.c42
2 files changed, 80 insertions, 15 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d9cef31f4cbf..edc235c51a68 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -676,21 +676,41 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
676 * @RX_FLAG_HT_GF: This frame was received in a HT-greenfield transmission, if 676 * @RX_FLAG_HT_GF: This frame was received in a HT-greenfield transmission, if
677 * the driver fills this value it should add %IEEE80211_RADIOTAP_MCS_HAVE_FMT 677 * the driver fills this value it should add %IEEE80211_RADIOTAP_MCS_HAVE_FMT
678 * to hw.radiotap_mcs_details to advertise that fact 678 * to hw.radiotap_mcs_details to advertise that fact
679 * @RX_FLAG_AMPDU_DETAILS: A-MPDU details are known, in particular the reference
680 * number (@ampdu_reference) must be populated and be a distinct number for
681 * each A-MPDU
682 * @RX_FLAG_AMPDU_REPORT_ZEROLEN: driver reports 0-length subframes
683 * @RX_FLAG_AMPDU_IS_ZEROLEN: This is a zero-length subframe, for
684 * monitoring purposes only
685 * @RX_FLAG_AMPDU_LAST_KNOWN: last subframe is known, should be set on all
686 * subframes of a single A-MPDU
687 * @RX_FLAG_AMPDU_IS_LAST: this subframe is the last subframe of the A-MPDU
688 * @RX_FLAG_AMPDU_DELIM_CRC_ERROR: A delimiter CRC error has been detected
689 * on this subframe
690 * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC
691 * is stored in the @ampdu_delimiter_crc field)
679 */ 692 */
680enum mac80211_rx_flags { 693enum mac80211_rx_flags {
681 RX_FLAG_MMIC_ERROR = 1<<0, 694 RX_FLAG_MMIC_ERROR = BIT(0),
682 RX_FLAG_DECRYPTED = 1<<1, 695 RX_FLAG_DECRYPTED = BIT(1),
683 RX_FLAG_MMIC_STRIPPED = 1<<3, 696 RX_FLAG_MMIC_STRIPPED = BIT(3),
684 RX_FLAG_IV_STRIPPED = 1<<4, 697 RX_FLAG_IV_STRIPPED = BIT(4),
685 RX_FLAG_FAILED_FCS_CRC = 1<<5, 698 RX_FLAG_FAILED_FCS_CRC = BIT(5),
686 RX_FLAG_FAILED_PLCP_CRC = 1<<6, 699 RX_FLAG_FAILED_PLCP_CRC = BIT(6),
687 RX_FLAG_MACTIME_MPDU = 1<<7, 700 RX_FLAG_MACTIME_MPDU = BIT(7),
688 RX_FLAG_SHORTPRE = 1<<8, 701 RX_FLAG_SHORTPRE = BIT(8),
689 RX_FLAG_HT = 1<<9, 702 RX_FLAG_HT = BIT(9),
690 RX_FLAG_40MHZ = 1<<10, 703 RX_FLAG_40MHZ = BIT(10),
691 RX_FLAG_SHORT_GI = 1<<11, 704 RX_FLAG_SHORT_GI = BIT(11),
692 RX_FLAG_NO_SIGNAL_VAL = 1<<12, 705 RX_FLAG_NO_SIGNAL_VAL = BIT(12),
693 RX_FLAG_HT_GF = 1<<13, 706 RX_FLAG_HT_GF = BIT(13),
707 RX_FLAG_AMPDU_DETAILS = BIT(14),
708 RX_FLAG_AMPDU_REPORT_ZEROLEN = BIT(15),
709 RX_FLAG_AMPDU_IS_ZEROLEN = BIT(16),
710 RX_FLAG_AMPDU_LAST_KNOWN = BIT(17),
711 RX_FLAG_AMPDU_IS_LAST = BIT(18),
712 RX_FLAG_AMPDU_DELIM_CRC_ERROR = BIT(19),
713 RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(20),
694}; 714};
695 715
696/** 716/**
@@ -714,17 +734,22 @@ enum mac80211_rx_flags {
714 * HT rates are use (RX_FLAG_HT) 734 * HT rates are use (RX_FLAG_HT)
715 * @flag: %RX_FLAG_* 735 * @flag: %RX_FLAG_*
716 * @rx_flags: internal RX flags for mac80211 736 * @rx_flags: internal RX flags for mac80211
737 * @ampdu_reference: A-MPDU reference number, must be a different value for
738 * each A-MPDU but the same for each subframe within one A-MPDU
739 * @ampdu_delimiter_crc: A-MPDU delimiter CRC
717 */ 740 */
718struct ieee80211_rx_status { 741struct ieee80211_rx_status {
719 u64 mactime; 742 u64 mactime;
720 u32 device_timestamp; 743 u32 device_timestamp;
721 u16 flag; 744 u32 ampdu_reference;
745 u32 flag;
722 u16 freq; 746 u16 freq;
723 u8 rate_idx; 747 u8 rate_idx;
724 u8 rx_flags; 748 u8 rx_flags;
725 u8 band; 749 u8 band;
726 u8 antenna; 750 u8 antenna;
727 s8 signal; 751 s8 signal;
752 u8 ampdu_delimiter_crc;
728}; 753};
729 754
730/** 755/**
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 0cb4edee6af5..78bf6c7e80c8 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -60,7 +60,9 @@ static inline int should_drop_frame(struct sk_buff *skb,
60 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 60 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
61 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 61 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
62 62
63 if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) 63 if (status->flag & (RX_FLAG_FAILED_FCS_CRC |
64 RX_FLAG_FAILED_PLCP_CRC |
65 RX_FLAG_AMPDU_IS_ZEROLEN))
64 return 1; 66 return 1;
65 if (unlikely(skb->len < 16 + present_fcs_len)) 67 if (unlikely(skb->len < 16 + present_fcs_len))
66 return 1; 68 return 1;
@@ -91,6 +93,13 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local,
91 if (status->flag & RX_FLAG_HT) /* HT info */ 93 if (status->flag & RX_FLAG_HT) /* HT info */
92 len += 3; 94 len += 3;
93 95
96 if (status->flag & RX_FLAG_AMPDU_DETAILS) {
97 /* padding */
98 while (len & 3)
99 len++;
100 len += 8;
101 }
102
94 return len; 103 return len;
95} 104}
96 105
@@ -215,6 +224,37 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
215 pos++; 224 pos++;
216 *pos++ = status->rate_idx; 225 *pos++ = status->rate_idx;
217 } 226 }
227
228 if (status->flag & RX_FLAG_AMPDU_DETAILS) {
229 u16 flags = 0;
230
231 /* ensure 4 byte alignment */
232 while ((pos - (u8 *)rthdr) & 3)
233 pos++;
234 rthdr->it_present |=
235 cpu_to_le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS);
236 put_unaligned_le32(status->ampdu_reference, pos);
237 pos += 4;
238 if (status->flag & RX_FLAG_AMPDU_REPORT_ZEROLEN)
239 flags |= IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN;
240 if (status->flag & RX_FLAG_AMPDU_IS_ZEROLEN)
241 flags |= IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN;
242 if (status->flag & RX_FLAG_AMPDU_LAST_KNOWN)
243 flags |= IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN;
244 if (status->flag & RX_FLAG_AMPDU_IS_LAST)
245 flags |= IEEE80211_RADIOTAP_AMPDU_IS_LAST;
246 if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_ERROR)
247 flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR;
248 if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN)
249 flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN;
250 put_unaligned_le16(flags, pos);
251 pos += 2;
252 if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN)
253 *pos++ = status->ampdu_delimiter_crc;
254 else
255 *pos++ = 0;
256 *pos++ = 0;
257 }
218} 258}
219 259
220/* 260/*