[PATCH RFC wireless-next 7/7] wifi: mac80211: add MSCS packet classification
Aishwarya R
aishwarya.r at oss.qualcomm.com
Wed Oct 14 22:54:41 PDT 2026
Use the negotiated MSCS configuration to classify uplink traffic and
enforce the configured user priority limit during transmit queue
selection for AP-forwarded packets.
For packets received from an associated non-AP STA, the RX path checks
the received user priority against the negotiated MSCS user-priority
bitmap. When a match is found, mac80211 records an MSCS tag together
with the received user priority in skb->mark.
The received user priority can be associated with a connection by
copying skb->mark to the conntrack mark using nftables. Since the
conntrack entry is shared by both directions of the connection, the
stored metadata can later be restored into skb->mark for corresponding
downlink packets. When such a packet is forwarded to mac80211,
ieee80211_select_queue() consumes the metadata from skb->mark, applies
the negotiated MSCS user-priority limit, updates skb->priority, and
normal queue selection maps it to the transmit TID.
Intra-BSS forwarding requires per-station peer isolation to ensure the
MSCS mark is preserved at transmit queue selection.
Signed-off-by: Aishwarya R <aishwarya.r at oss.qualcomm.com>
---
net/mac80211/rx.c | 29 +++++++++++++++++++++++++++++
net/mac80211/wme.c | 23 +++++++++++++++++------
2 files changed, 46 insertions(+), 6 deletions(-)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index ecee9348c70d..930de5b412c5 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1003,6 +1003,31 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
rx->skb->priority = (tid > 7) ? 0 : tid;
}
+static void ieee80211_qos_mgmt_mscs_set_mark(struct ieee80211_rx_data *rx)
+{
+ struct ieee80211_sta_qos_rcu *qos;
+ u8 tid;
+
+ if (!rx->sta ||
+ (rx->sdata->vif.type != NL80211_IFTYPE_AP &&
+ rx->sdata->vif.type != NL80211_IFTYPE_AP_VLAN) ||
+ rx->seqno_idx >= IEEE80211_QOS_MGMT_MAX_TID)
+ return;
+
+ tid = rx->skb->priority;
+
+ qos = rcu_dereference(rx->sta->qos);
+ if (!qos || !qos->data.mscs_enabled ||
+ !(BIT(tid) & qos->data.mscs_user_priority_bitmap))
+ return;
+
+ rx->skb->mark = u32_replace_bits(rx->skb->mark,
+ IEEE80211_QOS_MGMT_MSCS_TAG,
+ IEEE80211_QOS_MGMT_TAG_MASK);
+ rx->skb->mark = u32_replace_bits(rx->skb->mark, tid,
+ IEEE80211_QOS_MGMT_ID_MASK);
+}
+
/**
* DOC: Packet alignment
*
@@ -3333,6 +3358,9 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
rx->skb->dev = dev;
+ if (!port_control)
+ ieee80211_qos_mgmt_mscs_set_mark(rx);
+
if (!ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS) &&
local->ps_sdata && local->hw.conf.dynamic_ps_timeout > 0 &&
!is_multicast_ether_addr(
@@ -4996,6 +5024,7 @@ static void ieee80211_rx_8023(struct ieee80211_rx_data *rx,
stats->packets++;
skb->dev = fast_rx->dev;
+ ieee80211_qos_mgmt_mscs_set_mark(rx);
dev_sw_netstats_rx_add(fast_rx->dev, skb->len);
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index 4d1bad27a8d6..feca08f28185 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -126,10 +126,11 @@ ieee80211_qos_mgmt_set_priority(struct sta_info *sta, struct sk_buff *skb)
qos_tag = u32_get_bits(skb->mark, IEEE80211_QOS_MGMT_TAG_MASK);
qos_id = u32_get_bits(skb->mark, IEEE80211_QOS_MGMT_ID_MASK);
- if (qos_tag != IEEE80211_QOS_MGMT_SCS_TAG)
+ if (qos_tag != IEEE80211_QOS_MGMT_SCS_TAG &&
+ qos_tag != IEEE80211_QOS_MGMT_MSCS_TAG)
return;
- if (!qos_id)
+ if (qos_tag == IEEE80211_QOS_MGMT_SCS_TAG && !qos_id)
return;
guard(rcu)();
@@ -138,11 +139,21 @@ ieee80211_qos_mgmt_set_priority(struct sta_info *sta, struct sk_buff *skb)
if (!qos)
return;
- if (!qos->data.scs_enabled ||
- !test_bit(qos_id, qos->data.active_scs_id))
- return;
+ if (qos_tag == IEEE80211_QOS_MGMT_SCS_TAG) {
+ if (!qos->data.scs_enabled ||
+ !test_bit(qos_id, qos->data.active_scs_id))
+ return;
+
+ tid = qos->data.scs_id_tid_mapping[qos_id];
+ } else {
+ if (!qos->data.mscs_enabled ||
+ qos_id >= IEEE80211_QOS_MGMT_MAX_TID ||
+ !(qos->data.mscs_user_priority_bitmap & BIT(qos_id)))
+ return;
- tid = qos->data.scs_id_tid_mapping[qos_id];
+ tid = min_t(u8, qos_id,
+ qos->data.mscs_user_priority_limit);
+ }
if (tid < IEEE80211_QOS_MGMT_MAX_TID)
skb->priority = tid;
--
2.34.1
More information about the ath12k
mailing list