]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP MLD: Add a separate MLD level structure
authorAditya Kumar Singh <quic_adisi@quicinc.com>
Wed, 6 Mar 2024 06:37:13 +0000 (12:07 +0530)
committerJouni Malinen <j@w1.fi>
Wed, 27 Mar 2024 09:15:10 +0000 (11:15 +0200)
MLD level information like MLD MAC address, next link ID, etc. was
stored in each BSS. However, only the first link BSS assigns values to
these members and the other link BSSs store references to the first BSS.
However, if the first BSS is disabled, the first BSS reference in all
BSS should be updated which is an overhead. Also, this does not seem to
scale.

Instead, a separate MLD level structure can be maintained which can
store all this ML related information. All affiliated link BSSs can keep
reference to this MLD structure.

This commit adds that MLD level structure. However, assigning values to
it and using that instead of BSS level members will be done in
subsequent commits.

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
hostapd/main.c
src/ap/hostapd.c
src/ap/hostapd.h

index ec3d112fcf73337068bd30d1bcb6d22b5e4b8b9d..602c3c0826e5bab27d06513c63f6f687a6c6f6d8 100644 (file)
@@ -755,6 +755,29 @@ static void hostapd_periodic(void *eloop_ctx, void *timeout_ctx)
 }
 
 
+static void hostapd_global_cleanup_mld(struct hapd_interfaces *interfaces)
+{
+#ifdef CONFIG_IEEE80211BE
+       size_t i;
+
+       if (!interfaces || !interfaces->mld)
+               return;
+
+       for (i = 0; i < interfaces->mld_count; i++) {
+               if (!interfaces->mld[i])
+                       continue;
+
+               os_free(interfaces->mld[i]);
+               interfaces->mld[i] = NULL;
+       }
+
+       os_free(interfaces->mld);
+       interfaces->mld = NULL;
+       interfaces->mld_count = 0;
+#endif /* CONFIG_IEEE80211BE */
+}
+
+
 int main(int argc, char *argv[])
 {
        struct hapd_interfaces interfaces;
@@ -1035,6 +1058,8 @@ int main(int argc, char *argv[])
        interfaces.iface = NULL;
        interfaces.count = 0;
 
+       hostapd_global_cleanup_mld(&interfaces);
+
 #ifdef CONFIG_DPP
        dpp_global_deinit(interfaces.dpp);
 #endif /* CONFIG_DPP */
index aaabd46445bae4c22e6e6f05b966c558338aeaf2..bf3335a6a6be88169aab4c0a11cc17871f89741d 100644 (file)
@@ -2866,6 +2866,65 @@ struct hostapd_iface * hostapd_alloc_iface(void)
 }
 
 
