From patchwork Mon Nov 20 23:51:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrei Otcheretianski X-Patchwork-Id: 1866379 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=1mKpsF/g; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=MfWiDStX; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=patchwork.ozlabs.org) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4SZ4964x7yz1ySN for ; Tue, 21 Nov 2023 10:54:02 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=nS/pGB7QRnYdrvuQjTYaCiQde5GpKY5aD2g81qIpO3A=; b=1mKpsF/gV6nHNI KsqizoCPhognvd9+K7shnomZHx+aLbCJTkPUeZnycS1VbK1DD8u7PBpVDFHroxWtP9Lu5mRpl21OT iFKrltTay04YEVbDoT+m2ej/I6nj6sEaJ+0UWuKtoGo4r7phbQEDN21pXiAABj0nZnxFuKdvv5sRx 11eN/yELrZVJ56AdSA6ARFCq6ixeHYFAfOH6nY0XUf3W8ip9tiPCVjedwY5CMI8ZAkA/0/eGCzSWx ltnoXhL9WXa8N6k6JK7u7iKGBXqZGxmG3puUf2504vOpzjNiltCEovsA+fdNUmAc/oSoNNiK6MkNu li8jL1GjdLej1nX5N59g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1r5E4y-00F6ID-1o; Mon, 20 Nov 2023 23:53:24 +0000 Received: from mgamail.intel.com ([134.134.136.126]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1r5E4U-00F5l1-0J for hostap@lists.infradead.org; Mon, 20 Nov 2023 23:52:56 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1700524374; x=1732060374; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+YDRKhH5mfOZiGaEdldogN2nPyn7hRqHm8vzMRbNP/M=; b=MfWiDStXu7tNStPTlDnKBNt0/vcpRoOAxR0ysHy59GNhLh5H+q6jeBjN ytn9BUZS9UfeYiU7iuuKzW1o/hpgnz+pW6eGkylUkOssy+HnvvIyjfRNw CfH4ZlX+movrgi88SbQMQEgIWsykoBShwgVZYu4AJWCdgN4gcxvSMczcT 0c2M9LnVcwn3N3CBj7zDdTvwJnjigACdIX5IvzAq+YneaRcu2RAguFFDK CQa9ZkGYsaNFA+wLUSEcUqu4cvm465o5kBvW2menT07gh1ebwl4e6BKs0 zJ3/ncPWfP0PFbvuHWbSjpg5/8juNysGVrlYv0Doyrr9mAUjPpaPEx5bM g==; X-IronPort-AV: E=McAfee;i="6600,9927,10900"; a="376769789" X-IronPort-AV: E=Sophos;i="6.04,214,1695711600"; d="scan'208";a="376769789" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Nov 2023 15:52:53 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10900"; a="1097871412" X-IronPort-AV: E=Sophos;i="6.04,214,1695711600"; d="scan'208";a="1097871412" Received: from saarm-mobl2.ger.corp.intel.com (HELO localhost.localdomain) ([10.254.156.6]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 Nov 2023 15:52:52 -0800 From: Andrei Otcheretianski To: hostap@lists.infradead.org Cc: Benjamin Berg , Andrei Otcheretianski Subject: [PATCH 21/42] ML: Add basic handling of ML probe requests Date: Tue, 21 Nov 2023 01:51:35 +0200 Message-Id: <20231120235156.363852-22-andrei.otcheretianski@intel.com> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20231120235156.363852-1-andrei.otcheretianski@intel.com> References: <20231120235156.363852-1-andrei.otcheretianski@intel.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231120_155254_222880_53434B08 X-CRM114-Status: GOOD ( 26.53 ) X-Spam-Score: -0.4 (/) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Benjamin Berg This responds by simply embedding most of the IEs from the other links into the ML element. This is not correct really, as inheritance rules should be applied and an inheritance element may need to be [...] Content analysis details: (-0.4 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 SPF_NONE SPF: sender does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.2 DKIMWL_WL_HIGH DKIMwl.org - High trust sender X-BeenThere: hostap@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Hostap" Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Benjamin Berg This responds by simply embedding most of the IEs from the other links into the ML element. This is not correct really, as inheritance rules should be applied and an inheritance element may need to be added. Signed-off-by: Benjamin Berg Signed-off-by: Andrei Otcheretianski --- src/ap/beacon.c | 216 +++++++++++++++++++++++++++++++++------- src/ap/ieee802_11.h | 3 + src/ap/ieee802_11_eht.c | 64 ++++++++++-- 3 files changed, 241 insertions(+), 42 deletions(-) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index e8acedd32b..c72da1b88d 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -568,6 +568,11 @@ struct probe_resp_params { const struct ieee80211_mgmt *req; bool is_p2p; + /* Generated IEs will be included inside an ML element */ + bool is_ml_sta_info; + struct hostapd_data *mld_ap; + struct mld_info *mld_info; + struct ieee80211_mgmt *resp; size_t resp_len; u8 *csa_pos; @@ -629,20 +634,18 @@ static size_t hostapd_probe_resp_elems_len(struct hostapd_data *hapd, if (hapd->iconf->punct_bitmap) buflen += EHT_OPER_DISABLED_SUBCHAN_BITMAP_SIZE; - /* - * TODO: Multi-Link element has variable length and can be - * long based on the common info and number of per - * station profiles. For now use 256. - */ - if (hapd->conf->mld_ap) - buflen += 256; + if (!params->is_ml_sta_info && hapd->conf->mld_ap) { + struct hostapd_data *ml_elem_ap = + params->mld_ap ? params->mld_ap : hapd; + + buflen += hostapd_eid_eht_ml_beacon_len( + ml_elem_ap, params->mld_info, !!params->mld_ap); + } } #endif /* CONFIG_IEEE80211BE */ - buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL, - params->known_bss, - params->known_bss_len, NULL); - buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP); + if (!params->is_ml_sta_info) + buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP); buflen += hostapd_mbo_ie_len(hapd); buflen += hostapd_eid_owe_trans_len(hapd); buflen += hostapd_eid_dpp_cc_len(hapd); @@ -660,10 +663,13 @@ static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd, epos = pos + len; - *pos++ = WLAN_EID_SSID; - *pos++ = hapd->conf->ssid.ssid_len; - os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len); - pos += hapd->conf->ssid.ssid_len; + if (!params->is_ml_sta_info) { + *pos++ = WLAN_EID_SSID; + *pos++ = hapd->conf->ssid.ssid_len; + os_memcpy(pos, hapd->conf->ssid.ssid, + hapd->conf->ssid.ssid_len); + pos += hapd->conf->ssid.ssid_len; + } /* Supported rates */ pos = hostapd_eid_supp_rates(hapd, pos); @@ -676,13 +682,18 @@ static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd, /* Power Constraint element */ pos = hostapd_eid_pwr_constraint(hapd, pos); - /* CSA IE */ - csa_pos = hostapd_eid_csa(hapd, pos); - if (csa_pos != pos) - params->csa_pos = csa_pos - 1; - else - params->csa_pos = NULL; - pos = csa_pos; + /* + * CSA IE + * TODO: This should be included inside the ML sta profile + */ + if (!params->is_ml_sta_info) { + csa_pos = hostapd_eid_csa(hapd, pos); + if (csa_pos != pos) + params->csa_pos = csa_pos - 1; + else + params->csa_pos = NULL; + pos = csa_pos; + } /* ERP Information element */ pos = hostapd_eid_erp_info(hapd, pos); @@ -698,13 +709,18 @@ static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd, pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos); pos = hostapd_get_mde(hapd, pos, epos - pos); - /* eCSA IE */ - csa_pos = hostapd_eid_ecsa(hapd, pos); - if (csa_pos != pos) - params->ecsa_pos = csa_pos - 1; - else - params->ecsa_pos = NULL; - pos = csa_pos; + /* + * eCSA IE + * TODO: This should be included inside the ML sta profile + */ + if (!params->is_ml_sta_info) { + csa_pos = hostapd_eid_ecsa(hapd, pos); + if (csa_pos != pos) + params->ecsa_pos = csa_pos - 1; + else + params->ecsa_pos = NULL; + pos = csa_pos; + } pos = hostapd_eid_supported_op_classes(hapd, pos); pos = hostapd_eid_ht_capabilities(hapd, pos); @@ -748,7 +764,8 @@ static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd, pos = hostapd_eid_wb_chsw_wrapper(hapd, pos); - pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_PROBE_RESP); + if (!params->is_ml_sta_info) + pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_PROBE_RESP); pos = hostapd_eid_fils_indic(hapd, pos, 0); pos = hostapd_get_rsnxe(hapd, pos, epos - pos); @@ -775,8 +792,14 @@ static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd, #ifdef CONFIG_IEEE80211BE if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) { - if (hapd->conf->mld_ap) - pos = hostapd_eid_eht_ml_beacon(hapd, NULL, pos, true); + struct hostapd_data *ml_elem_ap = + params->mld_ap ? params->mld_ap : hapd; + + if (ml_elem_ap->conf->mld_ap) + pos = hostapd_eid_eht_ml_beacon( + ml_elem_ap, params->mld_info, + pos, !!params->mld_ap); + pos = hostapd_eid_eht_capab(hapd, pos, IEEE80211_MODE_AP); pos = hostapd_eid_eht_operation(hapd, pos); } @@ -882,6 +905,117 @@ void hostapd_gen_probe_resp(struct hostapd_data *hapd, } +#ifdef CONFIG_IEEE80211BE +static void hostapd_fill_probe_resp_ml_params(struct hostapd_data *hapd, + struct probe_resp_params *params, + const struct ieee80211_mgmt *mgmt, + int mld_id, u16 links) +{ + struct probe_resp_params sta_info_params; + struct hostapd_data *link; + u8 probed_mld_id, i, j; + + params->mld_ap = NULL; + params->mld_info = os_zalloc(sizeof(*params->mld_info)); + if (!params->mld_info) + return; + + wpa_printf(MSG_DEBUG, + "MLD: Got ML probe request with AP MLD ID %d for links %04x", + mld_id, links); + + /* + * We want to include the AP MLD ID in the response if it was + * included in the request. + */ + probed_mld_id = mld_id != -1 ? mld_id : hapd->conf->mld_id; + + for_each_mld_link(link, i, j, hapd->iface->interfaces, + probed_mld_id) { + struct mld_link_info *link_info; + size_t buflen; + u8 mld_link_id = link->mld_link_id; + u8 *epos; + + /* + * Set mld_ap iff the ML probe request explicitly + * requested a specific MLD ID. In that case, targeted + * AP may have been a nontransmitted BSSID on the same + * interface. + */ + if (mld_id != -1 && link->iface == hapd->iface) + params->mld_ap = link; + + /* Never duplicate main probe response body */ + if (link == hapd) + continue; + + /* Only include requested links */ + if (!(BIT(mld_link_id) & links)) + continue; + + link_info = ¶ms->mld_info->links[mld_link_id]; + + sta_info_params.req = params->req; + sta_info_params.is_p2p = false; + sta_info_params.is_ml_sta_info = true; + sta_info_params.mld_ap = NULL; + sta_info_params.mld_info = NULL; + + buflen = MAX_PROBERESP_LEN; + buflen += hostapd_probe_resp_elems_len(link, &sta_info_params); + + if (buflen > sizeof(link_info->resp_sta_profile)) { + wpa_printf(MSG_DEBUG, + "MLD: Not including link %d in ML probe response (%zu bytes is too long)", + mld_link_id, buflen); + goto fail; + } + + /* + * NOTE: This does not properly handle inheritance and + * various other things. + */ + link_info->valid = true; + epos = link_info->resp_sta_profile; + + /* capabilities is the only fixed parameter */ + WPA_PUT_LE16(link_info->resp_sta_profile, + hostapd_own_capab_info(hapd)); + + epos = hostapd_probe_resp_fill_elems( + link, &sta_info_params, + link_info->resp_sta_profile + 2, + sizeof(link_info->resp_sta_profile) - 2); + link_info->resp_sta_profile_len = + epos - link_info->resp_sta_profile; + os_memcpy(link_info->local_addr, link->own_addr, + ETH_ALEN); + + wpa_printf(MSG_DEBUG, + "MLD: ML probe response includes link sta info for %d: %zu bytes (estimate %zu)", + mld_link_id, + link_info->resp_sta_profile_len, + buflen); + } + + if (mld_id != -1 && !params->mld_ap) { + wpa_printf(MSG_DEBUG, + "MLD: No nontransmitted BSSID for MLD ID %d", + mld_id); + goto fail; + } + + return; + +fail: + os_free(params->mld_info); + params->mld_ap = NULL; + params->mld_info = NULL; +} +#endif /* CONFIG_IEEE80211BE */ + + enum ssid_match_result { NO_SSID_MATCH, EXACT_SSID_MATCH, @@ -1330,13 +1464,14 @@ void handle_probe_req(struct hostapd_data *hapd, wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR " signal=%d", MAC2STR(mgmt->sa), ssi_signal); + os_memset(¶ms, 0, sizeof(params)); + #ifdef CONFIG_IEEE80211BE if (hapd->conf->mld_ap && elems.probe_req_mle && parse_ml_probe_req((struct ieee80211_eht_ml *)elems.probe_req_mle, elems.probe_req_mle_len, &mld_id, &links)) { - wpa_printf(MSG_DEBUG, - "MLD: Got ML probe request with AP MLD ID %d for links %04x", - mld_id, links); + hostapd_fill_probe_resp_ml_params(hapd, ¶ms, mgmt, + mld_id, links); } #endif /* CONFIG_IEEE80211BE */ @@ -1344,7 +1479,12 @@ void handle_probe_req(struct hostapd_data *hapd, params.is_p2p = !!elems.p2p; params.known_bss = elems.mbssid_known_bss; params.known_bss_len = elems.mbssid_known_bss_len; + params.is_ml_sta_info = false; + hostapd_gen_probe_resp(hapd, ¶ms); + + os_free(params.mld_info); + if (!params.resp) return; @@ -1419,6 +1559,9 @@ static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd, params.is_p2p = false; params.known_bss = NULL; params.known_bss_len = 0; + params.is_ml_sta_info = false; + params.mld_ap = NULL; + params.mld_info = NULL; hostapd_gen_probe_resp(hapd, ¶ms); *resp_len = params.resp_len; @@ -1453,6 +1596,9 @@ static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd, probe_params.is_p2p = false; probe_params.known_bss = NULL; probe_params.known_bss_len = 0; + probe_params.is_ml_sta_info = false; + probe_params.mld_ap = NULL; + probe_params.mld_info = NULL; hostapd_gen_probe_resp(hapd, &probe_params); params->unsol_bcast_probe_resp_tmpl_len = probe_params.resp_len; diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index ada6dc5e88..dce26c398d 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -94,6 +94,9 @@ u8 * hostapd_eid_eht_ml_beacon(struct hostapd_data *hapd, u8 *eid, bool include_mld_id); u8 * hostapd_eid_eht_ml_assoc(struct hostapd_data *hapd, struct sta_info *info, u8 *eid); +size_t hostapd_eid_eht_ml_beacon_len(struct hostapd_data *hapd, + struct mld_info *info, + bool include_mld_id); struct wpabuf * hostapd_ml_auth_resp(struct hostapd_data *hapd); const u8 * hostapd_process_ml_auth(struct hostapd_data *hapd, const struct ieee80211_mgmt *mgmt, diff --git a/src/ap/ieee802_11_eht.c b/src/ap/ieee802_11_eht.c index 7b60e6647a..3c5334a203 100644 --- a/src/ap/ieee802_11_eht.c +++ b/src/ap/ieee802_11_eht.c @@ -455,7 +455,8 @@ static u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd, * BSS Parameters Change Count (1) + EML Capabilities (2) + * MLD Capabilities and Operations (2) */ - common_info_len = 13; +#define EHT_ML_COMMON_INFO_LEN 13 + common_info_len = EHT_ML_COMMON_INFO_LEN; if (include_mld_id) { /* AP MLD ID */ @@ -503,8 +504,9 @@ static u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd, * beacon interval (2) + TSF offset (8) + DTIM info (2) + BSS * parameters change counter (1) + station profile length. */ - const size_t fixed_len = 22; - size_t total_len = fixed_len + link->resp_sta_profile_len; +#define EHT_ML_STA_INFO_LEN 22 + size_t total_len = EHT_ML_STA_INFO_LEN + + link->resp_sta_profile_len; /* Skip the local one */ if (link_id == hapd->mld_link_id || !link->valid) @@ -535,10 +537,8 @@ static u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd, EHT_PER_STA_CTRL_BSS_PARAM_CNT_PRESENT_MSK; wpabuf_put_le16(buf, control); - /* STA Info */ - /* STA Info Length */ - wpabuf_put_u8(buf, fixed_len - 2); + wpabuf_put_u8(buf, EHT_ML_STA_INFO_LEN - 2); wpabuf_put_data(buf, link->local_addr, ETH_ALEN); wpabuf_put_le16(buf, link_bss->iconf->beacon_int); @@ -563,7 +563,7 @@ static u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd, ptr = link->resp_sta_profile; len = link->resp_sta_profile_len; - slice_len = 255 - fixed_len; + slice_len = 255 - EHT_ML_STA_INFO_LEN; wpabuf_put_data(buf, ptr, slice_len); len -= slice_len; @@ -700,6 +700,48 @@ static u8 *hostapd_eid_eht_reconf_ml(struct hostapd_data *hapd, } +static size_t hostapd_eid_eht_ml_len(struct mld_info *info, + bool include_mld_id) +{ + size_t len = 0; + size_t eht_ml_len = 2 + EHT_ML_COMMON_INFO_LEN; + u8 link_id; + + if (include_mld_id) + eht_ml_len += 1; + + for (link_id = 0; + info && link_id < ARRAY_SIZE(info->links); + link_id++) { + struct mld_link_info *link; + int sta_len = EHT_ML_STA_INFO_LEN; + + link = &info->links[link_id]; + if (!link->valid) + continue; + + sta_len += link->resp_sta_profile_len; + + /* Element data and (fragmentation) headers */ + eht_ml_len += sta_len; + eht_ml_len += 2 + sta_len / 255 * 2; + } + + /* Element data */ + len += eht_ml_len; + + /* First header (254 bytes of data) */ + len += 3; + + /* Fragmentation headers; +1 for shorter first chunk */ + len += (eht_ml_len + 1) / 255 * 2; + + return len; +} +#undef EHT_ML_COMMON_INFO_LEN +#undef EHT_ML_STA_INFO_LEN + + u8 * hostapd_eid_eht_ml_beacon(struct hostapd_data *hapd, struct mld_info *info, u8 *eid, bool include_mld_id) @@ -721,6 +763,14 @@ u8 * hostapd_eid_eht_ml_assoc(struct hostapd_data *hapd, struct sta_info *info, } +size_t hostapd_eid_eht_ml_beacon_len(struct hostapd_data *hapd, + struct mld_info *info, + bool include_mld_id) +{ + return hostapd_eid_eht_ml_len(info, include_mld_id); +} + + struct wpabuf * hostapd_ml_auth_resp(struct hostapd_data *hapd) { struct wpabuf *buf = wpabuf_alloc(12);