wlan-ap-Telecominfraproject/feeds/qca/hostapd/patches/r04-009-hostapd-clean-up-MLD-when-not-required-any-further.patch
John Crispin 008ca9618d
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
ipq95xx: import ath12.4-cs kernel and drivers
Signed-off-by: John Crispin <john@phrozen.org>
2024-10-20 09:25:13 +02:00

272 lines
7.5 KiB
Diff

From 7537683c937418ec03f2f622445b09b23898d0f1 Mon Sep 17 00:00:00 2001
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
Date: Fri, 29 Dec 2023 12:08:13 +0530
Subject: [PATCH] hostapd: clean up MLD when not required any further
Currently, whenever a new BSS is created, if it is an EHT then it is tied
to a corresponding MLD structure. If structure does not exist already, a
new one is created and tied to it. Accordingly link ID is assigned as well.
However, when BSS is deleted, the MLD structure is not freed and when the
next time it is again created, it increments the link ID further and gets a
wrong link ID.
For example - 2 GHz SLO AP case.
First Wifi, link ID 0 would be assigned and mld wlan0 would be created.
When wifi down is issued, BSS would be deleted but mld wlan0 will not. When
again wifi is issued, BSS will tie back to mld wlan0 but this time link ID
will be incremented again and 1 would be assigned. Hence at subsequent wifi
down/up, link ID keeps on incrementing.
Since link ID remains till lifetime of the BSS and MLD, the next link ID
counter can not be just reset back to 0 when a BSS is deleted. Otherwise,
in interleaved link enable/disable case, link ID would be changed.
Hence to overcome this situation, add changes so that whenever a BSS is
deleted, if the MLD is not referenced by any other existing BSS, delete the
MLD structure itself.
In order to know how many BSSes are referring a given MLD, introduce a new
member refcount in MLD. If he value is 0 then it is safe to delete the MLD.
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
---
src/ap/hostapd.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++
src/ap/hostapd.h | 2 +
2 files changed, 130 insertions(+)
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -75,6 +75,11 @@ static void hostapd_switch_color_timeout
static void hostapd_interface_update_fils_ubpr(struct hostapd_iface *iface,
bool iface_enabled);
+#ifdef CONFIG_IEEE80211BE
+static void hostapd_mld_ref_inc(struct hostapd_mld *mld);
+static void hostapd_mld_ref_dec(struct hostapd_mld *mld);
+#endif /* CONFIG_IEEE80211BE */
+
int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
int (*cb)(struct hostapd_iface *iface,
void *ctx), void *ctx)
@@ -2993,6 +2998,9 @@ void hostapd_interface_free(struct hosta
for (j = 0; j < iface->num_bss; j++) {
if (!iface->bss)
break;
+#ifdef CONFIG_IEEE80211BE
+ hostapd_mld_ref_dec(iface->bss[j]->mld);
+#endif /* CONFIG_IEEE80211BE */
wpa_printf(MSG_DEBUG, "%s: free hapd %p",
__func__, iface->bss[j]);
os_free(iface->bss[j]);
@@ -3015,6 +3023,34 @@ struct hostapd_iface * hostapd_alloc_ifa
}
#ifdef CONFIG_IEEE80211BE
+static void hostapd_mld_ref_inc(struct hostapd_mld *mld)
+{
+ if (!mld)
+ return;
+
+ if (mld->refcount == HOSTAPD_MLD_MAX_REF_COUNT) {
+ wpa_printf(MSG_ERROR, "MLD %s: Ref count overflow",
+ mld->name);
+ return;
+ }
+
+ mld->refcount++;
+}
+
+static void hostapd_mld_ref_dec(struct hostapd_mld *mld)
+{
+ if (!mld)
+ return;
+
+ if (!mld->refcount) {
+ wpa_printf(MSG_ERROR, "MLD %s: Ref count underflow",
+ mld->name);
+ return;
+ }
+
+ mld->refcount--;
+}
+
static void hostapd_bss_alloc_link_id(struct hostapd_data *hapd)
{
hapd->mld_link_id = hapd->mld->next_link_id++;
@@ -3045,6 +3081,7 @@ static void hostapd_bss_setup_multi_link
continue;
hapd->mld = mld;
+ hostapd_mld_ref_inc(mld);
hostapd_bss_alloc_link_id(hapd);
break;
}
@@ -3059,12 +3096,14 @@ static void hostapd_bss_setup_multi_link
os_strlcpy(mld->name, conf->iface, sizeof(conf->iface));
mld->next_link_id = 0;
mld->num_links = 0;
+ mld->refcount = 0;
mld->fbss = NULL;
dl_list_init(&mld->links);
wpa_printf(MSG_DEBUG, "MLD %s created", mld->name);
hapd->mld = mld;
+ hostapd_mld_ref_inc(mld);
hostapd_bss_alloc_link_id(hapd);
all_mld = os_realloc_array(interfaces->mld, interfaces->mld_count + 1,
@@ -3086,6 +3125,79 @@ fail:
os_free(mld);
hapd->mld = NULL;
}
+
+static void hostapd_cleanup_unused_mlds(struct hapd_interfaces *interfaces)
+{
+ struct hostapd_mld *mld, **all_mld;
+ int i, j, num_mlds;
+ bool forced_remove, remove;
+
+ if (!interfaces || !interfaces->mld)
+ return;
+
+ num_mlds = interfaces->mld_count;
+
+ for (i = 0; i < interfaces->mld_count; i++) {
+ mld = interfaces->mld[i];
+ if (!mld)
+ continue;
+
+ remove = forced_remove = false;
+
+ if (!mld->refcount)
+ remove = true;
+
+ /* If mld is still being referenced but no. of interfaces are
+ * zero then it is safe to force delete it. Normally, this
+ * should not happen but even if it does, let us free the memory
+ */
+ if (!remove && !interfaces->count)
+ forced_remove = true;
+
+ if (!remove && !forced_remove)
+ continue;
+
+ wpa_printf(MSG_DEBUG, "MLD %s: freed (forced: %d)", mld->name,
+ forced_remove);
+ os_free(mld);
+ interfaces->mld[i] = NULL;
+ num_mlds--;
+ }
+
+ if (!num_mlds) {
+ interfaces->mld_count = 0;
+ os_free(interfaces->mld);
+ interfaces->mld = NULL;
+ return;
+ }
+
+ all_mld = os_zalloc(num_mlds * sizeof(struct hostapd_mld *));
+ if (!all_mld) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: failed to re-allocate the MLDs. Expect issues");
+ return;
+ }
+
+ for (i = 0, j = 0; i < interfaces->mld_count; i++) {
+ mld = interfaces->mld[i];
+ if (!mld)
+ continue;
+
+ all_mld[j++] = mld;
+ }
+
+ /* should not happen */
+ if (j != num_mlds) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: some error occured while reallocating MLDs. Expect issues.");
+ os_free(all_mld);
+ return;
+ }
+
+ os_free(interfaces->mld);
+ interfaces->mld = all_mld;
+ interfaces->mld_count = num_mlds;
+}
#endif /* CONFIG_IEEE80211BE */
/**
@@ -3746,6 +3858,9 @@ int hostapd_add_iface(struct hapd_interf
__func__, hapd, hapd->conf->iface);
hostapd_config_free_bss(hapd->conf);
hapd->conf = NULL;
+#ifdef CONFIG_IEEE80211BE
+ hostapd_mld_ref_dec(hapd->mld);
+#endif /* CONFIG_IEEE80211BE */
os_free(hapd);
return -1;
}
@@ -3837,6 +3952,9 @@ fail:
hapd->conf->iface);
hostapd_bss_link_deinit(hapd);
hostapd_cleanup(hapd);
+#ifdef CONFIG_IEEE80211BE
+ hostapd_mld_ref_dec(hapd->mld);
+#endif /* CONFIG_IEEE80211BE */
os_free(hapd);
hapd_iface->bss[i] = NULL;
}
@@ -3846,6 +3964,9 @@ fail:
if (new_iface) {
interfaces->count--;
interfaces->iface[interfaces->count] = NULL;
+#ifdef CONFIG_IEEE80211BE
+ hostapd_cleanup_unused_mlds(interfaces);
+#endif /* CONFIG_IEEE80211BE */
}
hostapd_cleanup_iface(hapd_iface);
}
@@ -3868,6 +3989,9 @@ static int hostapd_remove_bss(struct hos
__func__, hapd, hapd->conf->iface);
hostapd_config_free_bss(hapd->conf);
hapd->conf = NULL;
+#ifdef CONFIG_IEEE80211BE
+ hostapd_mld_ref_dec(hapd->mld);
+#endif /* CONFIG_IEEE80211BE */
os_free(hapd);
iface->num_bss--;
@@ -3910,6 +4034,10 @@ int hostapd_remove_iface(struct hapd_int
k++;
}
interfaces->count--;
+#ifdef CONFIG_IEEE80211BE
+ hostapd_cleanup_unused_mlds(interfaces);
+#endif /* CONFIG_IEEE80211BE */
+
return 0;
}
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -572,11 +572,19 @@ struct hostapd_mld {
u8 mld_addr[ETH_ALEN];
u8 next_link_id;
u8 num_links;
+ /* No. of hostapd_data (hapd) referencing to this. num_links can't
+ * be used since num_links can go to 0 even when bss is disabled
+ * and when it is enabled back, the MLD should exist hence it can
+ * not be freed when it is 0.
+ */
+ u8 refcount;
struct hostapd_data *fbss;
struct dl_list links; /* List HEAD of all affiliated links */
struct dl_list ft_ds_ml_stas;
};
+
+#define HOSTAPD_MLD_MAX_REF_COUNT 0xFF
#endif /* CONFIG_IEEE80211BE */
/**