Skip to contentSkip to conversation

Allow non-MLD sta to roam between MLD AP links

PATCH Superseded Remi Pommarel 2 participants 6 messages Jun 27, 2025 – Jul 10, 2025 mac80211

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover Allow non-MLD sta to roam between MLD AP links

This serie aims to allow non-MLD sta to roam between same MLD AP links as if they were two BSSs belonging to the same ESS.

The first issue is that when a non-MLD STA is connected to one MLD AP link all received management frames are reported to userland with the current associated link id even if STA sent those frames on one of the other links (e.g. offchannel probe request). Because hostapd relies on this link id information to select the proper link for answering those management frames, probe responses to offchannel requests are sent through the wrong link and the sta misses them.

To fix that, the first patch of this serie does not report management frames with a link id (link id == -1) and let hostapd do the freq to link conversion to respond. This relies on the fact that hostapd knows how to do this freq to link conversion which is needed anyway for the first pre-association scan. We can also do this conversion in mac80211 instead if it is deem preferrable.

The second issue comes from the fact that hostapd queries a sta removal for the previous association even after the sta has successfully roamed to the new link, causing the current sta to be removed. To avoid that the second patch checks the sta removal link id parameter. If a link id is supplied and the sta is not currently using this link, this removal is ignored. An additionnal hostapd patch is needed so that a link id parameter is added with NL80211_CMD_DEL_STATION requests, and will be sent to hostapd mailing if it appears that this serie makes sense.

The third patch fixes the link id information initialization when tx frame with 802.11 HW offloading, this will be needed later to get sta roaming working with ath12k. An additionnal ath12k fix will also be provided in order to get non-MLD sta roaming working with this driver.

This serie along with the mentionned hostapd patch allowes a non-MLD STA to successfully roam between several MLD AP links with hwsim.

Remi Pommarel (3):
wifi: mac80211: Do not set link_id for received management frame
wifi: mac80211: Check link id at station removal
wifi: mac80211: Correctly init MLO link in ieee80211_8023_xmit()

 net/mac80211/cfg.c      | 3 ++-
 net/mac80211/rx.c       | 7 ++++++-
 net/mac80211/sta_info.c | 7 ++++++-
 net/mac80211/sta_info.h | 2 +-
 net/mac80211/tx.c       | 2 ++
 5 files changed, 17 insertions(+), 4 deletions(-)
Signature · 1 line
2.40.0
#1 lore raw

PATCH 1/3 wifi: mac80211: Do not set link_id for received management frame

A non-MLD sta could want to send offchannel management frame (e.g. to do a offchannel scan). Because ieee80211_rx_for_interface() fills the link_id information with the link the sta is currently using; hostapd would send back management frame responses through wrong link causing the sta to miss them.

To fix that, do not fill link_id indication for management frames, relying on hostapd instead to infer the proper link from the received frame frequency.

---
 net/mac80211/rx.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
net/mac80211/rx.c +6 -1
index e73431549ce7..deebdce6d9c7 100644
@@ -5112,9 +5112,14 @@ static bool ieee80211_rx_for_interface(struct ieee80211_rx_data *rx,
 	 * have the link information if needed.
 	 */
 	link_sta = link_sta_info_get_bss(rx->sdata, hdr->addr2);
+
 	if (link_sta) {
 		sta = link_sta->sta;
-		link_id = link_sta->link_id;
+		/* Do no use sta link id information on management frames to allow for
+		 * offchannel scan, roaming, etc.
+		 */
+		if (!ieee80211_is_mgmt(hdr->frame_control))
+			link_id = link_sta->link_id;
 	} else {
 		struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 
Signature · 1 line
2.40.0
#2 lore raw

PATCH 2/3 wifi: mac80211: Check link id at station removal

In reply to Remi Pommarel

hostapd can remove a non-MLD sta connected to one link of one MLD AP several times. If the sta roamed to another link of the same MLD AP between two of those removals the wrong sta_info could be removed.

To fix that remove sta only if it is currently using the link specified in NL80211_CMD_DEL_STATION if they are any.

---
 net/mac80211/cfg.c      | 3 ++-
 net/mac80211/sta_info.c | 7 ++++++-
 net/mac80211/sta_info.h | 2 +-
 3 files changed, 9 insertions(+), 3 deletions(-)
net/mac80211/cfg.c +2 -1
index d9d88f2f2831..3dfe8e0759bb 100644
@@ -2195,7 +2195,8 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
 	if (params->mac)
-		return sta_info_destroy_addr_bss(sdata, params->mac);
+		return sta_info_destroy_addr_bss(sdata, params->mac,
+						 params->link_id);
 
 	sta_info_flush(sdata, params->link_id);
 	return 0;
net/mac80211/sta_info.c +6 -1
index 61583173629e..7e58ae507a14 100644
@@ -1530,13 +1530,18 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr)
 }
 
 int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata,