+static void hostapd_bss_setup_multi_link(struct hostapd_data *hapd,
+                                        struct hapd_interfaces *interfaces)
+{
+#ifdef CONFIG_IEEE80211BE
+       struct hostapd_mld *mld, **all_mld;
+       struct hostapd_bss_config *conf;
+       size_t i;
+
+       conf = hapd->conf;
+
+       if (!hapd->iconf || !hapd->iconf->ieee80211be || !conf->mld_ap ||
+           conf->disable_11be)
+               return;
+
+       for (i = 0; i < interfaces->mld_count; i++) {
+               mld = interfaces->mld[i];
+
+               if (!mld || os_strcmp(conf->iface, mld->name) != 0)
+                       continue;
+
+               hapd->mld = mld;
+               break;
+       }
+
+       if (hapd->mld)
+               return;
+
+       mld = os_zalloc(sizeof(struct hostapd_mld));
+       if (!mld)
+               goto fail;
+
+       os_strlcpy(mld->name, conf->iface, sizeof(conf->iface));
+       dl_list_init(&mld->links);
+
+       wpa_printf(MSG_DEBUG, "AP MLD %s created", mld->name);
+
+       hapd->mld = mld;
+
+       all_mld = os_realloc_array(interfaces->mld, interfaces->mld_count + 1,
+                                  sizeof(struct hostapd_mld *));
+       if (!all_mld)
+               goto fail;
+
+       interfaces->mld = all_mld;
+       interfaces->mld[interfaces->mld_count] = mld;
+       interfaces->mld_count++;
+
+       return;
+fail:
+       if (!mld)
+               return;
+
+       wpa_printf(MSG_DEBUG, "AP MLD %s: free mld %p", mld->name, mld);
+       os_free(mld);
+       hapd->mld = NULL;
+#endif /* CONFIG_IEEE80211BE */
+}
+
+
 /**
  * hostapd_init - Allocate and initialize per-interface data
  * @config_file: Path to the configuration file
@@ -2909,6 +2968,7 @@ struct hostapd_iface * hostapd_init(struct hapd_interfaces *interfaces,
                if (hapd == NULL)
                        goto fail;
                hapd->msg_ctx = hapd;
+               hostapd_bss_setup_multi_link(hapd, interfaces);
        }
 
        return hapd_iface;
@@ -3030,6 +3090,8 @@ hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
                iface->conf->last_bss = bss;
                iface->bss[iface->num_bss] = hapd;
                hapd->msg_ctx = hapd;
+               hostapd_bss_setup_multi_link(hapd, interfaces);
+
 
                bss_idx = iface->num_bss++;
                conf->num_bss--;
@@ -3370,6 +3432,7 @@ static int hostapd_data_alloc(struct hostapd_iface *hapd_iface,
                        return -1;
                }
                hapd->msg_ctx = hapd;
+               hostapd_bss_setup_multi_link(hapd, hapd_iface->interfaces);
        }
 
        hapd_iface->conf = conf;
@@ -4446,6 +4509,104 @@ u8 hostapd_get_mld_id(struct hostapd_data *hapd)
        /* TODO: MLD ID for Multiple BSS cases */
 }
 
+
+int hostapd_mld_add_link(struct hostapd_data *hapd)
+{
+       struct hostapd_mld *mld = hapd->mld;
+
+       if (!hapd->conf->mld_ap)
+               return 0;
+
+       /* Should not happen */
+       if (!mld)
+               return -1;
+
+       dl_list_add_tail(&mld->links, &hapd->link);
+       mld->num_links++;
+
+       wpa_printf(MSG_DEBUG, "AP MLD %s: Link ID %d added. num_links: %d",
+                  mld->name, hapd->mld_link_id, mld->num_links);
+
+       if (mld->fbss)
+               return 0;
+
+       mld->fbss = hapd;
+       wpa_printf(MSG_DEBUG, "AP MLD %s: First link BSS set to %p",
+                  mld->name, mld->fbss);
+       return 0;
+}
+
+
+int hostapd_mld_remove_link(struct hostapd_data *hapd)
+{
+       struct hostapd_mld *mld = hapd->mld;
+       struct hostapd_data *next_fbss;
+
+       if (!hapd->conf->mld_ap)
+               return 0;
+
+       /* Should not happen */
+       if (!mld)
+               return -1;
+
+       dl_list_del(&hapd->link);
+       mld->num_links--;
+
+       wpa_printf(MSG_DEBUG, "AP MLD %s: Link ID %d removed. num_links: %d",
+                  mld->name, hapd->mld_link_id, mld->num_links);
+
+       if (mld->fbss != hapd)
+               return 0;
+
+       /* If the list is empty, all links are removed */
+       if (dl_list_empty(&mld->links)) {
+               mld->fbss = NULL;
+       } else {
+               next_fbss = dl_list_entry(mld->links.next, struct hostapd_data,
+                                         link);
+               mld->fbss = next_fbss;
+       }
+
+       wpa_printf(MSG_DEBUG, "AP MLD %s: First link BSS set to %p",
+                  mld->name, mld->fbss);
+       return 0;
+}
+
+
+bool hostapd_mld_is_first_bss(struct hostapd_data *hapd)
+{
+       struct hostapd_mld *mld = hapd->mld;
+
+       if (!hapd->conf->mld_ap)
+               return true;
+
+       /* Should not happen */
+       if (!mld)
+               return false;
+
+       /* If fbss is not set, it is safe to assume the caller is the first BSS.
+        */
+       if (!mld->fbss)
+               return true;
+
+       return hapd == mld->fbss;
+}
+
+
+struct hostapd_data * hostapd_mld_get_first_bss(struct hostapd_data *hapd)
+{
+       struct hostapd_mld *mld = hapd->mld;
+
+       if (!hapd->conf->mld_ap)
+               return NULL;
+
+       /* Should not happen */
+       if (!mld)
+               return NULL;
+
+       return mld->fbss;
+}
+
 #endif /* CONFIG_IEEE80211BE */
 
 
