[PATCH 3/3] SME: MLD: Handle reconfiguration Multi-Link element
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Mon Jun 12 12:59:50 PDT 2023
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 at intel.com>
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
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
More information about the Hostap
mailing list