summaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>2022-07-13 12:05:27 +0300
committerJohannes Berg <johannes.berg@intel.com>2022-07-15 11:43:23 +0200
commit3e0278b717b077f9ccf0280580ce6c5eb9c4dbac (patch)
tree8cfee08b4889bb7241d28501531ec94dd0125f35 /net/mac80211
parentf36fe0a2df03209f4d681fa954f20bfa4eefec45 (diff)
downloadlinux-3e0278b717b077f9ccf0280580ce6c5eb9c4dbac.tar.bz2
wifi: mac80211: select link when transmitting to non-MLO stations
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>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c4
-rw-r--r--net/mac80211/tx.c19
2 files changed, 21 insertions, 2 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 1cacd1e0fc85..fe6500b36953 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -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;
}
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 5dd29288c009..1d60eab8308a 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -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;