wlan-ap-Telecominfraproject/feeds/qca/hostapd/patches/r02-001-hostapd-add-support-to-use-underlying-hw_idx-for-mul.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

475 lines
13 KiB
Diff

From ade710c95f8c249b97e87e41b5cebb40c74ee63e Mon Sep 17 00:00:00 2001
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
Date: Tue, 10 Oct 2023 15:24:10 +0530
Subject: [PATCH 1/2] hostapd: add support to use underlying hw_idx for
multi-hardware under single phy mode
During multi-hardware under singly phy scenario, single channel list is
maintained for a given band which does not clearly tells how many different
underlying hardwares are being used to form that band. For example - in
5 GHz split hardware case, two underlying hardwares 5 GHz Low and 5 GHz High
are being used to enable full 5 GHz band. Now, when channel is selected from
list of channels, it is possible that a channel can be picked which the
hardware does not support (lower chanels can be picked for 5 GHz high
hardware) which is wrong.
However, the kernel does tells us about the underlying hardwares and the
list of supported frequencies.
Hence, add support to get the advertised hw_idx and the corresponding list
of supported frequencies and then decide what is the current hw_idx being
used.
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
---
src/ap/ap_drv_ops.c | 9 ++
src/ap/ap_drv_ops.h | 3 +
src/ap/hostapd.c | 7 ++
src/ap/hostapd.h | 4 +
src/ap/hw_features.c | 77 ++++++++++++++++
src/ap/hw_features.h | 14 +++
src/drivers/driver.h | 31 +++++++
src/drivers/driver_nl80211.c | 1 +
src/drivers/driver_nl80211.h | 2 +
src/drivers/driver_nl80211_capa.c | 144 ++++++++++++++++++++++++++++++
tests/fuzzing/ap-mgmt/ap-mgmt.c | 2 +
11 files changed, 294 insertions(+)
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -1165,3 +1165,12 @@ int hostapd_drv_set_secure_ranging_ctx(s
return hapd->driver->set_secure_ranging_ctx(hapd->drv_priv, &params);
}
#endif /* CONFIG_PASN */
+
+struct hostapd_multi_hw_info *
+hostapd_get_multi_hw_info(struct hostapd_data *hapd, u8 *num_multi_hws)
+{
+ if (hapd->driver == NULL ||
+ hapd->driver->get_multi_hw_info == NULL)
+ return NULL;
+ return hapd->driver->get_multi_hw_info(hapd->drv_priv, num_multi_hws);
+}
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -462,4 +462,7 @@ static inline int hostapd_drv_link_add(s
}
#endif /* CONFIG_IEEE80211BE */
+struct hostapd_multi_hw_info *
+hostapd_get_multi_hw_info(struct hostapd_data *hapd, u8 *num_multi_hws);
+
#endif /* AP_DRV_OPS */
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -683,6 +683,9 @@ void hostapd_cleanup_iface_partial(struc
ap_list_deinit(iface);
sta_track_deinit(iface);
airtime_policy_update_deinit(iface);
+ hostapd_free_multi_hw_info(iface->multi_hw_info, iface->num_multi_hws);
+ iface->multi_hw_info = NULL;
+ iface->current_hw_info = NULL;
}
@@ -2466,6 +2469,10 @@ static int hostapd_setup_interface_compl
hostapd_hw_mode_txt(iface->conf->hw_mode),
iface->conf->channel, iface->freq);
+ if (hostapd_set_current_hw_info(iface, iface->freq)) {
+ wpa_printf(MSG_ERROR, "Failed to get operating hw mac id");
+ goto fail;
+ }
#ifdef NEED_AP_MLME
/* Handle DFS only if it is not offloaded to the driver */
if (!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) {
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -719,6 +719,10 @@ struct hostapd_iface {
/* Configured freq of interface is NO_IR */
bool is_no_ir;
+
+ struct hostapd_multi_hw_info *multi_hw_info;
+ u8 num_multi_hws;
+ struct hostapd_multi_hw_info *current_hw_info;
};
/* Iterate over all affiliated links in MLD to which @self belongs.
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -79,6 +79,8 @@ int hostapd_get_hw_features(struct hosta
u16 num_modes, flags;
struct hostapd_hw_modes *modes;
u8 dfs_domain;
+ struct hostapd_multi_hw_info *multi_hw_info;
+ u8 num_multi_hws;
if (hostapd_drv_none(hapd))
return -1;
@@ -141,6 +143,35 @@ int hostapd_get_hw_features(struct hosta
}
}
+ multi_hw_info = hostapd_get_multi_hw_info(hapd, &num_multi_hws);
+ if (multi_hw_info == NULL)
+ return 0;
+
+ hostapd_free_multi_hw_info(iface->multi_hw_info, iface->num_multi_hws);
+ iface->multi_hw_info = multi_hw_info;
+ iface->num_multi_hws = num_multi_hws;
+
+ wpa_printf(MSG_DEBUG, "Multi Underlying Hardwares Info: ");
+
+ for (i = 0; i < num_multi_hws; i++) {
+ struct hostapd_multi_hw_info *hw_info = &multi_hw_info[i];
+ char str[1000];
+ char *pos = str;
+ char *end = pos + sizeof(str);
+ int res;
+
+ for (j = 0; j < hw_info->num_freqs; j++) {
+ res = os_snprintf(pos, end - pos, "%d, ", hw_info->freqs[j]);
+ if (os_snprintf_error(end - pos, res))
+ break;
+ pos += res;
+ }
+
+ *pos = '\0';
+ wpa_printf(MSG_DEBUG, " %d. hw_idx=%u, frequencies: %s",
+ i + 1, hw_info->hw_idx, str);
+ }
+
return 0;
}
@@ -1431,3 +1462,49 @@ int hostapd_hw_skip_mode(struct hostapd_
}
return 0;
}
+
+void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_hw_info,
+ size_t num_multi_hws)
+{
+ size_t i;
+
+ if (multi_hw_info == NULL)
+ return;
+
+ for (i = 0; i < num_multi_hws; i++)
+ os_free(multi_hw_info[i].freqs);
+
+ os_free(multi_hw_info);
+}
+
+int hostapd_set_current_hw_info(struct hostapd_iface *iface, u32 oper_freq)
+{
+ struct hostapd_multi_hw_info *hw_info;
+ int i, j;
+ bool found = false;
+
+ if (!iface->num_multi_hws)
+ return 0;
+
+ for (i = 0; i < iface->num_multi_hws; i++) {
+ hw_info = &iface->multi_hw_info[i];
+
+ for (j = 0; j < hw_info->num_freqs; j++) {
+ if (hw_info->freqs[j] == oper_freq) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ break;
+ }
+
+ if (i >= iface->num_multi_hws)
+ return 1;
+
+ iface->current_hw_info = hw_info;
+ wpa_printf(MSG_DEBUG, "Mode: Selected underlying HW: hw_idx=%u",
+ iface->current_hw_info->hw_idx);
+ return 0;
+}
--- a/src/ap/hw_features.h
+++ b/src/ap/hw_features.h
@@ -29,6 +29,9 @@ void hostapd_stop_setup_timers(struct ho
int hostapd_hw_skip_mode(struct hostapd_iface *iface,
struct hostapd_hw_modes *mode);
void hostapd_determine_mode(struct hostapd_iface *iface);
+void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_macs,
+ size_t num_multi_hws);
+int hostapd_set_current_hw_info(struct hostapd_iface *iface, u32 oper_freq);
#else /* NEED_AP_MLME */
static inline void
hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
@@ -96,6 +99,17 @@ static inline void hostapd_determine_mod
{
}
+static inline
+void hostapd_free_multi_hw_info(struct hostapd_multi_hw_info *multi_macs,
+ size_t num_multi_hws)
+{
+}
+
+static inline int hostapd_set_current_hw_info(struct hostapd_iface *iface,
+ u32 oper_freq)
+{
+ return 0;
+}
#endif /* NEED_AP_MLME */
#endif /* HW_FEATURES_H */
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -320,6 +320,25 @@ struct hostapd_hw_modes {
s8 psd_values[NL80211_REG_NUM_POWER_MODES];
};
+/**
+ * struct hostapd_multi_hw_info: Supported multiple underyling hardware info
+ */
+struct hostapd_multi_hw_info {
+ /**
+ * hw_idx - Hardware index
+ */
+ u8 hw_idx;
+
+ /**
+ * num_freqs - Number of entries in the freqs array
+ */
+ u8 num_freqs;
+
+ /**
+ * freqs - Array of supported frequencies
+ */
+ u32 *freqs;
+};
#define IEEE80211_CAP_ESS 0x0001
#define IEEE80211_CAP_IBSS 0x0002
@@ -5225,6 +5244,18 @@ struct wpa_driver_ops {
*/
int (*can_share_drv)(void *ctx, struct wpa_init_params *params, void **drv_priv);
#endif /* CONFIG_IEEE80211BE */
+
+ /**
+ * get_multi_hw_info - Get multi hardware data (hardware IDx and
+ * supported frequencies)
+ * @priv: Private driver interface data
+ * @num_multi_hws: Variable for returning the number of returned hardware
+ * info data
+ * Returns: Pointer to allocated mutli hardware data on success or
+ * %NULL on failure. Caller is responsible for freeing this.
+ */
+ struct hostapd_multi_hw_info * (*get_multi_hw_info)(void *priv,
+ u8 *num_multi_hws);
};
/**
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -14020,6 +14020,12 @@ free_all:
}
#endif /* CONFIG_IEEE80211BE */
+static struct hostapd_multi_hw_info *
+wpa_driver_get_multi_hw_info(void *priv, u8 *num_multi_hws)
+{
+ return nl80211_get_multi_hw_info(priv, num_multi_hws);
+}
+
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
@@ -14179,4 +14185,5 @@ const struct wpa_driver_ops wpa_driver_n
.get_drv_shared_status = wpa_driver_get_shared_status,
.can_share_drv = wpa_driver_nl80211_can_share_drv,
#endif /* CONFIG_IEEE80211BE */
+ .get_multi_hw_info = wpa_driver_get_multi_hw_info,
};
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -368,5 +368,7 @@ int wpa_driver_nl80211_vendor_scan(struc
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);
+struct hostapd_multi_hw_info *
+nl80211_get_multi_hw_info(void *priv, u8 *num_multi_hws);
#endif /* DRIVER_NL80211_H */
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -1599,6 +1599,12 @@ struct phy_info_arg {
u8 pwr_mode;
};
+struct phy_multi_hw_info_arg {
+ int failed;
+ u8 *num_multi_hws;
+ struct hostapd_multi_hw_info *multi_hws;
+};
+
static void phy_info_ht_capa(struct hostapd_hw_modes *mode, struct nlattr *capa,
struct nlattr *ampdu_factor,
struct nlattr *ampdu_density,
@@ -2677,6 +2683,144 @@ nl80211_get_hw_feature_data(void *priv,
}
return NULL;
+}
+
+static int phy_multi_hw_info_parse(struct phy_multi_hw_info_arg *multi_hw_info,
+ struct nlattr *nl_hw_macs)
+{
+ struct nlattr *tb_hw[NL80211_MULTI_HW_MAC_ATTR_MAX + 1];
+ struct nlattr *tb_freq[NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_MAX + 1];
+ struct nlattr *nl_freq_list;
+ struct hostapd_multi_hw_info *multi_hws;
+ int rem_freq_list;
+ u8 hw_idx, freq_idx = 0, i;
+ u32 freq[256];
+
+ nla_parse(tb_hw, NL80211_MULTI_HW_MAC_ATTR_MAX, nla_data(nl_hw_macs),
+ nla_len(nl_hw_macs), NULL);
+
+ if (!tb_hw[NL80211_MULTI_HW_MAC_ATTR_IDX] ||
+ !tb_hw[NL80211_MULTI_HW_MAC_ATTR_CHAN_LIST])
+ return NL_STOP;
+
+ hw_idx = nla_get_u8(tb_hw[NL80211_MULTI_HW_MAC_ATTR_IDX]);
+
+ nla_for_each_nested(nl_freq_list, tb_hw[NL80211_MULTI_HW_MAC_ATTR_CHAN_LIST],
+ rem_freq_list)
+ {
+ nla_parse(tb_freq, NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_MAX,
+ nla_data(nl_freq_list), nla_len(nl_freq_list), NULL);
+
+ if (!tb_freq[NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_FREQ])
+ return NL_STOP;
+
+ freq[freq_idx++] =
+ nla_get_u32(tb_freq[NL80211_MULTI_HW_MAC_CHAN_LIST_ATTR_FREQ]);
+ }
+
+ multi_hws = os_realloc_array(multi_hw_info->multi_hws,
+ *multi_hw_info->num_multi_hws + 1,
+ sizeof(*multi_hws));
+ if (!multi_hws) {
+ multi_hw_info->failed = 1;
+ return NL_STOP;
+ }
+
+ multi_hw_info->multi_hws = multi_hws;
+
+ multi_hws = &multi_hw_info->multi_hws[*(multi_hw_info->num_multi_hws)];
+
+ multi_hws->hw_idx = hw_idx;
+ multi_hws->num_freqs = freq_idx;
+
+ multi_hws->freqs = os_calloc(multi_hws->num_freqs, sizeof(u32));
+ if (!multi_hws->freqs) {
+ multi_hw_info->failed = 1;
+ return NL_STOP;
+ }
+
+ for (i = 0; i < multi_hws->num_freqs; i++)
+ multi_hws->freqs[i] = freq[i];
+
+ *(multi_hw_info->num_multi_hws) += 1;
+
+ return NL_OK;
+}
+
+static int phy_multi_hw_info_handler(struct nl_msg *msg, void *arg)
+{
+ struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct phy_multi_hw_info_arg *multi_hw_info = arg;
+ struct nlattr *nl_hw_macs;
+ int rem_hw_macs, res;
+
+ nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ if (!tb_msg[NL80211_ATTR_MULTI_HW_MACS])
+ return NL_SKIP;
+
+ nla_for_each_nested(nl_hw_macs, tb_msg[NL80211_ATTR_MULTI_HW_MACS],
+ rem_hw_macs)
+ {
+ res = phy_multi_hw_info_parse(multi_hw_info, nl_hw_macs);
+ if (res != NL_OK)
+ return res;
+ }
+
+ return NL_SKIP;
+}
+
+struct hostapd_multi_hw_info *
+nl80211_get_multi_hw_info(void *priv, u8 *num_multi_hws)
+{
+ u32 feat;
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ int nl_flags = 0;
+ struct nl_msg *msg;
+ struct phy_multi_hw_info_arg result = {
+ .failed = 0,
+ .num_multi_hws = num_multi_hws,
+ .multi_hws = NULL,
+ };
+
+ *num_multi_hws = 0;
+
+ if (!drv->has_capability)
+ return NULL;
+
+ if (!(drv->capa.flags2 & WPA_DRIVER_FLAGS2_MLO))
+ return NULL;
+
+ feat = get_nl80211_protocol_features(drv);
+ if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP)
+ nl_flags = NLM_F_DUMP;
+ if (!(msg = nl80211_cmd_msg(bss, nl_flags, NL80211_CMD_GET_WIPHY)) ||
+ nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP)) {
+ nlmsg_free(msg);
+ return NULL;
+ }
+
+ if (send_and_recv_msgs(drv, msg, phy_multi_hw_info_handler, &result,
+ NULL, NULL) == 0) {
+ if (result.failed) {
+ int i;
+
+ for (i = 0; result.num_multi_hws && i < *num_multi_hws; i++)
+ os_free(result.multi_hws[i].freqs);
+
+ os_free(result.multi_hws);
+ *num_multi_hws = 0;
+
+ return NULL;
+ }
+
+ return result.multi_hws;
+ }
+
+ return NULL;
}
#ifdef CONFIG_IEEE80211BE
--- a/tests/fuzzing/ap-mgmt/ap-mgmt.c
+++ b/tests/fuzzing/ap-mgmt/ap-mgmt.c
@@ -156,6 +156,8 @@ int LLVMFuzzerTestOneInput(const uint8_t
hostapd_free_stas(&ctx.hapd);
hostapd_free_hw_features(ctx.hapd.iface->hw_features,
ctx.hapd.iface->num_hw_features);
+ hostapd_free_multi_hw_info(ctx.hapd.iface->multi_hw_info,
+ ctx.hapd.iface->num_multi_hws);
fail:
hostapd_config_free(ctx.hapd.iconf);