From c60717f839649c522757e01541f3d4b749658299 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 28 Jan 2020 15:09:53 +0000 Subject: [PATCH] hostapd: Add support for DFS channels in CHAN_SWITCH Enable support for DFS channels in the CHAN_SWITCH command. Perform CAC instead of CSA if DFS channel is selected. Then restart normal AP operations. Note that the current implementation provides a simplified approach. It does not check if the selected DFS channel block is already in the HOSTAPD_CHAN_DFS_AVAILABLE state. CAC procedure is restarted anyway. Signed-off-by: Sergey Matyukevich --- hostapd/ctrl_iface.c | 59 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index f35f87edc..d90b5dc8f 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" @@ -2528,7 +2529,10 @@ 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; + u8 chan; ret = hostapd_parse_csa_settings(pos, &settings); if (ret) @@ -2541,6 +2545,61 @@ 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 */