MLD STA: Fetch MLO connection info into core wpa_supplicant

Add support to fetch MLO connection info from the driver to the
wpa_supplicant instance of corresponding MLD STA interface. In addition,
return true for BSSs associated with MLO links from wpa_bss_in_use() to
avoid getting them cleared from scan results.

Co-authored-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
Signed-off-by: Shivani Baranwal <quic_shivbara@quicinc.com>
This commit is contained in:
Shivani Baranwal 2022-09-08 20:14:11 +05:30 committed by Jouni Malinen
parent e2147f917f
commit 7784964cbe
6 changed files with 154 additions and 3 deletions

View file

@ -4803,6 +4803,17 @@ struct wpa_driver_ops {
*/
int (*send_pasn_resp)(void *priv, struct pasn_auth *params);
/**
* get_sta_mlo_info - Get the current multi-link association info
* @priv: Private driver interface data
* @mlo: Pointer to fill multi-link association 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);
#ifdef CONFIG_TESTING_OPTIONS
int (*register_frame)(void *priv, u16 type,
const u8 *match, size_t match_len,

View file

@ -1020,6 +1020,20 @@ 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)
@ -12777,6 +12791,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
#ifdef CONFIG_DPP
.dpp_listen = nl80211_dpp_listen,
#endif /* CONFIG_DPP */
.get_sta_mlo_info = nl80211_get_sta_mlo_info,
#ifdef CONFIG_TESTING_OPTIONS
.register_frame = testing_nl80211_register_frame,
.radio_disable = testing_nl80211_radio_disable,

View file

@ -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) &&
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);
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;
}

View file

@ -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, &params);
}
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 */

View file

@ -167,6 +167,21 @@ wpa_supplicant_update_current_bss(struct wpa_supplicant *wpa_s, const u8 *bssid)
}
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)
{
struct wpa_ssid *ssid, *old_ssid;
@ -285,6 +300,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 +380,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 +3355,60 @@ 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) != 0 ||
os_memcmp(wpa_s->links[i].bssid, mlo.links[i].bssid,
ETH_ALEN) != 0) {
match = false;
break;
}
}
if (match &&
os_memcmp(wpa_s->ap_mld_addr, mlo.ap_mld_addr,
ETH_ALEN) == 0)
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 +3444,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,

View file

@ -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];
unsigned int freq;
struct wpa_bss *bss;
} links[MAX_NUM_MLD_LINKS];
u8 *last_con_fail_realm;
size_t last_con_fail_realm_len;