[PATCH] d80211: add radiotap support

2006-12-16 Thread Michael Wu
d80211: add radiotap support

This patch adds support for radiotap to d80211. The driver must set
IEEE80211_HW_MONITOR_DURING_OPER as well as
IEEE80211_HW_RADIOTAP_SUPPORTED, and it must send radiotap frames when
there is at least one monitor interface up. Tested with zd1211rw-d80211.

Signed-off-by: Michael Wu <[EMAIL PROTECTED]>
---

 include/net/d80211.h |3 +++
 net/d80211/ieee80211.c   |   43 --
 net/d80211/ieee80211_iface.c |5 -
 3 files changed, 40 insertions(+), 11 deletions(-)

diff --git a/include/net/d80211.h b/include/net/d80211.h
index 30980e1..27b2487 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -501,6 +501,9 @@ struct ieee80211_hw {
 * per-packet RC4 key with each TX frame when doing hwcrypto */
 #define IEEE80211_HW_TKIP_REQ_PHASE2_KEY (1<<14)
 
+   /* Driver supports radiotap. Temporary until all drivers support it. */
+#define IEEE80211_HW_RADIOTAP_SUPPORTED (1<<20)
+
u32 flags;  /* hardware flags defined above */
 
/* Set to the size of a needed device specific skb headroom for TX 
skbs. */
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 6e10db5..c686f02 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -8,6 +8,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -284,6 +285,14 @@ int ieee80211_get_hdrlen_from_skb(struct
 }
 EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
 
+static int ieee80211_get_radiotap_len(struct sk_buff *skb)
+{
+   struct ieee80211_radiotap_header *hdr =
+   (struct ieee80211_radiotap_header *) skb->data;
+
+   return le16_to_cpu(hdr->it_len);
+}
+
 #ifdef CONFIG_D80211_LOWTX_FRAME_DUMP
 static void ieee80211_dump_frame(const char *ifname, const char *title,
 struct sk_buff *skb)
@@ -2650,24 +2659,26 @@ ieee80211_rx_monitor(struct net_device *
 
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-   if (skb_headroom(skb) < hlen) {
-   I802_DEBUG_INC(local->rx_expand_skb_head);
-   if (pskb_expand_head(skb, hlen, 0, GFP_ATOMIC)) {
-   dev_kfree_skb(skb);
-return;
+   if (!(local->hw.flags & IEEE80211_HW_RADIOTAP_SUPPORTED)) {
+   if (skb_headroom(skb) < hlen) {
+   I802_DEBUG_INC(local->rx_expand_skb_head);
+   if (pskb_expand_head(skb, hlen, 0, GFP_ATOMIC)) {
+   dev_kfree_skb(skb);
+   return;
+   }
}
-   }
 
-   fi = (struct ieee80211_frame_info *) skb_push(skb, hlen);
+   fi = (struct ieee80211_frame_info *) skb_push(skb, hlen);
+   ieee80211_fill_frame_info(local, fi, status);
+   }
 
-   ieee80211_fill_frame_info(local, fi, status);
sdata->stats.rx_packets++;
sdata->stats.rx_bytes += skb->len;
 
skb->mac.raw = skb->data;
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->pkt_type = PACKET_OTHERHOST;
-   skb->protocol = htons(ETH_P_802_2);
+   skb->protocol = __constant_htons(ETH_P_802_2);
memset(skb->cb, 0, sizeof(skb->cb));
netif_rx(skb);
 }
@@ -3064,6 +3075,10 @@ ieee80211_rx_h_monitor(struct ieee80211_
return TXRX_QUEUED;
}
 
+   if (rx->local->monitors &&
+   rx->local->hw.flags & IEEE80211_HW_RADIOTAP_SUPPORTED)
+   skb_pull(rx->skb, ieee80211_get_radiotap_len(rx->skb));
+
return TXRX_CONTINUE;
 }
 
@@ -3628,6 +3643,13 @@ void __ieee80211_rx(struct ieee80211_hw
struct ieee80211_txrx_data rx;
u16 type;
int multicast;
+   int radiotap_len = 0;
+
+   if (local->monitors &&
+   local->hw.flags & IEEE80211_HW_RADIOTAP_SUPPORTED) {
+   radiotap_len = ieee80211_get_radiotap_len(skb);
+   skb_pull(skb, radiotap_len);
+   }
 
hdr = (struct ieee80211_hdr *) skb->data;
memset(&rx, 0, sizeof(rx));
@@ -3664,6 +3686,7 @@ void __ieee80211_rx(struct ieee80211_hw
goto end;
skb = rx.skb;
 
+   skb_push(skb, radiotap_len);
if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS) &&
!local->iff_promiscs && !multicast) {
rx.u.rx.ra_match = 1;
@@ -3672,7 +3695,7 @@ void __ieee80211_rx(struct ieee80211_hw
} else {
struct ieee80211_sub_if_data *prev = NULL;
struct sk_buff *skb_new;
-   u8 *bssid = ieee80211_get_bssid(hdr, skb->len);
+   u8 *bssid = ieee80211_get_bssid(hdr, skb->len - radiotap_len);
 
list_for_each_entry(sdata, &local->sub_if_list, list) {
rx.u.rx.ra_match = 1;
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index 3e9d531..c1bb6d0 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee802

Re: [PATCH] d80211: add radiotap support

2006-12-18 Thread David Kimdon
On Sat, Dec 16, 2006 at 06:01:03PM -0500, Michael Wu wrote:
>   skb->mac.raw = skb->data;
>   skb->ip_summed = CHECKSUM_UNNECESSARY;
>   skb->pkt_type = PACKET_OTHERHOST;
> - skb->protocol = htons(ETH_P_802_2);
> + skb->protocol = __constant_htons(ETH_P_802_2);
>   memset(skb->cb, 0, sizeof(skb->cb));
>   netif_rx(skb);

htons and friends can handle determining the argument is a constant on
their own, so this change should be dropped.

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] d80211: add radiotap support

2006-12-18 Thread Michael Wu
On Monday 18 December 2006 12:20, David Kimdon wrote:
> htons and friends can handle determining the argument is a constant on
> their own, so this change should be dropped.
>
Hm, appears so. Didn't know that. I'll resend the patch without this change.

Thanks,
-Michael Wu


pgpAgXQMS5hq0.pgp
Description: PGP signature


Re: [PATCH] d80211: add radiotap support

2006-12-18 Thread Jiri Benc
On Sat, 16 Dec 2006 18:01:03 -0500, Michael Wu wrote:
> This patch adds support for radiotap to d80211. The driver must set
> IEEE80211_HW_MONITOR_DURING_OPER as well as
> IEEE80211_HW_RADIOTAP_SUPPORTED, and it must send radiotap frames when
> there is at least one monitor interface up. Tested with zd1211rw-d80211.

Shouldn't the stack create the radiotap header for the driver?

 Jiri

-- 
Jiri Benc
SUSE Labs
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] d80211: add radiotap support

2006-12-18 Thread Michael Wu
On Monday 18 December 2006 14:31, Jiri Benc wrote:
> Shouldn't the stack create the radiotap header for the driver?
>
I will replace the current avs header generating code with basic (fixed len 
header) radiotap code too, but since radiotap is a variable length header, it 
is easier for the driver to fill it properly. Having drivers fill the 
radiotap header also avoids the problem of running out of header space.

-Michael Wu


pgpHliOi1pRSA.pgp
Description: PGP signature


[PATCH] d80211: add radiotap support (v2)

2006-12-18 Thread Michael Wu
d80211: add radiotap support

This patch adds support for radiotap to d80211. The driver must set
IEEE80211_HW_MONITOR_DURING_OPER as well as
IEEE80211_HW_RADIOTAP_SUPPORTED, and it must send radiotap frames when
there is at least one monitor interface up. Tested with zd1211rw-d80211.

Signed-off-by: Michael Wu <[EMAIL PROTECTED]>
---

 include/net/d80211.h |3 +++
 net/d80211/ieee80211.c   |   41 -
 net/d80211/ieee80211_iface.c |5 -
 3 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/include/net/d80211.h b/include/net/d80211.h
index 30980e1..27b2487 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -501,6 +501,9 @@ struct ieee80211_hw {
 * per-packet RC4 key with each TX frame when doing hwcrypto */
 #define IEEE80211_HW_TKIP_REQ_PHASE2_KEY (1<<14)
 
+   /* Driver supports radiotap. Temporary until all drivers support it. */
+#define IEEE80211_HW_RADIOTAP_SUPPORTED (1<<20)
+
u32 flags;  /* hardware flags defined above */
 
/* Set to the size of a needed device specific skb headroom for TX 
skbs. */
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 6e10db5..a73046c 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -8,6 +8,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -284,6 +285,14 @@ int ieee80211_get_hdrlen_from_skb(struct
 }
 EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
 
+static int ieee80211_get_radiotap_len(struct sk_buff *skb)
+{
+   struct ieee80211_radiotap_header *hdr =
+   (struct ieee80211_radiotap_header *) skb->data;
+
+   return le16_to_cpu(hdr->it_len);
+}
+
 #ifdef CONFIG_D80211_LOWTX_FRAME_DUMP
 static void ieee80211_dump_frame(const char *ifname, const char *title,
 struct sk_buff *skb)
@@ -2650,17 +2659,19 @@ ieee80211_rx_monitor(struct net_device *
 
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-   if (skb_headroom(skb) < hlen) {
-   I802_DEBUG_INC(local->rx_expand_skb_head);
-   if (pskb_expand_head(skb, hlen, 0, GFP_ATOMIC)) {
-   dev_kfree_skb(skb);
-return;
+   if (!(local->hw.flags & IEEE80211_HW_RADIOTAP_SUPPORTED)) {
+   if (skb_headroom(skb) < hlen) {
+   I802_DEBUG_INC(local->rx_expand_skb_head);
+   if (pskb_expand_head(skb, hlen, 0, GFP_ATOMIC)) {
+   dev_kfree_skb(skb);
+   return;
+   }
}
-   }
 
-   fi = (struct ieee80211_frame_info *) skb_push(skb, hlen);
+   fi = (struct ieee80211_frame_info *) skb_push(skb, hlen);
+   ieee80211_fill_frame_info(local, fi, status);
+   }
 
-   ieee80211_fill_frame_info(local, fi, status);
sdata->stats.rx_packets++;
sdata->stats.rx_bytes += skb->len;
 
@@ -3064,6 +3075,10 @@ ieee80211_rx_h_monitor(struct ieee80211_
return TXRX_QUEUED;
}
 
+   if (rx->local->monitors &&
+   rx->local->hw.flags & IEEE80211_HW_RADIOTAP_SUPPORTED)
+   skb_pull(rx->skb, ieee80211_get_radiotap_len(rx->skb));
+
return TXRX_CONTINUE;
 }
 
@@ -3628,6 +3643,13 @@ void __ieee80211_rx(struct ieee80211_hw
struct ieee80211_txrx_data rx;
u16 type;
int multicast;
+   int radiotap_len = 0;
+
+   if (local->monitors &&
+   local->hw.flags & IEEE80211_HW_RADIOTAP_SUPPORTED) {
+   radiotap_len = ieee80211_get_radiotap_len(skb);
+   skb_pull(skb, radiotap_len);
+   }
 
hdr = (struct ieee80211_hdr *) skb->data;
memset(&rx, 0, sizeof(rx));
@@ -3664,6 +3686,7 @@ void __ieee80211_rx(struct ieee80211_hw
goto end;
skb = rx.skb;
 
+   skb_push(skb, radiotap_len);
if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS) &&
!local->iff_promiscs && !multicast) {
rx.u.rx.ra_match = 1;
@@ -3672,7 +3695,7 @@ void __ieee80211_rx(struct ieee80211_hw
} else {
struct ieee80211_sub_if_data *prev = NULL;
struct sk_buff *skb_new;
-   u8 *bssid = ieee80211_get_bssid(hdr, skb->len);
+   u8 *bssid = ieee80211_get_bssid(hdr, skb->len - radiotap_len);
 
list_for_each_entry(sdata, &local->sub_if_list, list) {
rx.u.rx.ra_match = 1;
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index 3e9d531..c1bb6d0 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -198,7 +198,10 @@ void ieee80211_if_set_type(struct net_de
break;
}
case IEEE80211_IF_TYPE_MNTR:
-   dev->type = ARPHRD_IEEE80211_PRISM;
+   if (sdata->local->hw.flags & IEEE80211_HW_RADIOTAP_SUPPORTED)
+