Files
wlan-ap/feeds/qca-wifi-7/hostapd/patches/r23-hostapd-Add-support-for-parsing-ML-Probe-request.patch
John Crispin 68cf54d9f7 qca-wifi-7: update to ath12.5.5
Signed-off-by: John Crispin <john@phrozen.org>
2025-02-27 12:45:52 +01:00

391 lines
14 KiB
Diff

From 8eac2331ffb149d6323c8d47fbe4da146a9324db Mon Sep 17 00:00:00 2001
From: Yuvarani V <quic_yuvarani@quicinc.com>
Date: Thu, 21 Mar 2024 02:38:07 +0530
Subject: [PATCH] hostapd: Add support for parsing ML Probe request
Currently, AP responds with all Per-STA Profile,
included in MLE for a ML Probe Request.
Add support to parse link_id from ML Probe Request
and include only STA requested APs in MLE in Probe
response.
Signed-off-by: Yuvarani V <quic_yuvarani@quicinc.com>
---
src/ap/beacon.c | 43 +++++++++++++++++++++-------------
src/ap/ieee802_11.c | 6 ++---
src/ap/ieee802_11.h | 6 +++--
src/ap/ieee802_11_eht.c | 15 ++++++++++--
src/ap/wpa_auth_glue.c | 4 ++--
src/common/ieee802_11_common.c | 43 +++++++++++++++++++++++++++++-----
src/common/ieee802_11_common.h | 3 ++-
src/common/ieee802_11_defs.h | 6 +++++
8 files changed, 94 insertions(+), 32 deletions(-)
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -43,7 +43,7 @@ static u8 * hostapd_gen_probe_resp(struc
const struct ieee80211_mgmt *req,
int is_p2p, size_t *resp_len,
const u8 *known_bss, u8 known_bss_len,
- bool ml_probe);
+ bool ml_probe, struct multi_link_data *ml_data);
static u8 * hostapd_eid_bss_load(struct hostapd_data *hapd, u8 *eid, size_t len)
{
@@ -848,7 +848,7 @@ void hostapd_gen_per_sta_profiles(struct
own_data = (struct ieee80211_mgmt *)hostapd_gen_probe_resp(hapd, NULL, false,
&own_data_len,
- NULL, 0, false);
+ NULL, 0, false, NULL);
if (own_data == NULL) {
wpa_printf(MSG_ERROR, "Error building per sta profile");
@@ -871,7 +871,7 @@ void hostapd_gen_per_sta_profiles(struct
link_data = (struct ieee80211_mgmt *)hostapd_gen_probe_resp(link_bss, NULL, false,
&link_data_len,
- NULL, 0, false);
+ NULL, 0, false, NULL);
if (link_data == NULL) {
wpa_printf(MSG_ERROR, "Couldnt generate Link STA profile");
@@ -906,7 +906,7 @@ static u8 * hostapd_gen_probe_resp(struc
const struct ieee80211_mgmt *req,
int is_p2p, size_t *resp_len,
const u8 *known_bss, u8 known_bss_len,
- bool ml_probe)
+ bool ml_probe, struct multi_link_data *ml_data)
{
struct ieee80211_mgmt *resp;
u8 *pos, *epos, *csa_pos;
@@ -986,10 +986,18 @@ static u8 * hostapd_gen_probe_resp(struc
buflen += (6 + 2 + 4 +
sizeof(struct ieee80211_240mhz_vendor_oper));
- if (hapd_probed != hapd && hapd_probed->conf->mld_ap && ml_probe)
- buflen += hostapd_eid_eht_basic_ml_len(hapd_probed,
- hapd->partner_links, true,
- WLAN_FC_STYPE_PROBE_RESP);
+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
+ if (hapd->conf->mld_ap) {
+ if (hapd_probed == hapd && ml_probe)
+ buflen += hostapd_eid_eht_basic_ml_len(hapd,
+ hapd->partner_links, false, WLAN_FC_STYPE_PROBE_RESP, ml_data);
+ else
+ buflen += hostapd_eid_eht_basic_ml_len(hapd, NULL, false, WLAN_FC_STYPE_PROBE_RESP, NULL);
+ }
+ if (hapd_probed != hapd && hapd_probed->conf->mld_ap && ml_probe)
+ buflen += hostapd_eid_eht_basic_ml_len(hapd_probed,
+ hapd_probed->partner_links, true, WLAN_FC_STYPE_PROBE_RESP, ml_data);
+ }
}
#endif /* CONFIG_IEEE80211BE */
@@ -1166,10 +1174,10 @@ static u8 * hostapd_gen_probe_resp(struc
if (hapd_probed == hapd && ml_probe)
pos = hostapd_eid_eht_basic_ml(hapd, pos,
hapd->partner_links, false,
- WLAN_FC_STYPE_PROBE_RESP);
+ WLAN_FC_STYPE_PROBE_RESP, ml_data);
else
pos = hostapd_eid_eht_basic_ml(hapd, pos, NULL, false,
- WLAN_FC_STYPE_PROBE_RESP);
+ WLAN_FC_STYPE_PROBE_RESP, NULL);
}
pos = hostapd_eid_eht_capab(hapd, pos, IEEE80211_MODE_AP);
pos = hostapd_eid_eht_operation(hapd, pos, IEEE80211_MODE_AP);
@@ -1178,7 +1186,7 @@ static u8 * hostapd_gen_probe_resp(struc
if (hapd_probed != hapd && hapd_probed->conf->mld_ap && ml_probe)
pos = hostapd_eid_eht_basic_ml(hapd_probed, pos,
hapd_probed->partner_links, true,
- WLAN_FC_STYPE_PROBE_RESP);
+ WLAN_FC_STYPE_PROBE_RESP, ml_data);
}
#endif /* CONFIG_IEEE80211BE */
@@ -1460,7 +1468,9 @@ void handle_probe_req(struct hostapd_dat
bool ml_probe = false;
struct hostapd_data *hapd_probed = hapd;
struct wpabuf *mlbuf = NULL;
- u8 mld_id = 0;
+ struct multi_link_data ml_data;
+
+ os_memset(&ml_data, 0, sizeof(struct multi_link_data));
if (hapd->iconf->rssi_ignore_probe_request && ssi_signal &&
ssi_signal < hapd->iconf->rssi_ignore_probe_request)
@@ -1700,17 +1710,17 @@ void handle_probe_req(struct hostapd_dat
#ifdef CONFIG_IEEE80211BE
mlbuf = ieee802_11_defrag_mle(&elems, MULTI_LINK_CONTROL_TYPE_PROBE_REQ);
- if (hapd->conf->mld_ap && mlbuf && ieee802_11_parse_ml_probe_req(mlbuf, &mld_id)) {
+ if (hapd->conf->mld_ap && mlbuf && ieee802_11_parse_ml_probe_req(mlbuf, &ml_data)) {
ml_probe = true;
/* MLD ID Probing */
- if ((hapd == hostapd_mbssid_get_tx_bss(hapd)) && mld_id) {
- if (mld_id < hapd->iface->num_bss)
- hapd_probed = hapd->iface->bss[mld_id];
+ if ((hapd == hostapd_mbssid_get_tx_bss(hapd)) && ml_data.preq.mld_id) {
+ if (ml_data.preq.mld_id < hapd->iface->num_bss)
+ hapd_probed = hapd->iface->bss[ml_data.preq.mld_id];
else {
wpa_printf(MSG_INFO,
"Ignore Probe Request from " MACSTR
" since No Matched Non-tx vap found for BSSID Index %d",
- MAC2STR(mgmt->sa), mld_id);
+ MAC2STR(mgmt->sa), ml_data.preq.mld_id);
return;
}
}
@@ -1719,7 +1729,7 @@ void handle_probe_req(struct hostapd_dat
#endif
resp = hostapd_gen_probe_resp(hapd_probed, mgmt, elems.p2p != NULL,
&resp_len, elems.mbssid_known_bss,
- elems.mbssid_known_bss_len, ml_probe);
+ elems.mbssid_known_bss_len, ml_probe, &ml_data);
if (resp == NULL)
return;
@@ -1789,7 +1799,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, false);
+ return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, NULL, 0, false, NULL);
}
#endif /* NEED_AP_MLME */
@@ -1820,7 +1830,7 @@ u8 *hostapd_unsol_bcast_probe_resp(struc
return hostapd_gen_probe_resp(hapd, NULL, 0,
&ubpr->unsol_bcast_probe_resp_tmpl_len,
- NULL, 0, false);
+ NULL, 0, false, NULL);
}
#endif /* CONFIG_IEEE80211AX */
@@ -2469,7 +2479,7 @@ int ieee802_11_build_ap_params(struct ho
if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
if (hapd->conf->mld_ap)
tailpos = hostapd_eid_eht_basic_ml(hapd, tailpos, NULL,
- false, WLAN_FC_STYPE_BEACON);
+ false, WLAN_FC_STYPE_BEACON, NULL);
tailpos = hostapd_eid_eht_capab(hapd, tailpos,
IEEE80211_MODE_AP);
startpos = tailpos;
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -5128,7 +5128,7 @@ rsnxe_done:
if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
if (hapd->conf->mld_ap && sta->mld_info.mld_sta)
p = hostapd_eid_eht_basic_ml(hapd, p, sta->mld_info.links, false,
- WLAN_FC_STYPE_ASSOC_RESP);
+ WLAN_FC_STYPE_ASSOC_RESP, NULL);
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);
@@ -8750,7 +8750,7 @@ static size_t hostapd_eid_mbssid_elem_le
/* For ML Probe resp, solicited hapd's MLE will be in the frame body */
if (bss->conf->mld_ap && (bss != hapd_probed || !ml_probe))
nontx_profile_len += hostapd_eid_eht_basic_ml_len(bss, NULL, true,
- frame_type);
+ frame_type, NULL);
#endif /* CONFIG_IEEE80211BE */
if (ie_count || ext_ie_count) {
@@ -8932,7 +8932,7 @@ static u8 * hostapd_eid_mbssid_elem(stru
#ifdef CONFIG_IEEE80211BE
/* For ML Probe resp, solicited hapd's MLE will be in the frame body */
if (bss->conf->mld_ap && (bss != hapd_probed || !ml_probe))
- eid = hostapd_eid_eht_basic_ml(bss, eid, NULL, true, frame_type);
+ eid = hostapd_eid_eht_basic_ml(bss, eid, NULL, true, frame_type, NULL);
#endif /* CONFIG_IEEE80211BE */
if (ie_count || ext_ie_count) {
*eid++ = WLAN_EID_EXTENSION;
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -102,10 +102,12 @@ void hostapd_get_eht_capab(struct hostap
size_t len);
u8 * hostapd_eid_eht_basic_ml(struct hostapd_data *hapd, u8 *eid,
struct mld_link_info *link_info,
- bool include_mld_id, u32 type);
+ bool include_mld_id, u32 type,
+ struct multi_link_data *ml_data);
size_t hostapd_eid_eht_basic_ml_len(struct hostapd_data *hapd,
struct mld_link_info *info,
- bool include_mld_id, u32 type);
+ bool include_mld_id, u32 type,
+ struct multi_link_data *ml_data);
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,
--- a/src/ap/ieee802_11_eht.c
+++ b/src/ap/ieee802_11_eht.c
@@ -601,7 +601,8 @@ 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 mld_link_info *info, bool include_mld_id, u32 type)
+ struct mld_link_info *info, bool include_mld_id, u32 type,
+ struct multi_link_data *ml_data)
{
struct wpabuf *buf;
u16 control, mld_cap;
@@ -707,6 +708,11 @@ u8 * hostapd_eid_eht_basic_ml(struct hos
struct mld_link_info *link = &info[link_id];
struct hostapd_data *link_bss;
+ if (ml_data) {
+ if (!(ml_data->preq.link_bmap & BIT(link_id)))
+ continue;
+ }
+
/*
* control (2) + station info length (1) + MAC address (6) +
* beacon interval (2) + TSF offset (8) + DTIM info (2) + BSS
@@ -850,7 +856,8 @@ out:
*/
size_t hostapd_eid_eht_basic_ml_len(struct hostapd_data *hapd,
struct mld_link_info *info,
- bool include_mld_id, u32 type)
+ bool include_mld_id, u32 type,
+ struct multi_link_data *ml_data)
{
int link_id;
size_t len, num_frags;
@@ -879,6 +886,10 @@ size_t hostapd_eid_eht_basic_ml_len(stru
struct mld_link_info *link = &info[link_id];
struct hostapd_data *link_bss;
+ if (ml_data) {
+ if (!(ml_data->preq.link_bmap & BIT(link_id)))
+ continue;
+ }
size_t sta_prof_len = MLE_STA_INFO_LENGTH + link->resp_sta_profile_len;
/* Add BSS Parameters Change Count in per STA for (Re)Assoc resp */
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -1566,7 +1566,7 @@ static u8 *hostapd_wpa_ft_add_bmle(void
{
struct hostapd_data *hapd = ctx;
- return hostapd_eid_eht_basic_ml(hapd, bmle_ie, NULL, true, WLAN_FC_STYPE_AUTH);
+ return hostapd_eid_eht_basic_ml(hapd, bmle_ie, NULL, true, WLAN_FC_STYPE_AUTH, NULL);
}
@@ -1574,7 +1574,7 @@ static size_t hostapd_wpa_ft_add_bmle_le
{
struct hostapd_data *hapd = ctx;
- return hostapd_eid_eht_basic_ml_len(hapd, NULL, true, WLAN_FC_STYPE_AUTH);
+ return hostapd_eid_eht_basic_ml_len(hapd, NULL, true, WLAN_FC_STYPE_AUTH, NULL);
}
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -1070,10 +1070,11 @@ void ieee802_11_elems_clear_ext_ids(stru
}
}
-bool ieee802_11_parse_ml_probe_req(struct wpabuf *mlbuf, u8 *mld_id)
+bool ieee802_11_parse_ml_probe_req(struct wpabuf *mlbuf, struct multi_link_data *ml_data)
{
const struct ieee80211_eht_ml *ml;
const u8 *pos;
+ const struct element *sub;
size_t len, cmn_info_len;
u16 ml_control;
@@ -1095,21 +1096,51 @@ bool ieee802_11_parse_ml_probe_req(struc
return false;
}
- cmn_info_len = pos;
pos += sizeof(ml->ml_control);
+ cmn_info_len = *pos;
if (ml_control & EHT_ML_PRES_BM_PROBE_REQ_AP_MLD_ID) {
if (cmn_info_len < 2) {
wpa_printf(MSG_DEBUG,
"MLD: ML probe req too short for MLD ID");
return false;
}
- if (mld_id != NULL)
- *mld_id = *(pos + 1);
+ ml_data->preq.mld_id = *(pos + 1);
}
- /* 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
- */
+ pos += cmn_info_len;
+ len = len - cmn_info_len - sizeof(ml->ml_control);
+
+ /* Link Info not present, send response for all affiliated AP in this MLD */
+ if (!len) {
+ ml_data->preq.link_bmap = 0xffff;
+ return true;
+ }
+
+ /* Parse subelements */
+ for_each_element_id(sub, 0, pos, len) {
+ const struct ieee80211_eht_per_sta_profile *sta;
+ u16 sta_control;
+
+ if (sub->datalen <
+ sizeof(struct ieee80211_eht_per_sta_profile)) {
+ ml_data->preq.link_bmap = 0xffff;
+ wpa_printf(MSG_DEBUG,
+ "MLD: ML probe req %d too short for sta profile",
+ sub->datalen);
+ return true;
+ }
+
+ sta = (struct ieee80211_eht_per_sta_profile *) sub->data;
+
+ sta_control = le_to_host16(sta->sta_control);
+ ml_data->preq.link_bmap |= BIT(sta_control & EHT_PER_STA_CTRL_LINK_ID_MSK);
+ }
+
+ if (!for_each_element_completed(sub, pos, len)) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: ML probe req sub-elements parsing error");
+ return false;
+ }
+
return true;
}
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -228,7 +228,8 @@ 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, u8 *mld_id);
+bool ieee802_11_parse_ml_probe_req(struct wpabuf *mlbuf,
+ struct multi_link_data *ml_data);
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_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -2786,6 +2786,13 @@ struct ieee80211_eht_ml {
u8 variable[];
} STRUCT_PACKED;
+struct multi_link_data {
+ struct multi_link_preq_info {
+ u8 mld_id;
+ u16 link_bmap;
+ } preq;
+};
+
/* Table 9-401c - Optional subelement IDs for Link Info field of the
* Multi-Link element */
enum ieee80211_eht_ml_sub_elem {