* [RFC] mac80211: radiotap vendor data
@ 2010-05-01 17:13 Johannes Berg
2010-05-03 22:16 ` Luis R. Rodriguez
0 siblings, 1 reply; 3+ messages in thread
From: Johannes Berg @ 2010-05-01 17:13 UTC (permalink / raw)
To: linux-wireless
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;
}
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFC] mac80211: radiotap vendor data
2010-05-01 17:13 [RFC] mac80211: radiotap vendor data Johannes Berg
@ 2010-05-03 22:16 ` Luis R. Rodriguez
2010-05-04 7:52 ` Johannes Berg
0 siblings, 1 reply; 3+ messages in thread
From: Luis R. Rodriguez @ 2010-05-03 22:16 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, Joshua Zhao, Matt Smith
On Sat, May 1, 2010 at 10:13 AM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> 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.
Thanks a lot for all your work on this area, on the standardization
part, mac80211 and even for providing a simple example, its really
appreciated! Some comments below.
> Note: 11n shouldn't be done there, in case somebody
> got ideas!!
Well you mean 802.11n standard stuff, I take it, because there are
vendor 802.11n specific stuff.
> 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.
I see your WARN_ON() on the alignment being set to 0 and set it to 1
then. Can you clarify a little more on this here. If there is no
strict alignment requirements why not just treat 0 as 1 then?
> + * @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;
Why is this needed though? We already memset(rthdr, 0, rtap_len); above.
> 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;
> +
Heh nice, now we just need a sample radiotap vendor extension parser example.
Thanks!!!
Luis
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFC] mac80211: radiotap vendor data
2010-05-03 22:16 ` Luis R. Rodriguez
@ 2010-05-04 7:52 ` Johannes Berg
0 siblings, 0 replies; 3+ messages in thread
From: Johannes Berg @ 2010-05-04 7:52 UTC (permalink / raw)
To: Luis R. Rodriguez; +Cc: linux-wireless, Joshua Zhao, Matt Smith
On Mon, 2010-05-03 at 15:16 -0700, Luis R. Rodriguez wrote:
> > Note: 11n shouldn't be done there, in case somebody
> > got ideas!!
>
> Well you mean 802.11n standard stuff, I take it, because there are
> vendor 802.11n specific stuff.
Well most of it should really be standardised :)
> > + * @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.
>
> I see your WARN_ON() on the alignment being set to 0 and set it to 1
> then. Can you clarify a little more on this here. If there is no
> strict alignment requirements why not just treat 0 as 1 then?
Just want people to be aware that they need to think about alignment --
zero being the default value for most things here due to kzalloc would
mean accepting it people wouldn't think about allocations. And most of
the time alignment should be required.
> > @@ -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;
>
> Why is this needed though? We already memset(rthdr, 0, rtap_len); above.
Yeah you're probably right, dunno.
> > + 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;
> > +
>
> Heh nice, now we just need a sample radiotap vendor extension parser example.
http://git.sipsolutions.net/?p=radiotap.git;a=summary
https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=4421
johannes
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2010-05-04 7:53 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-01 17:13 [RFC] mac80211: radiotap vendor data Johannes Berg
2010-05-03 22:16 ` Luis R. Rodriguez
2010-05-04 7:52 ` Johannes Berg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).