From: Shivani Baranwal <quic_shivbara@xxxxxxxxxxx> Add support to fetch MLO connection info from driver to wpa_s instance of corresponding MLD STA interface. In addition, return true for BSSes associated with MLO links from wpa_bss_in_use() to avoid getting them cleared from scan results. Co-authored-by: Veerendranath Jakkam <quic_vjakkam@xxxxxxxxxxx> Signed-off-by: Veerendranath Jakkam <quic_vjakkam@xxxxxxxxxxx> Signed-off-by: Shivani Baranwal <quic_shivbara@xxxxxxxxxxx> --- src/drivers/driver.h | 13 +++++ src/drivers/driver_nl80211.c | 14 +++++ wpa_supplicant/bss.c | 22 +++++++- wpa_supplicant/driver_i.h | 10 ++++ wpa_supplicant/events.c | 93 +++++++++++++++++++++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 8 +++ 6 files changed, 157 insertions(+), 3 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 5d5075347..9bebebcc6 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -4808,6 +4808,19 @@ struct wpa_driver_ops { const u8 *match, size_t match_len, bool multicast); #endif /* CONFIG_TESTING_OPTIONS */ + + + /** + * get_sta_mlo_info - Get the current multi-link associtaion info + * @priv: private driver interface data + * @mlo: pointer to fill multi-link associtaion info + * Returns: 0 on success, -1 on failure + * + * This callback is used to fetch multi-link of the current association. + */ + int (*get_sta_mlo_info)(void *priv, + struct driver_sta_mlo_info *mlo_info); + }; /** diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 93b3eea69..0235e69d8 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -1020,6 +1020,19 @@ static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid) } +static int nl80211_get_sta_mlo_info(void *priv, + struct driver_sta_mlo_info *mlo_info) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + + if (!drv->associated) + return -1; + + os_memcpy(mlo_info, &drv->sta_mlo_info, sizeof(*mlo_info)); + return 0; +} + static void wpa_driver_nl80211_event_newlink( struct nl80211_global *global, struct wpa_driver_nl80211_data *drv, int ifindex, const char *ifname) @@ -12785,4 +12798,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .register_frame = testing_nl80211_register_frame, .radio_disable = testing_nl80211_radio_disable, #endif /* CONFIG_TESTING_OPTIONS */ + .get_sta_mlo_info = nl80211_get_sta_mlo_info, }; diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index eb97a618d..7dcdb9969 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -379,6 +379,8 @@ static int wpa_bss_known(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) { + int i; + if (bss == wpa_s->current_bss) return 1; @@ -388,9 +390,23 @@ static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) bss->ssid_len) != 0)) return 0; /* SSID has changed */ - return !is_zero_ether_addr(bss->bssid) && - (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 || - os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0); + if (!is_zero_ether_addr(bss->bssid) && + (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 || + os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0)) + return 1; + + if (!wpa_s->valid_links) + return 0; + + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) { + if (!(wpa_s->valid_links & BIT(i))) + continue; + + if (os_memcmp(bss->bssid, wpa_s->links[i].bssid, ETH_ALEN) == 0) + return 1; + } + + return 0; } diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index d20e06136..41d353f91 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -1152,4 +1152,14 @@ static inline int wpa_drv_set_secure_ranging_ctx(struct wpa_supplicant *wpa_s, return wpa_s->driver->set_secure_ranging_ctx(wpa_s->drv_priv, ¶ms); } +static inline int +wpas_drv_get_sta_mlo_info(struct wpa_supplicant *wpa_s, + struct driver_sta_mlo_info *mlo_info) +{ + if (!wpa_s->driver->get_sta_mlo_info) + return 0; + + return wpa_s->driver->get_sta_mlo_info(wpa_s->drv_priv, mlo_info); +} + #endif /* DRIVER_I_H */ diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index b3b2c4932..fc662a770 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -166,6 +166,20 @@ wpa_supplicant_update_current_bss(struct wpa_supplicant *wpa_s, const u8 *bssid) return bss; } +static void wpa_supplicant_update_link_bss(struct wpa_supplicant *wpa_s, + u8 link_id, + const u8 *bssid) +{ + struct wpa_bss *bss = wpa_supplicant_get_new_bss(wpa_s, bssid); + + if (!bss) { + wpa_supplicant_update_scan_results(wpa_s); + bss = wpa_supplicant_get_new_bss(wpa_s, bssid); + } + + if (bss) + wpa_s->links[link_id].bss = bss; +} static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s) { @@ -285,6 +299,19 @@ void wpa_supplicant_stop_countermeasures(void *eloop_ctx, void *sock_ctx) } +static void wpas_reset_mlo_info(struct wpa_supplicant *wpa_s) +{ + int i; + + if (!wpa_s->valid_links) + return; + + wpa_s->valid_links = 0; + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) + wpa_s->links[i].bss = NULL; +} + + void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) { int bssid_changed; @@ -352,6 +379,8 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0) wpa_s->enabled_4addr_mode = 0; + + wpas_reset_mlo_info(wpa_s); } @@ -3325,6 +3354,63 @@ static void wpas_fst_update_mb_assoc(struct wpa_supplicant *wpa_s, } +static int wpa_drv_get_mlo_info(struct wpa_supplicant *wpa_s) +{ + struct driver_sta_mlo_info mlo; + int i; + + mlo.valid_links = 0; + if (wpas_drv_get_sta_mlo_info(wpa_s, &mlo)) { + wpa_dbg(wpa_s, MSG_ERROR, "Failed to get MLO link info"); + wpa_supplicant_deauthenticate( + wpa_s, WLAN_REASON_DEAUTH_LEAVING); + return -1; + } + + if (wpa_s->valid_links == mlo.valid_links) { + bool match = true; + + if (!mlo.valid_links) + return 0; + + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) { + if (!(mlo.valid_links & BIT(i))) + continue; + + if (os_memcmp(wpa_s->links[i].addr, mlo.links[i].addr, + ETH_ALEN)) { + match = false; + break; + } + + if (os_memcmp(wpa_s->links[i].bssid, mlo.links[i].bssid, + ETH_ALEN)) { + match = false; + break; + } + } + + if (match && + !os_memcmp(wpa_s->ap_mld_addr, mlo.ap_mld_addr, ETH_ALEN)) + return 0; + } + + wpa_s->valid_links = mlo.valid_links; + os_memcpy(wpa_s->ap_mld_addr, mlo.ap_mld_addr, ETH_ALEN); + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) { + if (!(wpa_s->valid_links & BIT(i))) + continue; + + os_memcpy(wpa_s->links[i].addr, mlo.links[i].addr, ETH_ALEN); + os_memcpy(wpa_s->links[i].bssid, mlo.links[i].bssid, ETH_ALEN); + wpa_s->links[i].freq = mlo.links[i].freq; + wpa_supplicant_update_link_bss(wpa_s, i, mlo.links[i].bssid); + } + + return 0; +} + + static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { @@ -3360,6 +3446,13 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, return; } + if (wpa_drv_get_mlo_info(wpa_s) < 0) { + wpa_dbg(wpa_s, MSG_ERROR, "Failed to get MLO connection info"); + wpa_supplicant_deauthenticate( + wpa_s, WLAN_REASON_DEAUTH_LEAVING); + return; + } + if (ft_completed && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION)) { wpa_msg(wpa_s, MSG_INFO, "Attempt to roam to " MACSTR, diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 076081ec8..a9af64ab1 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -739,6 +739,14 @@ struct wpa_supplicant { struct wpa_bss *current_bss; int ap_ies_from_associnfo; unsigned int assoc_freq; + u8 ap_mld_addr[ETH_ALEN]; + u8 valid_links; /* bitmap of valid MLO link IDs */ + struct { + u8 addr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + u32 freq; + struct wpa_bss *bss; + } links[MAX_NUM_MLD_LINKS]; u8 *last_con_fail_realm; size_t last_con_fail_realm_len; -- 2.25.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap