Parse the reconfiguration Multi-Link element and: - Don't select a BSS for connection if it is part of an MLD and is going to be removed. - Don't scan for missing links that are to be removed. - Don't include removed links in association. Signed-off-by: Ilan Peer <ilan.peer@xxxxxxxxx> Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@xxxxxxxxx> --- src/common/ieee802_11_defs.h | 9 ++++ wpa_supplicant/bss.c | 80 ++++++++++++++++++++++++++++++++++++ wpa_supplicant/bss.h | 2 + wpa_supplicant/events.c | 36 +++++++++++++++- wpa_supplicant/sme.c | 10 +++++ 5 files changed, 136 insertions(+), 1 deletion(-) diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index e36f6db139..a93d5e742d 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -2674,6 +2674,15 @@ struct eht_ml_basic_common_info { #define EHT_PER_STA_CTRL_NSTR_BM_SIZE_MSK 0x0400 #define EHT_PER_STA_CTRL_BSS_PARAM_CNT_PRESENT_MSK 0x0800 +#define RECONF_MULTI_LINK_CTRL_PRES_MLD_MAC_ADDR 0x0001 + +#define EHT_PER_STA_RECONF_CTRL_LINK_ID_MSK 0x000f +#define EHT_PER_STA_RECONF_CTRL_COMPLETE_PROFILE 0x0010 +#define EHT_PER_STA_RECONF_CTRL_MAC_ADDR 0x0020 +#define EHT_PER_STA_RECONF_CTRL_AP_REMOVAL_TIMER 0x0040 +#define EHT_PER_STA_RECONF_CTRL_OP_UPDATE_TYPE_MSK 0x0780 +#define EHT_PER_STA_RECONF_CTRL_OP_PARAMS 0x0800 + /* IEEE P802.11be/D2.0, 9.4.2.312.2.4 - Per-STA Profile subelement format */ struct ieee80211_eht_per_sta_profile { le16 sta_control; diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 1aa490bcbc..9d3f0fe308 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -1697,3 +1697,83 @@ out: wpabuf_free(mlbuf); return ret; } + + +/* + * wpa_bss_parse_reconf_ml_element - Parse the reconfiguration ML element + * @wpa_s: Pointer to wpa_supplicant data + * @bss: BSS table entry + * Returns: The bitmap of links that are going to be removed + */ +u16 wpa_bss_parse_reconf_ml_element(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss) +{ + struct ieee802_11_elems elems; + struct wpabuf *mlbuf; + const u8 *pos = wpa_bss_ie_ptr(bss); + size_t len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len; + struct ieee80211_eht_ml *ml; + u16 removed_links = 0; + u8 ml_common_len; + + if (ieee802_11_parse_elems(pos, len, &elems, 1) == ParseFailed) + return 0; + + if (!elems.reconf_mle || !elems.reconf_mle_len) + return 0; + + mlbuf = ieee802_11_defrag_mle(&elems, MULTI_LINK_CONTROL_TYPE_RECONF); + if (!mlbuf) + return 0; + + ml = (struct ieee80211_eht_ml *)wpabuf_head(mlbuf); + len = wpabuf_len(mlbuf); + + if (len < sizeof(*ml)) + goto out; + + ml_common_len = 1; + if (ml->ml_control & RECONF_MULTI_LINK_CTRL_PRES_MLD_MAC_ADDR) + ml_common_len += ETH_ALEN; + + if (len < sizeof(*ml) + ml_common_len) { + wpa_printf(MSG_DEBUG, + "MLD: unexpected reconf ML element length: (%zu != %zu)", + len, sizeof(*ml) + ml_common_len); + goto out; + } + + pos = ml->variable + ml_common_len; + len -= sizeof(*ml) + ml_common_len; + + while (len >= 2 + sizeof(struct ieee80211_eht_per_sta_profile)) { + size_t sub_elem_len = *(pos + 1); + + if (2 + sub_elem_len > len) { + wpa_printf(MSG_DEBUG, + "MLD: invalid link info len: %zu %zu", + 2 + sub_elem_len, len); + goto out; + } + + if (*pos == EHT_ML_SUB_ELEM_PER_STA_PROFILE) { + struct ieee80211_eht_per_sta_profile *sta_prof = + (struct ieee80211_eht_per_sta_profile *) + (pos + 2); + u16 control = le_to_host16(sta_prof->sta_control); + u8 link_id = control & + EHT_PER_STA_RECONF_CTRL_LINK_ID_MSK; + + removed_links |= BIT(link_id); + } + + pos += 2 + sub_elem_len; + len -= 2 + sub_elem_len; + } + + wpa_printf(MSG_DEBUG, "MLD: reconfiguration: removed_links=0x%x", + removed_links); +out: + wpabuf_free(mlbuf); + return removed_links; +} diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index 291f02b912..b93a5eea46 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -215,4 +215,6 @@ int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, u8 *ap_mld_addr, u16 *missing_links); +u16 wpa_bss_parse_reconf_ml_element(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss); #endif /* BSS_H */ diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index b666d7b202..b8e59c727d 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1176,6 +1176,27 @@ static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, } +static int wpas_valid_ml_bss(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss) + +{ + u16 removed_links; + + if (wpa_bss_parse_basic_ml_element(wpa_s, bss, NULL, NULL)) + return 0; + + if (bss->n_mld_links == 0) + return 0; + + /* Check if the current BSS is going to be removed */ + removed_links = wpa_bss_parse_reconf_ml_element(wpa_s, bss); + if (BIT(bss->mld_links[0].link_id) & removed_links) + return -1; + + return 0; +} + + int disabled_freq(struct wpa_supplicant *wpa_s, int freq) { int i, j; @@ -1578,6 +1599,13 @@ skip_assoc_disallow: return false; } + if (wpas_valid_ml_bss(wpa_s, bss) < 0) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - ML BSS going to be removed"); + return false; + } + /* Matching configuration found */ return true; } @@ -1856,7 +1884,7 @@ static int wpa_supplicant_connect_ml_missing(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { int *freqs; - u16 missing_links = 0; + u16 missing_links = 0, removed_links; if (!((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))) @@ -1867,6 +1895,12 @@ static int wpa_supplicant_connect_ml_missing(struct wpa_supplicant *wpa_s, &missing_links) || !missing_links) return 0; + removed_links = wpa_bss_parse_reconf_ml_element(wpa_s, selected); + missing_links &= ~removed_links; + + if (!missing_links) + return 0; + wpa_dbg(wpa_s, MSG_DEBUG, "MLD: Doing an ML probe for missing links 0x%04x", missing_links); diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 4ed0a3003f..1acd415bc5 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -541,6 +541,15 @@ out: } +static void wpas_ml_handle_removed_links(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss) +{ + u16 removed_links = wpa_bss_parse_reconf_ml_element(wpa_s, bss); + + wpa_s->valid_links &= ~removed_links; +} + + static void wpas_sme_ml_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data, int ie_offset) @@ -639,6 +648,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, params.mld = true; params.mld_link_id = wpa_s->mlo_assoc_link_id; params.ap_mld_addr = wpa_s->ap_mld_addr; + wpas_ml_handle_removed_links(wpa_s, bss); } if (wpa_s->sme.ssid_len != params.ssid_len || -- 2.38.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap