@@ -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);
@@ -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,
@@ -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;
@@ -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 ||
@@ -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);
}
@@ -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")