* [RFC PATCH v2 wireless-next 0/3] Allow non-MLD sta to roam between MLD AP links
@ 2025-07-11 10:03 Remi Pommarel
2025-07-11 10:03 ` [RFC PACTH v2 wireless-next 1/3] wifi: mac80211: Get link_id from freq for received management frame Remi Pommarel
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Remi Pommarel @ 2025-07-11 10:03 UTC (permalink / raw)
To: linux-wireless, linux-kernel; +Cc: Johannes Berg, Remi Pommarel
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 tries to match reported
management frames link id with the received frequency. In case no
suitable link is found, frames are reported without link information
(link id == -1) and hostapd does the freq to link conversion to respond.
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.
---
Changes v1 -> v2:
- Moving this serie as RFC. I am not fully satisfied with Patch 1/3
but can't find a leaner way to handle off channel mgmt frames.
Remi Pommarel (3):
wifi: mac80211: Get link_id from freq for received management frame
wifi: mac80211: Correctly init MLO link in ieee80211_8023_xmit()
wifi: mac80211: Check link id at station removal
net/mac80211/cfg.c | 3 ++-
net/mac80211/rx.c | 41 ++++++++++++++++++++++++++++++++++++++++-
net/mac80211/sta_info.c | 7 ++++++-
net/mac80211/sta_info.h | 2 +-
net/mac80211/tx.c | 2 ++
5 files changed, 51 insertions(+), 4 deletions(-)
--
2.40.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [RFC PACTH v2 wireless-next 1/3] wifi: mac80211: Get link_id from freq for received management frame
2025-07-11 10:03 [RFC PATCH v2 wireless-next 0/3] Allow non-MLD sta to roam between MLD AP links Remi Pommarel
@ 2025-07-11 10:03 ` Remi Pommarel
2025-07-22 12:22 ` Johannes Berg
2025-07-11 10:03 ` [RFC PATCH v2 wireless-next 2/3] wifi: mac80211: Correctly init MLO link in ieee80211_8023_xmit() Remi Pommarel
2025-07-11 10:03 ` [RFC PATCH v2 wireless-next 3/3] wifi: mac80211: Check link id at station removal Remi Pommarel
2 siblings, 1 reply; 7+ messages in thread
From: Remi Pommarel @ 2025-07-11 10:03 UTC (permalink / raw)
To: linux-wireless, linux-kernel; +Cc: Johannes Berg, Remi Pommarel
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, use link_id that matches the received frame frequency if
any or do not fill link_id indication for management frames, relying
on hostapd instead to infer the proper link from the received frame
frequency.
Signed-off-by: Remi Pommarel <repk@triplefau.lt>
---
net/mac80211/rx.c | 41 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index caa3e6b3f46e..26be0f378b3f 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -5114,6 +5114,37 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw,
dev_kfree_skb(skb);
}
+static int ieee80211_rx_get_link_from_freq(struct ieee80211_rx_data *rx,
+ struct sk_buff *skb,
+ struct link_sta_info *link_sta)
+{
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+ struct ieee80211_sta *sta = &link_sta->sta->sta;
+ struct ieee80211_link_data *link;
+ struct ieee80211_bss_conf *bss_conf;
+ struct ieee80211_chanctx_conf *conf;
+
+ if (!status->freq)
+ return link_sta->link_id;
+
+ for_each_link_data(rx->sdata, link) {
+ bss_conf = link->conf;
+ if (!bss_conf)
+ continue;
+ conf = rcu_dereference(bss_conf->chanctx_conf);
+ if (!conf || !conf->def.chan)
+ continue;
+
+ if (conf->def.chan->center_freq != status->freq)
+ continue;
+
+ if (ieee80211_rx_is_valid_sta_link_id(sta, link->link_id))
+ return link->link_id;
+ }
+
+ return -1;
+}
+
static bool ieee80211_rx_for_interface(struct ieee80211_rx_data *rx,
struct sk_buff *skb, bool consume)
{
@@ -5131,7 +5162,15 @@ static bool ieee80211_rx_for_interface(struct ieee80211_rx_data *rx,
link_sta = link_sta_info_get_bss(rx->sdata, hdr->addr2);
if (link_sta) {
sta = link_sta->sta;
- link_id = link_sta->link_id;
+
+ /* Use freq to get link id information on management frames to
+ * allow for offchannel scan, roaming, etc.
+ */
+ if (ieee80211_is_mgmt(hdr->frame_control))
+ link_id = ieee80211_rx_get_link_from_freq(rx, skb,
+ link_sta);
+ else
+ link_id = link_sta->link_id;
} else {
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
--
2.40.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [RFC PATCH v2 wireless-next 2/3] wifi: mac80211: Correctly init MLO link in ieee80211_8023_xmit()
2025-07-11 10:03 [RFC PATCH v2 wireless-next 0/3] Allow non-MLD sta to roam between MLD AP links Remi Pommarel
2025-07-11 10:03 ` [RFC PACTH v2 wireless-next 1/3] wifi: mac80211: Get link_id from freq for received management frame Remi Pommarel
@ 2025-07-11 10:03 ` Remi Pommarel
2025-07-22 12:25 ` Johannes Berg
2025-07-11 10:03 ` [RFC PATCH v2 wireless-next 3/3] wifi: mac80211: Check link id at station removal Remi Pommarel
2 siblings, 1 reply; 7+ messages in thread
From: Remi Pommarel @ 2025-07-11 10:03 UTC (permalink / raw)
To: linux-wireless, linux-kernel; +Cc: Johannes Berg, 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.
Signed-off-by: Remi Pommarel <repk@triplefau.lt>
---
net/mac80211/tx.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 6fa883a9250d..1d6b976bba72 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4638,6 +4638,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;
--
2.40.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [RFC PATCH v2 wireless-next 3/3] wifi: mac80211: Check link id at station removal
2025-07-11 10:03 [RFC PATCH v2 wireless-next 0/3] Allow non-MLD sta to roam between MLD AP links Remi Pommarel
2025-07-11 10:03 ` [RFC PACTH v2 wireless-next 1/3] wifi: mac80211: Get link_id from freq for received management frame Remi Pommarel
2025-07-11 10:03 ` [RFC PATCH v2 wireless-next 2/3] wifi: mac80211: Correctly init MLO link in ieee80211_8023_xmit() Remi Pommarel
@ 2025-07-11 10:03 ` Remi Pommarel
2025-07-22 12:26 ` Johannes Berg
2 siblings, 1 reply; 7+ messages in thread
From: Remi Pommarel @ 2025-07-11 10:03 UTC (permalink / raw)
To: linux-wireless, linux-kernel; +Cc: Johannes Berg, 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.
Signed-off-by: Remi Pommarel <repk@triplefau.lt>
---
net/mac80211/cfg.c | 3 ++-
net/mac80211/sta_info.c | 7 ++++++-
net/mac80211/sta_info.h | 2 +-
3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 56540c3701ed..727eea74bd37 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2217,7 +2217,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;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 8c550aab9bdc..f43ebc97134f 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1579,13 +1579,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);
}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 5288d5286651..a6d2c847a91c 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -932,7 +932,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);
--
2.40.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [RFC PACTH v2 wireless-next 1/3] wifi: mac80211: Get link_id from freq for received management frame
2025-07-11 10:03 ` [RFC PACTH v2 wireless-next 1/3] wifi: mac80211: Get link_id from freq for received management frame Remi Pommarel
@ 2025-07-22 12:22 ` Johannes Berg
0 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2025-07-22 12:22 UTC (permalink / raw)
To: Remi Pommarel, linux-wireless, linux-kernel
On Fri, 2025-07-11 at 12:03 +0200, Remi Pommarel wrote:
>
> +static int ieee80211_rx_get_link_from_freq(struct ieee80211_rx_data *rx,
> + struct sk_buff *skb,
> + struct link_sta_info *link_sta)
> +{
> + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
> + struct ieee80211_sta *sta = &link_sta->sta->sta;
> + struct ieee80211_link_data *link;
> + struct ieee80211_bss_conf *bss_conf;
> + struct ieee80211_chanctx_conf *conf;
> +
> + if (!status->freq)
> + return link_sta->link_id;
> +
> + for_each_link_data(rx->sdata, link) {
..._rcu()
> + bss_conf = link->conf;
> + if (!bss_conf)
> + continue;
> + conf = rcu_dereference(bss_conf->chanctx_conf);
> + if (!conf || !conf->def.chan)
> + continue;
> +
> + if (conf->def.chan->center_freq != status->freq)
> + continue;
> +
> + if (ieee80211_rx_is_valid_sta_link_id(sta, link->link_id))
> + return link->link_id;
> + }
But this is now almost the same as the code added via
https://patch.msgid.link/20250721062929.1662700-1-michael-cy.lee@mediatek.com
so I think it should be refactored/combined.
> @@ -5131,7 +5162,15 @@ static bool ieee80211_rx_for_interface(struct ieee80211_rx_data *rx,
> link_sta = link_sta_info_get_bss(rx->sdata, hdr->addr2);
> if (link_sta) {
> sta = link_sta->sta;
> - link_id = link_sta->link_id;
> +
> + /* Use freq to get link id information on management frames to
> + * allow for offchannel scan, roaming, etc.
> + */
> + if (ieee80211_is_mgmt(hdr->frame_control))
> + link_id = ieee80211_rx_get_link_from_freq(rx, skb,
> + link_sta);
It seems to me taht _iff_ the link ID ends up not being link_sta-
>link_id here, we should set link_sta=NULL. Otherwise we think we're
actually receiving from that STA but we aren't really, and if we then
use sta->link[link_id] we'd crash, and I'd be very surprised if this
were impossible.
I'm not sure what consequences that has, but OTOH it really should not
be sending anything other than probe requests, authentication frames and
some few public action frames on another link. We need not handle other
frames as if we didn't realise the link was different, it's fine to even
just drop them because we don't recognise the STA there.
So I think that's what we should do. As written this seems really
problematic to have a link_sta != NULL and thus sta != NULL but then
sta->link[link_id] == NULL and not == link_sta.
Arguably, given the code we already have, we should perhaps implement
this in another way and after doing the link_sta lookup via
link_sta_info_get_bss() simply reject the link_sta (set it to NULL) if
the RX link doesn't match the link it's expected to be on. Then we'd
fall back to the existing code I linked to above anyway, which seems
almost better.
johannes
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH v2 wireless-next 2/3] wifi: mac80211: Correctly init MLO link in ieee80211_8023_xmit()
2025-07-11 10:03 ` [RFC PATCH v2 wireless-next 2/3] wifi: mac80211: Correctly init MLO link in ieee80211_8023_xmit() Remi Pommarel
@ 2025-07-22 12:25 ` Johannes Berg
0 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2025-07-22 12:25 UTC (permalink / raw)
To: Remi Pommarel, linux-wireless, linux-kernel
On Fri, 2025-07-11 at 12:03 +0200, Remi Pommarel wrote:
> 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.
I'm not against this and the patch looks fine, but I guess I'm surprised
it even matters to anyone. The encap offloading fundamentally requires
that the driver do more work to identify the destination STA, and then
anyway the link is picked by driver/FW? Or is there a case of encap
offload with _multicast_?
Anyway, looks OK and just sets a few bits that I feel like it's weird
that they're even used, so doesn't matter :)
johannes
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH v2 wireless-next 3/3] wifi: mac80211: Check link id at station removal
2025-07-11 10:03 ` [RFC PATCH v2 wireless-next 3/3] wifi: mac80211: Check link id at station removal Remi Pommarel
@ 2025-07-22 12:26 ` Johannes Berg
0 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2025-07-22 12:26 UTC (permalink / raw)
To: Remi Pommarel, linux-wireless, linux-kernel
On Fri, 2025-07-11 at 12:03 +0200, Remi Pommarel wrote:
> 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.
That also looks fine.
Would be nice if you could later contribute the hwsim test for it, since
it sounded like you had one :)
johannes
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-07-22 12:26 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-11 10:03 [RFC PATCH v2 wireless-next 0/3] Allow non-MLD sta to roam between MLD AP links Remi Pommarel
2025-07-11 10:03 ` [RFC PACTH v2 wireless-next 1/3] wifi: mac80211: Get link_id from freq for received management frame Remi Pommarel
2025-07-22 12:22 ` Johannes Berg
2025-07-11 10:03 ` [RFC PATCH v2 wireless-next 2/3] wifi: mac80211: Correctly init MLO link in ieee80211_8023_xmit() Remi Pommarel
2025-07-22 12:25 ` Johannes Berg
2025-07-11 10:03 ` [RFC PATCH v2 wireless-next 3/3] wifi: mac80211: Check link id at station removal Remi Pommarel
2025-07-22 12:26 ` Johannes Berg
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).