wlan-ap-Telecominfraproject/feeds/qca/hostapd/patches/r02-017-hostapd-support-ML-probe-response.patch
John Crispin 008ca9618d
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
ipq95xx: import ath12.4-cs kernel and drivers
Signed-off-by: John Crispin <john@phrozen.org>
2024-10-20 09:25:13 +02:00

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,
&params->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,