Search Linux Wireless

[RFC] mac80211: radiotap vendor data

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This allows drivers to add radiotap vendor data
to any received frame, which will be simply
passed into userspace and ignored by the kernel.
Can be used by drivers to convey hw-specific
information.

Note: 11n shouldn't be done there, in case somebody
got ideas!!

Note: didn't test this after the paged RX changes
---
 drivers/net/wireless/mac80211_hwsim.c |   17 ++++++++++
 include/net/mac80211.h                |   12 +++++++
 net/mac80211/rx.c                     |   53 ++++++++++++++++++++++++++++++----
 3 files changed, 77 insertions(+), 5 deletions(-)

--- wireless-testing.orig/include/net/mac80211.h	2010-05-01 08:46:26.000000000 +0200
+++ wireless-testing/include/net/mac80211.h	2010-05-01 08:47:54.000000000 +0200
@@ -565,6 +565,13 @@ enum mac80211_rx_flags {
  * @rate_idx: index of data rate into band's supported rates or MCS index if
  *	HT rates are use (RX_FLAG_HT)
  * @flag: %RX_FLAG_*
+ * @vendor_radiotap_bitmap: radiotap vendor namespace presence bitmap
+ * @vendor_radiotap_len: radiotap vendor namespace length
+ * @vendor_radiotap_align: radiotap vendor namespace alignment. Note
+ *	that the actual data must be at the start of the SKB data
+ *	already.
+ * @vendor_radiotap_oui: radiotap vendor namespace OUI
+ * @vendor_radiotap_subns: radiotap vendor sub namespace
  */
 struct ieee80211_rx_status {
 	u64 mactime;
@@ -575,6 +582,11 @@ struct ieee80211_rx_status {
 	int antenna;
 	int rate_idx;
 	int flag;
+	u32 vendor_radiotap_bitmap;
+	u16 vendor_radiotap_len;
+	u8 vendor_radiotap_align;
+	u8 vendor_radiotap_oui[3];
+	u8 vendor_radiotap_subns;
 };
 
 /**
--- wireless-testing.orig/net/mac80211/rx.c	2010-05-01 08:46:26.000000000 +0200
+++ wireless-testing/net/mac80211/rx.c	2010-05-01 08:47:54.000000000 +0200
@@ -37,6 +37,8 @@
 static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
 					   struct sk_buff *skb)
 {
+	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+
 	if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) {
 		if (likely(skb->len > FCS_LEN))
 			__pskb_trim(skb, skb->len - FCS_LEN);
@@ -48,6 +50,9 @@ static struct sk_buff *remove_monitor_in
 		}
 	}
 
+	if (status->vendor_radiotap_len)
+		__pskb_pull(skb, status->vendor_radiotap_len);
+
 	return skb;
 }
 
@@ -69,8 +74,8 @@ static inline int should_drop_frame(stru
 }
 
 static int
-ieee80211_rx_radiotap_len(struct ieee80211_local *local,
-			  struct ieee80211_rx_status *status)
+ieee80211_rx_radiotap_space(struct ieee80211_local *local,
+			    struct ieee80211_rx_status *status)
 {
 	int len;
 
@@ -87,6 +92,21 @@ ieee80211_rx_radiotap_len(struct ieee802
 	if (len & 1) /* padding for RX_FLAGS if necessary */
 		len++;
 
+	if (status->vendor_radiotap_len) {
+		/* allocate extra bitmap */
+		len += 4;
+
+		if (WARN_ON(status->vendor_radiotap_align == 0))
+			status->vendor_radiotap_align = 1;
+		/* align standard part of vendor namespace */
+		len = ALIGN(len, 2);
+		/* allocate standard part of vendor namespace */
+		len += 6;
+		/* align vendor-defined part */
+		len = ALIGN(len, status->vendor_radiotap_align);
+		/* vendor-defined part is already in skb */
+	}
+
 	return len;
 }
 
@@ -115,10 +135,18 @@ ieee80211_add_rx_radiotap_header(struct
 			    (1 << IEEE80211_RADIOTAP_CHANNEL) |
 			    (1 << IEEE80211_RADIOTAP_ANTENNA) |
 			    (1 << IEEE80211_RADIOTAP_RX_FLAGS));
-	rthdr->it_len = cpu_to_le16(rtap_len);
+	rthdr->it_len = cpu_to_le16(rtap_len + status->vendor_radiotap_len);
 
 	pos = (unsigned char *)(rthdr+1);
 
+	if (status->vendor_radiotap_len) {
+		rthdr->it_present |=
+			cpu_to_le32(BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE)) |
+			cpu_to_le32(BIT(IEEE80211_RADIOTAP_EXT));
+		put_unaligned_le32(status->vendor_radiotap_bitmap, pos);
+		pos += 4;
+	}
+
 	/* the order of the following fields is important */
 
 	/* IEEE80211_RADIOTAP_TSFT */
