wifi: mac80211: add MLO link ID to TX frame metadata
authorJohannes Berg <johannes.berg@intel.com>
Thu, 9 Jun 2022 20:05:07 +0000 (22:05 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 20 Jun 2022 10:56:04 +0000 (12:56 +0200)
Take a few bits out of the control.flags to add the link ID
to TX frame metadata, so drivers don't need to look it up
by the address themselves. Implement that lookup where it's
needed, for internal frame TX, and set it to "unspecified"
for data transmissions.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/mac80211.h
net/mac80211/tx.c

index 8222419c9ead892a20c631256007daa711cf03c7..1bea225c0d4df15af2b12e6a349dc19c4b4b0bb2 100644 (file)
@@ -867,6 +867,10 @@ enum mac80211_tx_info_flags {
  * @IEEE80211_TX_CTRL_DONT_REORDER: This frame should not be reordered
  *     relative to other frames that have this flag set, independent
  *     of their QoS TID or other priority field values.
+ * @IEEE80211_TX_CTRL_MLO_LINK: If not @IEEE80211_LINK_UNSPECIFIED, this
+ *     frame should be transmitted on the specific link. This really is
+ *     only relevant for frames that do not have data present, and is
+ *     also not used for 802.3 format frames.
  *
  * These flags are used in tx_info->control.flags.
  */
@@ -880,8 +884,11 @@ enum mac80211_tx_control_flags {
        IEEE80211_TX_INTCFL_NEED_TXPROCESSING   = BIT(6),
        IEEE80211_TX_CTRL_NO_SEQNO              = BIT(7),
        IEEE80211_TX_CTRL_DONT_REORDER          = BIT(8),
+       IEEE80211_TX_CTRL_MLO_LINK              = 0xf0000000,
 };
 
+#define IEEE80211_LINK_UNSPECIFIED     0xf
+
 /**
  * enum mac80211_tx_status_flags - flags to describe transmit status
  *
index e8a5e27a3dd14e87e6839efae58665e15dda5dcc..17313954c628fb0344d463d13a2b49f8da644552 100644 (file)
@@ -2889,7 +2889,9 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
        info->flags = info_flags;
        info->ack_frame_id = info_id;
        info->band = band;
-       info->control.flags = ctrl_flags;
+       info->control.flags = ctrl_flags |
+                             u32_encode_bits(IEEE80211_LINK_UNSPECIFIED,
+                                             IEEE80211_TX_CTRL_MLO_LINK);
 
        return skb;
  free:
@@ -3558,7 +3560,9 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
        info->flags = IEEE80211_TX_CTL_FIRST_FRAGMENT |
                      IEEE80211_TX_CTL_DONTFRAG |
                      (tid_tx ? IEEE80211_TX_CTL_AMPDU : 0);
-       info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT;
+       info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT |
+                             u32_encode_bits(IEEE80211_LINK_UNSPECIFIED,
+                                             IEEE80211_TX_CTRL_MLO_LINK);
 
 #ifdef CONFIG_MAC80211_DEBUGFS
        if (local->force_tx_status)
@@ -5668,7 +5672,9 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
                                 struct sk_buff *skb, int tid,
                                 enum nl80211_band band)
 {
+       const struct ieee80211_hdr *hdr = (void *)skb->data;
        int ac = ieee80211_ac_from_tid(tid);
+       unsigned int link;
 
        skb_reset_mac_header(skb);
        skb_set_queue_mapping(skb, ac);
@@ -5676,6 +5682,30 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
 
        skb->dev = sdata->dev;
 
+       BUILD_BUG_ON(IEEE80211_LINK_UNSPECIFIED < IEEE80211_MLD_MAX_NUM_LINKS);
+       BUILD_BUG_ON(!FIELD_FIT(IEEE80211_TX_CTRL_MLO_LINK,
+                               IEEE80211_LINK_UNSPECIFIED));
+
+       if (!sdata->vif.valid_links) {
+               link = 0;
+       } else if (memcmp(sdata->vif.addr, hdr->addr2, ETH_ALEN) == 0) {
+               /* address from the MLD */
+               link = IEEE80211_LINK_UNSPECIFIED;
+       } else {
+               /* otherwise must be addressed from a link */
+               for (link = 0; link < ARRAY_SIZE(sdata->vif.link_conf); link++) {
+                       if (memcmp(sdata->vif.link_conf[link]->addr,
+                                  hdr->addr2, ETH_ALEN) == 0)
+                               break;
+               }
+
+               if (WARN_ON_ONCE(link == ARRAY_SIZE(sdata->vif.link_conf)))
+                       link = ffs(sdata->vif.valid_links) - 1;
+       }
+
+       IEEE80211_SKB_CB(skb)->control.flags |=
+               u32_encode_bits(link, IEEE80211_TX_CTRL_MLO_LINK);
+
        /*
         * The other path calling ieee80211_xmit is from the tasklet,
         * and while we can handle concurrent transmissions locking