2020-08-12 08:06:33

by P Praneesh

[permalink] [raw]
Subject: mac80211: fix xmit callback when hwencap enable

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 <[email protected]>
---
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


2020-09-18 11:09:14

by Johannes Berg

[permalink] [raw]
Subject: Re: mac80211: fix xmit callback when hwencap enable

On Wed, 2020-08-12 at 13:35 +0530, P Praneesh wrote:
> 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.

This has some major conflicts with Felix's work, please check if that is
already fixing the issue. I think it is.

johannes