* [PATCH wireless 1/2] wifi: mac80211: use link address as TA for non-MLO 4-addr station on MLD AP
@ 2026-09-30 8:48 Felix Fietkau
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
0 siblings, 1 reply; 2+ messages in thread
From: Felix Fietkau @ 2026-09-30 8:48 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 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
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [PATCH wireless 2/2] wifi: mac80211: use the AP address as RA for a 4-addr MLO station
2026-09-30 8:48 [PATCH wireless 1/2] wifi: mac80211: use link address as TA for non-MLO 4-addr station on MLD AP Felix Fietkau
@ 2026-09-30 8:48 ` Felix Fietkau
0 siblings, 0 replies; 2+ messages in thread
From: Felix Fietkau @ 2026-09-30 8:48 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes
In 4-address mode, ieee80211_build_hdr() and ieee80211_check_fast_xmit()
set A1 to sdata->deflink.u.mgd.bssid, which is not valid for an MLO
connection.
Use sdata->vif.cfg.ap_addr instead, like the 3-address case does.
Fixes: 8a9be422f5ff ("wifi: mac80211: tx: use AP address in some places for MLO")
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
net/mac80211/tx.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 072b1287066c..e764211edcf7 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2896,7 +2896,7 @@ 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, sdata->deflink.u.mgd.bssid, ETH_ALEN);
+ memcpy(hdr.addr1, sdata->vif.cfg.ap_addr, ETH_ALEN);
memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
memcpy(hdr.addr3, skb->data, ETH_ALEN);
memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
@@ -3247,7 +3247,7 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
IEEE80211_FCTL_TODS);
/* RA TA DA SA */
- memcpy(hdr->addr1, sdata->deflink.u.mgd.bssid, ETH_ALEN);
+ memcpy(hdr->addr1, sdata->vif.cfg.ap_addr, ETH_ALEN);
memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
build.da_offs = offsetof(struct ieee80211_hdr, addr3);
build.sa_offs = offsetof(struct ieee80211_hdr, addr4);
--
2.47.3
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-30 8:48 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-30 8:48 [PATCH wireless 1/2] wifi: mac80211: use link address as TA for non-MLO 4-addr station on MLD AP Felix Fietkau
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
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).