]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
wifi: nl80211/mac80211: clarify link ID in control port TX
authorJohannes Berg <johannes.berg@intel.com>
Tue, 19 Jul 2022 08:26:50 +0000 (10:26 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 22 Jul 2022 12:28:16 +0000 (14:28 +0200)
Clarify the link ID behaviour in control port TX, we need it
to select the link to transmit on for both MLD and non-MLD
receivers, but select the link address as the SA only if the
receiver is not an MLD.

Fixes: 67207bab9341 ("wifi: cfg80211/mac80211: Support control port TX from specific link")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/uapi/linux/nl80211.h
net/mac80211/tx.c

index 3fa586e38f88965da320a74bd599bc98bb1c1075..d4d6ba585b41ccc3866da2654fd89877586921d7 100644 (file)
  *     has been received. %NL80211_ATTR_FRAME is used to specify the
  *     frame contents.  The frame is the raw EAPoL data, without ethernet or
  *     802.11 headers.
+ *     For an MLD transmitter, the %NL80211_ATTR_MLO_LINK_ID may be given and
+ *     its effect will depend on the destination: If the destination is known
+ *     to be an MLD, this will be used as a hint to select the link to transmit
+ *     the frame on. If the destination is not an MLD, this will select both
+ *     the link to transmit on and the source address will be set to the link
+ *     address of that link.
  *     When used as an event indication %NL80211_ATTR_CONTROL_PORT_ETHERTYPE,
  *     %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT and %NL80211_ATTR_MAC are added
  *     indicating the protocol type of the received frame; whether the frame
index 772108c2cc6be271d8df145b5a96cba503e54c2c..06ec152e8188ae47ed18fa7fb3d5a63c7a477745 100644 (file)
@@ -2896,9 +2896,35 @@ 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 |
-                             u32_encode_bits(link_id,
+
+       if (likely(!cookie)) {
+               ctrl_flags |= u32_encode_bits(link_id,
                                              IEEE80211_TX_CTRL_MLO_LINK);
+       } else {
+               unsigned int pre_conf_link_id;
+
+               /*
+                * ctrl_flags already have been set by
+                * ieee80211_tx_control_port(), here
+                * we just sanity check that
+                */
+
+               pre_conf_link_id = u32_get_bits(ctrl_flags,
+                                               IEEE80211_TX_CTRL_MLO_LINK);
+
+               if (pre_conf_link_id != link_id &&
+                   link_id != IEEE80211_LINK_UNSPECIFIED) {
+#ifdef CPTCFG_MAC80211_VERBOSE_DEBUG
+                       net_info_ratelimited("%s: dropped frame to %pM with bad link ID request (%d vs. %d)\n",
+                                            sdata->name, hdr.addr1,
+                                            pre_conf_link_id, link_id);
+#endif
+                       ret = -EINVAL;
+                       goto free;
+               }
+       }
+
+       info->control.flags = ctrl_flags;
 
        return skb;
  free:
@@ -5745,11 +5771,17 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
        ehdr = skb_push(skb, sizeof(struct ethhdr));
        memcpy(ehdr->h_dest, dest, ETH_ALEN);
 
+       /* we may override the SA for MLO STA later */
        if (link_id < 0) {
+               ctrl_flags |= u32_encode_bits(IEEE80211_LINK_UNSPECIFIED,
+                                             IEEE80211_TX_CTRL_MLO_LINK);
                memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN);
        } else {
                struct ieee80211_bss_conf *link_conf;
 
+               ctrl_flags |= u32_encode_bits(link_id,
+                                             IEEE80211_TX_CTRL_MLO_LINK);
+
                rcu_read_lock();
                link_conf = rcu_dereference(sdata->vif.link_conf[link_id]);
                if (!link_conf) {
@@ -5784,6 +5816,13 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
 
                skb_set_queue_mapping(skb, queue);
                skb_get_hash(skb);
+
+               /*
+                * for MLO STA, the SA should be the AP MLD address, but
+                * the link ID has been selected already
+                */
+               if (sta->sta.mlo)
+                       memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN);
        }
        rcu_read_unlock();