mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-22 11:53:02 +00:00
Some checks failed
Build OpenWrt/uCentral images / build (cig_wf186h) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf186w) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf188n) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf189) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf196) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cybertan_eww631-a1) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cybertan_eww631-b1) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap101) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap102) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap104) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap105) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap111) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap112) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101-6e) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101e) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101e-6e) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x_2) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x_3) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x_w) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4xe) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4xi) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4xi_w) (push) Has been cancelled
Build OpenWrt/uCentral images / build (indio_um-305ax) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sercomm_ap72tip) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sonicfi_rap630c-311g) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sonicfi_rap630w-211g) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sonicfi_rap630w-311g) (push) Has been cancelled
Build OpenWrt/uCentral images / build (udaya_a6-id2) (push) Has been cancelled
Build OpenWrt/uCentral images / build (udaya_a6-od2) (push) Has been cancelled
Build OpenWrt/uCentral images / build (wallys_dr5018) (push) Has been cancelled
Build OpenWrt/uCentral images / build (wallys_dr6018) (push) Has been cancelled
Build OpenWrt/uCentral images / build (wallys_dr6018-v4) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_ax820) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_ax840) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_fap640) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_fap650) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_fap655) (push) Has been cancelled
Build OpenWrt/uCentral images / trigger-testing (push) Has been cancelled
Build OpenWrt/uCentral images / create-x64_vm-ami (push) Has been cancelled
Signed-off-by: John Crispin <john@phrozen.org>
505 lines
16 KiB
Diff
505 lines
16 KiB
Diff
From c3bd1ff2d9f67eb39c39b58bf3b3679d9a9a4894 Mon Sep 17 00:00:00 2001
|
|
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
|
|
Date: Wed, 18 Oct 2023 14:57:14 +0530
|
|
Subject: [PATCH 3/4] hostapd: de-initialize/disable link BSS properly
|
|
|
|
Currently, if first link BSS of an interface is getting de-initialized/
|
|
disabled, then whole MLD is brought down. All other links are made
|
|
to stop beaconing and links are removed. And if, non-first link BSS
|
|
is de-initialized/disabled, nothing happens. Even beaconing is not
|
|
stopped which is wrong.
|
|
|
|
Fix the above by properly bringing down the intended link alone from the
|
|
interface. If only 1 link was there, then the interface will be removed.
|
|
|
|
And if first link BSS is removed, make the next link as the the new first
|
|
link of the BSS. Accordingly, cache the bss->ctx and drv->ctx as well.
|
|
|
|
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
|
|
---
|
|
hostapd/main.c | 1 +
|
|
src/ap/ap_drv_ops.c | 17 +++++
|
|
src/ap/ap_drv_ops.h | 2 +
|
|
src/ap/hostapd.c | 128 ++++++++++++++++++++++++-----------
|
|
src/drivers/driver.h | 27 ++++++++
|
|
src/drivers/driver_nl80211.c | 84 +++++++++++++++++++++++
|
|
src/drivers/driver_nl80211.h | 1 +
|
|
7 files changed, 219 insertions(+), 41 deletions(-)
|
|
|
|
--- a/hostapd/main.c
|
|
+++ b/hostapd/main.c
|
|
@@ -181,6 +181,7 @@ static int hostapd_driver_init(struct ho
|
|
|
|
if (h_hapd) {
|
|
hapd->drv_priv = h_hapd->drv_priv;
|
|
+ hapd->interface_added = h_hapd->interface_added;
|
|
|
|
/*
|
|
* All interfaces participating in the AP MLD would have
|
|
--- a/src/ap/ap_drv_ops.c
|
|
+++ b/src/ap/ap_drv_ops.c
|
|
@@ -535,12 +535,29 @@ int hostapd_if_add(struct hostapd_data *
|
|
}
|
|
|
|
|
|
+int hostapd_if_link_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
|
+ const char *ifname, u8 link_id)
|
|
+{
|
|
+ if (hapd->driver == NULL || hapd->drv_priv == NULL ||
|
|
+ hapd->driver->if_link_remove == NULL)
|
|
+ return -1;
|
|
+
|
|
+ return hapd->driver->if_link_remove(hapd->drv_priv, type, ifname,
|
|
+ hapd->mld_link_id);
|
|
+}
|
|
+
|
|
int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
|
const char *ifname)
|
|
{
|
|
if (hapd->driver == NULL || hapd->drv_priv == NULL ||
|
|
hapd->driver->if_remove == NULL)
|
|
return -1;
|
|
+
|
|
+#ifdef CONFIG_IEEE80211BE
|
|
+ if (hapd->conf->mld_ap)
|
|
+ return hostapd_if_link_remove(hapd, type, ifname, hapd->mld_link_id);
|
|
+#endif /* CONFIG_IEEE80211BE */
|
|
+
|
|
return hapd->driver->if_remove(hapd->drv_priv, type, ifname);
|
|
}
|
|
|
|
--- a/src/ap/ap_drv_ops.h
|
|
+++ b/src/ap/ap_drv_ops.h
|
|
@@ -61,6 +61,8 @@ int hostapd_if_add(struct hostapd_data *
|
|
const char *bridge, int use_existing);
|
|
int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
|
const char *ifname);
|
|
+int hostapd_if_link_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
|
+ const char *ifname, u8 link_id);
|
|
int hostapd_set_ieee8021x(struct hostapd_data *hapd,
|
|
struct wpa_bss_params *params);
|
|
int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd,
|
|
--- a/src/ap/hostapd.c
|
|
+++ b/src/ap/hostapd.c
|
|
@@ -472,30 +472,6 @@ static int hostapd_broadcast_wep_set(str
|
|
|
|
#endif /* CONFIG_WEP */
|
|
|
|
-
|
|
-static void hostapd_clear_drv_priv(struct hostapd_data *hapd)
|
|
-{
|
|
-#ifdef CONFIG_IEEE80211BE
|
|
- unsigned int i, j;
|
|
-
|
|
- for (i = 0; i < hapd->iface->interfaces->count && hapd->conf->mld_ap; i++) {
|
|
- struct hostapd_iface *iface = hapd->iface->interfaces->iface[i];
|
|
-
|
|
- if (!iface || hapd->iface == iface)
|
|
- continue;
|
|
-
|
|
- for (j = 0; j < iface->num_bss; j++) {
|
|
- if (iface->bss && iface->bss[j] &&
|
|
- hostapd_mld_get_first_bss(iface->bss[j]) == hapd)
|
|
- iface->bss[j]->drv_priv = NULL;
|
|
- }
|
|
- }
|
|
-#endif /* CONFIG_IEEE80211BE */
|
|
-
|
|
- hapd->drv_priv = NULL;
|
|
-}
|
|
-
|
|
-
|
|
void hostapd_free_hapd_data(struct hostapd_data *hapd)
|
|
{
|
|
os_free(hapd->probereq_cb);
|
|
@@ -559,10 +535,22 @@ void hostapd_free_hapd_data(struct hosta
|
|
* driver wrapper may have removed its internal instance
|
|
* and hapd->drv_priv is not valid anymore.
|
|
*/
|
|
- hostapd_clear_drv_priv(hapd);
|
|
+ hapd->drv_priv = NULL;
|
|
}
|
|
}
|
|
|
|
+#ifdef CONFIG_IEEE80211BE
|
|
+ /* If interface was not added as well as it is not the first bss, then
|
|
+ * at least link should be removed here since deinit will take care only
|
|
+ * for the first bss.
|
|
+ */
|
|
+ if (hapd->conf->mld_ap && !hapd->interface_added &&
|
|
+ hapd->iface->bss[0] != hapd) {
|
|
+ hostapd_if_link_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface,
|
|
+ hapd->mld_link_id);
|
|
+ }
|
|
+#endif /* CONFIG_IEEE80211BE */
|
|
+
|
|
wpabuf_free(hapd->time_adv);
|
|
hapd->time_adv = NULL;
|
|
|
|
@@ -616,6 +604,39 @@ void hostapd_free_hapd_data(struct hosta
|
|
#endif /* CONFIG_IEEE80211AX */
|
|
}
|
|
|
|
+/* hostapd_bss_link_deinit - Per-BSS ML cleanup (deinitialization)
|
|
+ * @hapd: Pointer to BSS data
|
|
+ *
|
|
+ * This function is used to unlink the BSS from the MLD.
|
|
+ * If the BSS being removed is the first link, then the next link
|
|
+ * becomes the first BSS.
|
|
+ */
|
|
+static void hostapd_bss_link_deinit(struct hostapd_data *hapd)
|
|
+{
|
|
+#ifdef CONFIG_IEEE80211BE
|
|
+ if (!hapd->conf->mld_ap)
|
|
+ return;
|
|
+
|
|
+ /* if not started then not yet linked to the MLD. However, first BSS,
|
|
+ * is always linked since it is linked during driver_init(), hence
|
|
+ * need to remove it from MLD
|
|
+ */
|
|
+ if (!hapd->started && hapd->iface->bss[0] != hapd)
|
|
+ return;
|
|
+
|
|
+ /* first BSS can also be only linked when at least driver_init() is
|
|
+ * executd. But, if previous interface fails, then it will not, hence
|
|
+ * safe to skip
|
|
+ */
|
|
+ if (hapd->iface->bss[0] == hapd && !hapd->drv_priv)
|
|
+ return;
|
|
+
|
|
+ if (!hapd->mld->num_links)
|
|
+ return;
|
|
+
|
|
+ hostapd_mld_remove_link(hapd);
|
|
+#endif
|
|
+}
|
|
|
|
/**
|
|
* hostapd_cleanup - Per-BSS cleanup (deinitialization)
|
|
@@ -1361,6 +1382,7 @@ static int hostapd_setup_bss(struct host
|
|
|
|
if (h_hapd) {
|
|
hapd->drv_priv = h_hapd->drv_priv;
|
|
+ hapd->interface_added = h_hapd->interface_added;
|
|
hostapd_mld_add_link(hapd);
|
|
wpa_printf(MSG_DEBUG, "TSetup of non first link BSS(link id %d) of MLD %s",
|
|
hapd->mld_link_id, hapd->conf->iface);
|
|
@@ -1783,6 +1805,7 @@ static int start_ctrl_iface(struct hosta
|
|
static void hostapd_no_ir_cleanup(struct hostapd_data *bss)
|
|
{
|
|
hostapd_bss_deinit_no_free(bss);
|
|
+ hostapd_bss_link_deinit(bss);
|
|
hostapd_free_hapd_data(bss);
|
|
hostapd_cleanup_iface_partial(bss->iface);
|
|
}
|
|
@@ -2518,6 +2541,7 @@ static int hostapd_setup_interface_compl
|
|
for (;;) {
|
|
hapd = iface->bss[j];
|
|
hostapd_bss_deinit_no_free(hapd);
|
|
+ hostapd_bss_link_deinit(hapd);
|
|
hostapd_free_hapd_data(hapd);
|
|
if (j == 0)
|
|
break;
|
|
@@ -2536,6 +2560,7 @@ static int hostapd_setup_interface_compl
|
|
for (;;) {
|
|
hapd = iface->bss[j];
|
|
hostapd_bss_deinit_no_free(hapd);
|
|
+ hostapd_bss_link_deinit(hapd);
|
|
hostapd_free_hapd_data(hapd);
|
|
if (j == 0)
|
|
break;
|
|
@@ -2847,10 +2872,8 @@ static void hostapd_bss_deinit(struct ho
|
|
hapd->rad_attr_db = NULL;
|
|
}
|
|
#endif /* CONFIG_SQLITE */
|
|
-#ifdef CONFIG_IEEE80211BE
|
|
- if (hapd->conf->mld_ap)
|
|
- hostapd_mld_remove_link(hapd);
|
|
-#endif
|
|
+
|
|
+ hostapd_bss_link_deinit(hapd);
|
|
hostapd_cleanup(hapd);
|
|
}
|
|
|
|
@@ -3193,6 +3216,40 @@ hostapd_interface_init_bss(struct hapd_i
|
|
return iface;
|
|
}
|
|
|
|
+static void hostapd_cleanup_driver(const struct wpa_driver_ops *driver,
|
|
+ void *drv_priv,
|
|
+ struct hostapd_iface *iface)
|
|
+{
|
|
+ bool ap_mld = false;
|
|
+
|
|
+ if (!driver || !driver->hapd_deinit || !drv_priv)
|
|
+ return;
|
|
+
|
|
+#ifdef CONFIG_IEEE80211BE
|
|
+ ap_mld = !!iface->bss[0]->conf->mld_ap;
|
|
+#endif /* CONFIG_IEEE80211BE */
|
|
+
|
|
+ /* In case of non-ML operation, de-init. But, if ML operation exist, then
|
|
+ * even if thats the last BSS in the interface, the driver (drv) could
|
|
+ * be in use for a different MLD. Hence, need to check if drv is still
|
|
+ * being used by some other bss before de-initiallizing
|
|
+ */
|
|
+ if (!ap_mld)
|
|
+ driver->hapd_deinit(drv_priv);
|
|
+ else if (hostapd_mld_is_first_bss(iface->bss[0]) &&
|
|
+ driver->get_drv_shared_status &&
|
|
+ !driver->get_drv_shared_status(drv_priv, iface->bss[0])) {
|
|
+ driver->hapd_deinit(drv_priv);
|
|
+ } else if (hostapd_if_link_remove(iface->bss[0],
|
|
+ WPA_IF_AP_BSS,
|
|
+ iface->bss[0]->conf->iface,
|
|
+ iface->bss[0]->mld_link_id)) {
|
|
+ wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s",
|
|
+ iface->bss[0]->conf->iface);
|
|
+ }
|
|
+
|
|
+ iface->bss[0]->drv_priv = NULL;
|
|
+}
|
|
|
|
void hostapd_interface_deinit_free(struct hostapd_iface *iface)
|
|
{
|
|
@@ -3211,13 +3268,7 @@ void hostapd_interface_deinit_free(struc
|
|
hostapd_interface_deinit(iface);
|
|
wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
|
|
__func__, driver, drv_priv);
|
|
- if (driver && driver->hapd_deinit && drv_priv) {
|
|
-#ifdef CONFIG_IEEE80211BE
|
|
- if (hostapd_mld_is_first_bss(iface->bss[0]))
|
|
-#endif /* CONFIG_IEEE80211BE */
|
|
- driver->hapd_deinit(drv_priv);
|
|
- hostapd_clear_drv_priv(iface->bss[0]);
|
|
- }
|
|
+ hostapd_cleanup_driver(driver, drv_priv, iface);
|
|
hostapd_interface_free(iface);
|
|
}
|
|
|
|
@@ -3256,21 +3307,22 @@ static void hostapd_deinit_driver(const
|
|
|
|
wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
|
|
__func__, driver, drv_priv);
|
|
+
|
|
+ hostapd_cleanup_driver(driver, drv_priv, hapd_iface);
|
|
+
|
|
if (driver && driver->hapd_deinit && drv_priv) {
|
|
-#ifdef CONFIG_IEEE80211BE
|
|
- if (hostapd_mld_is_first_bss(iface->bss[0]))
|
|
-#endif /* CONFIG_IEEE80211BE */
|
|
- 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) {
|
|
- 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;
|
|
- }
|
|
+
|
|
+ if (hapd_iface->bss[j]->drv_priv != drv_priv)
|
|
+ continue;
|
|
+
|
|
+ hapd_iface->bss[j]->drv_priv = NULL;
|
|
+ hapd_iface->extended_capa = NULL;
|
|
+ hapd_iface->extended_capa_mask = NULL;
|
|
+ hapd_iface->extended_capa_len = 0;
|
|
}
|
|
}
|
|
}
|
|
@@ -3389,6 +3441,7 @@ int hostapd_disable_iface(struct hostapd
|
|
for (j = 0; j < hapd_iface->num_bss; j++) {
|
|
struct hostapd_data *hapd = hapd_iface->bss[j];
|
|
hostapd_bss_deinit_no_free(hapd);
|
|
+ hostapd_bss_link_deinit(hapd);
|
|
hostapd_free_hapd_data(hapd);
|
|
}
|
|
|
|
@@ -3587,6 +3640,7 @@ int hostapd_add_iface(struct hapd_interf
|
|
if (start_ctrl_iface_bss(hapd) < 0 ||
|
|
(hapd_iface->state == HAPD_IFACE_ENABLED &&
|
|
hostapd_setup_bss(hapd, -1, true))) {
|
|
+ hostapd_bss_link_deinit(hapd);
|
|
hostapd_cleanup(hapd);
|
|
hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
|
|
hapd_iface->conf->num_bss--;
|
|
@@ -3684,6 +3738,7 @@ fail:
|
|
wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)",
|
|
__func__, hapd_iface->bss[i],
|
|
hapd->conf->iface);
|
|
+ hostapd_bss_link_deinit(hapd);
|
|
hostapd_cleanup(hapd);
|
|
os_free(hapd);
|
|
hapd_iface->bss[i] = NULL;
|
|
--- a/src/drivers/driver.h
|
|
+++ b/src/drivers/driver.h
|
|
@@ -5184,6 +5184,33 @@ struct wpa_driver_ops {
|
|
const u8 *match, size_t match_len,
|
|
bool multicast);
|
|
#endif /* CONFIG_TESTING_OPTIONS */
|
|
+
|
|
+#ifdef CONFIG_IEEE80211BE
|
|
+ /**
|
|
+ * if_link_remove - Remove a link alone from virtual interface
|
|
+ * @priv: Private driver interface data
|
|
+ * @type: Interface type
|
|
+ * @ifname: Interface name of the virtual interface from where link is
|
|
+ * to be removed
|
|
+ * @link_id: Valid link ID to remove
|
|
+ * Returns: 0 on success, -1 on failure
|
|
+ */
|
|
+ int (*if_link_remove)(void *priv, enum wpa_driver_if_type type,
|
|
+ const char *ifname, int link_id);
|
|
+
|
|
+ /**
|
|
+ * get_drv_shared_status - Get shared status of driver interface
|
|
+ * @priv: private driver interface data from init()
|
|
+ * @bss_ctx: BSS context for %WPA_IF_AP_BSS interfaces
|
|
+ *
|
|
+ * Checks whether driver interface is being used by other partner BSS(s)
|
|
+ * or not. This is used to decide whether driver interface needs to be
|
|
+ * deinitilized when one iface is getting deinitialized.
|
|
+ *
|
|
+ * Returns: True if it is being used or else False.
|
|
+ */
|
|
+ bool (*get_drv_shared_status)(void *priv, void *bss_ctx);
|
|
+#endif /* CONFIG_IEEE80211BE */
|
|
};
|
|
|
|
/**
|
|
--- a/src/drivers/driver_nl80211.c
|
|
+++ b/src/drivers/driver_nl80211.c
|
|
@@ -4121,6 +4121,19 @@ int wpa_driver_nl80211_authenticate_retr
|
|
return wpa_driver_nl80211_authenticate(bss, ¶ms);
|
|
}
|
|
|
|
+int nl80211_valid_link(struct i802_bss *bss, s8 link_id)
|
|
+{
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < bss->n_links; i++) {
|
|
+ if (bss->links[i].link_id != link_id)
|
|
+ continue;
|
|
+
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
|
|
struct i802_link * nl80211_get_link(struct i802_bss *bss, s8 link_id)
|
|
{
|
|
@@ -8958,6 +8971,37 @@ static int wpa_driver_nl80211_if_remove(
|
|
return 0;
|
|
}
|
|
|
|
+static int wpa_driver_nl80211_if_link_remove(struct i802_bss *bss,
|
|
+ enum wpa_driver_if_type type,
|
|
+ const char *ifname,
|
|
+ int link_id)
|
|
+{
|
|
+ struct wpa_driver_nl80211_data *drv = bss->drv;
|
|
+ struct i802_link *link;
|
|
+ int num_links = bss->n_links;
|
|
+
|
|
+ wpa_printf(MSG_DEBUG, "nl80211: %s(type=%d ifname=%s num_links=%d) link_id=%d",
|
|
+ __func__, type, ifname, num_links, link_id);
|
|
+
|
|
+ link = nl80211_get_link(bss, link_id);
|
|
+
|
|
+ wpa_printf(MSG_DEBUG, "nl80211: Teardown AP(%s) link %d", bss->ifname,
|
|
+ link_id);
|
|
+ wpa_driver_nl80211_del_beacon(bss, link);
|
|
+ nl80211_remove_link(bss, link_id);
|
|
+
|
|
+ bss->ctx = bss->links[0].ctx;
|
|
+
|
|
+ if (drv->first_bss == bss && num_links > 1)
|
|
+ drv->ctx = bss->ctx;
|
|
+
|
|
+ if (num_links == 1) {
|
|
+ wpa_printf(MSG_DEBUG, "nl80211: Only 1 link was there hence remove interface");
|
|
+ return wpa_driver_nl80211_if_remove(bss, type, ifname);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
|
|
static int cookie_handler(struct nl_msg *msg, void *arg)
|
|
{
|
|
@@ -10602,6 +10646,22 @@ static int driver_nl80211_if_remove(void
|
|
return wpa_driver_nl80211_if_remove(bss, type, ifname);
|
|
}
|
|
|
|
+static int driver_nl80211_if_link_remove(void *priv, enum wpa_driver_if_type type,
|
|
+ const char *ifname, int link_id)
|
|
+{
|
|
+ struct i802_bss *bss = priv;
|
|
+
|
|
+ if (link_id < 0 || link_id >= MAX_NUM_MLD_LINKS)
|
|
+ return -1;
|
|
+
|
|
+ if (type != WPA_IF_AP_BSS)
|
|
+ return -1;
|
|
+
|
|
+ if (!nl80211_valid_link(bss, link_id))
|
|
+ return -1;
|
|
+
|
|
+ return wpa_driver_nl80211_if_link_remove(bss, type, ifname, link_id);
|
|
+}
|
|
|
|
static int driver_nl80211_send_mlme(void *priv, const u8 *data,
|
|
size_t data_len, int noack,
|
|
@@ -13794,6 +13854,29 @@ fail:
|
|
return ret;
|
|
}
|
|
|
|
+static bool wpa_driver_get_shared_status(void *priv, void *bss_ctx)
|
|
+{
|
|
+ struct i802_bss *bss = priv;
|
|
+ struct wpa_driver_nl80211_data *drv = bss->drv;
|
|
+ int num_bss = 0;
|
|
+
|
|
+ /* more than one links means some one is still using */
|
|
+ if (bss->n_links > 1)
|
|
+ return true;
|
|
+
|
|
+ /* If any other bss exist, means someone else is using since at this
|
|
+ * time, we would have removed all bss created by this driver and only
|
|
+ * this bss should be remaining if driver is not shared by anyone
|
|
+ */
|
|
+ for (bss = drv->first_bss; bss; bss = bss->next)
|
|
+ num_bss++;
|
|
+
|
|
+ if (num_bss > 1)
|
|
+ return true;
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
|
.name = "nl80211",
|
|
.desc = "Linux nl80211/cfg80211",
|
|
@@ -13948,4 +14031,8 @@ const struct wpa_driver_ops wpa_driver_n
|
|
.radio_disable = testing_nl80211_radio_disable,
|
|
#endif /* CONFIG_TESTING_OPTIONS */
|
|
.set_6gclient_type = nl80211_set_6gclient_type,
|
|
+#ifdef CONFIG_IEEE80211BE
|
|
+ .if_link_remove = driver_nl80211_if_link_remove,
|
|
+ .get_drv_shared_status = wpa_driver_get_shared_status,
|
|
+#endif /* CONFIG_IEEE80211BE */
|
|
};
|
|
--- a/src/drivers/driver_nl80211.h
|
|
+++ b/src/drivers/driver_nl80211.h
|
|
@@ -326,6 +326,7 @@ const char * nl80211_iftype_str(enum nl8
|
|
|
|
void nl80211_restore_ap_mode(struct i802_bss *bss);
|
|
struct i802_link * nl80211_get_link(struct i802_bss *bss, s8 link_id);
|
|
+int nl80211_valid_link(struct i802_bss *bss, s8 link_id);
|
|
|
|
#ifdef ANDROID
|
|
int android_nl_socket_set_nonblocking(struct nl_sock *handle);
|