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 --- 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