linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [mac80211] mac80211:  Support receiving data frames on multiple vifs.
@ 2010-09-20 17:52 greearb
  2010-09-20 19:10 ` Johannes Berg
  0 siblings, 1 reply; 12+ messages in thread
From: greearb @ 2010-09-20 17:52 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear

From: Ben Greear <greearb@candelatech.com>

When using multiple STA interfaces on the same radio, some
data packets need to be received on all interfaces
(broadcast, for instance).

Remove special loop for data-only packets and just process all
packets in the big loop that previously only handled non-data
packets.

This needs review.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 c036815... 63baa04... M	net/mac80211/rx.c
 net/mac80211/rx.c |  121 ++++++++++++++++++++++-------------------------------
 1 files changed, 50 insertions(+), 71 deletions(-)

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index c036815..63baa04 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2613,8 +2613,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 	int prepares;
 	struct ieee80211_sub_if_data *prev = NULL;
 	struct sk_buff *skb_new;
-	struct sta_info *sta, *tmp;
-	bool found_sta = false;
 	int err = 0;
 
 	fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
@@ -2643,87 +2641,68 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 	ieee80211_parse_qos(&rx);
 	ieee80211_verify_alignment(&rx);
 
-	if (ieee80211_is_data(fc)) {
-		for_each_sta_info(local, hdr->addr2, sta, tmp) {
-			rx.sta = sta;
-			found_sta = true;
-			rx.sdata = sta->sdata;
-
-			rx.flags |= IEEE80211_RX_RA_MATCH;
-			prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
-			if (prepares) {
-				if (status->flag & RX_FLAG_MMIC_ERROR) {
-					if (rx.flags & IEEE80211_RX_RA_MATCH)
-						ieee80211_rx_michael_mic_report(hdr, &rx);
-				} else
-					prev = rx.sdata;
-			}
-		}
-	}
-	if (!found_sta) {
-		list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-			if (!ieee80211_sdata_running(sdata))
-				continue;
-
-			if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
-			    sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-				continue;
+	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+		if (!ieee80211_sdata_running(sdata))
+			continue;
 
-			/*
-			 * frame is destined for this interface, but if it's
-			 * not also for the previous one we handle that after
-			 * the loop to avoid copying the SKB once too much
-			 */
+		if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
+		    sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+			continue;
 
-			if (!prev) {
-				prev = sdata;
-				continue;
-			}
+		/*
+		 * frame is destined for this interface, but if it's
+		 * not also for the previous one we handle that after
+		 * the loop to avoid copying the SKB once too much
+		 */
 
-			rx.sta = sta_info_get_bss(prev, hdr->addr2);
+		if (!prev) {
+			prev = sdata;
+			continue;
+		}
 
-			rx.flags |= IEEE80211_RX_RA_MATCH;
-			prepares = prepare_for_handlers(prev, &rx, hdr);
+		rx.sta = sta_info_get_bss(prev, hdr->addr2);
+		rx.sdata = prev;
+		rx.flags |= IEEE80211_RX_RA_MATCH;
+		prepares = prepare_for_handlers(prev, &rx, hdr);
 
-			if (!prepares)
-				goto next;
+		if (!prepares)
+			goto next;
 
-			if (status->flag & RX_FLAG_MMIC_ERROR) {
-				rx.sdata = prev;
-				if (rx.flags & IEEE80211_RX_RA_MATCH)
-					ieee80211_rx_michael_mic_report(hdr,
-									&rx);
-				goto next;
-			}
+		if (status->flag & RX_FLAG_MMIC_ERROR) {
+			rx.sdata = prev;
+			if (rx.flags & IEEE80211_RX_RA_MATCH)
+				ieee80211_rx_michael_mic_report(hdr, &rx);
+			goto next;
+		}
 
-			/*
-			 * frame was destined for the previous interface
-			 * so invoke RX handlers for it
-			 */
+		/*
+		 * frame was destined for the previous interface
+		 * so invoke RX handlers for it
+		 */
 
-			skb_new = skb_copy(skb, GFP_ATOMIC);
-			if (!skb_new) {
-				if (net_ratelimit())
-					wiphy_debug(local->hw.wiphy,
-						    "failed to copy multicast frame for %s\n",
-						    prev->name);
-				goto next;
-			}
-			ieee80211_invoke_rx_handlers(prev, &rx, skb_new);
-next:
-			prev = sdata;
+		skb_new = skb_copy(skb, GFP_ATOMIC);
+		if (!skb_new) {
+			if (net_ratelimit())
+				wiphy_debug(local->hw.wiphy,
+					    "failed to copy multicast frame for %s\n",
+					    prev->name);
+			goto next;
 		}
+		ieee80211_invoke_rx_handlers(prev, &rx, skb_new);
+next:
+		prev = sdata;
+	} /* for all interfaces */
 
-		if (prev) {
-			rx.sta = sta_info_get_bss(prev, hdr->addr2);
-
-			rx.flags |= IEEE80211_RX_RA_MATCH;
-			prepares = prepare_for_handlers(prev, &rx, hdr);
+	if (prev) {
+		rx.sta = sta_info_get_bss(prev, hdr->addr2);
+		rx.sdata = prev;
+		rx.flags |= IEEE80211_RX_RA_MATCH;
+		prepares = prepare_for_handlers(prev, &rx, hdr);
 
-			if (!prepares)
-				prev = NULL;
-		}
+		if (!prepares)
+			prev = NULL;
 	}
+
 	if (prev)
 		ieee80211_invoke_rx_handlers(prev, &rx, skb);
 	else
-- 
1.7.2.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread
* [mac80211] mac80211:  Support receiving data frames on multiple vifs.
@ 2010-09-20 21:39 greearb
  2010-09-21  6:47 ` Johannes Berg
  0 siblings, 1 reply; 12+ messages in thread
