Search Linux Wireless

mac80211: fix xmit callback when hwencap enable

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Since transmit control port uses same callback for both
(ieee80211_subif_start_xmit) ethernet mode and native
wifi mode, which causes authentication issue (M2 Handshake failure)
in ethernet mode with encryption(psk2+ccmp).
This will also be an issue for hw/fw which doesn't support per
packet tx/rx encap/decap.

Added hardware encap check to filter out ethernet mode
packets to follow ieee80211_subif_start_xmit_8023 path.

Fixes: a7528198add8 ("mac80211: support control port TX status reporting")
Signed-off-by: P Praneesh <ppranees@xxxxxxxxxxxxxx>
---
 net/mac80211/ieee80211_i.h |  5 +++++
 net/mac80211/tx.c          | 49 ++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 46 insertions(+), 8 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ec1a71a..d2c4d68 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1783,6 +1783,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 				       struct net_device *dev);
 netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
 					    struct net_device *dev);
+netdev_tx_t __ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
+					      struct net_device *dev,
+					      u32 info_flags,
+					      u32 ctrl_flags,
+					      u64 *cookie);
 void __ieee80211_subif_start_xmit(struct sk_buff *skb,
 				  struct net_device *dev,
 				  u32 info_flags,
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 3529d13..a9d1b8d 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4150,6 +4150,25 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 	return NETDEV_TX_OK;
 }
 
+netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
+					    struct net_device *dev)
+{
+	netdev_tx_t ret;
+
+	if (unlikely(ieee80211_multicast_to_unicast(skb, dev))) {
+		struct sk_buff_head queue;
+
+		__skb_queue_head_init(&queue);
+		ieee80211_convert_to_unicast(skb, dev, &queue);
+		while ((skb = __skb_dequeue(&queue)))
+			ret = __ieee80211_subif_start_xmit_8023(skb, dev, 0, 0, NULL);
+	} else {
+		ret = __ieee80211_subif_start_xmit_8023(skb, dev, 0, 0, NULL);
+	}
+
+	return ret;
+}
+
 static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
 			      struct sk_buff *skb, int led_len,
 			      struct sta_info *sta,
@@ -4193,7 +4212,8 @@ static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
 
 static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
 				struct net_device *dev, struct sta_info *sta,
-				struct sk_buff *skb)
+				struct sk_buff *skb, u32 info_flags,
+				u32 ctrl_flags, u64  *cookie)
 {
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ethhdr *ehdr = (struct ethhdr *)skb->data;
@@ -4232,10 +4252,11 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
 
 	memset(info, 0, sizeof(*info));
 
-	if (unlikely(!multicast && skb->sk &&
-		     skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS))
+	if (unlikely(!multicast && ((skb->sk &&
+		     skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS) ||
+		     ctrl_flags & IEEE80211_TX_CTL_REQ_TX_STATUS)))
 		info->ack_frame_id = ieee80211_store_ack_skb(local, skb,
-							     &info->flags, NULL);
+							     &info_flags, cookie);
 
 	if (unlikely(sdata->control_port_protocol == ehdr->h_proto)) {
 		if (sdata->control_port_no_encrypt)
@@ -4259,6 +4280,7 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
 		sdata = container_of(sdata->bss,
 				     struct ieee80211_sub_if_data, u.ap);
 
+	info->flags = info_flags;
 	info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP;
 	info->control.vif = &sdata->vif;
 
@@ -4270,8 +4292,11 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
 	kfree_skb(skb);
 }
 
-netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
-					    struct net_device *dev)
+netdev_tx_t __ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
+					      struct net_device *dev,
+					      u32 info_flags,
+					      u32 ctrl_flags,
+					      u64 *cookie)
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct sta_info *sta;
@@ -4291,7 +4316,8 @@ netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
 	if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
 		kfree_skb(skb);
 	else
-		ieee80211_8023_xmit(sdata, dev, sta, skb);
+		ieee80211_8023_xmit(sdata, dev, sta, skb,
+				    info_flags, ctrl_flags, cookie);
 
 	rcu_read_unlock();
 
@@ -5410,7 +5436,14 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
 	mutex_lock(&local->mtx);
 
 	local_bh_disable();
-	__ieee80211_subif_start_xmit(skb, skb->dev, flags, ctrl_flags, cookie);
+
+	if (sdata->hw_80211_encap)
+		__ieee80211_subif_start_xmit_8023(skb, skb->dev, flags,
+						  ctrl_flags, cookie);
+	else
+		__ieee80211_subif_start_xmit(skb, skb->dev, flags,
+					     ctrl_flags, cookie);
+
 	local_bh_enable();
 
 	mutex_unlock(&local->mtx);
-- 
2.7.4




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux