wlan-ap-Telecominfraproject/feeds/qca/hostapd/patches/r00-011-hostapd-re-assign-driver-context-if-existing-ML-part.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

424 lines
13 KiB
Diff

From b4bd16074a9655c0b40e462325c6946c0c3f99c4 Mon Sep 17 00:00:00 2001
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
Date: Fri, 20 Oct 2023 15:39:32 +0530
Subject: [PATCH] hostapd: re-assign driver context if existing ML partner is
found
Currently multiple driver contexts were maintained for a single interface
in certain co-hosted situations. For instance - 5 GHz SLO and 5 GHz +
6 GHz MLD. In this case, if 6 GHz config is passed first then driver would
be created. And when 5 GHz config is parsed, since bss[0] is SLO, there
won't be any partner and hence again driver would be created. This makes
5 GHz interface to have two different drivers. During de-initialization,
proper deinitialization will not happen and a few times seg fault could
be seen.
Hence to avoid this situation, try to maintain single driver if possible.
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
---
src/ap/ap_drv_ops.h | 9 +++++
src/ap/hostapd.c | 1 +
src/drivers/driver.h | 10 +++++
src/drivers/driver_nl80211.c | 71 ++++++++++++++++++++++++++++++++++++
4 files changed, 91 insertions(+)
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -249,6 +249,15 @@ static int hostapd_driver_init(struct ho
params.own_addr = hapd->own_addr;
+#ifdef CONFIG_IEEE80211BE
+ if (hapd->driver->can_share_drv &&
+ !hapd->driver->can_share_drv(hapd, &params, &hapd->drv_priv)) {
+ hapd->interface_added = 1;
+ os_free(params.bridge);
+ goto pre_setup_mld;
+ }
+#endif /* CONFIG_IEEE80211BE */
+
hapd->drv_priv = hapd->driver->hapd_init(hapd, &params);
if (hapd->conf->is_bonded_iface_enabled)
hostapd_mld_update_bridge_conn(hapd->conf->bridge, hapd->conf->iface);
@@ -261,6 +270,7 @@ static int hostapd_driver_init(struct ho
}
#ifdef CONFIG_IEEE80211BE
+pre_setup_mld:
/*
* 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
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -523,7 +523,10 @@ void hostapd_free_hapd_data(struct hosta
authsrv_deinit(hapd);
- if (hapd->interface_added) {
+ /* For single drv, first bss would have interface_added flag set. Don't
+ * remove interface now. driver deinit part will take care
+ */
+ if (hapd->interface_added && hapd->iface->bss[0] != hapd) {
hapd->interface_added = 0;
if (hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) {
wpa_printf(MSG_WARNING,
@@ -3216,25 +3219,26 @@ static void hostapd_cleanup_driver(const
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])) {
+ if (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)) {
+ goto exit;
+ }
+
+ if (ap_mld) {
+ 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 link BSS interface %s",
+ iface->bss[0]->conf->iface);
+ } else if (hostapd_if_remove(iface->bss[0], WPA_IF_AP_BSS,
+ iface->bss[0]->conf->iface)) {
wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s",
iface->bss[0]->conf->iface);
}
+exit:
iface->bss[0]->drv_priv = NULL;
}
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -5210,6 +5210,20 @@ struct wpa_driver_ops {
* Returns: True if it is being used or else False.
*/
bool (*get_drv_shared_status)(void *priv, void *bss_ctx);
+
+ /**
+ * can_share_drv - Check if already a drv exist in the same global driver
+ * which can be shared instead of creating a new drv.
+ * Used during single wiphy operation.
+ *
+ * @ctx: Pointer to hostapd context
+ * @params: Configuration for the driver wrapper
+ * @drv_priv: Pointer for overwriting the driver context or %NULL if
+ * cant' find a shared drv
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+ int (*can_share_drv)(void *ctx, struct wpa_init_params *params, void **drv_priv);
#endif /* CONFIG_IEEE80211BE */
};
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -2916,10 +2916,12 @@ wpa_driver_nl80211_finish_drv_init(struc
if (!bss->if_dynamic && nl80211_get_ifmode(bss) == NL80211_IFTYPE_AP)
bss->static_ap = 1;
- if (first &&
- nl80211_get_ifmode(bss) != NL80211_IFTYPE_P2P_DEVICE &&
- linux_iface_up(drv->global->ioctl_sock, bss->ifname) > 0)
- drv->start_iface_up = 1;
+ if (nl80211_get_ifmode(bss) != NL80211_IFTYPE_P2P_DEVICE &&
+ linux_iface_up(drv->global->ioctl_sock, bss->ifname) > 0) {
+ if (first)
+ drv->start_iface_up = 1;
+ bss->start_iface_up = 1;
+ }
if (wpa_driver_nl80211_capa(drv))
return -1;
@@ -2936,8 +2938,11 @@ wpa_driver_nl80211_finish_drv_init(struc
set_addr)))
return -1;
- if (first && nl80211_get_ifmode(bss) == NL80211_IFTYPE_STATION)
- drv->start_mode_sta = 1;
+ if (nl80211_get_ifmode(bss) == NL80211_IFTYPE_STATION) {
+ if (first)
+ drv->start_mode_sta = 1;
+ bss->start_mode_sta = 1;
+ }
if (drv->hostapd || bss->static_ap)
nlmode = NL80211_IFTYPE_AP;
@@ -8907,6 +8912,7 @@ static int wpa_driver_nl80211_if_remove(
{
struct wpa_driver_nl80211_data *drv = bss->drv;
int ifindex = if_nametoindex(ifname);
+ enum nl80211_iftype nlmode;
wpa_printf(MSG_DEBUG, "nl80211: %s(type=%d ifname=%s) ifindex=%d added_if=%d",
__func__, type, ifname, ifindex, bss->added_if);
@@ -8945,12 +8951,20 @@ static int wpa_driver_nl80211_if_remove(
for (tbss = drv->first_bss; tbss; tbss = tbss->next) {
if (tbss->next == bss) {
tbss->next = bss->next;
- /* Unsubscribe management frames */
- nl80211_teardown_ap(bss);
+ bss->in_deinit = 1;
nl80211_remove_links(bss);
- nl80211_destroy_bss(bss);
+ nlmode = drv->nlmode;
if (!bss->added_if)
i802_set_iface_flags(bss, 0);
+ if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE &&
+ bss->start_mode_sta)
+ wpa_driver_nl80211_set_mode(bss,
+ NL80211_IFTYPE_STATION);
+ else
+ /* Unsubscribe management frames */
+ nl80211_teardown_ap(bss);
+ nl80211_destroy_bss(bss);
+ drv->nlmode = nlmode;
os_free(bss);
bss = NULL;
break;
@@ -8960,16 +8974,29 @@ static int wpa_driver_nl80211_if_remove(
wpa_printf(MSG_INFO, "nl80211: %s - could not find "
"BSS %p in the list", __func__, bss);
} else {
- wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context");
- nl80211_teardown_ap(bss);
+ bss->in_deinit = 1;
nl80211_remove_links(bss);
- nl80211_destroy_bss(bss);
- if (!bss->added_if)
+ nlmode = drv->nlmode;
+ if (!bss->start_iface_up)
i802_set_iface_flags(bss, 0);
+ if (drv->nlmode != NL80211_IFTYPE_P2P_DEVICE &&
+ bss->start_mode_sta)
+ wpa_driver_nl80211_set_mode(bss,
+ NL80211_IFTYPE_STATION);
+ else
+ nl80211_teardown_ap(bss);
+ nl80211_destroy_bss(bss);
+ drv->nlmode = nlmode;
+
+ wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context");
if (drv->first_bss->next) {
drv->first_bss = drv->first_bss->next;
drv->ctx = drv->first_bss->ctx;
+ drv->ifindex = drv->first_bss->ifindex;
+ drv->start_iface_up = drv->first_bss->start_iface_up;
+ drv->start_mode_sta = drv->first_bss->start_mode_sta;
os_free(bss);
+ bss = NULL;
} else {
wpa_printf(MSG_DEBUG, "nl80211: No second BSS to reassign context to");
}
@@ -13884,6 +13911,120 @@ static bool wpa_driver_get_shared_status
return false;
}
+#ifdef CONFIG_IEEE80211BE
+static bool wpa_driver_nl80211_name_match(struct wpa_driver_nl80211_data *drv,
+ struct wpa_driver_nl80211_data **match_drv)
+{
+ struct wpa_driver_nl80211_data *drv_itr, *tmp;
+
+ dl_list_for_each_safe(drv_itr, tmp, &drv->global->interfaces,
+ struct wpa_driver_nl80211_data, list) {
+ if (os_strcmp(drv_itr->phyname, drv->phyname) == 0) {
+ if (match_drv)
+ *match_drv = drv_itr;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static int wpa_driver_nl80211_can_share_drv(void *ctx,
+ struct wpa_init_params *params,
+ void **drv_priv)
+{
+ struct wpa_driver_nl80211_data *drv, *match_drv;
+ struct i802_bss *bss, *new_bss;
+ char force_ifname[IFNAMSIZ];
+ u8 if_addr[ETH_ALEN];
+ const u8 *addr;
+ int ret = -1;
+
+ /* create a dummy drv to read the phyname */
+ if (params->global_priv == NULL)
+ return ret;
+ drv = os_zalloc(sizeof(*drv));
+
+ if (drv == NULL)
+ return ret;
+ drv->global = params->global_priv;
+ drv->ctx = ctx;
+
+ drv->first_bss = os_zalloc(sizeof(*drv->first_bss));
+ if (!drv->first_bss) {
+ os_free(drv);
+ return ret;
+ }
+ bss = drv->first_bss;
+ bss->drv = drv;
+ bss->ctx = ctx;
+
+ os_strlcpy(bss->ifname, params->ifname, sizeof(bss->ifname));
+
+ if (nl80211_init_bss(bss))
+ goto free_all;
+
+ drv->ifindex = if_nametoindex(bss->ifname);
+ bss->ifindex = drv->ifindex;
+
+ if (wpa_driver_set_phyname(drv))
+ goto free_all;
+
+ match_drv = NULL;
+ if (!wpa_driver_nl80211_name_match(drv, &match_drv))
+ goto free_all;
+
+ if (!match_drv)
+ goto free_all;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Driver for phy %s already exist. Using that.",
+ match_drv->phyname);
+
+ /* store the original state and mode */
+ if (nl80211_get_ifmode(bss) != NL80211_IFTYPE_P2P_DEVICE &&
+ linux_iface_up(match_drv->global->ioctl_sock, bss->ifname) > 0)
+ bss->start_iface_up = 1;
+
+ if (nl80211_get_ifmode(bss) == NL80211_IFTYPE_STATION)
+ bss->start_mode_sta = 1;
+
+ addr = params->bssid;
+ if (wpa_driver_nl80211_if_add(match_drv->first_bss, WPA_IF_AP_BSS,
+ params->ifname, addr, ctx, drv_priv,
+ force_ifname, if_addr,
+ params->num_bridge && params->bridge[0] ? params->bridge[0] : NULL,
+ 0, 1)) {
+ wpa_printf(MSG_DEBUG, "nl80211: Failed to add BSS. Expect issues!");
+ goto free_all;
+ }
+
+ if (!addr)
+ os_memcpy(params->own_addr, if_addr, ETH_ALEN);
+ else
+ os_memcpy(params->own_addr, addr, ETH_ALEN);
+
+ /* retain the state and mode in newly created bss. This will be used during
+ * driver deinit and reassigning first bss to this bss
+ */
+ new_bss = *drv_priv;
+ new_bss->start_iface_up = bss->start_iface_up;
+ new_bss->start_mode_sta = bss->start_mode_sta;
+
+ /* This flag was set in wpa_driver_nl80211_if_add(), but it was already
+ * present, hence reset it back. This would be useful during deinit flow
+ */
+ new_bss->added_if = 0;
+
+ ret = 0;
+
+free_all:
+ nl80211_destroy_bss(bss);
+ os_free(bss);
+ os_free(drv);
+ return ret;
+}
+#endif /* CONFIG_IEEE80211BE */
+
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
@@ -14041,5 +14182,6 @@ const struct wpa_driver_ops wpa_driver_n
#ifdef CONFIG_IEEE80211BE
.if_link_remove = driver_nl80211_if_link_remove,
.get_drv_shared_status = wpa_driver_get_shared_status,
+ .can_share_drv = wpa_driver_nl80211_can_share_drv,
#endif /* CONFIG_IEEE80211BE */
};
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -82,6 +82,8 @@ struct i802_bss {
unsigned int added_if:1;
unsigned int static_ap:1;
unsigned int use_nl_connect:1;
+ unsigned int start_iface_up:1;
+ unsigned int start_mode_sta:1;
u8 addr[ETH_ALEN];
u8 prev_addr[ETH_ALEN];
@@ -365,5 +367,6 @@ int wpa_driver_nl80211_abort_scan(void *
int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
struct wpa_driver_scan_params *params);
int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len);
+int wpa_driver_set_phyname(struct wpa_driver_nl80211_data *drv);
#endif /* DRIVER_NL80211_H */
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -2678,3 +2678,46 @@ nl80211_get_hw_feature_data(void *priv,
return NULL;
}
+
+#ifdef CONFIG_IEEE80211BE
+static int wpa_driver_get_wiphy_name(struct nl_msg *msg, void *arg)
+{
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct wpa_driver_nl80211_data *drv = arg;
+
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ if (!tb[NL80211_ATTR_WIPHY_NAME])
+ return NL_SKIP;
+
+ os_strlcpy(drv->phyname, nla_get_string(tb[NL80211_ATTR_WIPHY_NAME]),
+ sizeof(drv->phyname));
+
+ return NL_SKIP;
+}
+
+int wpa_driver_set_phyname(struct wpa_driver_nl80211_data *drv)
+{
+ struct nl_msg *msg;
+ u32 feat, nl_flags;
+
+ feat = get_nl80211_protocol_features(drv);
+ if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
+ nl_flags = NLM_F_DUMP;
+
+ if (!(msg = nl80211_cmd_msg(drv->first_bss, nl_flags,
+ NL80211_CMD_GET_WIPHY)) ||
+ nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP)) {
+ nlmsg_free(msg);
+ return -1;
+ }
+
+ if (send_and_recv_msgs(drv, msg, wpa_driver_get_wiphy_name, drv,
+ NULL, NULL))
+ return -1;
+
+ return 0;
+}
+#endif /* CONFIG_IEEE80211BE */