From: greearb @ 2010-09-20 21:39 UTC (permalink / raw)
  To: linux-wireless; +Cc: Ben Greear

From: Ben Greear <greearb@candelatech.com>

When using multiple STA interfaces on the same radio, some
data packets need to be received on all interfaces
(broadcast, for instance).

Make the STA loop look similar to the mgt-data loop.

Also, add logic to check RX_FLAG_MMIC_ERROR for last
interface in mgt-data loop.

This needs review.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 c036815... a7847e1... M	net/mac80211/rx.c
 net/mac80211/rx.c |   80 ++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 70 insertions(+), 10 deletions(-)

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index c036815..a7847e1 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2613,7 +2613,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 	int prepares;
 	struct ieee80211_sub_if_data *prev = NULL;
 	struct sk_buff *skb_new;
-	struct sta_info *sta, *tmp;
+	struct sta_info *sta, *tmp, *prev_sta;
 	bool found_sta = false;
 	int err = 0;
 
@@ -2644,22 +2644,74 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 	ieee80211_verify_alignment(&rx);
 
 	if (ieee80211_is_data(fc)) {
+		prev_sta = NULL;
 		for_each_sta_info(local, hdr->addr2, sta, tmp) {
-			rx.sta = sta;
 			found_sta = true;
-			rx.sdata = sta->sdata;
+			if (!prev_sta) {
+				prev_sta = sta;
+				continue;
+			}
+
+			rx.sta = prev_sta;
+			rx.sdata = prev_sta->sdata;
 
 			rx.flags |= IEEE80211_RX_RA_MATCH;
 			prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
-			if (prepares) {
-				if (status->flag & RX_FLAG_MMIC_ERROR) {
-					if (rx.flags & IEEE80211_RX_RA_MATCH)
-						ieee80211_rx_michael_mic_report(hdr, &rx);
-				} else
-					prev = rx.sdata;
+			if (!prepares)
+				goto next_sta;
+
+			if (status->flag & RX_FLAG_MMIC_ERROR) {
+				if (rx.flags & IEEE80211_RX_RA_MATCH)
+					ieee80211_rx_michael_mic_report(hdr, &rx);
+				goto next_sta;
+			}
+
+			/*
+			 * frame was destined for the previous interface
+			 * so invoke RX handlers for it
+			 */
+			skb_new = skb_copy(skb, GFP_ATOMIC);
+			if (!skb_new) {
+				if (net_ratelimit())
+					wiphy_debug(local->hw.wiphy,
+						    "failed to copy multicast"
+						    " frame for %s\n",
+						    prev_sta->sdata->name);
+				goto next_sta;
+			}
+			ieee80211_invoke_rx_handlers(prev_sta->sdata, &rx,
+						     skb_new);
+next_sta:
+			prev_sta = sta;
+		} /* for all STA info */
+
+		if (prev_sta) {
+			rx.sta = prev_sta;
+			rx.sdata = prev_sta->sdata;
+
+			rx.flags |= IEEE80211_RX_RA_MATCH;
+			prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
+			if (!prepares)
+				prev_sta = NULL;
+
+			if (status->flag & RX_FLAG_MMIC_ERROR) {
+				if (rx.flags & IEEE80211_RX_RA_MATCH)
+					ieee80211_rx_michael_mic_report(hdr, &rx);
+				prev_sta = NULL;
 			}
 		}
-	}
+
+
+		if (prev_sta) {
+			ieee80211_invoke_rx_handlers(prev_sta->sdata, &rx, skb);
+			return;
+		} else {
+			if (found_sta) {
+				dev_kfree_skb(skb);
+				return;
+			}
+		}
+	} /* if data frame */
 	if (!found_sta) {
 		list_for_each_entry_rcu(sdata, &local->interfaces, list) {
 			if (!ieee80211_sdata_running(sdata))
@@ -2722,6 +2774,14 @@ next:
 
 			if (!prepares)
 				prev = NULL;
+
+			if (status->flag & RX_FLAG_MMIC_ERROR) {
+				rx.sdata = prev;
+				if (rx.flags & IEEE80211_RX_RA_MATCH)
+					ieee80211_rx_michael_mic_report(hdr,
+									&rx);
+				prev = NULL;
+			}
 		}
 	}
 	if (prev)
-- 
1.7.2.2


^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2010-09-23 19:07 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-09-20 17:52 [mac80211] mac80211: Support receiving data frames on multiple vifs greearb
2010-09-20 19:10 ` Johannes Berg
2010-09-20 19:56   ` Ben Greear
2010-09-21  6:32     ` Johannes Berg
  -- strict thread matches above, loose matches on Subject: below --
2010-09-20 21:39 greearb
2010-09-21  6:47 ` Johannes Berg
2010-09-23 13:57   ` Ben Greear
2010-09-23 14:06     ` Johannes Berg
2010-09-23 16:57       ` Ben Greear
2010-09-23 18:42         ` Johannes Berg
2010-09-23 18:48           ` Ben Greear
2010-09-23 19:07             ` Johannes Berg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).