hostapd: add fix for dealing with VHT 160 MHz via ext nss bw

Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Felix Fietkau 2023-07-14 10:01:30 +02:00
parent 61f674df4f
commit adfeda8491
11 changed files with 156 additions and 15 deletions

View File

@ -0,0 +1,141 @@
From d4c4ef302f98fd6bce173b8636e7e350d8b44981 Mon Sep 17 00:00:00 2001
From: P Praneesh <ppranees@codeaurora.org>
Date: Fri, 19 Mar 2021 12:17:27 +0530
Subject: [PATCH] hostapd: update cfs0 and cfs1 for 160MHz
As per standard Draft P802.11ax_D8.0,( Table 26-9—Setting
of the VHT Channel Width and VHT NSS at an HE STA
transmitting the OM Control subfield ), center frequency of
160MHz should be published in HT information subset 2 of
HT information when EXT NSS BW field is enabled.
If the supported number of NSS in 160MHz is at least max NSS
support, then center_freq_seg0 indicates the center frequency of 80MHz and
center_freq_seg1 indicates the center frequency of 160MHz.
If the supported number of NSS in 160MHz is less than max NSS
support, then center_freq_seg0 indicates the center frequency of 80MHz and
center_freq_seg1 is 0. The center frequency of 160MHz is published in HT
operation information element instead.
Signed-off-by: P Praneesh <ppranees@codeaurora.org>
---
hostapd/config_file.c | 2 ++
src/ap/ieee802_11_ht.c | 7 +++++++
src/ap/ieee802_11_vht.c | 16 ++++++++++++++++
src/common/hw_features_common.c | 1 +
src/common/ieee802_11_defs.h | 1 +
5 files changed, 27 insertions(+)
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -1153,6 +1153,8 @@ static int hostapd_config_vht_capab(stru
conf->vht_capab |= VHT_CAP_RX_ANTENNA_PATTERN;
if (os_strstr(capab, "[TX-ANTENNA-PATTERN]"))
conf->vht_capab |= VHT_CAP_TX_ANTENNA_PATTERN;
+ if (os_strstr(capab, "[EXT-NSS-BW-SUPP]"))
+ conf->vht_capab |= VHT_CAP_EXTENDED_NSS_BW_SUPPORT;
return 0;
}
#endif /* CONFIG_IEEE80211AC */
--- a/src/ap/ieee802_11_ht.c
+++ b/src/ap/ieee802_11_ht.c
@@ -82,7 +82,9 @@ u8 * hostapd_eid_ht_capabilities(struct
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
{
struct ieee80211_ht_operation *oper;
+ le32 vht_capabilities_info;
u8 *pos = eid;
+ u8 chwidth;
if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n ||
is_6ghz_op_class(hapd->iconf->op_class))
@@ -103,6 +105,13 @@ u8 * hostapd_eid_ht_operation(struct hos
oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
+ vht_capabilities_info = host_to_le32(hapd->iface->current_mode->vht_capab);
+ chwidth = hostapd_get_oper_chwidth(hapd->iconf);
+ if (vht_capabilities_info & VHT_CAP_EXTENDED_NSS_BW_SUPPORT
+ && ((chwidth == CHANWIDTH_160MHZ) || (chwidth == CHANWIDTH_80P80MHZ))) {
+ oper->operation_mode = host_to_le16(hapd->iconf->vht_oper_centr_freq_seg0_idx << 5);
+ }
+
pos += sizeof(*oper);
return pos;
--- a/src/ap/ieee802_11_vht.c
+++ b/src/ap/ieee802_11_vht.c
@@ -25,6 +25,7 @@ u8 * hostapd_eid_vht_capabilities(struct
struct ieee80211_vht_capabilities *cap;
struct hostapd_hw_modes *mode = hapd->iface->current_mode;
u8 *pos = eid;
+ u8 chwidth;
if (!mode || is_6ghz_op_class(hapd->iconf->op_class))
return eid;
@@ -62,6 +63,17 @@ u8 * hostapd_eid_vht_capabilities(struct
host_to_le32(nsts << VHT_CAP_BEAMFORMEE_STS_OFFSET);
}
+ chwidth = hostapd_get_oper_chwidth(hapd->iconf);
+ if (((host_to_le32(mode->vht_capab)) & VHT_CAP_EXTENDED_NSS_BW_SUPPORT)
+ && ((chwidth == CHANWIDTH_160MHZ) || (chwidth == CHANWIDTH_80P80MHZ))) {
+ cap->vht_capabilities_info |= VHT_CAP_EXTENDED_NSS_BW_SUPPORT;
+ cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ));
+ cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_160MHZ));
+ cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_MASK));
+ } else {
+ cap->vht_capabilities_info &= ~VHT_CAP_EXTENDED_NSS_BW_SUPPORT_MASK;
+ }
+
/* Supported MCS set comes from hw */
os_memcpy(&cap->vht_supported_mcs_set, mode->vht_mcs_set, 8);
@@ -74,6 +86,7 @@ u8 * hostapd_eid_vht_capabilities(struct
u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
{
struct ieee80211_vht_operation *oper;
+ le32 vht_capabilities_info;
u8 *pos = eid;
enum oper_chan_width oper_chwidth =
hostapd_get_oper_chwidth(hapd->iconf);
@@ -106,6 +119,7 @@ u8 * hostapd_eid_vht_operation(struct ho
oper->vht_op_info_chan_center_freq_seg1_idx = seg1;
oper->vht_op_info_chwidth = oper_chwidth;
+ vht_capabilities_info = host_to_le32(hapd->iface->current_mode->vht_capab);
if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
/*
* Convert 160 MHz channel width to new style as interop
@@ -119,6 +133,9 @@ u8 * hostapd_eid_vht_operation(struct ho
oper->vht_op_info_chan_center_freq_seg0_idx -= 8;
else
oper->vht_op_info_chan_center_freq_seg0_idx += 8;
+
+ if (vht_capabilities_info & VHT_CAP_EXTENDED_NSS_BW_SUPPORT)
+ oper->vht_op_info_chan_center_freq_seg1_idx = 0;
} else if (oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
/*
* Convert 80+80 MHz channel width to new style as interop
--- a/src/common/hw_features_common.c
+++ b/src/common/hw_features_common.c
@@ -808,6 +808,7 @@ int ieee80211ac_cap_check(u32 hw, u32 co
VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB);
VHT_CAP_CHECK(VHT_CAP_RX_ANTENNA_PATTERN);
VHT_CAP_CHECK(VHT_CAP_TX_ANTENNA_PATTERN);
+ VHT_CAP_CHECK(VHT_CAP_EXTENDED_NSS_BW_SUPPORT);
#undef VHT_CAP_CHECK
#undef VHT_CAP_CHECK_MAX
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -1348,6 +1348,8 @@ struct ieee80211_ampe_ie {
#define VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB ((u32) BIT(26) | BIT(27))
#define VHT_CAP_RX_ANTENNA_PATTERN ((u32) BIT(28))
#define VHT_CAP_TX_ANTENNA_PATTERN ((u32) BIT(29))
+#define VHT_CAP_EXTENDED_NSS_BW_SUPPORT ((u32) BIT(30))
+#define VHT_CAP_EXTENDED_NSS_BW_SUPPORT_MASK ((u32) BIT(30) | BIT(31))
#define VHT_OPMODE_CHANNEL_WIDTH_MASK ((u8) BIT(0) | BIT(1))
#define VHT_OPMODE_CHANNEL_RxNSS_MASK ((u8) BIT(4) | BIT(5) | \

View File

@ -1,6 +1,6 @@
--- a/hostapd/config_file.c --- a/hostapd/config_file.c
+++ b/hostapd/config_file.c +++ b/hostapd/config_file.c
@@ -3446,6 +3446,10 @@ static int hostapd_config_fill(struct ho @@ -3448,6 +3448,10 @@ static int hostapd_config_fill(struct ho
if (bss->ocv && !bss->ieee80211w) if (bss->ocv && !bss->ieee80211w)
bss->ieee80211w = 1; bss->ieee80211w = 1;
#endif /* CONFIG_OCV */ #endif /* CONFIG_OCV */
@ -36,7 +36,7 @@
hostapd_set_state(iface, HAPD_IFACE_HT_SCAN); hostapd_set_state(iface, HAPD_IFACE_HT_SCAN);
--- a/src/ap/ieee802_11_ht.c --- a/src/ap/ieee802_11_ht.c
+++ b/src/ap/ieee802_11_ht.c +++ b/src/ap/ieee802_11_ht.c
@@ -230,6 +230,9 @@ void hostapd_2040_coex_action(struct hos @@ -239,6 +239,9 @@ void hostapd_2040_coex_action(struct hos
return; return;
} }
@ -46,7 +46,7 @@
if (len < IEEE80211_HDRLEN + 2 + sizeof(*bc_ie)) { if (len < IEEE80211_HDRLEN + 2 + sizeof(*bc_ie)) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"Ignore too short 20/40 BSS Coexistence Management frame"); "Ignore too short 20/40 BSS Coexistence Management frame");
@@ -390,6 +393,9 @@ void ht40_intolerant_add(struct hostapd_ @@ -399,6 +402,9 @@ void ht40_intolerant_add(struct hostapd_
if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
return; return;

View File

@ -13,7 +13,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
--- a/hostapd/config_file.c --- a/hostapd/config_file.c
+++ b/hostapd/config_file.c +++ b/hostapd/config_file.c
@@ -3498,6 +3498,8 @@ static int hostapd_config_fill(struct ho @@ -3500,6 +3500,8 @@ static int hostapd_config_fill(struct ho
} else if (os_strcmp(buf, "he_bss_color") == 0) { } else if (os_strcmp(buf, "he_bss_color") == 0) {
conf->he_op.he_bss_color = atoi(pos) & 0x3f; conf->he_op.he_bss_color = atoi(pos) & 0x3f;
conf->he_op.he_bss_color_disabled = 0; conf->he_op.he_bss_color_disabled = 0;

View File

@ -1,6 +1,6 @@
--- a/hostapd/config_file.c --- a/hostapd/config_file.c
+++ b/hostapd/config_file.c +++ b/hostapd/config_file.c
@@ -2418,6 +2418,8 @@ static int hostapd_config_fill(struct ho @@ -2420,6 +2420,8 @@ static int hostapd_config_fill(struct ho
bss->isolate = atoi(pos); bss->isolate = atoi(pos);
} else if (os_strcmp(buf, "ap_max_inactivity") == 0) { } else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
bss->ap_max_inactivity = atoi(pos); bss->ap_max_inactivity = atoi(pos);
@ -9,7 +9,7 @@
} else if (os_strcmp(buf, "skip_inactivity_poll") == 0) { } else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
bss->skip_inactivity_poll = atoi(pos); bss->skip_inactivity_poll = atoi(pos);
} else if (os_strcmp(buf, "config_id") == 0) { } else if (os_strcmp(buf, "config_id") == 0) {
@@ -3128,6 +3130,8 @@ static int hostapd_config_fill(struct ho @@ -3130,6 +3132,8 @@ static int hostapd_config_fill(struct ho
} }
} else if (os_strcmp(buf, "acs_exclude_dfs") == 0) { } else if (os_strcmp(buf, "acs_exclude_dfs") == 0) {
conf->acs_exclude_dfs = atoi(pos); conf->acs_exclude_dfs = atoi(pos);

View File

@ -30,7 +30,7 @@
--- a/hostapd/config_file.c --- a/hostapd/config_file.c
+++ b/hostapd/config_file.c +++ b/hostapd/config_file.c
@@ -3353,6 +3353,8 @@ static int hostapd_config_fill(struct ho @@ -3355,6 +3355,8 @@ static int hostapd_config_fill(struct ho
#ifndef CONFIG_NO_VLAN #ifndef CONFIG_NO_VLAN
} else if (os_strcmp(buf, "dynamic_vlan") == 0) { } else if (os_strcmp(buf, "dynamic_vlan") == 0) {
bss->ssid.dynamic_vlan = atoi(pos); bss->ssid.dynamic_vlan = atoi(pos);

View File

@ -1,6 +1,6 @@
--- a/hostapd/config_file.c --- a/hostapd/config_file.c
+++ b/hostapd/config_file.c +++ b/hostapd/config_file.c
@@ -2316,6 +2316,8 @@ static int hostapd_config_fill(struct ho @@ -2318,6 +2318,8 @@ static int hostapd_config_fill(struct ho
sizeof(conf->bss[0]->iface)); sizeof(conf->bss[0]->iface));
} else if (os_strcmp(buf, "bridge") == 0) { } else if (os_strcmp(buf, "bridge") == 0) {
os_strlcpy(bss->bridge, pos, sizeof(bss->bridge)); os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));

View File

@ -1,6 +1,6 @@
--- a/hostapd/config_file.c --- a/hostapd/config_file.c
+++ b/hostapd/config_file.c +++ b/hostapd/config_file.c
@@ -2848,6 +2848,14 @@ static int hostapd_config_fill(struct ho @@ -2850,6 +2850,14 @@ static int hostapd_config_fill(struct ho
line, bss->max_num_sta, MAX_STA_COUNT); line, bss->max_num_sta, MAX_STA_COUNT);
return 1; return 1;
} }

View File

@ -1,6 +1,6 @@
--- a/hostapd/config_file.c --- a/hostapd/config_file.c
+++ b/hostapd/config_file.c +++ b/hostapd/config_file.c
@@ -3007,6 +3007,8 @@ static int hostapd_config_fill(struct ho @@ -3009,6 +3009,8 @@ static int hostapd_config_fill(struct ho
wpa_printf(MSG_INFO, wpa_printf(MSG_INFO,
"Line %d: Obsolete peerkey parameter ignored", line); "Line %d: Obsolete peerkey parameter ignored", line);
#ifdef CONFIG_IEEE80211R_AP #ifdef CONFIG_IEEE80211R_AP

View File

@ -55,7 +55,7 @@
"x_snoop: Failed to initialize L2 packet processing %s", "x_snoop: Failed to initialize L2 packet processing %s",
--- a/hostapd/config_file.c --- a/hostapd/config_file.c
+++ b/hostapd/config_file.c +++ b/hostapd/config_file.c
@@ -2320,6 +2320,8 @@ static int hostapd_config_fill(struct ho @@ -2322,6 +2322,8 @@ static int hostapd_config_fill(struct ho
os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge)); os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge));
} else if (os_strcmp(buf, "bridge_hairpin") == 0) { } else if (os_strcmp(buf, "bridge_hairpin") == 0) {
bss->bridge_hairpin = atoi(pos); bss->bridge_hairpin = atoi(pos);

View File

@ -1,6 +1,6 @@
--- a/hostapd/config_file.c --- a/hostapd/config_file.c
+++ b/hostapd/config_file.c +++ b/hostapd/config_file.c
@@ -1602,6 +1602,8 @@ static int parse_anqp_elem(struct hostap @@ -1604,6 +1604,8 @@ static int parse_anqp_elem(struct hostap
return 0; return 0;
} }
@ -9,7 +9,7 @@
static int parse_qos_map_set(struct hostapd_bss_config *bss, static int parse_qos_map_set(struct hostapd_bss_config *bss,
char *buf, int line) char *buf, int line)
@@ -1643,8 +1645,6 @@ static int parse_qos_map_set(struct host @@ -1645,8 +1647,6 @@ static int parse_qos_map_set(struct host
return 0; return 0;
} }
@ -18,7 +18,7 @@
#ifdef CONFIG_HS20 #ifdef CONFIG_HS20
static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf, static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf,
@@ -4064,10 +4064,10 @@ static int hostapd_config_fill(struct ho @@ -4066,10 +4066,10 @@ static int hostapd_config_fill(struct ho
bss->gas_frag_limit = val; bss->gas_frag_limit = val;
} else if (os_strcmp(buf, "gas_comeback_delay") == 0) { } else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
bss->gas_comeback_delay = atoi(pos); bss->gas_comeback_delay = atoi(pos);

View File

@ -98,7 +98,7 @@
hapd->conf->own_ip_addr.af == AF_INET && hapd->conf->own_ip_addr.af == AF_INET &&
--- a/hostapd/config_file.c --- a/hostapd/config_file.c
+++ b/hostapd/config_file.c +++ b/hostapd/config_file.c
@@ -2688,6 +2688,8 @@ static int hostapd_config_fill(struct ho @@ -2690,6 +2690,8 @@ static int hostapd_config_fill(struct ho
} else if (os_strcmp(buf, "iapp_interface") == 0) { } else if (os_strcmp(buf, "iapp_interface") == 0) {
wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used"); wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used");
#endif /* CONFIG_IAPP */ #endif /* CONFIG_IAPP */