* [PATCH wireless-next] wifi: mac80211: use link address as TA for non-MLO 4-addr station on MLD AP
@ 2026-10-07 10:52 Felix Fietkau
0 siblings, 0 replies; only message in thread
From: Felix Fietkau @ 2026-10-07 10:52 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes
A 4-address AP_VLAN always sets A2 to sdata->vif.addr, which on an MLD
AP is the AP MLD address. For a non-MLO station, A2 must be the link
address it associated to.
Use the link address for a non-MLO station in the 4-address case as
well, like the AP case already does in ieee80211_build_hdr() and
ieee80211_check_fast_xmit(). Share the address selection between both
cases and both TX paths.
Fixes: 3e0278b717b0 ("wifi: mac80211: select link when transmitting to non-MLO stations")
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
net/mac80211/tx.c | 68 ++++++++++++++++++++++++++++-------------------
1 file changed, 40 insertions(+), 28 deletions(-)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index efe12384c59b..8bebda8038c5 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2698,6 +2698,32 @@ static void ieee80211_store_ack_skb(struct ieee80211_local *local,
}
}
+static int ieee80211_ap_tx_addr_get(struct ieee80211_sub_if_data *sdata,
+ struct sta_info *sta, u8 *addr, u8 *link_id)
+{
+ struct ieee80211_link_data *link;
+ int ret = 0;
+
+ if (!ieee80211_vif_is_mld(&sdata->vif) || sta->sta.mlo) {
+ memcpy(addr, sdata->vif.addr, ETH_ALEN);
+ return 0;
+ }
+
+ rcu_read_lock();
+ link = rcu_dereference(sdata->link[sta->deflink.link_id]);
+ if (WARN_ON(!link)) {
+ ret = -ENOLINK;
+ goto out;
+ }
+
+ memcpy(addr, link->conf->addr, ETH_ALEN);
+ if (link_id)
+ *link_id = sta->deflink.link_id;
+out:
+ rcu_read_unlock();
+ return ret;
+}
+
/**
* ieee80211_build_hdr - build 802.11 header in the given frame
* @sdata: virtual interface to build the header for
@@ -2762,7 +2788,10 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
/* RA TA DA SA */
memcpy(hdr.addr1, sta->sta.addr, ETH_ALEN);
- memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
+ ret = ieee80211_ap_tx_addr_get(sdata, sta, hdr.addr2,
+ &link_id);
+ if (ret)
+ goto free;
memcpy(hdr.addr3, skb->data, ETH_ALEN);
memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
hdrlen = 30;
@@ -2787,18 +2816,12 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
/* DA BSSID SA */
memcpy(hdr.addr1, skb->data, ETH_ALEN);
- if (ieee80211_vif_is_mld(&sdata->vif) && 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;
+ if (sta) {
+ ret = ieee80211_ap_tx_addr_get(sdata, sta, hdr.addr2,
+ &link_id);
+ if (ret)
goto free;
- }
- memcpy(hdr.addr2, link->conf->addr, ETH_ALEN);
- } else if (link_id == IEEE80211_LINK_UNSPECIFIED ||
- (sta && sta->sta.mlo)) {
+ } else if (link_id == IEEE80211_LINK_UNSPECIFIED) {
memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
} else {
struct ieee80211_bss_conf *conf;
@@ -3230,7 +3253,9 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
IEEE80211_FCTL_TODS);
/* RA TA DA SA */
memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN);
- memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
+ if (ieee80211_ap_tx_addr_get(sdata, sta, hdr->addr2,
+ NULL))
+ goto out;
build.da_offs = offsetof(struct ieee80211_hdr, addr3);
build.sa_offs = offsetof(struct ieee80211_hdr, addr4);
build.hdr_len = 30;
@@ -3241,21 +3266,8 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
/* DA BSSID SA */
build.da_offs = offsetof(struct ieee80211_hdr, addr1);
- if (sta->sta.mlo || !ieee80211_vif_is_mld(&sdata->vif)) {
- memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
- } else {
- unsigned int link_id = sta->deflink.link_id;
- struct ieee80211_link_data *link;
-
- rcu_read_lock();
- link = rcu_dereference(sdata->link[link_id]);
- if (WARN_ON(!link)) {
- rcu_read_unlock();
- goto out;
- }
- memcpy(hdr->addr2, link->conf->addr, ETH_ALEN);
- rcu_read_unlock();
- }
+ if (ieee80211_ap_tx_addr_get(sdata, sta, hdr->addr2, NULL))
+ goto out;
build.sa_offs = offsetof(struct ieee80211_hdr, addr3);
build.hdr_len = 24;
break;
--
2.47.3
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-07 10:52 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-07 10:52 [PATCH wireless-next] wifi: mac80211: use link address as TA for non-MLO 4-addr station on MLD AP Felix Fietkau
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox