[PATCH v2 05/17] MLD STA: set MLO connection info to wpa_sm
Peer, Ilan
ilan.peer at intel.com
Mon Oct 3 05:29:48 PDT 2022
Hi,
> -----Original Message-----
> From: Hostap <hostap-bounces at lists.infradead.org> On Behalf Of
> Veerendranath Jakkam
> Sent: Saturday, October 01, 2022 11:21
> To: hostap at lists.infradead.org
> Cc: quic_vjakkam at quicinc.com
> Subject: [PATCH v2 05/17] MLD STA: set MLO connection info to wpa_sm
>
> Update below MLO connection info to wpa_sm:
> - AP MLD address and link ID of the (re)association link.
> - For each requested link
> - own link address
> - AP's link bssid, RSNE, RSNXE
>
> Signed-off-by: Veerendranath Jakkam <quic_vjakkam at quicinc.com>
> +int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct
> wpa_sm_mlo
> +*mlo) {
> + int i;
> + char title[50];
> + int ret;
> +
> + if (!sm)
> + return -1;
> +
> + os_memcpy(sm->mlo.ap_mld_addr, mlo->ap_mld_addr,
> ETH_ALEN);
> + sm->mlo.assoc_link_id = mlo->assoc_link_id;
> + sm->mlo.setup_links = mlo->setup_links;
> + sm->mlo.req_links = mlo->req_links;
Maybe verify that setup_links is a subset of requested links? And that assoc_link_id is part of the setup links
> + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
> + const u8 *ie;
> + size_t len;
> +
> + os_memcpy(sm->mlo.links[i].addr, mlo->links[i].addr,
> ETH_ALEN);
> + os_memcpy(sm->mlo.links[i].bssid, mlo->links[i].bssid,
> + ETH_ALEN);
This should be done only for the requested links, as otherwise it would contain
garbage.
> +
> + ie = mlo->links[i].ap_rsne;
> + len = mlo->links[i].ap_rsne_len;
> + os_free(sm->mlo.links[i].ap_rsne);
> + if (ie == NULL || len == 0) {
I think I asked this before: I do not think that it is valid to have an MLD connection without RSN.
> + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
> + "WPA: clearing MLO link[%u] AP RSNE", i);
> + sm->mlo.links[i].ap_rsne = NULL;
> + sm->mlo.links[i].ap_rsne_len = 0;
This can be done unconditionally (also for the rsnxe).
> + } else {
> + ret = os_snprintf(title, sizeof(title),
> + "RSN: set MLO link[%u] AP RSNE", i);
> + if (!os_snprintf_error(sizeof(title), ret))
> + wpa_hexdump(MSG_DEBUG, title, ie, len);
> + sm->mlo.links[i].ap_rsne = os_memdup(ie, len);
> + if (!sm->mlo.links[i].ap_rsne)
> + return -1;
> + sm->mlo.links[i].ap_rsne_len = len;
> + }
> +
> + ie = mlo->links[i].ap_rsnxe;
> + len = mlo->links[i].ap_rsnxe_len;
> + os_free(sm->mlo.links[i].ap_rsnxe);
> + if (ie == NULL || len == 0) {
> + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
> + "WPA: clearing MLO link[%u] AP RSNXE", i);
> + sm->mlo.links[i].ap_rsnxe = NULL;
> + sm->mlo.links[i].ap_rsnxe_len = 0;
Same here.
> + } else {
> + ret = os_snprintf(title, sizeof(title),
> + "RSN: set MLO link[%u] AP RSNXE",
> i);
> + if (!os_snprintf_error(sizeof(title), ret))
> + wpa_hexdump(MSG_DEBUG, title, ie, len);
> + sm->mlo.links[i].ap_rsnxe = os_memdup(ie, len);
> + if (!sm->mlo.links[i].ap_rsnxe)
> + return -1;
> + sm->mlo.links[i].ap_rsnxe_len = len;
> + }
> + }
> +
> + return 0;
> +}
Snip ..
> +static void wpas_get_basic_mle_links_info(const u8 *mle, size_t mle_len,
> + struct links_info *info)
> +{
> + size_t rem_len;
> + const u8 *pos;
> +#define ML_CTRL_FIELD_LEN 2
Move the definition to ieee802_11_defs.h?
> + if (mle_len < (ML_CTRL_FIELD_LEN + 1) ||
> + (mle_len - ML_CTRL_FIELD_LEN < mle[ML_CTRL_FIELD_LEN]))
> + return;
> +
> + // Skip Common Info
> + pos = mle + ML_CTRL_FIELD_LEN + mle[ML_CTRL_FIELD_LEN];
> + rem_len = mle_len - ML_CTRL_FIELD_LEN -
> mle[ML_CTRL_FIELD_LEN];
> +
> + // Parse Subelements
> + while (rem_len > 2) {
> + int ie_len = 2 + pos[1];
> +
> + if (rem_len < ie_len)
> + return;
> +
> + if (pos[0] == MULTI_LINK_SUB_ELEM_ID_PER_STA_PROFILE)
> {
> + u8 link_id;
> + const u8 *sta_profile;
> +
> +#define BASIC_ML_STA_INFO_STA_MAC_IDX \
> + (2 + /* STA Control field */ \
> + 1) /* STA Info Length field (Basic) */
Also move to ieee802_11_defs.h
> + if (pos[1] < (BASIC_ML_STA_INFO_STA_MAC_IDX +
> ETH_ALEN))
> + goto next_subelem;
> +
> + sta_profile = &pos[2];
> + link_id = sta_profile[0] &
> + BASIC_ML_STA_CTRL0_LINK_ID_MASK;
> + if (link_id >= MAX_NUM_MLD_LINKS)
> + goto next_subelem;
> +
> + if (!(sta_profile[0] &
> BASIC_ML_STA_CTRL0_PRES_STA_MAC))
> + goto next_subelem;
> +
> + info->non_assoc_links |= BIT(link_id);
> + os_memcpy(info->addr[link_id],
> +
> &sta_profile[BASIC_ML_STA_INFO_STA_MAC_IDX],
> + ETH_ALEN);
> + }
> +next_subelem:
> + pos += ie_len;
> + rem_len -= ie_len;
> + }
> +}
> +
> +
> +static int wpa_sm_set_ml_info(struct wpa_supplicant *wpa_s,
> + union wpa_event_data *data)
> +{
> + int i;
> + struct wpabuf *mle;
> + struct ieee802_11_elems req_elems, resp_elems;
> + struct links_info req_links, resp_links;
> + struct wpa_sm_mlo mlo;
> + const u8 *bss_rsn = NULL, *bss_rsnx = NULL;
> +
> + os_memset(&mlo, 0, sizeof(mlo));
> + if (!wpa_s->valid_links)
> + return wpa_sm_set_mlo_params(wpa_s->wpa, &mlo);
> +
> + if (!data || !data->assoc_info.req_ies || !data->assoc_info.resp_ies)
> + return -1;
> +
> + if (ieee802_11_parse_elems(data->assoc_info.resp_ies,
> + data->assoc_info.resp_ies_len,
> &resp_elems,
> + 0) == ParseFailed ||
> + ieee802_11_parse_elems(data->assoc_info.req_ies,
> + data->assoc_info.req_ies_len, &req_elems,
> + 0) == ParseFailed) {
> + wpa_dbg(wpa_s, MSG_ERROR,
> + "MLO: Failed to parse Association request/response
> IEs");
> + return -1;
> + }
> +
> + mle = ieee802_11_defrag_mle(&req_elems,
> MULTI_LINK_CONTROL_TYPE_BASIC);
> + if (!mle) {
> + wpa_dbg(wpa_s, MSG_ERROR,
> + "MLO: Basic Multi-Link element not found in
> Association request");
> + return -1;
> + }
> + os_memset(&req_links, 0, sizeof(req_links));
> + wpas_get_basic_mle_links_info((const u8 *) wpabuf_head(mle),
> + wpabuf_len(mle), &req_links);
> + wpabuf_free(mle);
> +
> + mle = ieee802_11_defrag_mle(&resp_elems,
> MULTI_LINK_CONTROL_TYPE_BASIC);
> + if (!mle) {
> + wpa_dbg(wpa_s, MSG_ERROR,
> + "MLO: Basic Multi-Link element not found in
> Association response");
> + return -1;
> + }
> + os_memset(&resp_links, 0, sizeof(resp_links));
> + wpas_get_basic_mle_links_info((const u8 *) wpabuf_head(mle),
> + wpabuf_len(mle), &resp_links);
> + wpabuf_free(mle);
> +
> + if (req_links.non_assoc_links != resp_links.non_assoc_links) {
> + wpa_dbg(wpa_s, MSG_ERROR,
> + "MLO: Association request and response links bitmap
> not equal");
> + return -1;
> + }
> +
> + mlo.assoc_link_id = wpa_s->mlo_assoc_link_id;
> + mlo.setup_links = wpa_s->valid_links;
> + mlo.req_links = req_links.non_assoc_links | BIT(mlo.assoc_link_id);
> + os_memcpy(mlo.ap_mld_addr, wpa_s->ap_mld_addr, ETH_ALEN);
> + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
> + struct wpa_bss *bss;
> +
> + if (!(mlo.req_links & BIT(i)))
> + continue;
> +
> + if (mlo.setup_links & BIT(i)) {
> + bss = wpa_s->links[i].bss;
> + } else {
> + bss = wpa_supplicant_get_new_bss(wpa_s,
> + resp_links.addr[i]);
> + if (!bss) {
> +
Since setup links should be subset of requested links, why not use 'bss = wpa_s->links[i].bss' as well?
Regards,
Ilan.
More information about the Hostap
mailing list