diff mbox series

[RFC,4/5] hostapd: add support for DFS channels in hostapd_cli chan_switch

Message ID 20200128150940.17018-5-sergey.matyukevich.os@quantenna.com
State Accepted
Headers show
Series hostapd: DFS channels in chan_switch command ane event | expand

Commit Message

Sergey Matyukevich Jan. 28, 2020, 3:09 p.m. UTC
Enable support for DFS channels in hostapd_cli chan_switch command.
Perform CAC instead of CSA if DFS channel is selected. Then restart
normal AP operations.

Note that current implementation provides a simplified approach. It
does not check if selected DFS channel block is already in
HOSTAPD_CHAN_DFS_AVAILABLE state. CAC procedure is restarted anyway.

Signed-off-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com>
---
 hostapd/ctrl_iface.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 59 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 4ea22e3d2..5b36755cb 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -59,6 +59,7 @@ 
 #include "ap/neighbor_db.h"
 #include "ap/rrm.h"
 #include "ap/dpp_hostapd.h"
+#include "ap/dfs.h"
 #include "wps/wps_defs.h"
 #include "wps/wps.h"
 #include "fst/fst_ctrl_iface.h"
@@ -2503,8 +2504,11 @@  static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
 {
 #ifdef NEED_AP_MLME
 	struct csa_settings settings;
-	int ret;
+	int dfs_range = 0;
 	unsigned int i;
+	int bandwidth;
+	int ret;
+	u8 chan;
 
 	ret = hostapd_parse_csa_settings(pos, &settings);
 	if (ret)
@@ -2516,6 +2520,60 @@  static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
 		return ret;
 	}
 
+	switch (settings.freq_params.bandwidth) {
+	case 40:
+		bandwidth = CHAN_WIDTH_40;
+		break;
+	case 80:
+		if (settings.freq_params.center_freq2)
+			bandwidth = CHAN_WIDTH_80P80;
+		else
+			bandwidth = CHAN_WIDTH_80;
+		break;
+	case 160:
+		bandwidth = CHAN_WIDTH_160;
+		break;
+	default:
+		bandwidth = CHAN_WIDTH_20;
+		break;
+	}
+
+	if (settings.freq_params.center_freq1)
+		dfs_range += hostapd_is_dfs_overlap(iface, bandwidth,
+						    settings.freq_params.center_freq1);
+	else
+		dfs_range += hostapd_is_dfs_overlap(iface, bandwidth,
+						    settings.freq_params.freq);
+
+	if (settings.freq_params.center_freq2)
+		dfs_range += hostapd_is_dfs_overlap(iface, bandwidth,
+						    settings.freq_params.center_freq2);
+
+	if (dfs_range) {
+		ret = ieee80211_freq_to_chan(settings.freq_params.freq, &chan);
+		if (ret == NUM_HOSTAPD_MODES) {
+			wpa_printf(MSG_ERROR, "failed to get channel for (freq=%d, sec_channel_offset=%d, bw=%d)",
+				   settings.freq_params.freq,
+				   settings.freq_params.sec_channel_offset,
+				   settings.freq_params.bandwidth);
+			return -1;
+		}
+
+		settings.freq_params.channel = chan;
+
+		wpa_printf(MSG_DEBUG,
+				"DFS/CAC to (channel=%u, freq=%d, sec_channel_offset=%d, bw=%d, center_freq1=%d)",
+				settings.freq_params.channel,
+				settings.freq_params.freq,
+				settings.freq_params.sec_channel_offset,
+				settings.freq_params.bandwidth,
+				settings.freq_params.center_freq1);
+
+		/* perform CAC and switch channel */
+		hostapd_switch_channel_fallback(iface, &settings.freq_params);
+		return 0;
+	}
+
 	for (i = 0; i < iface->num_bss; i++) {
 
 		/* Save CHAN_SWITCH VHT config */