-			      const u8 *addr)
+			      const u8 *addr, int link_id)
 {
 	struct sta_info *sta;
 
 	lockdep_assert_wiphy(sdata->local->hw.wiphy);
 
 	sta = sta_info_get_bss(sdata, addr);
+
+	if (sta && link_id >= 0 && sta->sta.valid_links &&
+	    !(sta->sta.valid_links & BIT(link_id)))
+		return -EINVAL;
+
 	return __sta_info_destroy(sta);
 }
 
net/mac80211/sta_info.h +1 -1
index 7a95d8d34fca..653eda1c2466 100644
@@ -878,7 +878,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta);
 int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata,
 			  const u8 *addr);
 int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata,
-			      const u8 *addr);
+			      const u8 *addr, int link_id);
 
 void sta_info_recalc_tim(struct sta_info *sta);
 
Signature · 1 line
2.40.0
#3 lore raw

PATCH 3/3 wifi: mac80211: Correctly init MLO link in ieee80211_8023_xmit()

In reply to Remi Pommarel

The IEEE80211_TX_CTRL_MLO_LINK info is the only part of ieee80211_tx_control where a 0 value has a specific meaning. Thus this should always be initialized with IEEE80211_LINK_UNSPECIFIED if there is no MLO link information associated with the skb, even using when 802.11 hw encap offloading.

---
 net/mac80211/tx.c | 2 ++
 1 file changed, 2 insertions(+)
net/mac80211/tx.c +2 -0
index d58b80813bdd..f65fb96a498e 100644
@@ -4637,6 +4637,8 @@ static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
 
 	info->flags |= IEEE80211_TX_CTL_HW_80211_ENCAP;
 	info->control.vif = &sdata->vif;
+	info->control.flags |= u32_encode_bits(IEEE80211_LINK_UNSPECIFIED,
+					       IEEE80211_TX_CTRL_MLO_LINK);
 
 	if (key)
 		info->control.hw_key = &key->conf;
Signature · 1 line
2.40.0
maintainer
#4 lore raw
In reply to Remi Pommarel
Quoted 7 lines · Remi Pommarel

To fix that, the first patch of this serie does not report management frames with a link id (link id == -1) and let hostapd do the freq to link conversion to respond. This relies on the fact that hostapd knows how to do this freq to link conversion which is needed anyway for the first pre-association scan. We can also do this conversion in mac80211 instead if it is deem preferrable.

You should probably send patches as RFC if you have things like that.

Quoted 2 lines

This serie along with the mentionned hostapd patch allowes a non-MLD STA to successfully roam between several MLD AP links with hwsim.

Maybe so, but does anything _else_ MLO related still work? Surely it cannot, given you just unconditionally made it no longer have a link ID ... And indeed most of the EHT hwsim tests no longer pass, and even crash the kernel.

Since you clearly were running hwsim tests, please run the existing ones too :)

Also, I suspect that https://lore.kernel.org/linux-
wireless/[email protected]/ might go some way towards fixing this as well?

johannes

#5 lore raw
Quoted 10 lines · Johannes Berg
Quoted 7 lines · Remi Pommarel

To fix that, the first patch of this serie does not report management frames with a link id (link id == -1) and let hostapd do the freq to link conversion to respond. This relies on the fact that hostapd knows how to do this freq to link conversion which is needed anyway for the first pre-association scan. We can also do this conversion in mac80211 instead if it is deem preferrable.

You should probably send patches as RFC if you have things like that.

Sure. Some subsystems have a tendency to ignore those RFCs patches but that does not seem to be the case for linux-wireless.

Quoted 11 lines
Quoted 3 lines

This serie along with the mentionned hostapd patch allowes a non-MLD STA to successfully roam between several MLD AP links with hwsim.

Maybe so, but does anything _else_ MLO related still work? Surely it cannot, given you just unconditionally made it no longer have a link ID ... And indeed most of the EHT hwsim tests no longer pass, and even crash the kernel.

Since you clearly were running hwsim tests, please run the existing ones too :)

Agh, sorry about that. I was not running the hostapd's hwsim tests because I just discovered they exist. With the mentionned hostapd patch most of them pass, but yes of course, let's not break old wpa_supplicant/hostapd with kernel changes.

Doing freq to link id conversion instead makes all eht test to pass (I will of course also add a hwsim test for this specific issue).

Quoted 4 lines

Also, I suspect that https://lore.kernel.org/linux-
wireless/[email protected]/ might go some way towards fixing this as well?

No I am afraid this one won't help.

The issue here is receiving off channel management frames and using the link id the sta is currently associated with to report them to userland. For example if sta is associated with link 0 and send a probe request on link 1 (off channel scan), this frame should be reported to hostapd with either no link id or a link id of 1.

Thanks

Signature · 1 line
Remi