]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP MLD: Reduce struct mld_link_info size
authorJouni Malinen <j@w1.fi>
Sun, 21 Jan 2024 19:06:18 +0000 (21:06 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 21 Jan 2024 19:59:11 +0000 (21:59 +0200)
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>
src/ap/beacon.c
src/ap/ieee802_11.c
src/ap/ieee802_11_eht.c
src/ap/sta_info.c
src/ap/sta_info.h

index 9b08f65a783bad6eb7f32e522aa7cc24e4b7ba65..e6a989d07f8adaf363a84414e3076183125512a6 100644 (file)
@@ -617,6 +617,19 @@ struct probe_resp_params {
 #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,
                                           struct probe_resp_params *params)
 {
@@ -955,6 +968,7 @@ static void hostapd_fill_probe_resp_ml_params(struct hostapd_data *hapd,
                size_t buflen;
                u8 mld_link_id = link->mld_link_id;
                u8 *epos;
+               u8 buf[EHT_ML_MAX_STA_PROF_LEN];
 
                /*
                 * 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 += 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,
                                   "MLD: Not including link %d in ML probe response (%zu bytes is too long)",
                                   mld_link_id, buflen);
@@ -996,18 +1010,21 @@ static void hostapd_fill_probe_resp_ml_params(struct hostapd_data *hapd,
                 * various other things.
                 */
                link_info->valid = true;
-               epos = link_info->resp_sta_profile;
+               epos = buf;
 
                /* Capabilities is the only fixed parameter */
-               WPA_PUT_LE16(link_info->resp_sta_profile,
-                            hostapd_own_capab_info(hapd));
+               WPA_PUT_LE16(epos, hostapd_own_capab_info(hapd));
+               epos += 2;
 
                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;
+                       link, &sta_info_params, epos,
+                       EHT_ML_MAX_STA_PROF_LEN - 2);
+               link_info->resp_sta_profile_len = epos - buf;
+               os_free(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);
 
                wpa_printf(MSG_DEBUG,
@@ -1026,7 +1043,7 @@ static void hostapd_fill_probe_resp_ml_params(struct hostapd_data *hapd,
        return;
 
 fail:
-       os_free(params->mld_info);
+       hostapd_free_probe_resp_params(params);
        params->mld_ap = NULL;
        params->mld_info = NULL;
 }
@@ -1584,7 +1601,7 @@ void handle_probe_req(struct hostapd_data *hapd,
 
        hostapd_gen_probe_resp(hapd, &params);
 
-       os_free(params.mld_info);
+       hostapd_free_probe_resp_params(&params);
 
        if (!params.resp)
                return;
index 114a01eb14eeabede2dbedef79108d67979e476b..88906a61ee6c5c2d4b3eddf7b51f6ba7ad5083cf 100644 (file)
@@ -3078,6 +3078,7 @@ static void handle_auth(struct hostapd_data *hapd,
 
 #ifdef CONFIG_IEEE80211BE
        if (auth_transaction == 1) {
+               ap_sta_free_sta_profile(&sta->mld_info);
                os_memset(&sta->mld_info, 0, sizeof(sta->mld_info));
 
                if (mld_sta) {
@@ -4319,22 +4320,23 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
 
 #ifdef CONFIG_IEEE80211BE
 
-static size_t ieee80211_ml_build_assoc_resp(struct hostapd_data *hapd,
-                                           u16 status_code,
-                                           u8 *buf, size_t buflen)
+static void ieee80211_ml_build_assoc_resp(struct hostapd_data *hapd,
+                                         struct mld_link_info *link)
 {
+       u8 buf[EHT_ML_MAX_STA_PROF_LEN];
        u8 *p = buf;
+       size_t buflen = sizeof(buf);
 
        /* Capability Info */
        WPA_PUT_LE16(p, hostapd_own_capab_info(hapd));
        p += 2;
 
        /* Status Code */
-       WPA_PUT_LE16(p, status_code);
+       WPA_PUT_LE16(p, link->status);
        p += 2;
 
-       if (status_code != WLAN_STATUS_SUCCESS)
-               return p - buf;
+       if (link->status != WLAN_STATUS_SUCCESS)
+               goto out;
 
        /* AID is not included */
        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);
        }
 
-       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 sta_info *sta = NULL;
        u16 status = WLAN_STATUS_SUCCESS;
+       int i;
 
        wpa_printf(MSG_DEBUG, "MLD: link: link_id=%u, peer=" MACSTR,
                   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;
 
        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,
@@ -4485,10 +4497,7 @@ out:
        if (sta && status != WLAN_STATUS_SUCCESS)
                ap_free_sta(hapd, sta);
 
-       link->resp_sta_profile_len =
-               ieee80211_ml_build_assoc_resp(hapd, link->status,
-                                             link->resp_sta_profile,
-                                             sizeof(link->resp_sta_profile));
+       ieee80211_ml_build_assoc_resp(hapd, link);
 }
 
 
@@ -4552,19 +4561,11 @@ static void hostapd_process_assoc_ml_info(struct hostapd_data *hapd,
                                   "MLD: No link match for link_id=%u", i);
 
                        link->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
-                       link->resp_sta_profile_len =
-                               ieee80211_ml_build_assoc_resp(
-                                       hapd, link->status,
-                                       link->resp_sta_profile,
-                                       sizeof(link->resp_sta_profile));
+                       ieee80211_ml_build_assoc_resp(hapd, link);
                } else if (tx_link_status != WLAN_STATUS_SUCCESS) {
                        /* TX link rejected the connection */
                        link->status = WLAN_STATUS_DENIED_TX_LINK_NOT_ACCEPTED;
-                       link->resp_sta_profile_len =
-                               ieee80211_ml_build_assoc_resp(
-                                       hapd, link->status,
-                                       link->resp_sta_profile,
-                                       sizeof(link->resp_sta_profile));
+                       ieee80211_ml_build_assoc_resp(hapd, link);
                } else {
                        ieee80211_ml_process_link(iface->bss[0], sta, link,
                                                  ies, ies_len, reassoc);
index 8dbf66a9caa58a67b2a2eade8cd3709039724397..c703017af907cd83fd8210ca9b694c84a11272d1 100644 (file)
@@ -583,6 +583,9 @@ static u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
                /* BSS Parameters Change Count */
                wpabuf_put_u8(buf, hapd->eht_mld_bss_param_change);
 
+               if (!link->resp_sta_profile)
+                       continue;
+
                /* Fragment the sub element if needed */
                if (total_len <= 255) {
                        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,
                                              false);
+       ap_sta_free_sta_profile(&info->mld_info);
        return hostapd_eid_eht_reconf_ml(hapd, eid);
 }
 
index 3003b201d65e9d971c37ec4992de4ae56c0bd3fe..042a5a28622c57ba4f60010493359f1024921caf 100644 (file)
@@ -350,6 +350,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
 #ifdef CONFIG_INTERWORKING
        if (sta->gas_dialog) {
                int i;
+
                for (i = 0; i < GAS_DIALOG_MAX; i++)
                        gas_serv_dialog_clear(&sta->gas_dialog[i]);
                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);
 
+#ifdef CONFIG_IEEE80211BE
+       ap_sta_free_sta_profile(&sta->mld_info);
+#endif /* CONFIG_IEEE80211BE */
+
 #ifdef CONFIG_TESTING_OPTIONS
        os_free(sta->sae_postponed_commit);
        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;
        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 */
index d2ff03b3f743e6591e8cfc058eb203a977787e47..f459f6278c2b10e839a9638575d7a53322cc4b84 100644 (file)
@@ -93,7 +93,7 @@ struct mld_info {
 
                u16 status;
                size_t resp_sta_profile_len;
-               u8 resp_sta_profile[EHT_ML_MAX_STA_PROF_LEN];
+               u8 *resp_sta_profile;
 
                const u8 *rsne, *rsnxe;
        } 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 */
 }
 
+void ap_sta_free_sta_profile(struct mld_info *info);
+
 #endif /* STA_INFO_H */