aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-11-22 17:00:18 -0500
committerJohannes Berg <johannes.berg@intel.com>2012-11-27 05:56:18 -0500
commit5164892184d1b9ce19e45e97e9ca405ea8b9ceb2 (patch)
tree011ba3d92ccf3b10f34ffff9c0ea09d339521a49
parentf2d9d270c15ae0139b54a7e7466d738327e97e03 (diff)
mac80211: support (partial) VHT radiotap information
Add some information that we have about VHT to radiotap. This at least lets one see the MCS and NSS information. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/ieee80211_radiotap.h24
-rw-r--r--include/net/mac80211.h5
-rw-r--r--net/mac80211/main.c2
-rw-r--r--net/mac80211/rx.c40
4 files changed, 71 insertions, 0 deletions
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
index 7f0df133d11..c3999632e61 100644
--- a/include/net/ieee80211_radiotap.h
+++ b/include/net/ieee80211_radiotap.h
@@ -186,6 +186,10 @@ struct ieee80211_radiotap_header {
186 * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless 186 * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless
187 * 187 *
188 * Contains the AMPDU information for the subframe. 188 * Contains the AMPDU information for the subframe.
189 *
190 * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16
191 *
192 * Contains VHT information about this frame.
189 */ 193 */
190enum ieee80211_radiotap_type { 194enum ieee80211_radiotap_type {
191 IEEE80211_RADIOTAP_TSFT = 0, 195 IEEE80211_RADIOTAP_TSFT = 0,
@@ -209,6 +213,7 @@ enum ieee80211_radiotap_type {
209 213
210 IEEE80211_RADIOTAP_MCS = 19, 214 IEEE80211_RADIOTAP_MCS = 19,
211 IEEE80211_RADIOTAP_AMPDU_STATUS = 20, 215 IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
216 IEEE80211_RADIOTAP_VHT = 21,
212 217
213 /* valid in every it_present bitmap, even vendor namespaces */ 218 /* valid in every it_present bitmap, even vendor namespaces */
214 IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, 219 IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
@@ -282,6 +287,25 @@ enum ieee80211_radiotap_type {
282#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 287#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010
283#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 288#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020
284 289
290/* For IEEE80211_RADIOTAP_VHT */
291#define IEEE80211_RADIOTAP_VHT_KNOWN_STBC 0x0001
292#define IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA 0x0002
293#define IEEE80211_RADIOTAP_VHT_KNOWN_GI 0x0004
294#define IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS 0x0008
295#define IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM 0x0010
296#define IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED 0x0020
297#define IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH 0x0040
298#define IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID 0x0080
299#define IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID 0x0100
300
301#define IEEE80211_RADIOTAP_VHT_FLAG_STBC 0x01
302#define IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA 0x02
303#define IEEE80211_RADIOTAP_VHT_FLAG_SGI 0x04
304#define IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 0x08
305#define IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM 0x10
306#define IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED 0x20
307
308
285/* helpers */ 309/* helpers */
286static inline int ieee80211_get_radiotap_len(unsigned char *data) 310static inline int ieee80211_get_radiotap_len(unsigned char *data)
287{ 311{
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index db7680acd0d..e806f1d81f6 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1473,6 +1473,10 @@ enum ieee80211_hw_flags {
1473 * include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_* values, only 1473 * include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_* values, only
1474 * adding _BW is supported today. 1474 * adding _BW is supported today.
1475 * 1475 *
1476 * @radiotap_vht_details: lists which VHT MCS information the HW reports,
1477 * the default is _GI | _BANDWIDTH.
1478 * Use the %IEEE80211_RADIOTAP_VHT_KNOWN_* values.
1479 *
1476 * @netdev_features: netdev features to be set in each netdev created 1480 * @netdev_features: netdev features to be set in each netdev created
1477 * from this HW. Note only HW checksum features are currently 1481 * from this HW. Note only HW checksum features are currently
1478 * compatible with mac80211. Other feature bits will be rejected. 1482 * compatible with mac80211. Other feature bits will be rejected.
@@ -1499,6 +1503,7 @@ struct ieee80211_hw {
1499 u8 max_tx_aggregation_subframes; 1503 u8 max_tx_aggregation_subframes;
1500 u8 offchannel_tx_hw_queue; 1504 u8 offchannel_tx_hw_queue;
1501 u8 radiotap_mcs_details; 1505 u8 radiotap_mcs_details;
1506 u16 radiotap_vht_details;
1502 netdev_features_t netdev_features; 1507 netdev_features_t netdev_features;
1503}; 1508};
1504 1509
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 6e933409979..c4ed83b74e5 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -638,6 +638,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
638 local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS | 638 local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
639 IEEE80211_RADIOTAP_MCS_HAVE_GI | 639 IEEE80211_RADIOTAP_MCS_HAVE_GI |
640 IEEE80211_RADIOTAP_MCS_HAVE_BW; 640 IEEE80211_RADIOTAP_MCS_HAVE_BW;
641 local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
642 IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
641 local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; 643 local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
642 wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask; 644 wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
643 645
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 825f33cf7bb..9b13b8b2424 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -111,6 +111,11 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local,
111 len += 8; 111 len += 8;
112 } 112 }
113 113
114 if (status->flag & RX_FLAG_VHT) {
115 len = ALIGN(len, 2);
116 len += 12;
117 }
118
114 if (status->vendor_radiotap_len) { 119 if (status->vendor_radiotap_len) {
115 if (WARN_ON_ONCE(status->vendor_radiotap_align == 0)) 120 if (WARN_ON_ONCE(status->vendor_radiotap_align == 0))
116 status->vendor_radiotap_align = 1; 121 status->vendor_radiotap_align = 1;
@@ -297,6 +302,41 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
297 *pos++ = 0; 302 *pos++ = 0;
298 } 303 }
299 304
305 if (status->flag & RX_FLAG_VHT) {
306 u16 known = local->hw.radiotap_vht_details;
307
308 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
309 /* known field - how to handle 80+80? */
310 if (status->flag & RX_FLAG_80P80MHZ)
311 known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
312 put_unaligned_le16(known, pos);
313 pos += 2;
314 /* flags */
315 if (status->flag & RX_FLAG_SHORT_GI)
316 *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
317 pos++;
318 /* bandwidth */
319 if (status->flag & RX_FLAG_80MHZ)
320 *pos++ = 4;
321 else if (status->flag & RX_FLAG_80P80MHZ)
322 *pos++ = 0; /* marked not known above */
323 else if (status->flag & RX_FLAG_160MHZ)
324 *pos++ = 11;
325 else if (status->flag & RX_FLAG_40MHZ)
326 *pos++ = 1;
327 else /* 20 MHz */
328 *pos++ = 0;
329 /* MCS/NSS */
330 *pos = (status->rate_idx << 4) | status->vht_nss;
331 pos += 4;
332 /* coding field */
333 pos++;
334 /* group ID */
335 pos++;
336 /* partial_aid */
337 pos += 2;
338 }
339
300 if (status->vendor_radiotap_len) { 340 if (status->vendor_radiotap_len) {
301 /* ensure 2 byte alignment for the vendor field as required */ 341 /* ensure 2 byte alignment for the vendor field as required */
302 if ((pos - (u8 *)rthdr) & 1) 342 if ((pos - (u8 *)rthdr) & 1)