Skip to content

Commit

Permalink
mac80211: backport fix for nl80211 control port tx (fixes FS#3857)
Browse files Browse the repository at this point in the history
Signed-off-by: Felix Fietkau <nbd@nbd.name>
  • Loading branch information
nbd168 committed Jun 30, 2021
1 parent 8bb4437 commit de49957
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 17 deletions.
@@ -0,0 +1,116 @@
From: Markus Theil <markus.theil@tu-ilmenau.de>
Date: Sat, 6 Feb 2021 12:51:12 +0100
Subject: [PATCH] mac80211: enable QoS support for nl80211 ctrl port

This patch unifies sending control port frames
over nl80211 and AF_PACKET sockets a little more.

Before this patch, EAPOL frames got QoS prioritization
only when using AF_PACKET sockets.

__ieee80211_select_queue only selects a QoS-enabled queue
for control port frames, when the control port protocol
is set correctly on the skb. For the AF_PACKET path this
works, but the nl80211 path used ETH_P_802_3.

Another check for injected frames in wme.c then prevented
the QoS TID to be copied in the frame.

In order to fix this, get rid of the frame injection marking
for nl80211 ctrl port and set the correct ethernet protocol.

Please note:
An erlier version of this path tried to prevent
frame aggregation for control port frames in order to speed up
the initial connection setup a little. This seemed to cause
issues on my older Intel dvm-based hardware, and was therefore
removed again. Future commits which try to reintroduce this
have to check carefully how hw behaves with aggregated and
non-aggregated traffic for the same TID.
My NIC: Intel(R) Centrino(R) Ultimate-N 6300 AGN, REV=0x74

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
Link: https://lore.kernel.org/r/20210206115112.567881-1-markus.theil@tu-ilmenau.de
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---

--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -628,16 +628,12 @@ static void ieee80211_report_ack_skb(str
u64 cookie = IEEE80211_SKB_CB(skb)->ack.cookie;
struct ieee80211_sub_if_data *sdata;
struct ieee80211_hdr *hdr = (void *)skb->data;
- __be16 ethertype = 0;
-
- if (skb->len >= ETH_HLEN && skb->protocol == cpu_to_be16(ETH_P_802_3))
- skb_copy_bits(skb, 2 * ETH_ALEN, &ethertype, ETH_TLEN);

rcu_read_lock();
sdata = ieee80211_sdata_from_skb(local, skb);
if (sdata) {
- if (ethertype == sdata->control_port_protocol ||
- ethertype == cpu_to_be16(ETH_P_PREAUTH))
+ if (skb->protocol == sdata->control_port_protocol ||
+ skb->protocol == cpu_to_be16(ETH_P_PREAUTH))
cfg80211_control_port_tx_status(&sdata->wdev,
cookie,
skb->data,
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1195,9 +1195,7 @@ ieee80211_tx_prepare(struct ieee80211_su
tx->sta = rcu_dereference(sdata->u.vlan.sta);
if (!tx->sta && sdata->wdev.use_4addr)
return TX_DROP;
- } else if (info->flags & (IEEE80211_TX_INTFL_NL80211_FRAME_TX |
- IEEE80211_TX_CTL_INJECTED) ||
- tx->sdata->control_port_protocol == tx->skb->protocol) {
+ } else if (tx->sdata->control_port_protocol == tx->skb->protocol) {
tx->sta = sta_info_get_bss(sdata, hdr->addr1);
}
if (!tx->sta && !is_multicast_ether_addr(hdr->addr1))
@@ -5421,6 +5419,7 @@ int ieee80211_tx_control_port(struct wip
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
+ struct sta_info *sta;
struct sk_buff *skb;
struct ethhdr *ehdr;
u32 ctrl_flags = 0;
@@ -5443,8 +5442,7 @@ int ieee80211_tx_control_port(struct wip
if (cookie)
ctrl_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;

- flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX |
- IEEE80211_TX_CTL_INJECTED;
+ flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX;

skb = dev_alloc_skb(local->hw.extra_tx_headroom +
sizeof(struct ethhdr) + len);
@@ -5461,10 +5459,25 @@ int ieee80211_tx_control_port(struct wip
ehdr->h_proto = proto;

skb->dev = dev;
- skb->protocol = htons(ETH_P_802_3);
+ skb->protocol = proto;
skb_reset_network_header(skb);
skb_reset_mac_header(skb);

+ /* update QoS header to prioritize control port frames if possible,
+ * priorization also happens for control port frames send over
+ * AF_PACKET
+ */
+ rcu_read_lock();
+
+ if (ieee80211_lookup_ra_sta(sdata, skb, &sta) == 0 && !IS_ERR(sta)) {
+ u16 queue = __ieee80211_select_queue(sdata, sta, skb);
+
+ skb_set_queue_mapping(skb, queue);
+ skb_get_hash(skb);
+ }
+
+ rcu_read_unlock();
+
/* mutex lock is only needed for incrementing the cookie counter */
mutex_lock(&local->mtx);

Expand Up @@ -28,7 +28,7 @@ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
*
* Transmit and frame generation functions.
*/
@@ -1403,8 +1403,17 @@ static void ieee80211_txq_enqueue(struct
@@ -1401,8 +1401,17 @@ static void ieee80211_txq_enqueue(struct
ieee80211_set_skb_enqueue_time(skb);

spin_lock_bh(&fq->lock);
Expand All @@ -48,7 +48,7 @@ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
spin_unlock_bh(&fq->lock);
}

@@ -3846,6 +3855,9 @@ bool ieee80211_txq_airtime_check(struct
@@ -3844,6 +3853,9 @@ bool ieee80211_txq_airtime_check(struct
if (!txq->sta)
return true;

Expand Down
Expand Up @@ -9,7 +9,7 @@ Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>

--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4173,6 +4173,9 @@ static bool ieee80211_tx_8023(struct iee
@@ -4171,6 +4171,9 @@ static bool ieee80211_tx_8023(struct iee
unsigned long flags;
int q = info->hw_queue;

Expand Down
Expand Up @@ -76,7 +76,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
.rate_init = minstrel_ht_rate_init,
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3933,6 +3933,29 @@ void ieee80211_txq_schedule_start(struct
@@ -3931,6 +3931,29 @@ void ieee80211_txq_schedule_start(struct
}
EXPORT_SYMBOL(ieee80211_txq_schedule_start);

Expand Down Expand Up @@ -106,7 +106,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
void __ieee80211_subif_start_xmit(struct sk_buff *skb,
struct net_device *dev,
u32 info_flags,
@@ -3963,6 +3986,8 @@ void __ieee80211_subif_start_xmit(struct
@@ -3961,6 +3984,8 @@ void __ieee80211_subif_start_xmit(struct
skb_get_hash(skb);
}

Expand All @@ -115,7 +115,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
if (sta) {
struct ieee80211_fast_tx *fast_tx;

@@ -4226,6 +4251,8 @@ static void ieee80211_8023_xmit(struct i
@@ -4224,6 +4249,8 @@ static void ieee80211_8023_xmit(struct i

memset(info, 0, sizeof(*info));

Expand Down
Expand Up @@ -10,7 +10,7 @@ Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>

--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1780,8 +1780,6 @@ static int invoke_tx_handlers_early(stru
@@ -1778,8 +1778,6 @@ static int invoke_tx_handlers_early(stru
CALL_TXH(ieee80211_tx_h_ps_buf);
CALL_TXH(ieee80211_tx_h_check_control_port_protocol);
CALL_TXH(ieee80211_tx_h_select_key);
Expand All @@ -19,7 +19,7 @@ Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>

txh_done:
if (unlikely(res == TX_DROP)) {
@@ -1814,6 +1812,9 @@ static int invoke_tx_handlers_late(struc
@@ -1812,6 +1810,9 @@ static int invoke_tx_handlers_late(struc
goto txh_done;
}

Expand All @@ -29,7 +29,7 @@ Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
CALL_TXH(ieee80211_tx_h_michael_mic_add);
CALL_TXH(ieee80211_tx_h_sequence);
CALL_TXH(ieee80211_tx_h_fragment);
@@ -3384,15 +3385,21 @@ out:
@@ -3382,15 +3383,21 @@ out:
* Can be called while the sta lock is held. Anything that can cause packets to
* be generated will cause deadlock!
*/
Expand All @@ -55,7 +55,7 @@ Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
if (key)
info->control.hw_key = &key->conf;

@@ -3441,6 +3448,8 @@ static void ieee80211_xmit_fast_finish(s
@@ -3439,6 +3446,8 @@ static void ieee80211_xmit_fast_finish(s
break;
}
}
Expand All @@ -64,7 +64,7 @@ Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
}

static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
@@ -3544,24 +3553,17 @@ static bool ieee80211_xmit_fast(struct i
@@ -3542,24 +3551,17 @@ static bool ieee80211_xmit_fast(struct i
tx.sta = sta;
tx.key = fast_tx->key;

Expand Down Expand Up @@ -97,7 +97,7 @@ Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>

if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
sdata = container_of(sdata->bss,
@@ -3672,8 +3674,12 @@ begin:
@@ -3670,8 +3672,12 @@ begin:
(tx.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))
pn_offs = ieee80211_hdrlen(hdr->frame_control);

Expand Down
Expand Up @@ -99,7 +99,7 @@ Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
tx->sta->tx_stats.last_rate = txrc.reported_rate;
} else if (tx->sta)
tx->sta->tx_stats.last_rate = txrc.reported_rate;
@@ -3662,8 +3664,16 @@ begin:
@@ -3660,8 +3662,16 @@ begin:
else
info->flags &= ~IEEE80211_TX_CTL_AMPDU;

Expand Down
Expand Up @@ -54,8 +54,8 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
int tid;

memset(tx, 0, sizeof(*tx));
@@ -1202,8 +1226,10 @@ ieee80211_tx_prepare(struct ieee80211_su
tx->sdata->control_port_protocol == tx->skb->protocol) {
@@ -1200,8 +1224,10 @@ ieee80211_tx_prepare(struct ieee80211_su
} else if (tx->sdata->control_port_protocol == tx->skb->protocol) {
tx->sta = sta_info_get_bss(sdata, hdr->addr1);
}
- if (!tx->sta && !is_multicast_ether_addr(hdr->addr1))
Expand All @@ -66,7 +66,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
}

if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) &&
@@ -1213,8 +1239,12 @@ ieee80211_tx_prepare(struct ieee80211_su
@@ -1211,8 +1237,12 @@ ieee80211_tx_prepare(struct ieee80211_su
struct tid_ampdu_tx *tid_tx;

tid = ieee80211_get_tid(hdr);
Expand All @@ -80,7 +80,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
if (tid_tx) {
bool queued;

@@ -3949,29 +3979,6 @@ void ieee80211_txq_schedule_start(struct
@@ -3947,29 +3977,6 @@ void ieee80211_txq_schedule_start(struct
}
EXPORT_SYMBOL(ieee80211_txq_schedule_start);

Expand Down

0 comments on commit de49957

Please sign in to comment.