wlan-ap-Telecominfraproject/feeds/ipq95xx/hostapd/patches/q02-048-hostapd-Update-11be-EHT-elements-to-Draft-2.0-versio.patch
John Crispin b9b03a6e38 ipq95xx: add Qualcomm wifi-7 support
Signed-off-by: John Crispin <john@phrozen.org>
2023-04-10 14:25:48 +02:00

290 lines
11 KiB
Diff

From 7377742385c93887bc125cecc21204387112517d Mon Sep 17 00:00:00 2001
From: Balamurugan Mahalingam <quic_bmahalin@quicinc.com>
Date: Tue, 16 Aug 2022 17:53:38 -0700
Subject: [PATCH] hostapd: Update 11be EHT elements to Draft 2.0 version
Update the EHT operations elements to Draft 2.0 and fix interop
issues with stations
Signed-off-by: Balamurugan Mahalingam <quic_bmahalin@quicinc.com>
---
hostapd/config_file.c | 2 ++
src/ap/ap_config.h | 9 +++++++++
src/ap/beacon.c | 5 +++++
src/ap/ctrl_iface_ap.c | 6 ++++--
src/ap/ieee802_11.c | 2 ++
src/ap/ieee802_11_eht.c | 34 ++++++++++++++++++++++++++++------
src/common/ieee802_11_defs.h | 35 +++++++++++++++++++++++------------
wpa_supplicant/mesh_mpm.c | 10 +++++-----
8 files changed, 78 insertions(+), 25 deletions(-)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 501d30c..d896d67 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -4689,6 +4689,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
conf->eht_oper_chwidth = atoi(pos);
} else if (os_strcmp(buf, "eht_oper_centr_freq_seg0_idx") == 0) {
conf->eht_oper_centr_freq_seg0_idx = atoi(pos);
+ } else if (os_strcmp(buf, "eht_oper_centr_freq_seg1_idx") == 0) {
+ conf->eht_oper_centr_freq_seg1_idx = atoi(pos);
} else if (os_strcmp(buf, "eht_su_beamformer") == 0) {
conf->eht_phy_capab.su_beamformer = atoi(pos);
} else if (os_strcmp(buf, "eht_su_beamformee") == 0) {
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index f6d1d56..83ba76c 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -1144,6 +1144,7 @@ struct hostapd_config {
#ifdef CONFIG_IEEE80211BE
u8 eht_oper_chwidth;
u8 eht_oper_centr_freq_seg0_idx;
+ u8 eht_oper_centr_freq_seg1_idx;
struct eht_phy_capabilities_info eht_phy_capab;
#endif /* CONFIG_IEEE80211BE */
@@ -1227,6 +1228,10 @@ hostapd_set_oper_centr_freq_seg0_idx(struct hostapd_config *conf,
static inline u8
hostapd_get_oper_centr_freq_seg1_idx(struct hostapd_config *conf)
{
+#ifdef CONFIG_IEEE80211BE
+ if (conf->ieee80211be)
+ return conf->eht_oper_centr_freq_seg1_idx;
+#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_IEEE80211AX
if (conf->ieee80211ax)
return conf->he_oper_centr_freq_seg1_idx;
@@ -1238,6 +1243,10 @@ static inline void
hostapd_set_oper_centr_freq_seg1_idx(struct hostapd_config *conf,
u8 oper_centr_freq_seg1_idx)
{
+#ifdef CONFIG_IEEE80211BE
+ if (conf->ieee80211be)
+ conf->eht_oper_centr_freq_seg1_idx = oper_centr_freq_seg1_idx;
+#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_IEEE80211AX
if (conf->ieee80211ax)
conf->he_oper_centr_freq_seg1_idx = oper_centr_freq_seg1_idx;
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 023729c..9536e76 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -643,6 +643,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
buflen += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP);
buflen += (3 + sizeof(struct ieee80211_eht_operation));
+ if (hapd->iconf->ru_punct_bitmap)
+ buflen += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE;
+
}
#endif /* CONFIG_IEEE80211BE */
@@ -1759,6 +1762,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
tail_len += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP);
tail_len += (3 + sizeof(struct ieee80211_eht_operation));
+ if (hapd->iconf->ru_punct_bitmap)
+ tail_len += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE;
}
#endif /* CONFIG_IEEE80211BE */
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 62db273..b697ad2 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -1065,9 +1065,11 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
if (iface->conf->ieee80211be && !hapd->conf->disable_11be) {
ret = os_snprintf(buf + len, buflen - len,
"eht_oper_chwidth=%d\n"
- "eht_oper_centr_freq_seg0_idx=%d\n",
+ "eht_oper_centr_freq_seg0_idx=%d\n"
+ "eht_oper_centr_freq_seg1_idx=%d\n",
iface->conf->eht_oper_chwidth,
- iface->conf->eht_oper_centr_freq_seg0_idx);
+ iface->conf->eht_oper_centr_freq_seg0_idx,
+ iface->conf->eht_oper_centr_freq_seg1_idx);
if (os_snprintf_error(buflen - len, ret))
return len;
len += ret;
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index b4efc17..8a6fed8 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -5106,6 +5106,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
buflen += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP);
buflen += (3 + sizeof(struct ieee80211_eht_operation));
+ if (hapd->iconf->ru_punct_bitmap)
+ buflen += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE;
}
#endif /* CONFIG_IEEE80211BE */
diff --git a/src/ap/ieee802_11_eht.c b/src/ap/ieee802_11_eht.c
index c7586ec..f54fee3 100644
--- a/src/ap/ieee802_11_eht.c
+++ b/src/ap/ieee802_11_eht.c
@@ -174,6 +174,7 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid,
{
struct hostapd_hw_modes *mode;
struct ieee80211_eht_operation *oper;
+ struct eht_capabilities *eht_cap;
u8 *pos = eid, oper_size = 0, chwidth;
mode = hapd->iface->current_mode;
@@ -185,15 +186,26 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid,
oper_size = sizeof(struct ieee80211_eht_operation);
*pos++ = WLAN_EID_EXTENSION;
- *pos++ = 1 + oper_size;
+
+ if (hapd->iconf->ru_punct_bitmap)
+ *pos++ = 1 + oper_size + DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE;
+ else
+ *pos++ = 1 + oper_size;
+
*pos++ = WLAN_EID_EXT_EHT_OPERATION;
oper = (struct ieee80211_eht_operation *) pos;
os_memset(oper, 0, sizeof(*oper));
- oper->ccfs = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf);
- if (!oper->ccfs)
- oper->ccfs = hapd->iconf->channel;
+ eht_cap = &mode->eht_capab[opmode];
+ oper->ehtop_params |= EHTOP_PARAMS_EHTOP_INFORMATION_PRESENT;
+ oper->ccfs0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf);
+ oper->ccfs1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
+ memcpy(&oper->mcs_nss_supported, &eht_cap->mcs,
+ EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY);
+
+ if (!oper->ccfs0)
+ oper->ccfs0 = hapd->iconf->channel;
if (is_6ghz_op_class(hapd->iconf->op_class))
chwidth = op_class_to_ch_width(hapd->iconf->op_class);
@@ -209,6 +221,14 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid,
switch (chwidth) {
case CHANWIDTH_320MHZ:
oper->width = EHT_OPERATION_CHANNEL_WIDTH_320MHZ;
+ if (!oper->ccfs1) {
+ /* CCFS0 points to center channel frequency in config */
+ oper->ccfs1 = oper->ccfs0;
+ if (hapd->iconf->channel < oper->ccfs0)
+ oper->ccfs0 = oper->ccfs1 - 16;
+ else
+ oper->ccfs0 = oper->ccfs1 + 16;
+ }
break;
case CHANWIDTH_160MHZ:
oper->width = EHT_OPERATION_CHANNEL_WIDTH_160MHZ;
@@ -246,8 +266,10 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid,
}
if (hapd->iconf->ru_punct_bitmap) {
- oper->disable_sub_chan_bitmap_present = 1;
- oper->disabled_subchannel_bitmap = host_to_le16(hapd->iconf->ru_punct_bitmap);
+ oper->ehtop_params |= EHTOP_PARAMS_DISABLED_SUBCHANNEL_BITMAP_PRESENT;
+ oper->disabled_subchannel_bitmap[0] =
+ host_to_le16(hapd->iconf->ru_punct_bitmap);
+ pos += DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE;
}
pos += oper_size;
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 752f65f..766ec1d 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -2462,28 +2462,39 @@ struct ieee80211_eht_capabilities {
u8 optional[71];
} STRUCT_PACKED;
-#define EHT_OPERATION_CCFS_SHIFT 4
/*
* struct ieee80211_eht_operation - eht operation element
*
* This structure is the "EHT Operation Element" fields as
- * described in P802.11be_D1.4 section 9.4.2.311
- *
- * FIXME: The spec is unclear how big the fields are, and doesn't
- * indicate the "Disabled Subchannel Bitmap Present" in the
- * structure (Figure 9-1002a) at all ...
+ * described in P802.11be_D2.0 section 9.4.2.311
*/
+
+#define EHTOP_PARAMS_EHTOP_INFORMATION_PRESENT BIT(0)
+#define EHTOP_PARAMS_DISABLED_SUBCHANNEL_BITMAP_PRESENT BIT(1)
+#define EHTOP_PARAMS_EHT_DEFAULT_PE_DURATION BIT(2)
+#define EHTOP_PARAMS_GROUP_ADDRESSED_BU_INDICATION_LIMIT BIT(3)
+#define EHTOP_PARAMS_GROUP_ADDRESSED_BU_INDICATION_EXPONENT BIT(4)
+
+#define DISABLED_SUBCHANNEL_BITMAP_BYTES_SIZE 2
+
+struct ieee80211_eht_mcs_nss_set {
+ u8 max_tx_mcs_nss_0_7;
+ u8 max_tx_mcs_nss_8_9;
+ u8 max_tx_mcs_nss_10_11;
+ u8 max_tx_mcs_nss_12_13;
+} STRUCT_PACKED;
+
struct ieee80211_eht_operation {
+ u8 ehtop_params;
+ struct ieee80211_eht_mcs_nss_set mcs_nss_supported;
u8 width:3,
reserved:5;
- u8 ccfs;
- u8 disable_sub_chan_bitmap_present:1,
- reserved2:7;
- le16 disabled_subchannel_bitmap;
-
- /* Add puncture pattern here when supported */
+ u8 ccfs0;
+ u8 ccfs1;
+ le16 disabled_subchannel_bitmap[0];
} STRUCT_PACKED;
+
#define EHT_OPERATION_CHANNEL_WIDTH_20MHZ 0
#define EHT_OPERATION_CHANNEL_WIDTH_40MHZ 1
#define EHT_OPERATION_CHANNEL_WIDTH_80MHZ 2
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index b527a77..c56801f 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -820,28 +820,28 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s,
eht_oper_ie = (struct ieee80211_eht_operation *)elems->eht_operation;
if (eht_oper_ie->width >= EHT_OPERATION_CHANNEL_WIDTH_80MHZ &&
- eht_oper_ie->disable_sub_chan_bitmap_present &&
+ eht_oper_ie->ehtop_params & EHTOP_PARAMS_DISABLED_SUBCHANNEL_BITMAP_PRESENT &&
eht_oper_ie->disabled_subchannel_bitmap) {
- params.ru_punct_bitmap = eht_oper_ie->disabled_subchannel_bitmap;
+ params.ru_punct_bitmap = eht_oper_ie->disabled_subchannel_bitmap[0];
/* Validate Peer's puncture bitmap and reset if invalid */
switch (eht_oper_ie->width) {
case EHT_OPERATION_CHANNEL_WIDTH_80MHZ:
bw = 80;
- start_chan = eht_oper_ie->ccfs - 6;
+ start_chan = eht_oper_ie->ccfs0 - 6;
if (!is_ru_punct_bitmap_valid(bw, (pri_chan - start_chan) / 4,
params.ru_punct_bitmap, 0))
params.ru_punct_bitmap = 0;
break;
case EHT_OPERATION_CHANNEL_WIDTH_160MHZ:
bw = 160;
- start_chan = eht_oper_ie->ccfs - 14;
+ start_chan = eht_oper_ie->ccfs0 - 14;
if (!is_ru_punct_bitmap_valid(bw, (pri_chan - start_chan) / 4,
params.ru_punct_bitmap, 0))
params.ru_punct_bitmap = 0;
break;
case EHT_OPERATION_CHANNEL_WIDTH_320MHZ:
bw = 320;
- start_chan = eht_oper_ie->ccfs - 30;
+ start_chan = eht_oper_ie->ccfs0 - 30;
if (!is_ru_punct_bitmap_valid(bw, (pri_chan - start_chan) / 4,
params.ru_punct_bitmap, 0))
params.ru_punct_bitmap = 0;
--
2.17.1