From: Felix Fietkau <nbd@nbd.name>
To: linux-wireless@vger.kernel.org
Cc: johannes@sipsolutions.net
Subject: [PATCH wireless 1/2] wifi: mac80211: use link address as TA for non-MLO 4-addr station on MLD AP
Date: Wed, 30 Sep 2026 10:48:18 +0200 [thread overview]
Message-ID: <20260930084819.3000572-1-nbd@nbd.name> (raw)
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 d51f810dd2c5..072b1287066c 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2653,6 +2653,32 @@ static void ieee80211_remove_ack_skb(struct ieee80211_local *local, u16 info_id)
kfree_skb(ack_skb);
}
+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
@@ -2721,7 +2747,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;
@@ -2746,18 +2775,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;
@@ -3244,7 +3267,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;
@@ -3255,21 +3280,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
next reply other threads:[~2026-09-30 8:48 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-30 8:48 Felix Fietkau [this message]
2026-09-30 8:48 ` [PATCH wireless 2/2] wifi: mac80211: use the AP address as RA for a 4-addr MLO station Felix Fietkau
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260930084819.3000572-1-nbd@nbd.name \
--to=nbd@nbd.name \
--cc=johannes@sipsolutions.net \
--cc=linux-wireless@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox