mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-21 03:13:17 +00:00
Some checks failed
Build OpenWrt/uCentral images / build (cig_wf186h) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf186w) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf188n) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf189) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf196) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cybertan_eww631-a1) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cybertan_eww631-b1) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap101) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap102) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap104) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap105) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap111) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap112) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101-6e) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101e) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101e-6e) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x_2) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x_3) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x_w) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4xe) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4xi) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4xi_w) (push) Has been cancelled
Build OpenWrt/uCentral images / build (indio_um-305ax) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sercomm_ap72tip) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sonicfi_rap630c-311g) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sonicfi_rap630w-211g) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sonicfi_rap630w-311g) (push) Has been cancelled
Build OpenWrt/uCentral images / build (udaya_a6-id2) (push) Has been cancelled
Build OpenWrt/uCentral images / build (udaya_a6-od2) (push) Has been cancelled
Build OpenWrt/uCentral images / build (wallys_dr5018) (push) Has been cancelled
Build OpenWrt/uCentral images / build (wallys_dr6018) (push) Has been cancelled
Build OpenWrt/uCentral images / build (wallys_dr6018-v4) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_ax820) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_ax840) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_fap640) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_fap650) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_fap655) (push) Has been cancelled
Build OpenWrt/uCentral images / trigger-testing (push) Has been cancelled
Build OpenWrt/uCentral images / create-x64_vm-ami (push) Has been cancelled
Signed-off-by: John Crispin <john@phrozen.org>
619 lines
18 KiB
Diff
619 lines
18 KiB
Diff
From c39be6df437aa02d2803b291a635dd6ff4ee5b93 Mon Sep 17 00:00:00 2001
|
|
From: Sriram R <quic_srirrama@quicinc.com>
|
|
Date: Fri, 10 Nov 2023 11:48:23 +0530
|
|
Subject: [PATCH] hostapd: support ML probe response
|
|
|
|
Add support to respond to ML probe requests with ML probe response
|
|
contaitning the sta profiles of the requested links.
|
|
|
|
Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
|
|
---
|
|
src/ap/beacon.c | 342 ++++++++++++++++++++++++++++++++-
|
|
src/ap/hostapd.h | 4 +
|
|
src/ap/ieee802_11.c | 8 +-
|
|
src/ap/ieee802_11.h | 2 +-
|
|
src/ap/ieee802_11_eht.c | 4 +-
|
|
src/ap/sta_info.h | 33 ++--
|
|
src/common/ieee802_11_common.c | 29 +++
|
|
src/common/ieee802_11_common.h | 1 +
|
|
8 files changed, 390 insertions(+), 33 deletions(-)
|
|
|
|
--- a/src/ap/beacon.c
|
|
+++ b/src/ap/beacon.c
|
|
@@ -36,6 +36,12 @@
|
|
|
|
#ifdef NEED_AP_MLME
|
|
|
|
+static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
|
+ const struct ieee80211_mgmt *req,
|
|
+ int is_p2p, size_t *resp_len,
|
|
+ const u8 *known_bss, u8 known_bss_len,
|
|
+ bool ml_probe);
|
|
+
|
|
static u8 * hostapd_eid_bss_load(struct hostapd_data *hapd, u8 *eid, size_t len)
|
|
{
|
|
if (len < 2 + 5)
|
|
@@ -593,10 +599,308 @@ static u8 * hostapd_eid_mbssid_config(st
|
|
}
|
|
|
|
|
|
+static bool hostapd_is_restricted_eid_in_sta_profile(u8 eid)
|
|
+{
|
|
+ switch(eid) {
|
|
+ case WLAN_EID_SSID:
|
|
+ case WLAN_EID_TIM:
|
|
+ case WLAN_EID_BSS_MAX_IDLE_PERIOD:
|
|
+ case WLAN_EID_MULTIPLE_BSSID:
|
|
+ case WLAN_EID_REDUCED_NEIGHBOR_REPORT:
|
|
+ case WLAN_EID_NEIGHBOR_REPORT:
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
+static bool hostapd_is_restricted_ext_eid_in_sta_profile(u8 eid)
|
|
+{
|
|
+ switch(eid) {
|
|
+ case WLAN_EID_EXT_MULTI_LINK:
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
+/* Create the link sta profile based on inheritance from the reporting
|
|
+ * profile. If @sta_profile is NULL, only the length of the sta_profile
|
|
+ * is returned
|
|
+ */
|
|
+static size_t hostapd_add_sta_profile(struct ieee80211_mgmt *own_fdata,
|
|
+ struct ieee80211_mgmt *link_fdata,
|
|
+ size_t own_data_len,
|
|
+ size_t link_data_len,
|
|
+ u8 *sta_profile, u32 type)
|
|
+{
|
|
+ /* the bitmap of parsed eids, max eid is 256, hence 32bytes to store the bitmap */
|
|
+ u8 parsed_eid_bmap[32] = {0}, parsed_ext_eid_bmap[32] = {0};
|
|
+ u8 oeid, leid, oelen, lelen;
|
|
+ const u8 *oelem_data, *lelem_data;
|
|
+ u8 *own_data, *link_data;
|
|
+ const struct element *oelem, *lelem;
|
|
+ bool is_ext, ie_found;
|
|
+ /* extra len used in the logic incudes the element id and len */
|
|
+ u8 extra_len = 2;
|
|
+ size_t sta_profile_len = 0;
|
|
+ u8 ninherit_elemlist[254] = {0}, ninherit_elemlist_len = 0;
|
|
+ u8 ninherit_elemextlist[254] = {0}, ninherit_elemextlist_len = 0;
|
|
+
|
|
+ /* include len for capab info */
|
|
+ sta_profile_len += sizeof(le16);
|
|
+
|
|
+ if (type == WLAN_FC_STYPE_PROBE_RESP) {
|
|
+ if (sta_profile) {
|
|
+ memcpy(sta_profile, &link_fdata->u.probe_resp.capab_info, sizeof(le16));
|
|
+ sta_profile += sizeof(le16);
|
|
+ }
|
|
+
|
|
+ own_data = own_fdata->u.probe_resp.variable;
|
|
+ link_data = link_fdata->u.probe_resp.variable;
|
|
+ } else {
|
|
+ if (sta_profile) {
|
|
+ memcpy(sta_profile, &link_fdata->u.assoc_resp.capab_info, sizeof(le16));
|
|
+ sta_profile += sizeof(le16);
|
|
+
|
|
+ memcpy(sta_profile, &link_fdata->u.assoc_resp.status_code, sizeof(le16));
|
|
+ sta_profile += sizeof(le16);
|
|
+ }
|
|
+
|
|
+ /* include len for status code */
|
|
+ sta_profile_len += sizeof(le16);
|
|
+
|
|
+ own_data = own_fdata->u.assoc_resp.variable;
|
|
+ link_data = link_fdata->u.assoc_resp.variable;
|
|
+ }
|
|
+
|
|
+ /* The below logic takes the reporting bss data and reported bss data and performs
|
|
+ * intersection to build the sta profile of the reported bss. Also certain IEs are
|
|
+ * not added to the sta profile as recommended in spec. Matching IE information
|
|
+ * in the reporting bss profile are ignored in the sta profile. Remaining IEs
|
|
+ * pertaining to the sta profile are appended at the end.
|
|
+ * Same logic is used by hostapd_sta_profile_len() to determine the length of
|
|
+ * the sta profile.
|
|
+ */
|
|
+ for_each_element(oelem, own_data, own_data_len) {
|
|
+ ie_found = false;
|
|
+ is_ext = false;
|
|
+ oelem_data = oelem->data;
|
|
+ oelen = oelem->datalen;
|
|
+ if (oelem->id == WLAN_EID_EXTENSION) {
|
|
+ is_ext = true;
|
|
+ oeid = *(oelem_data);
|
|
+ if (hostapd_is_restricted_ext_eid_in_sta_profile(oeid))
|
|
+ continue;
|
|
+ } else {
|
|
+ oeid = oelem->id;
|
|
+ if (hostapd_is_restricted_eid_in_sta_profile(oeid))
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ for_each_element(lelem, link_data, link_data_len) {
|
|
+ if ((lelem->id == WLAN_EID_EXTENSION && !is_ext) ||
|
|
+ (is_ext && lelem->id != WLAN_EID_EXTENSION))
|
|
+ continue;
|
|
+
|
|
+ lelem_data = lelem->data;
|
|
+ lelen = lelem->datalen;
|
|
+ if (lelem->id == WLAN_EID_EXTENSION) {
|
|
+ leid = *(lelem_data);
|
|
+ } else {
|
|
+ leid = lelem->id;
|
|
+ }
|
|
+
|
|
+ if (oeid == leid) {
|
|
+ ie_found = true;
|
|
+ if (oelen != lelen ||
|
|
+ memcmp(oelem->data, lelem->data, oelen)) {
|
|
+ if (sta_profile) {
|
|
+ memcpy(sta_profile, lelem->data - extra_len, lelen + extra_len);
|
|
+ sta_profile += lelen + extra_len;
|
|
+ }
|
|
+ sta_profile_len += lelen + extra_len;
|
|
+ }
|
|
+
|
|
+ if (is_ext)
|
|
+ parsed_ext_eid_bmap[oeid/8] |= BIT(oeid%8);
|
|
+ else
|
|
+ parsed_eid_bmap[oeid/8] |= BIT(oeid%8);
|
|
+
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (!ie_found) {
|
|
+ if (is_ext)
|
|
+ ninherit_elemextlist[ninherit_elemextlist_len++] = oeid;
|
|
+ else
|
|
+ ninherit_elemlist[ninherit_elemlist_len++] = oeid;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* parse the remaining elements in the link profile */
|
|
+ for_each_element(lelem, link_data, link_data_len) {
|
|
+ lelem_data = lelem->data;
|
|
+ lelen = lelem->datalen;
|
|
+ if (lelem->id == WLAN_EID_EXTENSION) {
|
|
+ leid = *(lelem_data);
|
|
+ if (parsed_ext_eid_bmap[leid/8] & BIT(leid%8))
|
|
+ continue;
|
|
+ if (hostapd_is_restricted_ext_eid_in_sta_profile(leid))
|
|
+ continue;
|
|
+ } else {
|
|
+ leid = lelem->id;
|
|
+ if (parsed_eid_bmap[leid/8] & BIT(leid%8))
|
|
+ continue;
|
|
+ if (hostapd_is_restricted_eid_in_sta_profile(leid))
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (sta_profile) {
|
|
+ memcpy(sta_profile, lelem->data - extra_len, lelen + extra_len);
|
|
+ sta_profile += lelen + extra_len;
|
|
+ }
|
|
+ sta_profile_len += lelen + extra_len;
|
|
+ }
|
|
+
|
|
+ if (sta_profile && (ninherit_elemlist_len || ninherit_elemextlist_len)) {
|
|
+ *sta_profile = WLAN_EID_EXTENSION;
|
|
+ sta_profile++;
|
|
+
|
|
+ *sta_profile = ninherit_elemlist_len + ninherit_elemextlist_len + 3;
|
|
+ sta_profile++;
|
|
+
|
|
+ *sta_profile = WLAN_EID_EXT_NON_INHERITANCE;
|
|
+ sta_profile++;
|
|
+
|
|
+ *sta_profile = ninherit_elemlist_len;
|
|
+ sta_profile++;
|
|
+ if (ninherit_elemlist_len)
|
|
+ memcpy(sta_profile, ninherit_elemlist, ninherit_elemlist_len);
|
|
+ sta_profile += ninherit_elemlist_len;
|
|
+
|
|
+ *sta_profile = ninherit_elemextlist_len;
|
|
+ sta_profile++;
|
|
+ if (ninherit_elemextlist_len)
|
|
+ memcpy(sta_profile, ninherit_elemextlist, ninherit_elemextlist_len);
|
|
+ sta_profile += ninherit_elemextlist_len;
|
|
+
|
|
+ }
|
|
+
|
|
+ /* Non-Inheritance IE = EID_EXT(1byte) + Total len field(1byte) +
|
|
+ * Ext tag number (1byte) + ninherit_elemlist_len(1byte) + ninherit_elemextlist_len(1byte) +
|
|
+ * data
|
|
+ */
|
|
+ if (ninherit_elemlist_len || ninherit_elemextlist_len)
|
|
+ sta_profile_len += 3 + 2 + ninherit_elemlist_len + ninherit_elemextlist_len;
|
|
+
|
|
+ return sta_profile_len;
|
|
+}
|
|
+
|
|
+static u8 * hostapd_gen_sta_profile(struct ieee80211_mgmt *own_data,
|
|
+ struct ieee80211_mgmt *link_data,
|
|
+ size_t own_data_len,
|
|
+ size_t link_data_len,
|
|
+ size_t *sta_profile_len, u32 type)
|
|
+{
|
|
+ u8 *sta_profile;
|
|
+
|
|
+ if (type != WLAN_FC_STYPE_PROBE_RESP &&
|
|
+ type != WLAN_FC_STYPE_ASSOC_RESP)
|
|
+ return NULL;
|
|
+
|
|
+ *sta_profile_len = hostapd_add_sta_profile(own_data, link_data,
|
|
+ own_data_len,
|
|
+ link_data_len,
|
|
+ NULL, type);
|
|
+
|
|
+ if (!(*sta_profile_len))
|
|
+ return NULL;
|
|
+
|
|
+ sta_profile = os_zalloc(*sta_profile_len);
|
|
+
|
|
+ if (sta_profile == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ hostapd_add_sta_profile(own_data, link_data, own_data_len,
|
|
+ link_data_len, sta_profile, type);
|
|
+
|
|
+ return sta_profile;
|
|
+}
|
|
+
|
|
+static void hostapd_gen_per_sta_profiles(struct hostapd_data *hapd)
|
|
+{
|
|
+ struct ieee80211_mgmt *own_data, *link_data;
|
|
+ struct hostapd_data *link_bss;
|
|
+ size_t own_data_len, link_data_len, sta_profile_len;
|
|
+ u8 *sta_profile, link_id;
|
|
+
|
|
+ if (!hapd->conf->mld_ap)
|
|
+ return;
|
|
+
|
|
+ if (dl_list_empty(&hapd->mld->links))
|
|
+ return;
|
|
+
|
|
+ own_data = (struct ieee80211_mgmt *)hostapd_gen_probe_resp(hapd, NULL, false,
|
|
+ &own_data_len,
|
|
+ NULL, 0, false);
|
|
+
|
|
+ if (own_data == NULL) {
|
|
+ wpa_printf(MSG_ERROR, "Error building per sta profile");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ own_data_len -= offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
|
|
+
|
|
+ for_each_partner_bss(link_bss, hapd) {
|
|
+ if (link_bss == hapd)
|
|
+ continue;
|
|
+
|
|
+ link_id = link_bss->mld_link_id;
|
|
+
|
|
+ if (link_id > MAX_NUM_MLD_LINKS)
|
|
+ continue;
|
|
+
|
|
+ sta_profile = NULL;
|
|
+ sta_profile_len = 0;
|
|
+
|
|
+ link_data = (struct ieee80211_mgmt *)hostapd_gen_probe_resp(link_bss, NULL, false,
|
|
+ &link_data_len,
|
|
+ NULL, 0, false);
|
|
+
|
|
+ if (link_data == NULL) {
|
|
+ wpa_printf(MSG_ERROR, "Couldnt generate Link STA profile");
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ link_data_len -= offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
|
|
+
|
|
+ sta_profile = hostapd_gen_sta_profile(own_data, link_data,
|
|
+ own_data_len, link_data_len,
|
|
+ &sta_profile_len,
|
|
+ WLAN_FC_STYPE_PROBE_RESP);
|
|
+
|
|
+ if (sta_profile == NULL || sta_profile_len > EHT_ML_MAX_STA_PROF_LEN) {
|
|
+ wpa_printf(MSG_ERROR, "Couldnt generate Link STA profile");
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ memcpy(hapd->partner_links[link_id].resp_sta_profile, sta_profile, sta_profile_len);
|
|
+ hapd->partner_links[link_id].resp_sta_profile_len = sta_profile_len;
|
|
+ memcpy(hapd->partner_links[link_id].local_addr, link_bss->own_addr, ETH_ALEN);
|
|
+ hapd->partner_links[link_id].valid = true;
|
|
+
|
|
+ os_free(link_data);
|
|
+ os_free(sta_profile);
|
|
+ }
|
|
+
|
|
+ os_free(own_data);
|
|
+}
|
|
+
|
|
static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
|
|
const struct ieee80211_mgmt *req,
|
|
int is_p2p, size_t *resp_len,
|
|
- const u8 *known_bss, u8 known_bss_len)
|
|
+ const u8 *known_bss, u8 known_bss_len,
|
|
+ bool ml_probe)
|
|
{
|
|
struct ieee80211_mgmt *resp;
|
|
u8 *pos, *epos, *csa_pos;
|
|
@@ -656,12 +960,17 @@ static u8 * hostapd_gen_probe_resp(struc
|
|
/*
|
|
* 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.
|
|
+ * station profiles. For now use 256 for non ML probe resp
|
|
+ * and 1024 for ML probe resp
|
|
*/
|
|
if (hapd->conf->mld_ap) {
|
|
- buflen += 256;
|
|
- /* inclusion on MCST IE is mandatory */
|
|
- buflen += 6;
|
|
+ if (ml_probe) {
|
|
+ buflen += 1024;
|
|
+ } else {
|
|
+ buflen += 256;
|
|
+ /* inclusion on MCST IE is mandatory */
|
|
+ buflen += 6;
|
|
+ }
|
|
}
|
|
/* QCN Vendor IE for 240MHz */
|
|
if (is_5ghz_freq(hapd->iface->freq))
|
|
@@ -836,8 +1145,13 @@ static u8 * hostapd_gen_probe_resp(struc
|
|
|
|
#ifdef CONFIG_IEEE80211BE
|
|
if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
|
|
- if (hapd->conf->mld_ap)
|
|
- pos = hostapd_eid_eht_basic_ml(hapd, pos, NULL, true);
|
|
+ if (hapd->conf->mld_ap) {
|
|
+ if (ml_probe)
|
|
+ pos = hostapd_eid_eht_basic_ml(hapd, pos,
|
|
+ hapd->partner_links, true);
|
|
+ else
|
|
+ pos = hostapd_eid_eht_basic_ml(hapd, pos, NULL, true);
|
|
+ }
|
|
pos = hostapd_eid_eht_capab(hapd, pos, IEEE80211_MODE_AP);
|
|
pos = hostapd_eid_eht_operation(hapd, pos, IEEE80211_MODE_AP);
|
|
pos = hostapd_eid_vendor_240mhz(hapd, pos, IEEE80211_MODE_AP);
|
|
@@ -1118,6 +1432,8 @@ void handle_probe_req(struct hostapd_dat
|
|
.ssi_signal = ssi_signal,
|
|
.elems = &elems,
|
|
};
|
|
+ bool ml_probe = false;
|
|
+ struct wpabuf *mlbuf = NULL;
|
|
|
|
if (hapd->iconf->rssi_ignore_probe_request && ssi_signal &&
|
|
ssi_signal < hapd->iconf->rssi_ignore_probe_request)
|
|
@@ -1355,9 +1671,16 @@ void handle_probe_req(struct hostapd_dat
|
|
wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR
|
|
" signal=%d", MAC2STR(mgmt->sa), ssi_signal);
|
|
|
|
+#ifdef CONFIG_IEEE80211BE
|
|
+ mlbuf = ieee802_11_defrag_mle(&elems, MULTI_LINK_CONTROL_TYPE_PROBE_REQ);
|
|
+ if (mlbuf && ieee802_11_parse_ml_probe_req(mlbuf)) {
|
|
+ ml_probe = true;
|
|
+ }
|
|
+ wpabuf_free(mlbuf);
|
|
+#endif
|
|
resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
|
|
&resp_len, elems.mbssid_known_bss,
|
|
- elems.mbssid_known_bss_len);
|
|
+ elems.mbssid_known_bss_len, ml_probe);
|
|
if (resp == NULL)
|
|
return;
|
|
|
|
@@ -1427,7 +1750,7 @@ static u8 * hostapd_probe_resp_offloads(
|
|
"this");
|
|
|
|
/* Generate a Probe Response template for the non-P2P case */
|
|
- return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, NULL, 0);
|
|
+ return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, NULL, 0, false);
|
|
}
|
|
|
|
#endif /* NEED_AP_MLME */
|
|
@@ -1458,7 +1781,7 @@ static u8 * hostapd_unsol_bcast_probe_re
|
|
|
|
return hostapd_gen_probe_resp(hapd, NULL, 0,
|
|
¶ms->unsol_bcast_probe_resp_tmpl_len,
|
|
- NULL, 0);
|
|
+ NULL, 0, false);
|
|
}
|
|
#endif /* CONFIG_IEEE80211AX */
|
|
|
|
@@ -2398,6 +2721,9 @@ int ieee802_11_set_beacon(struct hostapd
|
|
}
|
|
}
|
|
|
|
+ /* Generate per sta profiles for affiliated APs */
|
|
+ hostapd_gen_per_sta_profiles(hapd);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
--- a/src/ap/hostapd.h
|
|
+++ b/src/ap/hostapd.h
|
|
@@ -36,6 +36,7 @@ struct ieee80211_ht_capabilities;
|
|
struct full_dynamic_vlan;
|
|
enum wps_event;
|
|
union wps_event_data;
|
|
+struct mld_link_info;
|
|
#ifdef CONFIG_MESH
|
|
struct mesh_conf;
|
|
#endif /* CONFIG_MESH */
|
|
@@ -501,6 +502,9 @@ struct hostapd_data {
|
|
struct dl_list link;
|
|
u8 mld_link_id;
|
|
char ctrl_sock_iface[IFNAMSIZ + 1];
|
|
+
|
|
+ /* Store the partner info for ML probe response */
|
|
+ struct mld_link_info partner_links[MAX_NUM_MLD_LINKS];
|
|
#endif /* CONFIG_IEEE80211BE */
|
|
};
|
|
|
|
--- a/src/ap/ieee802_11.c
|
|
+++ b/src/ap/ieee802_11.c
|
|
@@ -4446,10 +4446,10 @@ static void ieee80211_ml_process_link(st
|
|
goto out;
|
|
|
|
if (ieee802_11_parse_link_assoc_req(ies, ies_len, &elems, mlbuf,
|
|
- hapd->mld_link_id, true) ==
|
|
- ParseFailed) {
|
|
+ hapd->mld_link_id, true) ==
|
|
+ ParseFailed) {
|
|
wpa_printf(MSG_DEBUG,
|
|
- "MLD: link: Failed to parse association request Multi-Link element");
|
|
+ "MLD: link: Failed to parse association request Multi-Link element");
|
|
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
|
goto out;
|
|
}
|
|
@@ -4946,7 +4946,7 @@ rsnxe_done:
|
|
#ifdef CONFIG_IEEE80211BE
|
|
if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
|
|
if (hapd->conf->mld_ap)
|
|
- p = hostapd_eid_eht_basic_ml(hapd, p, sta, false);
|
|
+ p = hostapd_eid_eht_basic_ml(hapd, p, sta->mld_info.links, false);
|
|
p = hostapd_eid_eht_capab(hapd, p, IEEE80211_MODE_AP);
|
|
p = hostapd_eid_eht_operation(hapd, p, IEEE80211_MODE_AP);
|
|
p = hostapd_eid_vendor_240mhz(hapd, p, IEEE80211_MODE_AP);
|
|
--- a/src/ap/ieee802_11.h
|
|
+++ b/src/ap/ieee802_11.h
|
|
@@ -97,7 +97,7 @@ void hostapd_get_eht_capab(struct hostap
|
|
struct ieee80211_eht_capabilities *dest,
|
|
size_t len);
|
|
u8 * hostapd_eid_eht_basic_ml(struct hostapd_data *hapd, u8 *eid,
|
|
- struct sta_info *info, bool include_mld_id);
|
|
+ struct mld_link_info *link_info, bool include_mld_id);
|
|
size_t hostapd_eid_eht_basic_ml_len(struct hostapd_data *hapd,
|
|
struct sta_info *info, bool include_mld_id);
|
|
struct wpabuf * hostapd_ml_auth_resp(struct hostapd_data *hapd);
|
|
--- a/src/ap/ieee802_11_eht.c
|
|
+++ b/src/ap/ieee802_11_eht.c
|
|
@@ -552,7 +552,7 @@ void hostapd_get_eht_capab(struct hostap
|
|
*/
|
|
#define MLE_COMMON_INFO_LEN 13
|
|
u8 * hostapd_eid_eht_basic_ml(struct hostapd_data *hapd, u8 *eid,
|
|
- struct sta_info *info, bool include_mld_id)
|
|
+ struct mld_link_info *info, bool include_mld_id)
|
|
{
|
|
struct wpabuf *buf;
|
|
u16 control;
|
|
@@ -617,7 +617,7 @@ u8 * hostapd_eid_eht_basic_ml(struct hos
|
|
|
|
/* Add link info for the other links */
|
|
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
|
|
- struct mld_link_info *link = &info->mld_info.links[link_id];
|
|
+ struct mld_link_info *link = &info[link_id];
|
|
struct hostapd_data *link_bss;
|
|
|
|
/*
|
|
--- a/src/ap/sta_info.h
|
|
+++ b/src/ap/sta_info.h
|
|
@@ -54,6 +54,7 @@
|
|
#define WLAN_SUPP_HT_RATES_MAX 77
|
|
|
|
struct hostapd_data;
|
|
+struct mld_link_info;
|
|
|
|
struct mbo_non_pref_chan_info {
|
|
struct mbo_non_pref_chan_info *next;
|
|
@@ -71,6 +72,21 @@ struct pending_eapol_rx {
|
|
};
|
|
|
|
#define EHT_ML_MAX_STA_PROF_LEN 1024
|
|
+
|
|
+struct mld_link_info {
|
|
+ u8 valid;
|
|
+ u8 local_addr[ETH_ALEN];
|
|
+ u8 peer_addr[ETH_ALEN];
|
|
+ size_t nstr_bitmap_len;
|
|
+ u8 nstr_bitmap[2];
|
|
+ u16 capability;
|
|
+ u16 status;
|
|
+ size_t resp_sta_profile_len;
|
|
+ /* TODO Make allocation dynamic */
|
|
+ u8 resp_sta_profile[EHT_ML_MAX_STA_PROF_LEN];
|
|
+ const u8 *rsne, *rsnxe;
|
|
+};
|
|
+
|
|
struct mld_info {
|
|
bool mld_sta;
|
|
|
|
@@ -81,22 +97,7 @@ struct mld_info {
|
|
u16 mld_capa;
|
|
} common_info;
|
|
|
|
- struct mld_link_info {
|
|
- u8 valid;
|
|
- u8 local_addr[ETH_ALEN];
|
|
- u8 peer_addr[ETH_ALEN];
|
|
-
|
|
- size_t nstr_bitmap_len;
|
|
- u8 nstr_bitmap[2];
|
|
-
|
|
- u16 capability;
|
|
-
|
|
- u16 status;
|
|
- size_t resp_sta_profile_len;
|
|
- u8 resp_sta_profile[EHT_ML_MAX_STA_PROF_LEN];
|
|
-
|
|
- const u8 *rsne, *rsnxe;
|
|
- } links[MAX_NUM_MLD_LINKS];
|
|
+ struct mld_link_info links[MAX_NUM_MLD_LINKS];
|
|
};
|
|
|
|
struct sta_info {
|
|
--- a/src/common/ieee802_11_common.c
|
|
+++ b/src/common/ieee802_11_common.c
|
|
@@ -976,6 +976,35 @@ void ieee802_11_elems_clear_ext_ids(stru
|
|
}
|
|
|
|
|
|
+bool ieee802_11_parse_ml_probe_req(struct wpabuf *mlbuf)
|
|
+{
|
|
+ const struct ieee80211_eht_ml *ml;
|
|
+ const u8 *pos;
|
|
+ size_t len;
|
|
+ u16 ml_control;
|
|
+
|
|
+ pos = wpabuf_head(mlbuf);
|
|
+ len = wpabuf_len(mlbuf);
|
|
+
|
|
+ /* Must have control and common info length */
|
|
+ if (len < sizeof(*ml) + 1 || len < sizeof(*ml) + pos[sizeof(*ml)])
|
|
+ return false;
|
|
+
|
|
+ ml = (const struct ieee80211_eht_ml *) pos;
|
|
+
|
|
+ ml_control = le_to_host16(ml->ml_control);
|
|
+ if ((ml_control & MULTI_LINK_CONTROL_TYPE_MASK) !=
|
|
+ MULTI_LINK_CONTROL_TYPE_PROBE_REQ)
|
|
+ return false;
|
|
+
|
|
+ /* TODO parse the ML probe request and send response accordingly
|
|
+ * Currently if ML probe request is sent, we support sending all
|
|
+ * link's profile in the ML probe response
|
|
+ */
|
|
+ return true;
|
|
+}
|
|
+
|
|
+
|
|
ParseRes ieee802_11_parse_link_assoc_req(const u8 *start, size_t len,
|
|
struct ieee802_11_elems *elems,
|
|
struct wpabuf *mlbuf,
|
|
--- a/src/common/ieee802_11_common.h
|
|
+++ b/src/common/ieee802_11_common.h
|
|
@@ -193,6 +193,7 @@ void ieee802_11_elems_clear_ids(struct i
|
|
const u8 *ids, size_t num);
|
|
void ieee802_11_elems_clear_ext_ids(struct ieee802_11_elems *elems,
|
|
const u8 *ids, size_t num);
|
|
+bool ieee802_11_parse_ml_probe_req(struct wpabuf *mlbuf);
|
|
ParseRes ieee802_11_parse_link_assoc_req(const u8 *start, size_t len,
|
|
struct ieee802_11_elems *elems,
|
|
struct wpabuf *mlbuf,
|