DFS: Use channel switch when radar is detected

Until now DFS was simply restarting the AP when radar was detected. Now
CSA is used to perform smooth switch to the new channel. Stations not
supporting CSA will behave as before.

Signed-hostap: Janusz Dziedzic <janusz.dziedzic@tieto.com>
Signed-hostap: Michal Kazior <michal.kazior@tieto.com>
This commit is contained in:
Janusz Dziedzic 2013-11-25 20:16:15 +01:00 committed by Jouni Malinen
parent 6c6c58d157
commit f7154ceef7
1 changed files with 100 additions and 29 deletions

View File

@ -627,27 +627,111 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
}
static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
{
struct hostapd_channel_data *channel;
int err = 1;
int secondary_channel;
u8 vht_oper_centr_freq_seg0_idx;
u8 vht_oper_centr_freq_seg1_idx;
int skip_radar = 1;
int skip_radar = 0;
int err = 1;
wpa_printf(MSG_DEBUG, "%s called", __func__);
/* Radar detected during active CAC */
iface->cac_started = 0;
channel = dfs_get_valid_channel(iface, &secondary_channel,
&vht_oper_centr_freq_seg0_idx,
&vht_oper_centr_freq_seg1_idx,
skip_radar);
if (channel) {
wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
channel->chan);
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
"freq=%d chan=%d sec_chan=%d", channel->freq,
channel->chan, secondary_channel);
if (!channel) {
wpa_printf(MSG_ERROR, "No valid channel available");
hostapd_setup_interface_complete(iface, err);
return err;
}
wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
channel->chan);
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
"freq=%d chan=%d sec_chan=%d", channel->freq,
channel->chan, secondary_channel);
iface->freq = channel->freq;
iface->conf->channel = channel->chan;
iface->conf->secondary_channel = secondary_channel;
iface->conf->vht_oper_centr_freq_seg0_idx =
vht_oper_centr_freq_seg0_idx;
iface->conf->vht_oper_centr_freq_seg1_idx =
vht_oper_centr_freq_seg1_idx;
err = 0;
hostapd_setup_interface_complete(iface, err);
return err;
}
static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
{
struct hostapd_channel_data *channel;
int secondary_channel;
u8 vht_oper_centr_freq_seg0_idx;
u8 vht_oper_centr_freq_seg1_idx;
int skip_radar = 1;
struct csa_settings csa_settings;
struct hostapd_data *hapd = iface->bss[0];
int err = 1;
wpa_printf(MSG_DEBUG, "%s called (CAC active: %s)", __func__,
iface->cac_started ? "yes" : "no");
/* Check if active CAC */
if (iface->cac_started)
return hostapd_dfs_start_channel_switch_cac(iface);
/* Perform channel switch/CSA */
channel = dfs_get_valid_channel(iface, &secondary_channel,
&vht_oper_centr_freq_seg0_idx,
&vht_oper_centr_freq_seg1_idx,
skip_radar);
if (!channel) {
/* FIXME: Wait for channel(s) to become available */
hostapd_disable_iface(iface);
return err;
}
wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
channel->chan);
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL
"freq=%d chan=%d sec_chan=%d", channel->freq,
channel->chan, secondary_channel);
/* Setup CSA request */
os_memset(&csa_settings, 0, sizeof(csa_settings));
csa_settings.cs_count = 5;
csa_settings.block_tx = 1;
err = hostapd_set_freq_params(&csa_settings.freq_params,
iface->conf->hw_mode,
channel->freq,
channel->chan,
iface->conf->ieee80211n,
iface->conf->ieee80211ac,
secondary_channel,
iface->conf->vht_oper_chwidth,
vht_oper_centr_freq_seg0_idx,
vht_oper_centr_freq_seg1_idx,
iface->current_mode->vht_capab);
if (err) {
wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
hostapd_disable_iface(iface);
return err;
}
err = hostapd_switch_channel(hapd, &csa_settings);
if (err) {
wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback",
err);
iface->freq = channel->freq;
iface->conf->channel = channel->chan;
iface->conf->secondary_channel = secondary_channel;
@ -655,29 +739,16 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
vht_oper_centr_freq_seg0_idx;
iface->conf->vht_oper_centr_freq_seg1_idx =
vht_oper_centr_freq_seg1_idx;
err = 0;
} else {
wpa_printf(MSG_ERROR, "No valid channel available");
}
if (iface->cac_started) {
wpa_printf(MSG_DEBUG, "DFS radar detected during CAC");
iface->cac_started = 0;
/* FIXME: Wait for channel(s) to become available if no channel
* has been found */
hostapd_setup_interface_complete(iface, err);
return err;
}
if (err) {
/* FIXME: Wait for channel(s) to become available */
hostapd_disable_iface(iface);
return err;
hostapd_enable_iface(iface);
return 0;
}
wpa_printf(MSG_DEBUG, "DFS radar detected");
hostapd_disable_iface(iface);
hostapd_enable_iface(iface);
/* Channel configuration will be updated once CSA completes and
* ch_switch_notify event is received */
wpa_printf(MSG_DEBUG, "DFS waiting channel switch event");
return 0;
}