* [PATCH 0/4] mac80211 radiotap TX cleanup
@ 2011-10-07 12:01 Johannes Berg
2011-10-07 12:01 ` [PATCH 1/4] mac80211: optimise monitor xmit Johannes Berg
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Johannes Berg @ 2011-10-07 12:01 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
These patches clean up/optimise the non-radiotap
TX path by moving all radiotap related parsing
right into monitor xmit.
johannes
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/4] mac80211: optimise monitor xmit
2011-10-07 12:01 [PATCH 0/4] mac80211 radiotap TX cleanup Johannes Berg
@ 2011-10-07 12:01 ` Johannes Berg
2011-10-07 12:01 ` [PATCH 2/4] mac80211: remove tx_data ethertype Johannes Berg
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Johannes Berg @ 2011-10-07 12:01 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
Since the only way the interface can be a monitor
interface in ieee80211_xmit() is because the frame
came from ieee80211_monitor_start_xmit() we can
move all the code there.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/tx.c | 108 ++++++++++++++++++++++++------------------------------
1 file changed, 49 insertions(+), 59 deletions(-)
--- a/net/mac80211/tx.c 2011-10-07 10:07:23.000000000 +0200
+++ b/net/mac80211/tx.c 2011-10-07 10:17:04.000000000 +0200
@@ -1539,55 +1539,11 @@ void ieee80211_xmit(struct ieee80211_sub
struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- struct ieee80211_sub_if_data *tmp_sdata;
int headroom;
bool may_encrypt;
rcu_read_lock();
- if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) {
- int hdrlen;
- u16 len_rthdr;
-
- info->flags |= IEEE80211_TX_CTL_INJECTED |
- IEEE80211_TX_INTFL_HAS_RADIOTAP;
-
- len_rthdr = ieee80211_get_radiotap_len(skb->data);
- hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
- hdrlen = ieee80211_hdrlen(hdr->frame_control);
-
- /* check the header is complete in the frame */
- if (likely(skb->len >= len_rthdr + hdrlen)) {
- /*
- * We process outgoing injected frames that have a
- * local address we handle as though they are our
- * own frames.
- * This code here isn't entirely correct, the local
- * MAC address is not necessarily enough to find
- * the interface to use; for that proper VLAN/WDS
- * support we will need a different mechanism.
- */
-
- list_for_each_entry_rcu(tmp_sdata, &local->interfaces,
- list) {
- if (!ieee80211_sdata_running(tmp_sdata))
- continue;
- if (tmp_sdata->vif.type ==
- NL80211_IFTYPE_MONITOR ||
- tmp_sdata->vif.type ==
- NL80211_IFTYPE_AP_VLAN ||
- tmp_sdata->vif.type ==
- NL80211_IFTYPE_WDS)
- continue;
- if (compare_ether_addr(tmp_sdata->vif.addr,
- hdr->addr2) == 0) {
- sdata = tmp_sdata;
- break;
- }
- }
- }
- }
-
may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT);
headroom = local->tx_headroom;
@@ -1628,8 +1584,9 @@ netdev_tx_t ieee80211_monitor_start_xmit
(struct ieee80211_radiotap_header *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr;
+ struct ieee80211_sub_if_data *tmp_sdata, *sdata;
u16 len_rthdr;
- u8 *payload;
+ int hdrlen;
/*
* Frame injection is not allowed if beaconing is not allowed
@@ -1680,30 +1637,63 @@ netdev_tx_t ieee80211_monitor_start_xmit
skb_set_network_header(skb, len_rthdr);
skb_set_transport_header(skb, len_rthdr);
+ if (skb->len < len_rthdr + 2)
+ goto fail;
+
+ hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
+
+ if (skb->len < len_rthdr + hdrlen)
+ goto fail;
+
/*
* Initialize skb->protocol if the injected frame is a data frame
* carrying a rfc1042 header
*/
- if (skb->len > len_rthdr + 2) {
- hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
- if (ieee80211_is_data(hdr->frame_control) &&
- skb->len >= len_rthdr +
- ieee80211_hdrlen(hdr->frame_control) +
- sizeof(rfc1042_header) + 2) {
- payload = (u8 *)hdr +
- ieee80211_hdrlen(hdr->frame_control);
- if (compare_ether_addr(payload, rfc1042_header) == 0)
- skb->protocol = cpu_to_be16((payload[6] << 8) |
- payload[7]);
- }
+ if (ieee80211_is_data(hdr->frame_control) &&
+ skb->len >= len_rthdr + hdrlen + sizeof(rfc1042_header) + 2) {
+ u8 *payload = (u8 *)hdr + hdrlen;
+
+ if (compare_ether_addr(payload, rfc1042_header) == 0)
+ skb->protocol = cpu_to_be16((payload[6] << 8) |
+ payload[7]);
}
memset(info, 0, sizeof(*info));
- info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
+ info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
+ IEEE80211_TX_CTL_INJECTED |
+ IEEE80211_TX_INTFL_HAS_RADIOTAP;
+
+ rcu_read_lock();
+
+ /*
+ * We process outgoing injected frames that have a local address
+ * we handle as though they are non-injected frames.
+ * This code here isn't entirely correct, the local MAC address
+ * isn't always enough to find the interface to use; for proper
+ * VLAN/WDS support we will need a different mechanism (which
+ * likely isn't going to be monitor interfaces).
+ */
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ list_for_each_entry_rcu(tmp_sdata, &local->interfaces, list) {
+ if (!ieee80211_sdata_running(tmp_sdata))
+ continue;
+ if (tmp_sdata->vif.type == NL80211_IFTYPE_MONITOR ||
+ tmp_sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+ tmp_sdata->vif.type == NL80211_IFTYPE_WDS)
+ continue;
+ if (compare_ether_addr(tmp_sdata->vif.addr, hdr->addr2) == 0) {
+ sdata = tmp_sdata;
+ break;
+ }
+ }
/* pass the radiotap header up to xmit */
- ieee80211_xmit(IEEE80211_DEV_TO_SUB_IF(dev), skb);
+ ieee80211_xmit(sdata, skb);
+ rcu_read_unlock();
+
return NETDEV_TX_OK;
fail:
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/4] mac80211: remove tx_data ethertype
2011-10-07 12:01 [PATCH 0/4] mac80211 radiotap TX cleanup Johannes Berg
2011-10-07 12:01 ` [PATCH 1/4] mac80211: optimise monitor xmit Johannes Berg
@ 2011-10-07 12:01 ` Johannes Berg
2011-10-07 12:01 ` [PATCH 3/4] mac80211: move fragment flag to info flag as dont-fragment Johannes Berg
2011-10-07 12:01 ` [PATCH 4/4] mac80211: parse radiotap header earlier Johannes Berg
3 siblings, 0 replies; 5+ messages in thread
From: Johannes Berg @ 2011-10-07 12:01 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
It's set, but never used, so kill it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/ieee80211_i.h | 1 -
net/mac80211/tx.c | 7 +------
2 files changed, 1 insertion(+), 7 deletions(-)
--- a/net/mac80211/ieee80211_i.h 2011-10-07 10:08:27.000000000 +0200
+++ b/net/mac80211/ieee80211_i.h 2011-10-07 10:23:10.000000000 +0200
@@ -149,7 +149,6 @@ struct ieee80211_tx_data {
struct ieee80211_channel *channel;
- u16 ethertype;
unsigned int flags;
};
--- a/net/mac80211/tx.c 2011-10-07 10:17:04.000000000 +0200
+++ b/net/mac80211/tx.c 2011-10-07 10:24:37.000000000 +0200
@@ -1198,7 +1198,7 @@ ieee80211_tx_prepare(struct ieee80211_su
struct ieee80211_local *local = sdata->local;
struct ieee80211_hdr *hdr;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- int hdrlen, tid;
+ int tid;
u8 *qc;
memset(tx, 0, sizeof(*tx));
@@ -1295,11 +1295,6 @@ ieee80211_tx_prepare(struct ieee80211_su
else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT))
info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
- hdrlen = ieee80211_hdrlen(hdr->frame_control);
- if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) {
- u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)];
- tx->ethertype = (pos[0] << 8) | pos[1];
- }
info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT;
return TX_CONTINUE;
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 3/4] mac80211: move fragment flag to info flag as dont-fragment
2011-10-07 12:01 [PATCH 0/4] mac80211 radiotap TX cleanup Johannes Berg
2011-10-07 12:01 ` [PATCH 1/4] mac80211: optimise monitor xmit Johannes Berg
2011-10-07 12:01 ` [PATCH 2/4] mac80211: remove tx_data ethertype Johannes Berg
@ 2011-10-07 12:01 ` Johannes Berg
2011-10-07 12:01 ` [PATCH 4/4] mac80211: parse radiotap header earlier Johannes Berg
3 siblings, 0 replies; 5+ messages in thread
From: Johannes Berg @ 2011-10-07 12:01 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
The purpose of this is two-fold:
1) by moving it out of tx_data.flags, we can in
another patch move the radiotap parsing so it
no longer is in the hotpath
2) if a device implements fragmentation but can
optionally skip it, the radiotap request for
not doing fragmentation may be honoured
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/net/mac80211.h | 4 ++++
net/mac80211/ieee80211_i.h | 1 -
net/mac80211/tx.c | 39 ++++++++++++++-------------------------
net/mac80211/wpa.c | 3 ++-
4 files changed, 20 insertions(+), 27 deletions(-)
--- a/include/net/mac80211.h 2011-10-07 11:01:01.000000000 +0200
+++ b/include/net/mac80211.h 2011-10-07 11:01:03.000000000 +0200
@@ -375,6 +375,9 @@ struct ieee80211_bss_conf {
* @IEEE80211_TX_CTL_USE_MINRATE: This frame will be sent at lowest rate.
* This flag is used to send nullfunc frame at minimum rate when
* the nullfunc is used for connection monitoring purpose.
+ * @IEEE80211_TX_CTL_DONTFRAG: Don't fragment this packet even if it
+ * would be fragmented by size (this is optional, only used for
+ * monitor injection).
*
* Note: If you have to add new flags to the enumeration, then don't
* forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary.
@@ -408,6 +411,7 @@ enum mac80211_tx_control_flags {
IEEE80211_TX_CTL_NO_CCK_RATE = BIT(27),
IEEE80211_TX_STATUS_EOSP = BIT(28),
IEEE80211_TX_CTL_USE_MINRATE = BIT(29),
+ IEEE80211_TX_CTL_DONTFRAG = BIT(30),
};
#define IEEE80211_TX_CTL_STBC_SHIFT 23
--- a/net/mac80211/ieee80211_i.h 2011-10-07 11:01:01.000000000 +0200
+++ b/net/mac80211/ieee80211_i.h 2011-10-07 11:01:03.000000000 +0200
@@ -136,7 +136,6 @@ typedef unsigned __bitwise__ ieee80211_t
#define TX_DROP ((__force ieee80211_tx_result) 1u)
#define TX_QUEUED ((__force ieee80211_tx_result) 2u)
-#define IEEE80211_TX_FRAGMENTED BIT(0)
#define IEEE80211_TX_UNICAST BIT(1)
#define IEEE80211_TX_PS_BUFFERED BIT(2)
--- a/net/mac80211/tx.c 2011-10-07 11:01:01.000000000 +0200
+++ b/net/mac80211/tx.c 2011-10-07 11:05:26.000000000 +0200
@@ -898,7 +898,10 @@ ieee80211_tx_h_fragment(struct ieee80211
int hdrlen;
int fragnum;
- if (!(tx->flags & IEEE80211_TX_FRAGMENTED))
+ if (info->flags & IEEE80211_TX_CTL_DONTFRAG)
+ return TX_CONTINUE;
+
+ if (tx->local->ops->set_frag_threshold)
return TX_CONTINUE;
/*
@@ -911,7 +914,7 @@ ieee80211_tx_h_fragment(struct ieee80211
hdrlen = ieee80211_hdrlen(hdr->frame_control);
- /* internal error, why is TX_FRAGMENTED set? */
+ /* internal error, why isn't DONTFRAG set? */
if (WARN_ON(skb->len + FCS_LEN <= frag_threshold))
return TX_DROP;
@@ -1050,17 +1053,13 @@ static bool __ieee80211_parse_tx_radiota
struct ieee80211_radiotap_iterator iterator;
struct ieee80211_radiotap_header *rthdr =
(struct ieee80211_radiotap_header *) skb->data;
- bool hw_frag;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
NULL);
u16 txflags;
- info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
- tx->flags &= ~IEEE80211_TX_FRAGMENTED;
-
- /* packet is fragmented in HW if we have a non-NULL driver callback */
- hw_frag = (tx->local->ops->set_frag_threshold != NULL);
+ info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
+ IEEE80211_TX_CTL_DONTFRAG;
/*
* for every radiotap entry that is present
@@ -1098,9 +1097,8 @@ static bool __ieee80211_parse_tx_radiota
}
if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP)
info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT;
- if ((*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG) &&
- !hw_frag)
- tx->flags |= IEEE80211_TX_FRAGMENTED;
+ if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
+ info->flags &= ~IEEE80211_TX_CTL_DONTFRAG;
break;
case IEEE80211_RADIOTAP_TX_FLAGS:
@@ -1206,13 +1204,6 @@ ieee80211_tx_prepare(struct ieee80211_su
tx->local = local;
tx->sdata = sdata;
tx->channel = local->hw.conf.channel;
- /*
- * Set this flag (used below to indicate "automatic fragmentation"),
- * it will be cleared/left by radiotap as desired.
- * Only valid when fragmentation is done by the stack.
- */
- if (!local->ops->set_frag_threshold)
- tx->flags |= IEEE80211_TX_FRAGMENTED;
/* process and remove the injection radiotap header */
if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) {
@@ -1281,13 +1272,11 @@ ieee80211_tx_prepare(struct ieee80211_su
*/
}
- if (tx->flags & IEEE80211_TX_FRAGMENTED) {
- if ((tx->flags & IEEE80211_TX_UNICAST) &&
- skb->len + FCS_LEN > local->hw.wiphy->frag_threshold &&
- !(info->flags & IEEE80211_TX_CTL_AMPDU))
- tx->flags |= IEEE80211_TX_FRAGMENTED;
- else
- tx->flags &= ~IEEE80211_TX_FRAGMENTED;
+ if (!(info->flags & IEEE80211_TX_CTL_DONTFRAG)) {
+ if (!(tx->flags & IEEE80211_TX_UNICAST) ||
+ skb->len + FCS_LEN <= local->hw.wiphy->frag_threshold ||
+ info->flags & IEEE80211_TX_CTL_AMPDU)
+ info->flags |= IEEE80211_TX_CTL_DONTFRAG;
}
if (!tx->sta)
--- a/net/mac80211/wpa.c 2011-10-07 11:01:01.000000000 +0200
+++ b/net/mac80211/wpa.c 2011-10-07 11:01:18.000000000 +0200
@@ -53,7 +53,8 @@ ieee80211_tx_h_michael_mic_add(struct ie
}
if (info->control.hw_key &&
- !(tx->flags & IEEE80211_TX_FRAGMENTED) &&
+ (info->flags & IEEE80211_TX_CTL_DONTFRAG ||
+ tx->local->ops->set_frag_threshold) &&
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
/* hwaccel - with no need for SW-generated MMIC */
return TX_CONTINUE;
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 4/4] mac80211: parse radiotap header earlier
2011-10-07 12:01 [PATCH 0/4] mac80211 radiotap TX cleanup Johannes Berg
` (2 preceding siblings ...)
2011-10-07 12:01 ` [PATCH 3/4] mac80211: move fragment flag to info flag as dont-fragment Johannes Berg
@ 2011-10-07 12:01 ` Johannes Berg
3 siblings, 0 replies; 5+ messages in thread
From: Johannes Berg @ 2011-10-07 12:01 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
We can now move the radiotap header parsing into
ieee80211_monitor_start_xmit(). This moves it out of
the hotpath, and also helps the code since now the
radiotap header will no longer be present in
ieee80211_xmit() etc. which is easier to understand.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/net/mac80211.h | 4
net/mac80211/tx.c | 201 +++++++++++++++++++++----------------------------
2 files changed, 89 insertions(+), 116 deletions(-)
--- a/net/mac80211/tx.c 2011-10-07 11:05:26.000000000 +0200
+++ b/net/mac80211/tx.c 2011-10-07 11:11:52.000000000 +0200
@@ -1035,103 +1035,6 @@ ieee80211_tx_h_calculate_duration(struct
/* actual transmit path */
-/*
- * deal with packet injection down monitor interface
- * with Radiotap Header -- only called for monitor mode interface
- */
-static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
- struct sk_buff *skb)
-{
- /*
- * this is the moment to interpret and discard the radiotap header that
- * must be at the start of the packet injected in Monitor mode
- *
- * Need to take some care with endian-ness since radiotap
- * args are little-endian
- */
-
- struct ieee80211_radiotap_iterator iterator;
- struct ieee80211_radiotap_header *rthdr =
- (struct ieee80211_radiotap_header *) skb->data;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
- NULL);
- u16 txflags;
-
- info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
- IEEE80211_TX_CTL_DONTFRAG;
-
- /*
- * for every radiotap entry that is present
- * (ieee80211_radiotap_iterator_next returns -ENOENT when no more
- * entries present, or -EINVAL on error)
- */
-
- while (!ret) {
- ret = ieee80211_radiotap_iterator_next(&iterator);
-
- if (ret)
- continue;
-
- /* see if this argument is something we can use */
- switch (iterator.this_arg_index) {
- /*
- * You must take care when dereferencing iterator.this_arg
- * for multibyte types... the pointer is not aligned. Use
- * get_unaligned((type *)iterator.this_arg) to dereference
- * iterator.this_arg for type "type" safely on all arches.
- */
- case IEEE80211_RADIOTAP_FLAGS:
- if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) {
- /*
- * this indicates that the skb we have been
- * handed has the 32-bit FCS CRC at the end...
- * we should react to that by snipping it off
- * because it will be recomputed and added
- * on transmission
- */
- if (skb->len < (iterator._max_length + FCS_LEN))
- return false;
-
- skb_trim(skb, skb->len - FCS_LEN);
- }
- if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP)
- info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT;
- if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
- info->flags &= ~IEEE80211_TX_CTL_DONTFRAG;
- break;
-
- case IEEE80211_RADIOTAP_TX_FLAGS:
- txflags = le16_to_cpu(get_unaligned((__le16*)
- iterator.this_arg));
- if (txflags & IEEE80211_RADIOTAP_F_TX_NOACK)
- info->flags |= IEEE80211_TX_CTL_NO_ACK;
- break;
-
- /*
- * Please update the file
- * Documentation/networking/mac80211-injection.txt
- * when parsing new fields here.
- */
-
- default:
- break;
- }
- }
-
- if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
- return false;
-
- /*
- * remove the radiotap header
- * iterator->_max_length was sanity-checked against
- * skb->len by iterator init
- */
- skb_pull(skb, iterator._max_length);
-
- return true;
-}
-
static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
struct sk_buff *skb,
struct ieee80211_tx_info *info,
@@ -1205,19 +1108,6 @@ ieee80211_tx_prepare(struct ieee80211_su
tx->sdata = sdata;
tx->channel = local->hw.conf.channel;
- /* process and remove the injection radiotap header */
- if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) {
- if (!__ieee80211_parse_tx_radiotap(tx, skb))
- return TX_DROP;
-
- /*
- * __ieee80211_parse_tx_radiotap has now removed
- * the radiotap header that was present and pre-filled
- * 'tx' with tx control information.
- */
- info->flags &= ~IEEE80211_TX_INTFL_HAS_RADIOTAP;
- }
-
/*
* If this flag is set to true anywhere, and we get here,
* we are doing the needed processing, so remove the flag
@@ -1559,6 +1449,89 @@ void ieee80211_xmit(struct ieee80211_sub
rcu_read_unlock();
}
+static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
+{
+ struct ieee80211_radiotap_iterator iterator;
+ struct ieee80211_radiotap_header *rthdr =
+ (struct ieee80211_radiotap_header *) skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len,
+ NULL);
+ u16 txflags;
+
+ info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
+ IEEE80211_TX_CTL_DONTFRAG;
+
+ /*
+ * for every radiotap entry that is present
+ * (ieee80211_radiotap_iterator_next returns -ENOENT when no more
+ * entries present, or -EINVAL on error)
+ */
+
+ while (!ret) {
+ ret = ieee80211_radiotap_iterator_next(&iterator);
+
+ if (ret)
+ continue;
+
+ /* see if this argument is something we can use */
+ switch (iterator.this_arg_index) {
+ /*
+ * You must take care when dereferencing iterator.this_arg
+ * for multibyte types... the pointer is not aligned. Use
+ * get_unaligned((type *)iterator.this_arg) to dereference
+ * iterator.this_arg for type "type" safely on all arches.
+ */
+ case IEEE80211_RADIOTAP_FLAGS:
+ if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) {
+ /*
+ * this indicates that the skb we have been
+ * handed has the 32-bit FCS CRC at the end...
+ * we should react to that by snipping it off
+ * because it will be recomputed and added
+ * on transmission
+ */
+ if (skb->len < (iterator._max_length + FCS_LEN))
+ return false;
+
+ skb_trim(skb, skb->len - FCS_LEN);
+ }
+ if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP)
+ info->flags &= ~IEEE80211_TX_INTFL_DONT_ENCRYPT;
+ if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
+ info->flags &= ~IEEE80211_TX_CTL_DONTFRAG;
+ break;
+
+ case IEEE80211_RADIOTAP_TX_FLAGS:
+ txflags = get_unaligned_le16(iterator.this_arg);
+ if (txflags & IEEE80211_RADIOTAP_F_TX_NOACK)
+ info->flags |= IEEE80211_TX_CTL_NO_ACK;
+ break;
+
+ /*
+ * Please update the file
+ * Documentation/networking/mac80211-injection.txt
+ * when parsing new fields here.
+ */
+
+ default:
+ break;
+ }
+ }
+
+ if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
+ return false;
+
+ /*
+ * remove the radiotap header
+ * iterator->_max_length was sanity-checked against
+ * skb->len by iterator init
+ */
+ skb_pull(skb, iterator._max_length);
+
+ return true;
+}
+
netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
@@ -1646,8 +1619,11 @@ netdev_tx_t ieee80211_monitor_start_xmit
memset(info, 0, sizeof(*info));
info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
- IEEE80211_TX_CTL_INJECTED |
- IEEE80211_TX_INTFL_HAS_RADIOTAP;
+ IEEE80211_TX_CTL_INJECTED;
+
+ /* process and remove the injection radiotap header */
+ if (!ieee80211_parse_tx_radiotap(skb))
+ goto fail;
rcu_read_lock();
@@ -1674,7 +1650,6 @@ netdev_tx_t ieee80211_monitor_start_xmit
}
}
- /* pass the radiotap header up to xmit */
ieee80211_xmit(sdata, skb);
rcu_read_unlock();
--- a/include/net/mac80211.h 2011-10-07 11:01:03.000000000 +0200
+++ b/include/net/mac80211.h 2011-10-07 11:09:41.000000000 +0200
@@ -349,8 +349,6 @@ struct ieee80211_bss_conf {
* @IEEE80211_TX_INTFL_RETRANSMISSION: This frame is being retransmitted
* after TX status because the destination was asleep, it must not
* be modified again (no seqno assignment, crypto, etc.)
- * @IEEE80211_TX_INTFL_HAS_RADIOTAP: This frame was injected and still
- * has a radiotap header at skb->data.
* @IEEE80211_TX_INTFL_NL80211_FRAME_TX: Frame was requested through nl80211
* MLME command (internal to mac80211 to figure out whether to send TX
* status to user space)
@@ -402,7 +400,7 @@ enum mac80211_tx_control_flags {
IEEE80211_TX_CTL_POLL_RESPONSE = BIT(17),
IEEE80211_TX_CTL_MORE_FRAMES = BIT(18),
IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19),
- IEEE80211_TX_INTFL_HAS_RADIOTAP = BIT(20),
+ /* hole at 20, use later */
IEEE80211_TX_INTFL_NL80211_FRAME_TX = BIT(21),
IEEE80211_TX_CTL_LDPC = BIT(22),
IEEE80211_TX_CTL_STBC = BIT(23) | BIT(24),
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2011-10-07 12:05 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-07 12:01 [PATCH 0/4] mac80211 radiotap TX cleanup Johannes Berg
2011-10-07 12:01 ` [PATCH 1/4] mac80211: optimise monitor xmit Johannes Berg
2011-10-07 12:01 ` [PATCH 2/4] mac80211: remove tx_data ethertype Johannes Berg
2011-10-07 12:01 ` [PATCH 3/4] mac80211: move fragment flag to info flag as dont-fragment Johannes Berg
2011-10-07 12:01 ` [PATCH 4/4] mac80211: parse radiotap header earlier Johannes Berg
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.