Skip to contentSkip to conversation

make d80211 use nl80211

RFC In review Johannes Berg 4 participants 6 messages Aug 22, 2006 – Aug 25, 2006

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

RFC 1/1 make d80211 use nl80211

This patch makes d80211 partially configurable using the infrastructure that nl80211 provides. So far, it allows packet injection and adding/removing virtual interfaces.

net/d80211/Kconfig +1 -0
@@ -3,6 +3,7 @@ config D80211
 	select CRYPTO
 	select CRYPTO_ARC4
 	select CRYPTO_AES
+	select NETLINK_80211
 	---help---
 	This option enables the hardware independent IEEE 802.11
 	networking stack.
net/d80211/Makefile +1 -0
@@ -8,6 +8,7 @@ obj-$(CONFIG_D80211) += 80211.o rate_con
 	sta_info.o \
 	wep.o \
 	wpa.o \
+	ieee80211_cfg.o \
 	ieee80211_scan.o \
 	ieee80211_sta.o \
 	ieee80211_dev.o \
net/d80211/ieee80211.c +65 -17

193 lines not on this page · raw message

net/d80211/ieee80211_cfg.c new file +120 -0

120 lines not on this page · raw message

net/d80211/ieee80211_cfg.h new file +9 -0
@@ -0,0 +1,9 @@
+#ifndef __IEEE80211_CFG_H
+#define __IEEE80211_CFG_H
+
+#include "ieee80211_i.h"
+
+extern int ieee80211_cfg_init(struct ieee80211_local *local);
+extern void ieee80211_cfg_exit(struct ieee80211_local *local);
+
+#endif /* __IEEE80211_CFG_H */
net/d80211/ieee80211_i.h +7 -6
@@ -153,12 +153,13 @@ struct ieee80211_txrx_data {
 struct ieee80211_tx_packet_data {
 	int ifindex;
 	unsigned long jiffies;
-	unsigned int req_tx_status:1;
-	unsigned int do_not_encrypt:1;
-	unsigned int pkt_probe_resp:1;
-	unsigned int requeue:1;
-	unsigned int queue:4;
-	unsigned int mgmt_iface:1;
+/* we simply re-use NL80211_FLAG_* here */
+	unsigned int flags;
+	unsigned int queue;
+#define TX_FLAG_INJECTED	(1<<0)
+#define TX_FLAG_REQUEUE		(1<<1)
+#define TX_FLAG_PROBERESP	(1<<2)
+	unsigned int internal_flags;
 };
 
 struct ieee80211_tx_stored_packet {
net/d80211/ieee80211_sta.c +6 -3
@@ -21,6 +21,7 @@
 #include <linux/if_arp.h>
 #include <linux/wireless.h>
 #include <linux/random.h>
+#include <linux/nl80211.h>
 #include <net/iw_handler.h>
 #include <asm/types.h>
 #include <asm/delay.h>
@@ -396,10 +397,12 @@ static void ieee80211_sta_tx(struct net_
 	pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
 	memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
 	pkt_data->ifindex = sdata->dev->ifindex;
-	pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
-	pkt_data->do_not_encrypt = !encrypt;
+	if (sdata->type == IEEE80211_IF_TYPE_MGMT)
+		pkt_data->internal_flags |= TX_FLAG_INJECTED;
+	if (encrypt)
+		pkt_data->flags |= NL80211_FLAG_ENCRYPT;
 	if (probe_resp)
-		pkt_data->pkt_probe_resp = 1;
+		pkt_data->internal_flags |= TX_FLAG_PROBERESP;
 
 	dev_queue_xmit(skb);
 }
net/d80211/wme.c +4 -2
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/if_arp.h>
 #include <linux/types.h>
+#include <linux/nl80211.h>
 #include <net/ip.h>
 #include <net/pkt_sched.h>
 
@@ -190,7 +191,8 @@ static inline int classify80211(struct s
 		return IEEE80211_TX_QUEUE_DATA0;
 	}
 
-	if (unlikely(pkt_data->mgmt_iface)) {
+	/* FIXME: this needs to be revisited for more generic injection */
+	if (unlikely(pkt_data->internal_flags & TX_FLAG_INJECTED)) {
 		/* Data frames from hostapd (mainly, EAPOL) use AC_VO
 		* and they will include QoS control fields if
 		* the target STA is using WME. */
@@ -236,7 +238,7 @@ static int wme_qdiscop_enqueue(struct sk
 	struct Qdisc *qdisc;
 	int err, queue;
 
-	if (pkt_data->requeue) {
+	if (pkt_data->internal_flags & TX_FLAG_REQUEUE) {
 		skb_queue_tail(&q->requeued[pkt_data->queue], skb);
 		return 0;
 	}
#1 lore raw
Quoted 3 lines · Johannes Berg

This patch makes d80211 partially configurable using the infrastructure that nl80211 provides. So far, it allows packet injection and adding/removing virtual interfaces.

Just minor things:

net/d80211/ieee80211.c struct net_device *ieee80211_alloc_hw(si · line 4369

Quoted 12 lines

[...]

net/d80211/ieee80211.c +1 -0
[...]
@@ -4323,6 +4363,7 @@ struct net_device *ieee80211_alloc_hw(si
 	priv_size = ((sizeof(struct ieee80211_sub_if_data) +
 		      NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) +
 		    priv_data_len;
+
 	mdev = alloc_netdev(priv_size, "wmaster%d", ether_setup);
 	if (!mdev) {
 		ieee80211_dev_free(local);

Remove this hunk, please.

net/d80211/ieee80211.c

Quoted 3 lines

[...]

net/d80211/ieee80211.c +2 -0
+static int d80211_interfaces(void *priv, void *data,
+			     int (*one)(void *data, int ifindex))

Please use ieee80211_ prefix, not d80211_.

Quoted 5 lines

[...]

net/d80211/ieee80211.c +4 -0
+static int d80211_inject(void *priv, void *frame, int framelen, u32 flags,
+			 int queue)
+{
+	struct ieee80211_local *local = priv;

net/d80211/ieee80211.c

Quoted 10 lines
net/d80211/ieee80211.c +10 -0
+	struct ieee80211_tx_packet_data *pkt_data;
+	struct sk_buff *pkt;
+	void *pktdata;
+
+	pkt = alloc_skb(framelen, GFP_KERNEL);
+	pktdata = skb_put(pkt, framelen);
+	memcpy(pktdata, frame, framelen);
+
+	pkt_data = (struct ieee80211_tx_packet_data *) pkt->cb;
+	memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));

This is not necessary, cb is zeroed in alloc_skb.

Thanks,

Jiri

Signature · 2 lines
Jiri Benc
SUSE Labs
#2 lore raw
In reply to Johannes Berg

new version of this one too...
--
Subject: d80211: use nl80211

This patch makes d80211 partially configurable using the infrastructure that nl80211 provides. So far, it allows packet injection and adding/removing virtual interfaces.

net/d80211/Kconfig +1 -0
@@ -3,6 +3,7 @@ config D80211
 	select CRYPTO
 	select CRYPTO_ARC4
 	select CRYPTO_AES
+	select NETLINK_80211
 	---help---
 	This option enables the hardware independent IEEE 802.11
 	networking stack.
net/d80211/Makefile +1 -0
@@ -8,6 +8,7 @@ obj-$(CONFIG_D80211) += 80211.o rate_con
 	sta_info.o \
 	wep.o \
 	wpa.o \
+	ieee80211_cfg.o \
 	ieee80211_scan.o \
 	ieee80211_sta.o \
 	ieee80211_dev.o \
net/d80211/ieee80211.c +64 -17

186 lines not on this page · raw message

net/d80211/ieee80211_cfg.c new file +143 -0

143 lines not on this page · raw message

net/d80211/ieee80211_cfg.h new file +9 -0
@@ -0,0 +1,9 @@
+#ifndef __IEEE80211_CFG_H
+#define __IEEE80211_CFG_H
+
+#include "ieee80211_i.h"
+
+extern int ieee80211_cfg_init(struct ieee80211_local *local);
+extern void ieee80211_cfg_exit(struct ieee80211_local *local);
+
+#endif /* __IEEE80211_CFG_H */
net/d80211/ieee80211_i.h +7 -6
@@ -153,12 +153,13 @@ struct ieee80211_txrx_data {
 struct ieee80211_tx_packet_data {
 	int ifindex;
 	unsigned long jiffies;
-	unsigned int req_tx_status:1;
-	unsigned int do_not_encrypt:1;
-	unsigned int pkt_probe_resp:1;
-	unsigned int requeue:1;
-	unsigned int queue:4;
-	unsigned int mgmt_iface:1;
+/* we simply re-use NL80211_FLAG_* here */
+	unsigned int flags;
+	unsigned int queue;
+#define TX_FLAG_INJECTED	(1<<0)
+#define TX_FLAG_REQUEUE		(1<<1)
+#define TX_FLAG_PROBERESP	(1<<2)
+	unsigned int internal_flags;
 };
 
 struct ieee80211_tx_stored_packet {
net/d80211/ieee80211_sta.c +6 -3
@@ -21,6 +21,7 @@
 #include <linux/if_arp.h>
 #include <linux/wireless.h>
 #include <linux/random.h>
+#include <linux/nl80211.h>
 #include <net/iw_handler.h>
 #include <asm/types.h>
 #include <asm/delay.h>
@@ -396,10 +397,12 @@ static void ieee80211_sta_tx(struct net_
 	pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
 	memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
 	pkt_data->ifindex = sdata->dev->ifindex;
-	pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
-	pkt_data->do_not_encrypt = !encrypt;
+	if (sdata->type == IEEE80211_IF_TYPE_MGMT)
+		pkt_data->internal_flags |= TX_FLAG_INJECTED;
+	if (encrypt)
+		pkt_data->flags |= NL80211_FLAG_ENCRYPT;
 	if (probe_resp)
-		pkt_data->pkt_probe_resp = 1;
+		pkt_data->internal_flags |= TX_FLAG_PROBERESP;
 
 	dev_queue_xmit(skb);
 }
net/d80211/wme.c +4 -2
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/if_arp.h>
 #include <linux/types.h>
+#include <linux/nl80211.h>
 #include <net/ip.h>
 #include <net/pkt_sched.h>
 
@@ -190,7 +191,8 @@ static inline int classify80211(struct s
 		return IEEE80211_TX_QUEUE_DATA0;
 	}
 
-	if (unlikely(pkt_data->mgmt_iface)) {
+	/* FIXME: this needs to be revisited for more generic injection */
+	if (unlikely(pkt_data->internal_flags & TX_FLAG_INJECTED)) {
 		/* Data frames from hostapd (mainly, EAPOL) use AC_VO
 		* and they will include QoS control fields if
 		* the target STA is using WME. */
@@ -236,7 +238,7 @@ static int wme_qdiscop_enqueue(struct sk
 	struct Qdisc *qdisc;
 	int err, queue;
 
-	if (pkt_data->requeue) {
+	if (pkt_data->internal_flags & TX_FLAG_REQUEUE) {
 		skb_queue_tail(&q->requeued[pkt_data->queue], skb);
 		return 0;
 	}
#3 lore raw
Quoted 12 lines · Johannes Berg

new version of this one too...
--
Subject: d80211: use nl80211

This patch makes d80211 partially configurable using the infrastructure that nl80211 provides. So far, it allows packet injection and adding/removing virtual interfaces.

net/d80211/ieee80211_cfg.c line 48

Quoted 9 lines
net/d80211/ieee80211_cfg.c new file +9 -0
+static int ieee80211_inject(void *priv, void *frame, int framelen, u32 flags,
+			    int queue)
+{
+	struct ieee80211_local *local = priv;
+	struct ieee80211_tx_packet_data *pkt_data;
+	struct sk_buff *pkt;
+	void *pktdata;
+
+	pkt = alloc_skb(framelen, GFP_KERNEL);

if (!pkt)

	return -ENOMEM;

net/d80211/ieee80211_cfg.c line 50

Quoted 2 lines
net/d80211/ieee80211_cfg.c new file +2 -0
+	pktdata = skb_put(pkt, framelen);
+	memcpy(pktdata, frame, framelen);

having two variables with almost the same name seems confusing to me. What about removing void *pktdata; and doing the following instead of the two lines above?

memcpy(skb_put(pkt, framelen), frame, framelen);

That is also how it's done in lots of other networking code.

Quoted 5 lines
net/d80211/ieee80211_cfg.c new file +5 -0
+	pkt_data = (struct ieee80211_tx_packet_data *) pkt->cb;
+	pkt_data->ifindex = local->mdev->ifindex;
+	pkt_data->internal_flags = TX_FLAG_INJECTED;
+	pkt_data->flags = flags;
+	/* FIXME: never used, I think? Or could be invalid? */

net/d80211/ieee80211_cfg.c line 66

Quoted 10 lines
net/d80211/ieee80211_cfg.c new file +10 -0
+	pkt_data->queue = queue;
+
+	/* FIXME */
+	pkt->priority = 20; /* use hardcoded priority for mgmt TX queue */
+
+	pkt->dev = local->mdev;
+	dev_queue_xmit(pkt);
+
+	return 0;
+}

The other code looks fine to me (the add nl80211 patch, too).

Signature · 1 line
Greetings Michael.
#4 lore raw

* Michael Buesch <[email protected]> 2006-08-24 19:09

Quoted 13 lines · Johannes Berg

net/d80211/ieee80211_cfg.c line 48

Quoted 1 line
net/d80211/ieee80211_cfg.c new file +1 -0
+	pkt = alloc_skb(framelen, GFP_KERNEL);

if (!pkt)

	return -ENOMEM;

net/d80211/ieee80211_cfg.c line 50

Quoted 2 lines
net/d80211/ieee80211_cfg.c new file +2 -0
+	pktdata = skb_put(pkt, framelen);
+	memcpy(pktdata, frame, framelen);

having two variables with almost the same name seems confusing to me. What about removing void *pktdata; and doing the following instead of the two lines above?

Quoted 3 lines

memcpy(skb_put(pkt, framelen), frame, framelen);

That is also how it's done in lots of other networking code.

You might want to use 'skb' instead of 'pkt', everyone has got used to it.

#5 lore raw

RFC 1/1 make d80211 use nl80211

In reply to Johannes Berg

This patch makes d80211 partially configurable using the infrastructure that nl80211 provides. So far, it allows packet injection and adding/removing virtual interfaces.

net/d80211/Kconfig +1 -0
@@ -3,6 +3,7 @@ config D80211
 	select CRYPTO
 	select CRYPTO_ARC4
 	select CRYPTO_AES
+	select NETLINK_80211
 	---help---
 	This option enables the hardware independent IEEE 802.11
 	networking stack.
net/d80211/Makefile +1 -0
@@ -8,6 +8,7 @@ obj-$(CONFIG_D80211) += 80211.o rate_con
 	sta_info.o \
 	wep.o \
 	wpa.o \
+	ieee80211_cfg.o \
 	ieee80211_scan.o \
 	ieee80211_sta.o \
 	ieee80211_dev.o \
net/d80211/ieee80211.c +64 -17

186 lines not on this page · raw message

net/d80211/ieee80211_cfg.c new file +144 -0

144 lines not on this page · raw message

net/d80211/ieee80211_cfg.h new file +9 -0
@@ -0,0 +1,9 @@
+#ifndef __IEEE80211_CFG_H
+#define __IEEE80211_CFG_H
+
+#include "ieee80211_i.h"
+
+extern int ieee80211_cfg_init(struct ieee80211_local *local);
+extern void ieee80211_cfg_exit(struct ieee80211_local *local);
+
+#endif /* __IEEE80211_CFG_H */
net/d80211/ieee80211_i.h +7 -6
@@ -153,12 +153,13 @@ struct ieee80211_txrx_data {
 struct ieee80211_tx_packet_data {
 	int ifindex;
 	unsigned long jiffies;
-	unsigned int req_tx_status:1;
-	unsigned int do_not_encrypt:1;
-	unsigned int pkt_probe_resp:1;
-	unsigned int requeue:1;
-	unsigned int queue:4;
-	unsigned int mgmt_iface:1;
+/* we simply re-use NL80211_FLAG_* here */
+	unsigned int flags;
+	unsigned int queue;
+#define TX_FLAG_INJECTED	(1<<0)
+#define TX_FLAG_REQUEUE		(1<<1)
+#define TX_FLAG_PROBERESP	(1<<2)
+	unsigned int internal_flags;
 };
 
 struct ieee80211_tx_stored_packet {
net/d80211/ieee80211_sta.c +6 -3
@@ -21,6 +21,7 @@
 #include <linux/if_arp.h>
 #include <linux/wireless.h>
 #include <linux/random.h>
+#include <linux/nl80211.h>
 #include <net/iw_handler.h>
 #include <asm/types.h>
 #include <asm/delay.h>
@@ -396,10 +397,12 @@ static void ieee80211_sta_tx(struct net_
 	pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
 	memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
 	pkt_data->ifindex = sdata->dev->ifindex;
-	pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
-	pkt_data->do_not_encrypt = !encrypt;
+	if (sdata->type == IEEE80211_IF_TYPE_MGMT)
+		pkt_data->internal_flags |= TX_FLAG_INJECTED;
+	if (encrypt)
+		pkt_data->flags |= NL80211_FLAG_ENCRYPT;
 	if (probe_resp)
-		pkt_data->pkt_probe_resp = 1;
+		pkt_data->internal_flags |= TX_FLAG_PROBERESP;
 
 	dev_queue_xmit(skb);
 }
net/d80211/wme.c +4 -2
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/if_arp.h>
 #include <linux/types.h>
+#include <linux/nl80211.h>
 #include <net/ip.h>
 #include <net/pkt_sched.h>
 
@@ -190,7 +191,8 @@ static inline int classify80211(struct s
 		return IEEE80211_TX_QUEUE_DATA0;
 	}
 
-	if (unlikely(pkt_data->mgmt_iface)) {
+	/* FIXME: this needs to be revisited for more generic injection */
+	if (unlikely(pkt_data->internal_flags & TX_FLAG_INJECTED)) {
 		/* Data frames from hostapd (mainly, EAPOL) use AC_VO
 		* and they will include QoS control fields if
 		* the target STA is using WME. */
@@ -236,7 +238,7 @@ static int wme_qdiscop_enqueue(struct sk
 	struct Qdisc *qdisc;
 	int err, queue;
 
-	if (pkt_data->requeue) {
+	if (pkt_data->internal_flags & TX_FLAG_REQUEUE) {
 		skb_queue_tail(&q->requeued[pkt_data->queue], skb);
 		return 0;
 	}