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