AP MLD: Reduce struct mld_link_info size
Replace the fixed length maximum buffer size for STA profile with dynamically allocated buffers for active links. This reduces struct mld_link_info size by almost 16 kB and drops the per-STA information in struct sta_info to a more reasonable size to avoid the almost 10x increase from MLO support. In addition, free the resp_sta_profile buffers as soon as the ML element has bee generated for (Re)Association Response frame since those buffers are not needed after that. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
b91572b308
commit
512b925240
5 changed files with 78 additions and 33 deletions
|
@ -617,6 +617,19 @@ struct probe_resp_params {
|
||||||
#endif /* CONFIG_IEEE80211AX */
|
#endif /* CONFIG_IEEE80211AX */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void hostapd_free_probe_resp_params(struct probe_resp_params *params)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
if (!params)
|
||||||
|
return;
|
||||||
|
ap_sta_free_sta_profile(params->mld_info);
|
||||||
|
os_free(params->mld_info);
|
||||||
|
params->mld_info = NULL;
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static size_t hostapd_probe_resp_elems_len(struct hostapd_data *hapd,
|
static size_t hostapd_probe_resp_elems_len(struct hostapd_data *hapd,
|
||||||
struct probe_resp_params *params)
|
struct probe_resp_params *params)
|
||||||
{
|
{
|
||||||
|
@ -955,6 +968,7 @@ static void hostapd_fill_probe_resp_ml_params(struct hostapd_data *hapd,
|
||||||
size_t buflen;
|
size_t buflen;
|
||||||
u8 mld_link_id = link->mld_link_id;
|
u8 mld_link_id = link->mld_link_id;
|
||||||
u8 *epos;
|
u8 *epos;
|
||||||
|
u8 buf[EHT_ML_MAX_STA_PROF_LEN];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set mld_ap iff the ML probe request explicitly
|
* Set mld_ap iff the ML probe request explicitly
|
||||||
|
@ -984,7 +998,7 @@ static void hostapd_fill_probe_resp_ml_params(struct hostapd_data *hapd,
|
||||||
buflen = MAX_PROBERESP_LEN;
|
buflen = MAX_PROBERESP_LEN;
|
||||||
buflen += hostapd_probe_resp_elems_len(link, &sta_info_params);
|
buflen += hostapd_probe_resp_elems_len(link, &sta_info_params);
|
||||||
|
|
||||||
if (buflen > sizeof(link_info->resp_sta_profile)) {
|
if (buflen > EHT_ML_MAX_STA_PROF_LEN) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"MLD: Not including link %d in ML probe response (%zu bytes is too long)",
|
"MLD: Not including link %d in ML probe response (%zu bytes is too long)",
|
||||||
mld_link_id, buflen);
|
mld_link_id, buflen);
|
||||||
|
@ -996,18 +1010,21 @@ static void hostapd_fill_probe_resp_ml_params(struct hostapd_data *hapd,
|
||||||
* various other things.
|
* various other things.
|
||||||
*/
|
*/
|
||||||
link_info->valid = true;
|
link_info->valid = true;
|
||||||
epos = link_info->resp_sta_profile;
|
epos = buf;
|
||||||
|
|
||||||
/* Capabilities is the only fixed parameter */
|
/* Capabilities is the only fixed parameter */
|
||||||
WPA_PUT_LE16(link_info->resp_sta_profile,
|
WPA_PUT_LE16(epos, hostapd_own_capab_info(hapd));
|
||||||
hostapd_own_capab_info(hapd));
|
epos += 2;
|
||||||
|
|
||||||
epos = hostapd_probe_resp_fill_elems(
|
epos = hostapd_probe_resp_fill_elems(
|
||||||
link, &sta_info_params,
|
link, &sta_info_params, epos,
|
||||||
link_info->resp_sta_profile + 2,
|
EHT_ML_MAX_STA_PROF_LEN - 2);
|
||||||
sizeof(link_info->resp_sta_profile) - 2);
|
link_info->resp_sta_profile_len = epos - buf;
|
||||||
link_info->resp_sta_profile_len =
|
os_free(link_info->resp_sta_profile);
|
||||||
epos - link_info->resp_sta_profile;
|
link_info->resp_sta_profile = os_memdup(
|
||||||
|
buf, link_info->resp_sta_profile_len);
|
||||||
|
if (!link_info->resp_sta_profile)
|
||||||
|
link_info->resp_sta_profile_len = 0;
|
||||||
os_memcpy(link_info->local_addr, link->own_addr, ETH_ALEN);
|
os_memcpy(link_info->local_addr, link->own_addr, ETH_ALEN);
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
|
@ -1026,7 +1043,7 @@ static void hostapd_fill_probe_resp_ml_params(struct hostapd_data *hapd,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
os_free(params->mld_info);
|
hostapd_free_probe_resp_params(params);
|
||||||
params->mld_ap = NULL;
|
params->mld_ap = NULL;
|
||||||
params->mld_info = NULL;
|
params->mld_info = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1584,7 +1601,7 @@ void handle_probe_req(struct hostapd_data *hapd,
|
||||||
|
|
||||||
hostapd_gen_probe_resp(hapd, ¶ms);
|
hostapd_gen_probe_resp(hapd, ¶ms);
|
||||||
|
|
||||||
os_free(params.mld_info);
|
hostapd_free_probe_resp_params(¶ms);
|
||||||
|
|
||||||
if (!params.resp)
|
if (!params.resp)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -3078,6 +3078,7 @@ static void handle_auth(struct hostapd_data *hapd,
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
if (auth_transaction == 1) {
|
if (auth_transaction == 1) {
|
||||||
|
ap_sta_free_sta_profile(&sta->mld_info);
|
||||||
os_memset(&sta->mld_info, 0, sizeof(sta->mld_info));
|
os_memset(&sta->mld_info, 0, sizeof(sta->mld_info));
|
||||||
|
|
||||||
if (mld_sta) {
|
if (mld_sta) {
|
||||||
|
@ -4319,22 +4320,23 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
|
||||||
static size_t ieee80211_ml_build_assoc_resp(struct hostapd_data *hapd,
|
static void ieee80211_ml_build_assoc_resp(struct hostapd_data *hapd,
|
||||||
u16 status_code,
|
struct mld_link_info *link)
|
||||||
u8 *buf, size_t buflen)
|
|
||||||
{
|
{
|
||||||
|
u8 buf[EHT_ML_MAX_STA_PROF_LEN];
|
||||||
u8 *p = buf;
|
u8 *p = buf;
|
||||||
|
size_t buflen = sizeof(buf);
|
||||||
|
|
||||||
/* Capability Info */
|
/* Capability Info */
|
||||||
WPA_PUT_LE16(p, hostapd_own_capab_info(hapd));
|
WPA_PUT_LE16(p, hostapd_own_capab_info(hapd));
|
||||||
p += 2;
|
p += 2;
|
||||||
|
|
||||||
/* Status Code */
|
/* Status Code */
|
||||||
WPA_PUT_LE16(p, status_code);
|
WPA_PUT_LE16(p, link->status);
|
||||||
p += 2;
|
p += 2;
|
||||||
|
|
||||||
if (status_code != WLAN_STATUS_SUCCESS)
|
if (link->status != WLAN_STATUS_SUCCESS)
|
||||||
return p - buf;
|
goto out;
|
||||||
|
|
||||||
/* AID is not included */
|
/* AID is not included */
|
||||||
p = hostapd_eid_supp_rates(hapd, p);
|
p = hostapd_eid_supp_rates(hapd, p);
|
||||||
|
@ -4372,7 +4374,10 @@ static size_t ieee80211_ml_build_assoc_resp(struct hostapd_data *hapd,
|
||||||
p += wpabuf_len(hapd->conf->assocresp_elements);
|
p += wpabuf_len(hapd->conf->assocresp_elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
return p - buf;
|
out:
|
||||||
|
os_free(link->resp_sta_profile);
|
||||||
|
link->resp_sta_profile = os_memdup(buf, p - buf);
|
||||||
|
link->resp_sta_profile_len = link->resp_sta_profile ? p - buf : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4386,6 +4391,7 @@ static void ieee80211_ml_process_link(struct hostapd_data *hapd,
|
||||||
struct wpabuf *mlbuf = NULL;
|
struct wpabuf *mlbuf = NULL;
|
||||||
struct sta_info *sta = NULL;
|
struct sta_info *sta = NULL;
|
||||||
u16 status = WLAN_STATUS_SUCCESS;
|
u16 status = WLAN_STATUS_SUCCESS;
|
||||||
|
int i;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "MLD: link: link_id=%u, peer=" MACSTR,
|
wpa_printf(MSG_DEBUG, "MLD: link: link_id=%u, peer=" MACSTR,
|
||||||
hapd->mld_link_id, MAC2STR(link->peer_addr));
|
hapd->mld_link_id, MAC2STR(link->peer_addr));
|
||||||
|
@ -4435,6 +4441,12 @@ static void ieee80211_ml_process_link(struct hostapd_data *hapd,
|
||||||
sta->mld_assoc_link_id = origin_sta->mld_assoc_link_id;
|
sta->mld_assoc_link_id = origin_sta->mld_assoc_link_id;
|
||||||
|
|
||||||
os_memcpy(&sta->mld_info, &origin_sta->mld_info, sizeof(sta->mld_info));
|
os_memcpy(&sta->mld_info, &origin_sta->mld_info, sizeof(sta->mld_info));
|
||||||
|
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
|
||||||
|
struct mld_link_info *li = &sta->mld_info.links[i];
|
||||||
|
|
||||||
|
li->resp_sta_profile = NULL;
|
||||||
|
li->resp_sta_profile_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the AID from the station on which the association was performed,
|
* Get the AID from the station on which the association was performed,
|
||||||
|
@ -4485,10 +4497,7 @@ out:
|
||||||
if (sta && status != WLAN_STATUS_SUCCESS)
|
if (sta && status != WLAN_STATUS_SUCCESS)
|
||||||
ap_free_sta(hapd, sta);
|
ap_free_sta(hapd, sta);
|
||||||
|
|
||||||
link->resp_sta_profile_len =
|
ieee80211_ml_build_assoc_resp(hapd, link);
|
||||||
ieee80211_ml_build_assoc_resp(hapd, link->status,
|
|
||||||
link->resp_sta_profile,
|
|
||||||
sizeof(link->resp_sta_profile));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4552,19 +4561,11 @@ static void hostapd_process_assoc_ml_info(struct hostapd_data *hapd,
|
||||||
"MLD: No link match for link_id=%u", i);
|
"MLD: No link match for link_id=%u", i);
|
||||||
|
|
||||||
link->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
link->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||||
link->resp_sta_profile_len =
|
ieee80211_ml_build_assoc_resp(hapd, link);
|
||||||
ieee80211_ml_build_assoc_resp(
|
|
||||||
hapd, link->status,
|
|
||||||
link->resp_sta_profile,
|
|
||||||
sizeof(link->resp_sta_profile));
|
|
||||||
} else if (tx_link_status != WLAN_STATUS_SUCCESS) {
|
} else if (tx_link_status != WLAN_STATUS_SUCCESS) {
|
||||||
/* TX link rejected the connection */
|
/* TX link rejected the connection */
|
||||||
link->status = WLAN_STATUS_DENIED_TX_LINK_NOT_ACCEPTED;
|
link->status = WLAN_STATUS_DENIED_TX_LINK_NOT_ACCEPTED;
|
||||||
link->resp_sta_profile_len =
|
ieee80211_ml_build_assoc_resp(hapd, link);
|
||||||
ieee80211_ml_build_assoc_resp(
|
|
||||||
hapd, link->status,
|
|
||||||
link->resp_sta_profile,
|
|
||||||
sizeof(link->resp_sta_profile));
|
|
||||||
} else {
|
} else {
|
||||||
ieee80211_ml_process_link(iface->bss[0], sta, link,
|
ieee80211_ml_process_link(iface->bss[0], sta, link,
|
||||||
ies, ies_len, reassoc);
|
ies, ies_len, reassoc);
|
||||||
|
|
|
@ -583,6 +583,9 @@ static u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
|
||||||
/* BSS Parameters Change Count */
|
/* BSS Parameters Change Count */
|
||||||
wpabuf_put_u8(buf, hapd->eht_mld_bss_param_change);
|
wpabuf_put_u8(buf, hapd->eht_mld_bss_param_change);
|
||||||
|
|
||||||
|
if (!link->resp_sta_profile)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* Fragment the sub element if needed */
|
/* Fragment the sub element if needed */
|
||||||
if (total_len <= 255) {
|
if (total_len <= 255) {
|
||||||
wpabuf_put_data(buf, link->resp_sta_profile,
|
wpabuf_put_data(buf, link->resp_sta_profile,
|
||||||
|
@ -784,6 +787,7 @@ u8 * hostapd_eid_eht_ml_assoc(struct hostapd_data *hapd, struct sta_info *info,
|
||||||
|
|
||||||
eid = hostapd_eid_eht_basic_ml_common(hapd, eid, &info->mld_info,
|
eid = hostapd_eid_eht_basic_ml_common(hapd, eid, &info->mld_info,
|
||||||
false);
|
false);
|
||||||
|
ap_sta_free_sta_profile(&info->mld_info);
|
||||||
return hostapd_eid_eht_reconf_ml(hapd, eid);
|
return hostapd_eid_eht_reconf_ml(hapd, eid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -350,6 +350,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||||
#ifdef CONFIG_INTERWORKING
|
#ifdef CONFIG_INTERWORKING
|
||||||
if (sta->gas_dialog) {
|
if (sta->gas_dialog) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < GAS_DIALOG_MAX; i++)
|
for (i = 0; i < GAS_DIALOG_MAX; i++)
|
||||||
gas_serv_dialog_clear(&sta->gas_dialog[i]);
|
gas_serv_dialog_clear(&sta->gas_dialog[i]);
|
||||||
os_free(sta->gas_dialog);
|
os_free(sta->gas_dialog);
|
||||||
|
@ -420,6 +421,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||||
|
|
||||||
os_free(sta->ifname_wds);
|
os_free(sta->ifname_wds);
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
ap_sta_free_sta_profile(&sta->mld_info);
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
os_free(sta->sae_postponed_commit);
|
os_free(sta->sae_postponed_commit);
|
||||||
forced_memzero(sta->last_tk, WPA_TK_MAX_LEN);
|
forced_memzero(sta->last_tk, WPA_TK_MAX_LEN);
|
||||||
|
@ -1791,3 +1796,19 @@ int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta)
|
||||||
sta->added_unassoc = 1;
|
sta->added_unassoc = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_IEEE80211BE
|
||||||
|
void ap_sta_free_sta_profile(struct mld_info *info)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
|
||||||
|
os_free(info->links[i].resp_sta_profile);
|
||||||
|
info->links[i].resp_sta_profile = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
|
@ -93,7 +93,7 @@ struct mld_info {
|
||||||
|
|
||||||
u16 status;
|
u16 status;
|
||||||
size_t resp_sta_profile_len;
|
size_t resp_sta_profile_len;
|
||||||
u8 resp_sta_profile[EHT_ML_MAX_STA_PROF_LEN];
|
u8 *resp_sta_profile;
|
||||||
|
|
||||||
const u8 *rsne, *rsnxe;
|
const u8 *rsne, *rsnxe;
|
||||||
} links[MAX_NUM_MLD_LINKS];
|
} links[MAX_NUM_MLD_LINKS];
|
||||||
|
@ -438,4 +438,6 @@ static inline void ap_sta_set_mld(struct sta_info *sta, bool mld)
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ap_sta_free_sta_profile(struct mld_info *info);
|
||||||
|
|
||||||
#endif /* STA_INFO_H */
|
#endif /* STA_INFO_H */
|
||||||
|
|
Loading…
Reference in a new issue