@@ -190,11 +218,26 @@ ieee80211_add_rx_radiotap_header(struct
 	/* IEEE80211_RADIOTAP_RX_FLAGS */
 	/* ensure 2 byte alignment for the 2 byte field as required */
 	if ((pos - (u8 *)rthdr) & 1)
-		pos++;
+		*pos++ = 0;
 	if (status->flag & RX_FLAG_FAILED_PLCP_CRC)
 		rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP;
 	put_unaligned_le16(rx_flags, pos);
 	pos += 2;
+
+	if (status->vendor_radiotap_len) {
+		/* ensure 2 byte alignment for the vendor field as required */
+		if ((pos - (u8 *)rthdr) & 1)
+			*pos++ = 0;
+		*pos++ = status->vendor_radiotap_oui[0];
+		*pos++ = status->vendor_radiotap_oui[1];
+		*pos++ = status->vendor_radiotap_oui[2];
+		*pos++ = status->vendor_radiotap_subns;
+		put_unaligned_le16(status->vendor_radiotap_len, pos);
+		pos += 2;
+		/* align the actual payload as requested */
+		while ((pos - (u8 *)rthdr) & (status->vendor_radiotap_align - 1))
+			*pos++ = 0;
+	}
 }
 
 /*
@@ -223,7 +266,7 @@ ieee80211_rx_monitor(struct ieee80211_lo
 	 */
 
 	/* room for the radiotap header based on driver features */
-	needed_headroom = ieee80211_rx_radiotap_len(local, status);
+	needed_headroom = ieee80211_rx_radiotap_space(local, status);
 
 	if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
 		present_fcs_len = FCS_LEN;
--- wireless-testing.orig/drivers/net/wireless/mac80211_hwsim.c	2010-05-01 08:46:27.000000000 +0200
+++ wireless-testing/drivers/net/wireless/mac80211_hwsim.c	2010-05-01 19:04:57.000000000 +0200
@@ -484,6 +484,7 @@ static bool mac80211_hwsim_tx_frame(stru
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_rx_status rx_status;
+	u8 *vendor_data;
 
 	if (data->idle) {
 		printk(KERN_DEBUG "%s: Trying to TX when idle - reject\n",
@@ -509,6 +510,20 @@ static bool mac80211_hwsim_tx_frame(stru
 	secpath_reset(skb);
 	nf_reset(skb);
 
+	vendor_data = skb_push(skb, 4);
+	rx_status.vendor_radiotap_len = 4;
+	rx_status.vendor_radiotap_align = 4;
+	rx_status.vendor_radiotap_oui[0] = 0xff;
+	rx_status.vendor_radiotap_oui[1] = 0xff;
+	rx_status.vendor_radiotap_oui[2] = 0xff;
+	rx_status.vendor_radiotap_subns = 129;
+	rx_status.vendor_radiotap_bitmap = 0x1;
+
+	*vendor_data++ = 1;
+	*vendor_data++ = 2;
+	*vendor_data++ = 3;
+	*vendor_data++ = 4;
+
 	/* Copy skb to all enabled radios that are on the current frequency */
 	spin_lock(&hwsim_radio_lock);
 	list_for_each_entry(data2, &hwsim_radios, list) {
@@ -535,6 +550,8 @@ static bool mac80211_hwsim_tx_frame(stru
 	}
 	spin_unlock(&hwsim_radio_lock);
 
+	skb_pull(skb, 4);
+
 	return ack;
 }
 


--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux