]> git.baikalelectronics.ru Git - kernel.git/commitdiff
wifi: mac80211: select link when transmitting to non-MLO stations
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>
Wed, 13 Jul 2022 09:05:27 +0000 (12:05 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 15 Jul 2022 09:43:23 +0000 (11:43 +0200)
When an MLO AP is transmitting to a non-MLO station, addr2 should be set
to a link address. This should be done before the frame is encrypted as
otherwise aad verification would fail. In case of software encryption
this can't be left for the device to handle, and should be done by
mac80211 when building the frame hdr.

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

index 6fc4253b56449bf0ca671096d31b1637d17fba79..6f856da28d713665f1554a0f684c6e7ed12d3247 100644 (file)
@@ -2147,6 +2147,7 @@ struct ieee80211_link_sta {
  * @tdls_initiator: indicates the STA is an initiator of the TDLS link. Only
  *     valid if the STA is a TDLS peer in the first place.
  * @mfp: indicates whether the STA uses management frame protection or not.
+ * @mlo: indicates whether the STA is MLO station.
  * @max_amsdu_subframes: indicates the maximal number of MSDUs in a single
  *     A-MSDU. Taken from the Extended Capabilities element. 0 means
  *     unlimited.
@@ -2180,6 +2181,7 @@ struct ieee80211_sta {
        bool tdls;
        bool tdls_initiator;
        bool mfp;
+       bool mlo;
        u8 max_amsdu_subframes;
 
        /**
index 1cacd1e0fc8524b1e80d17dfb0c2b035f33d766b..fe6500b36953e2b3dbea3afe9a83c6c6327cfeac 100644 (file)
@@ -1818,6 +1818,10 @@ static int sta_apply_parameters(struct ieee80211_local *local,
                        return ret;
        }
 
+       /* Mark the STA as MLO if MLD MAC address is available */
+       if (params->link_sta_params.mld_mac)
+               sta->sta.mlo = true;
+
        return 0;
 }
 
index 5dd29288c00911bd2cc23ede38662f0d0675c4a2..1d60eab8308aa7e827a96313850f4899db8c4c1c 100644 (file)
@@ -2570,6 +2570,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_chanctx_conf *chanctx_conf = NULL;
        enum nl80211_band band;
        int ret;
+       u8 link_id = IEEE80211_LINK_UNSPECIFIED;
 
        if (IS_ERR(sta))
                sta = NULL;
@@ -2618,7 +2619,21 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
                fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
                /* DA BSSID SA */
                memcpy(hdr.addr1, skb->data, ETH_ALEN);
-               memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
+
+               if (sdata->vif.valid_links && sta && !sta->sta.mlo) {
+                       struct ieee80211_link_data *link;
+
+                       link_id = sta->deflink.link_id;
+                       link = rcu_dereference(sdata->link[link_id]);
+                       if (WARN_ON(!link)) {
+                               ret = -ENOLINK;
+                               goto free;
+                       }
+                       memcpy(hdr.addr2, link->conf->addr, ETH_ALEN);
+               } else {
+                       memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
+               }
+
                memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
                hdrlen = 24;
                break;
@@ -2882,7 +2897,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
        info->ack_frame_id = info_id;
        info->band = band;
        info->control.flags = ctrl_flags |
-                             u32_encode_bits(IEEE80211_LINK_UNSPECIFIED,
+                             u32_encode_bits(link_id,
                                              IEEE80211_TX_CTRL_MLO_LINK);
 
        return skb;