index b3249a0b09133beba21675a87cae1fd9bdff3125..a5f1e5df2f358e85dca1f91f440dac282aedc379 100644 (file)
@@ -44,6 +44,7 @@ struct mesh_conf;
 #endif /* CONFIG_CTRL_IFACE_UDP */
 
 struct hostapd_iface;
+struct hostapd_mld;
 
 struct hapd_interfaces {
        int (*reload_config)(struct hostapd_iface *iface);
@@ -93,6 +94,10 @@ struct hapd_interfaces {
        unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN];
 #endif /* CONFIG_CTRL_IFACE_UDP */
 
+#ifdef CONFIG_IEEE80211BE
+       struct hostapd_mld **mld;
+       size_t mld_count;
+#endif /* CONFIG_IEEE80211BE */
 };
 
 enum hostapd_chan_status {
@@ -472,6 +477,8 @@ struct hostapd_data {
 
 #ifdef CONFIG_IEEE80211BE
        u8 eht_mld_bss_param_change;
+       struct hostapd_mld *mld;
+       struct dl_list link;
 #ifdef CONFIG_TESTING_OPTIONS
        u8 eht_mld_link_removal_count;
 #endif /* CONFIG_TESTING_OPTIONS */
@@ -493,6 +500,21 @@ struct hostapd_sta_info {
 #endif /* CONFIG_TAXONOMY */
 };
 
+#ifdef CONFIG_IEEE80211BE
+/**
+ * struct hostapd_mld - hostapd per-mld data structure
+ */
+struct hostapd_mld {
+       char name[IFNAMSIZ + 1];
+       u8 mld_addr[ETH_ALEN];
+       u8 next_link_id;
+       u8 num_links;
+
+       struct hostapd_data *fbss;
+       struct dl_list links; /* List head of all affiliated links */
+};
+#endif /* CONFIG_IEEE80211BE */
+
 /**
  * struct hostapd_iface - hostapd per-interface data structure
  */
@@ -784,8 +806,14 @@ int hostapd_link_remove(struct hostapd_data *hapd, u32 count);
 bool hostapd_is_ml_partner(struct hostapd_data *hapd1,
                           struct hostapd_data *hapd2);
 u8 hostapd_get_mld_id(struct hostapd_data *hapd);
+int hostapd_mld_add_link(struct hostapd_data *hapd);
+int hostapd_mld_remove_link(struct hostapd_data *hapd);
+struct hostapd_data * hostapd_mld_get_first_bss(struct hostapd_data *hapd);
 
 #ifdef CONFIG_IEEE80211BE
+
+bool hostapd_mld_is_first_bss(struct hostapd_data *hapd);
+
 #define for_each_mld_link(_link, _bss_idx, _iface_idx, _ifaces, _mld_id) \
        for (_iface_idx = 0;                                            \
             _iface_idx < (_ifaces)->count;                             \
@@ -799,9 +827,17 @@ u8 hostapd_get_mld_id(struct hostapd_data *hapd);
                            _link && _link->conf->mld_ap &&             \
                                hostapd_get_mld_id(_link) == _mld_id;   \
                            _link = NULL)
+
 #else /* CONFIG_IEEE80211BE */
+
+static inline bool hostapd_mld_is_first_bss(struct hostapd_data *hapd)
+{
+       return true;
+}
+
 #define for_each_mld_link(_link, _bss_idx, _iface_idx, _ifaces, _mld_id) \
        if (false)
+
 #endif /* CONFIG_IEEE80211BE */
 
 u16 hostapd_get_punct_bitmap(struct hostapd_data *hapd);