SME: MLD: Handle reconfiguration Multi-Link element
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@intel.com> Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
This commit is contained in:
parent
e933c4e5a3
commit
e5ea30feef
5 changed files with 136 additions and 3 deletions
|
@ -2700,9 +2700,17 @@ struct eht_ml_probe_req_common_info {
|
||||||
u8 variable[];
|
u8 variable[];
|
||||||
} STRUCT_PACKED;
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
/* IEEE P802.11be/D2.0, 9.4.2.312.4 - Reconfiguration Multi-Link element */
|
/* IEEE P802.11be/D4.0, 9.4.2.312.4 - Reconfiguration Multi-Link element */
|
||||||
|
|
||||||
#define EHT_ML_PRES_BM_RECONFIGURE_MLD_ADDRESS 0x0001
|
#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
|
||||||
|
#define EHT_PER_STA_RECONF_CTRL_NSTR_BITMAP_SIZE 0x1000
|
||||||
|
|
||||||
/* IEEE P802.11be/D2.0, 9.4.2.312.1 - Multi-Link element / General */
|
/* IEEE P802.11be/D2.0, 9.4.2.312.1 - Multi-Link element / General */
|
||||||
|
|
||||||
|
|
|
@ -1708,3 +1708,83 @@ out:
|
||||||
wpabuf_free(mlbuf);
|
wpabuf_free(mlbuf);
|
||||||
return ret;
|
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;
|
||||||
|
const 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 = (const 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 Reconfiguration 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) {
|
||||||
|
const struct ieee80211_eht_per_sta_profile *sta_prof =
|
||||||
|
(const struct ieee80211_eht_per_sta_profile *)
|
||||||
|
(pos + 2);
|
||||||
|
u16 control = le_to_host16(sta_prof->sta_control);
|
||||||
|
u8 link_id;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -215,5 +215,7 @@ int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_bss *bss,
|
struct wpa_bss *bss,
|
||||||
u8 *ap_mld_addr,
|
u8 *ap_mld_addr,
|
||||||
u16 *missing_links);
|
u16 *missing_links);
|
||||||
|
u16 wpa_bss_parse_reconf_ml_element(struct wpa_supplicant *wpa_s,
|
||||||
|
struct wpa_bss *bss);
|
||||||
|
|
||||||
#endif /* BSS_H */
|
#endif /* BSS_H */
|
||||||
|
|
|
@ -1177,6 +1177,26 @@ static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool 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 true;
|
||||||
|
|
||||||
|
if (bss->n_mld_links == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* 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 false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int disabled_freq(struct wpa_supplicant *wpa_s, int freq)
|
int disabled_freq(struct wpa_supplicant *wpa_s, int freq)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -1579,6 +1599,13 @@ skip_assoc_disallow:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!wpas_valid_ml_bss(wpa_s, bss)) {
|
||||||
|
if (debug_print)
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG,
|
||||||
|
" skip - ML BSS going to be removed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Matching configuration found */
|
/* Matching configuration found */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1856,7 +1883,7 @@ static int wpa_supplicant_connect_ml_missing(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_ssid *ssid)
|
struct wpa_ssid *ssid)
|
||||||
{
|
{
|
||||||
int *freqs;
|
int *freqs;
|
||||||
u16 missing_links = 0;
|
u16 missing_links = 0, removed_links;
|
||||||
|
|
||||||
if (!((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
|
if (!((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
|
||||||
(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)))
|
(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)))
|
||||||
|
@ -1867,6 +1894,12 @@ static int wpa_supplicant_connect_ml_missing(struct wpa_supplicant *wpa_s,
|
||||||
&missing_links) || !missing_links)
|
&missing_links) || !missing_links)
|
||||||
return 0;
|
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,
|
wpa_dbg(wpa_s, MSG_DEBUG,
|
||||||
"MLD: Doing an ML probe for missing links 0x%04x",
|
"MLD: Doing an ML probe for missing links 0x%04x",
|
||||||
missing_links);
|
missing_links);
|
||||||
|
|
|
@ -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,
|
static void wpas_sme_ml_auth(struct wpa_supplicant *wpa_s,
|
||||||
union wpa_event_data *data,
|
union wpa_event_data *data,
|
||||||
int ie_offset)
|
int ie_offset)
|
||||||
|
@ -639,6 +648,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
|
||||||
params.mld = true;
|
params.mld = true;
|
||||||
params.mld_link_id = wpa_s->mlo_assoc_link_id;
|
params.mld_link_id = wpa_s->mlo_assoc_link_id;
|
||||||
params.ap_mld_addr = wpa_s->ap_mld_addr;
|
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 ||
|
if (wpa_s->sme.ssid_len != params.ssid_len ||
|
||||||
|
|
Loading…
Reference in a new issue