return -1;
}
+#ifdef CONFIG_IEEE80211BE
+ for (i = 0; conf->mld_ap && i < iface->interfaces->count; i++) {
+ struct hostapd_iface *h = iface->interfaces->iface[i];
+ struct hostapd_data *h_hapd = h->bss[0];
+ struct hostapd_bss_config *hconf = h_hapd->conf;
+
+ if (h == iface) {
+ wpa_printf(MSG_DEBUG, "MLD: Skip own interface");
+ continue;
+ }
+
+ if (!hconf->mld_ap || hconf->mld_id != conf->mld_id) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: Skip non matching mld_id");
+ continue;
+ }
+
+ wpa_printf(MSG_DEBUG, "MLD: Found matching MLD interface");
+ if (!h_hapd->drv_priv) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: Matching MLD BSS not initialized yet");
+ continue;
+ }
+
+ hapd->drv_priv = h_hapd->drv_priv;
+
+ /*
+ * All interfaces participating in the AP MLD would have
+ * the same MLD address, which is the interface hardware
+ * address, while the interface address would be
+ * derived from the original interface address if BSSID
+ * is not configured, and otherwise it would be the
+ * configured BSSID.
+ */
+ os_memcpy(hapd->mld_addr, h_hapd->mld_addr, ETH_ALEN);
+ if (is_zero_ether_addr(b)) {
+ os_memcpy(hapd->own_addr, h_hapd->mld_addr, ETH_ALEN);
+ random_mac_addr_keep_oui(hapd->own_addr);
+ } else {
+ os_memcpy(hapd->own_addr, b, ETH_ALEN);
+ }
+
+ /*
+ * Mark the interface as a secondary interface, as this
+ * is needed for the de-initialization flow
+ */
+ hapd->mld_first_bss = h_hapd;
+ hapd->mld_link_id = hapd->mld_first_bss->mld_next_link_id++;
+
+ goto setup_mld;
+ }
+#endif /* CONFIG_IEEE80211BE */
+
/* Initialize the driver interface */
if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5]))
b = NULL;
return -1;
}
+#ifdef CONFIG_IEEE80211BE
+ /*
+ * This is the first interface added to the AP MLD, so have the
+ * interface hardware address be the MLD address and set a link address
+ * to this interface.
+ */
+ if (hapd->conf->mld_ap) {
+ os_memcpy(hapd->mld_addr, hapd->own_addr, ETH_ALEN);
+ random_mac_addr_keep_oui(hapd->own_addr);
+ hapd->mld_next_link_id = 0;
+ hapd->mld_link_id = hapd->mld_next_link_id++;
+ }
+
+setup_mld:
+#endif /* CONFIG_IEEE80211BE */
+
if (hapd->driver->get_capa &&
hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
struct wowlan_triggers *triggs;
iface->ema_max_periodicity = capa.ema_max_periodicity;
}
+#ifdef CONFIG_IEEE80211BE
+ if (hapd->conf->mld_ap) {
+ if (!(iface->drv_flags2 & WPA_DRIVER_FLAGS2_MLO)) {
+ wpa_printf(MSG_INFO,
+ "MLD: Not supported by the driver");
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG,
+ "MLD: Set link_id=%u, mld_addr=" MACSTR
+ ", own_addr=" MACSTR,
+ hapd->mld_link_id, MAC2STR(hapd->mld_addr),
+ MAC2STR(hapd->own_addr));
+
+ hostapd_drv_link_add(hapd, hapd->mld_link_id,
+ hapd->own_addr);
+ }
+#endif /* CONFIG_IEEE80211BE */
+
return 0;
}
#endif /* CONFIG_WEP */
+static void hostapd_clear_drv_priv(struct hostapd_data *hapd)
+{
+ unsigned int i;
+
+ for (i = 0; i < hapd->iface->interfaces->count; i++) {
+ struct hostapd_iface *iface = hapd->iface->interfaces->iface[i];
+
+ if (hapd->iface == iface)
+ continue;
+
+ if (iface->bss && iface->bss[0] &&
+ iface->bss[0]->mld_first_bss == hapd)
+ iface->bss[0]->drv_priv = NULL;
+ }
+
+ hapd->drv_priv = NULL;
+}
+
+
void hostapd_free_hapd_data(struct hostapd_data *hapd)
{
os_free(hapd->probereq_cb);
* driver wrapper may have removed its internal instance
* and hapd->drv_priv is not valid anymore.
*/
- hapd->drv_priv = NULL;
+ hostapd_clear_drv_priv(hapd);
}
}
wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
__func__, driver, drv_priv);
if (driver && driver->hapd_deinit && drv_priv) {
- driver->hapd_deinit(drv_priv);
- iface->bss[0]->drv_priv = NULL;
+ if (!iface->bss[0]->mld_first_bss)
+ driver->hapd_deinit(drv_priv);
+ hostapd_clear_drv_priv(iface->bss[0]);
}
hostapd_interface_free(iface);
}
wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
__func__, driver, drv_priv);
if (driver && driver->hapd_deinit && drv_priv) {
- driver->hapd_deinit(drv_priv);
+ if (!hapd_iface->bss[0]->mld_first_bss)
+ driver->hapd_deinit(drv_priv);
for (j = 0; j < hapd_iface->num_bss; j++) {
wpa_printf(MSG_DEBUG, "%s:bss[%d]->drv_priv=%p",
__func__, (int) j,
hapd_iface->bss[j]->drv_priv);
if (hapd_iface->bss[j]->drv_priv == drv_priv) {
- hapd_iface->bss[j]->drv_priv = NULL;
+ hostapd_clear_drv_priv(hapd_iface->bss[j]);
hapd_iface->extended_capa = NULL;
hapd_iface->extended_capa_mask = NULL;
hapd_iface->extended_capa_len = 0;
conf_file = ptr + 7;
for (i = 0; i < interfaces->count; i++) {
+ bool mld_ap = false;
+
+#ifdef CONFIG_IEEE80211BE
+ mld_ap = interfaces->iface[i]->conf->bss[0]->mld_ap;
+#endif /* CONFIG_IEEE80211BE */
+
if (!os_strcmp(interfaces->iface[i]->conf->bss[0]->iface,
- buf)) {
+ buf) && !mld_ap) {
wpa_printf(MSG_INFO, "Cannot add interface - it "
"already exists");
return -1;