All of lore.kernel.org
 help / color / mirror / Atom feed
From: Johannes Berg <johannes@sipsolutions.net>
To: John Linville <linville@tuxdriver.com>
Cc: linux-wireless@vger.kernel.org
Subject: [PATCH 1/4] mac80211: optimise monitor xmit
Date: Fri, 07 Oct 2011 14:01:23 +0200	[thread overview]
Message-ID: <20111007120216.631884561@sipsolutions.net> (raw)
In-Reply-To: 20111007120122.982757001@sipsolutions.net

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:



  reply	other threads:[~2011-10-07 12:04 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-10-07 12:01 [PATCH 0/4] mac80211 radiotap TX cleanup Johannes Berg
2011-10-07 12:01 ` Johannes Berg [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20111007120216.631884561@sipsolutions.net \
    --to=johannes@sipsolutions.net \
    --cc=linux-wireless@vger.kernel.org \
    --cc=linville@tuxdriver.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.