[PATCH 7/7] AP: Avoid disabling HT/VHT/HE/EHT during CSA

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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>
Reviewed-by: Otcheretianski, Andrei <andrei.otcheretianski@xxxxxxxxx>
Signed-off-by: Benjamin Berg <benjamin.berg@xxxxxxxxx>
---
 hostapd/ctrl_iface.c       | 14 ++++++++--
 src/ap/ap_config.h         | 21 +++++---------
 src/ap/ctrl_iface_ap.c     | 20 +++++++++++++
 src/ap/dfs.c               |  9 ++++++
 src/ap/drv_callbacks.c     | 57 +++++++++-----------------------------
 src/ap/hostapd.c           | 25 ++++++-----------
 tests/hwsim/test_ap_vht.py |  8 +++---
 7 files changed, 73 insertions(+), 81 deletions(-)

diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index f3b31c79de..f77f457430 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -2483,6 +2483,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) {
@@ -2517,8 +2529,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 af0d785be2..20aeaaccb3 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -1183,15 +1183,13 @@ 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;
@@ -1220,11 +1218,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/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index dcea7a0eb1..eb44e45015 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -1456,6 +1456,26 @@ int hostapd_parse_csa_settings(struct hostapd_iface *iface,
 		return ret;
 	}
 
+	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;
+	}
+
 	return 0;
 }
 
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 0cac194b26..3463740290 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -1028,7 +1028,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)
 			num_err++;
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index aebd52c0c7..0d9cf43398 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -1245,8 +1245,9 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
 		       HOSTAPD_LEVEL_INFO,
 		       "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,
+		       hapd->iface->freq, 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,
@@ -1321,49 +1322,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 65df420a06..8be1490b87 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -4646,27 +4646,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 3149d51177..16f846c311 100644
--- a/tests/hwsim/test_ap_vht.py
+++ b/tests/hwsim/test_ap_vht.py
@@ -948,8 +948,8 @@ def test_ap_vht_csa_vht20(dev, apdev):
     finally:
         clear_regdom(hapd, dev, 2)
 
-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
@@ -993,8 +993,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:
         clear_regdom(hapd, dev, count=2)
 
-- 
2.50.1


_______________________________________________
Hostap mailing list
Hostap@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/hostap



[Index of Archives]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux