From: Ilan Peer <ilan.peer@xxxxxxxxx> During CSA an AP should not disable its HT/VHT/HE/EHT capabilities as it is not allowed by the IEEE80211 specification. - Modify the CSA flow to preserve the current HT/VHT/HE/EHT capabilities allowing only to add additional ones. - Update the DFS CSA flow to also preserve the HT/VHT/HE/EHT capabilities. Modify one of the hwsim tests that verified that VHT capabilities are disabled during CSA, to verify that they are kept. Signed-off-by: Ilan Peer <ilan.peer@xxxxxxxxx> --- hostapd/ctrl_iface.c | 34 +++++++++++++++++++++-- src/ap/ap_config.h | 23 ++++++---------- src/ap/dfs.c | 9 ++++++ src/ap/drv_callbacks.c | 56 +++++++++----------------------------- src/ap/hostapd.c | 25 ++++++----------- tests/hwsim/test_ap_vht.py | 8 +++--- 6 files changed, 74 insertions(+), 81 deletions(-) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index f9a78651ca..e654d932c7 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -2603,6 +2603,26 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, break; } + if (!settings.freq_params.ht_enabled && iface->conf->ieee80211n) { + wpa_printf(MSG_WARNING, "CSA: Cannot disable HT. Ignore"); + settings.freq_params.ht_enabled = iface->conf->ieee80211n; + } + + if (!settings.freq_params.vht_enabled && iface->conf->ieee80211ac) { + wpa_printf(MSG_WARNING, "CSA: Cannot disable VHT. Ignore"); + settings.freq_params.vht_enabled = iface->conf->ieee80211ac; + } + + if (!settings.freq_params.he_enabled && iface->conf->ieee80211ax) { + wpa_printf(MSG_WARNING, "CSA: Cannot disable HE. Ignore"); + settings.freq_params.he_enabled = iface->conf->ieee80211ax; + } + + if (!settings.freq_params.eht_enabled && iface->conf->ieee80211be) { + wpa_printf(MSG_WARNING, "CSA: Cannot disable EHT. Ignore"); + settings.freq_params.eht_enabled = iface->conf->ieee80211be; + } + if (settings.freq_params.center_freq1) dfs_range += hostapd_is_dfs_overlap( iface, bandwidth, settings.freq_params.center_freq1); @@ -2614,6 +2634,18 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, dfs_range += hostapd_is_dfs_overlap( iface, bandwidth, settings.freq_params.center_freq2); + /* If VHT/HE/EHT was enabled, we must also set the bandwidth and center + * frequency + */ + if ((settings.freq_params.vht_enabled || + settings.freq_params.he_enabled || + settings.freq_params.eht_enabled) && + (!settings.freq_params.bandwidth || + !settings.freq_params.center_freq1)) { + settings.freq_params.bandwidth = 20; + settings.freq_params.center_freq1 = settings.freq_params.freq; + } + if (dfs_range) { ret = ieee80211_freq_to_chan(settings.freq_params.freq, &chan); if (ret == NUM_HOSTAPD_MODES) { @@ -2641,8 +2673,6 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, } for (i = 0; i < iface->num_bss; i++) { - - /* Save CHAN_SWITCH VHT, HE, and EHT config */ hostapd_chan_switch_config(iface->bss[i], &settings.freq_params); diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 1d39495595..baf2ebb8bf 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -1164,16 +1164,14 @@ struct hostapd_config { bool require_he; #endif /* CONFIG_IEEE80211AX */ - - /* VHT enable/disable config from CHAN_SWITCH */ -#define CH_SWITCH_VHT_ENABLED BIT(0) -#define CH_SWITCH_VHT_DISABLED BIT(1) - unsigned int ch_switch_vht_config; - - /* HE enable/disable config from CHAN_SWITCH */ -#define CH_SWITCH_HE_ENABLED BIT(0) -#define CH_SWITCH_HE_DISABLED BIT(1) - unsigned int ch_switch_he_config; + /* + * Save the expected HT/VHT/HE/EHT configuration so it could be used + * once CSA is done + */ + unsigned int ch_switch_ht_config:1; + unsigned int ch_switch_vht_config:1; + unsigned int ch_switch_he_config:1; + unsigned int ch_switch_eht_config:1; int rssi_reject_assoc_rssi; int rssi_reject_assoc_timeout; @@ -1202,11 +1200,6 @@ struct hostapd_config { u8 eht_bw320_offset; #endif /* CONFIG_IEEE80211BE */ - /* EHT enable/disable config from CHAN_SWITCH */ -#define CH_SWITCH_EHT_ENABLED BIT(0) -#define CH_SWITCH_EHT_DISABLED BIT(1) - unsigned int ch_switch_eht_config; - enum mbssid { MBSSID_DISABLED = 0, MBSSID_ENABLED = 1, diff --git a/src/ap/dfs.c b/src/ap/dfs.c index 18cb355a75..a91eb22475 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -1016,7 +1016,16 @@ static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface, return err; } + /* preserve the HT/VHT/HE/EHT configuration */ + csa_settings.freq_params.ht_enabled = iface->conf->ieee80211n; + csa_settings.freq_params.vht_enabled = iface->conf->ieee80211ac; + csa_settings.freq_params.he_enabled = iface->conf->ieee80211ax; + csa_settings.freq_params.eht_enabled = iface->conf->ieee80211be; + for (i = 0; i < iface->num_bss; i++) { + hostapd_chan_switch_config(iface->bss[i], + &csa_settings.freq_params); + err = hostapd_switch_channel(iface->bss[i], &csa_settings); if (err) break; diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 210068a94d..f30fa364da 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -1036,7 +1036,9 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, "driver %s channel switch: iface->freq=%d, freq=%d, ht=%d, vht_ch=0x%x, he_ch=0x%x, eht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d, puncturing_bitmap=0x%x", finished ? "had" : "starting", hapd->iface->freq, - freq, ht, hapd->iconf->ch_switch_vht_config, + freq, + hapd->iconf->ch_switch_ht_config, + hapd->iconf->ch_switch_vht_config, hapd->iconf->ch_switch_he_config, hapd->iconf->ch_switch_eht_config, offset, width, channel_width_to_string(width), cf1, cf2, @@ -1111,49 +1113,17 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, } hapd->iconf->channel = channel; - hapd->iconf->ieee80211n = ht; - if (!ht) - hapd->iconf->ieee80211ac = 0; - if (hapd->iconf->ch_switch_vht_config) { - /* CHAN_SWITCH VHT config */ - if (hapd->iconf->ch_switch_vht_config & - CH_SWITCH_VHT_ENABLED) - hapd->iconf->ieee80211ac = 1; - else if (hapd->iconf->ch_switch_vht_config & - CH_SWITCH_VHT_DISABLED) - hapd->iconf->ieee80211ac = 0; - } - if (hapd->iconf->ch_switch_he_config) { - /* CHAN_SWITCH HE config */ - if (hapd->iconf->ch_switch_he_config & - CH_SWITCH_HE_ENABLED) { - hapd->iconf->ieee80211ax = 1; - if (hapd->iface->freq > 4000 && - hapd->iface->freq < 5895) - hapd->iconf->ieee80211ac = 1; - } - else if (hapd->iconf->ch_switch_he_config & - CH_SWITCH_HE_DISABLED) - hapd->iconf->ieee80211ax = 0; - } -#ifdef CONFIG_IEEE80211BE - if (hapd->iconf->ch_switch_eht_config) { - /* CHAN_SWITCH EHT config */ - if (hapd->iconf->ch_switch_eht_config & - CH_SWITCH_EHT_ENABLED) { - hapd->iconf->ieee80211be = 1; - hapd->iconf->ieee80211ax = 1; - if (!is_6ghz_freq(hapd->iface->freq) && - hapd->iface->freq > 4000) - hapd->iconf->ieee80211ac = 1; - } else if (hapd->iconf->ch_switch_eht_config & - CH_SWITCH_EHT_DISABLED) - hapd->iconf->ieee80211be = 0; + hapd->iconf->ieee80211n = hapd->iconf->ch_switch_ht_config; + hapd->iconf->ieee80211ac = hapd->iconf->ch_switch_vht_config; + hapd->iconf->ieee80211ax = hapd->iconf->ch_switch_he_config; + hapd->iconf->ieee80211be = hapd->iconf->ch_switch_eht_config; + + if (finished) { + hapd->iconf->ch_switch_ht_config = 0; + hapd->iconf->ch_switch_vht_config = 0; + hapd->iconf->ch_switch_he_config = 0; + hapd->iconf->ch_switch_eht_config = 0; } -#endif /* CONFIG_IEEE80211BE */ - hapd->iconf->ch_switch_vht_config = 0; - hapd->iconf->ch_switch_he_config = 0; - hapd->iconf->ch_switch_eht_config = 0; if (width == CHAN_WIDTH_40 || width == CHAN_WIDTH_80 || width == CHAN_WIDTH_80P80 || width == CHAN_WIDTH_160 || diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 6a9b07e864..83ec043ba1 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -4034,27 +4034,18 @@ void hostapd_cleanup_cs_params(struct hostapd_data *hapd) void hostapd_chan_switch_config(struct hostapd_data *hapd, struct hostapd_freq_params *freq_params) { - if (freq_params->eht_enabled) - hapd->iconf->ch_switch_eht_config |= CH_SWITCH_EHT_ENABLED; - else - hapd->iconf->ch_switch_eht_config |= CH_SWITCH_EHT_DISABLED; - - if (freq_params->he_enabled) - hapd->iconf->ch_switch_he_config |= CH_SWITCH_HE_ENABLED; - else - hapd->iconf->ch_switch_he_config |= CH_SWITCH_HE_DISABLED; - - if (freq_params->vht_enabled) - hapd->iconf->ch_switch_vht_config |= CH_SWITCH_VHT_ENABLED; - else - hapd->iconf->ch_switch_vht_config |= CH_SWITCH_VHT_DISABLED; + hapd->iconf->ch_switch_ht_config = freq_params->ht_enabled; + hapd->iconf->ch_switch_vht_config = freq_params->vht_enabled; + hapd->iconf->ch_switch_he_config = freq_params->he_enabled; + hapd->iconf->ch_switch_eht_config = freq_params->eht_enabled; hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, - "CHAN_SWITCH EHT config 0x%x HE config 0x%x VHT config 0x%x", - hapd->iconf->ch_switch_eht_config, + "CHAN_SWITCH: config: ht=%u, vht=%u, he=%u, eht=%u", + hapd->iconf->ch_switch_ht_config, + hapd->iconf->ch_switch_vht_config, hapd->iconf->ch_switch_he_config, - hapd->iconf->ch_switch_vht_config); + hapd->iconf->ch_switch_eht_config); } diff --git a/tests/hwsim/test_ap_vht.py b/tests/hwsim/test_ap_vht.py index 2a7da8f68c..a6ef121229 100644 --- a/tests/hwsim/test_ap_vht.py +++ b/tests/hwsim/test_ap_vht.py @@ -969,8 +969,8 @@ def test_ap_vht_csa_vht20(dev, apdev): dev[0].flush_scan_cache() dev[1].flush_scan_cache() -def test_ap_vht_csa_vht40_disable(dev, apdev): - """VHT CSA with VHT40 getting disabled""" +def test_ap_vht_csa_vht40_unchanged(dev, apdev): + """VHT CSA with VHT not specified. Verify the VHT was not disabled""" csa_supported(dev[0]) try: hapd = None @@ -1014,8 +1014,8 @@ def test_ap_vht_csa_vht40_disable(dev, apdev): dev[1].connect("vht", key_mgmt="NONE", scan_freq="5200") hwsim_utils.test_connectivity(dev[1], hapd) - if dev[1].get_status_field("ieee80211ac") == '1': - raise Exception("VHT not disabled as part of channel switch") + if dev[1].get_status_field("ieee80211ac") != '1': + raise Exception("VHT unexpectedly disabled as part of channel switch") finally: dev[0].request("DISCONNECT") dev[1].request("DISCONNECT") -- 2.43.0 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap