hostapd: Fix to downgrade bandwidth in radar detection
Upon radar detection we used to search channels with the same bandwidth. This way we might not find any other channels. If there are no channels available with that bandwidth the AP service will be stopped. To avoid this problem, also search a suitable channel by downgrading the bandwidth. This scenario is applicable during CAC as well. Signed-off-by: Seevalamuthu Mariappan <seevalam@codeaurora.org>
This commit is contained in:
parent
7242087d1c
commit
4b37d24285
1 changed files with 67 additions and 23 deletions
90
src/ap/dfs.c
90
src/ap/dfs.c
|
@ -851,6 +851,41 @@ int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq,
|
|||
}
|
||||
|
||||
|
||||
static struct hostapd_channel_data *
|
||||
dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel,
|
||||
u8 *oper_centr_freq_seg0_idx,
|
||||
u8 *oper_centr_freq_seg1_idx, int *skip_radar)
|
||||
{
|
||||
struct hostapd_channel_data *channel;
|
||||
|
||||
for (;;) {
|
||||
channel = dfs_get_valid_channel(iface, secondary_channel,
|
||||
oper_centr_freq_seg0_idx,
|
||||
oper_centr_freq_seg1_idx,
|
||||
*skip_radar);
|
||||
if (channel) {
|
||||
wpa_printf(MSG_DEBUG, "DFS: Selected channel: %d",
|
||||
channel->chan);
|
||||
return channel;
|
||||
}
|
||||
|
||||
if (*skip_radar) {
|
||||
*skip_radar = 0;
|
||||
} else {
|
||||
if (iface->conf->vht_oper_chwidth == CHANWIDTH_USE_HT)
|
||||
break;
|
||||
*skip_radar = 1;
|
||||
iface->conf->vht_oper_chwidth--;
|
||||
}
|
||||
}
|
||||
|
||||
wpa_printf(MSG_INFO,
|
||||
"%s: no DFS channels left, waiting for NOP to finish",
|
||||
__func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
|
||||
{
|
||||
struct hostapd_channel_data *channel;
|
||||
|
@ -868,8 +903,14 @@ static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface)
|
|||
skip_radar);
|
||||
|
||||
if (!channel) {
|
||||
wpa_printf(MSG_ERROR, "No valid channel available");
|
||||
return err;
|
||||
channel = dfs_downgrade_bandwidth(iface, &secondary_channel,
|
||||
&oper_centr_freq_seg0_idx,
|
||||
&oper_centr_freq_seg1_idx,
|
||||
&skip_radar);
|
||||
if (!channel) {
|
||||
wpa_printf(MSG_ERROR, "No valid channel available");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
|
||||
|
@ -898,11 +939,13 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
|
|||
int secondary_channel;
|
||||
u8 oper_centr_freq_seg0_idx;
|
||||
u8 oper_centr_freq_seg1_idx;
|
||||
u8 new_vht_oper_chwidth;
|
||||
int skip_radar = 1;
|
||||
struct csa_settings csa_settings;
|
||||
unsigned int i;
|
||||
int err = 1;
|
||||
struct hostapd_hw_modes *cmode = iface->current_mode;
|
||||
u8 current_vht_oper_chwidth = iface->conf->vht_oper_chwidth;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)",
|
||||
__func__, iface->cac_started ? "yes" : "no",
|
||||
|
@ -936,28 +979,25 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
|
|||
* requires to perform a CAC first.
|
||||
*/
|
||||
skip_radar = 0;
|
||||
channel = dfs_get_valid_channel(iface, &secondary_channel,
|
||||
&oper_centr_freq_seg0_idx,
|
||||
&oper_centr_freq_seg1_idx,
|
||||
skip_radar);
|
||||
if (!channel) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"%s: no DFS channels left, waiting for NOP to finish",
|
||||
__func__);
|
||||
channel = dfs_downgrade_bandwidth(iface, &secondary_channel,
|
||||
&oper_centr_freq_seg0_idx,
|
||||
&oper_centr_freq_seg1_idx,
|
||||
&skip_radar);
|
||||
if (!channel)
|
||||
return err;
|
||||
if (!skip_radar) {
|
||||
iface->freq = channel->freq;
|
||||
iface->conf->channel = channel->chan;
|
||||
iface->conf->secondary_channel = secondary_channel;
|
||||
hostapd_set_oper_centr_freq_seg0_idx(
|
||||
iface->conf, oper_centr_freq_seg0_idx);
|
||||
hostapd_set_oper_centr_freq_seg1_idx(
|
||||
iface->conf, oper_centr_freq_seg1_idx);
|
||||
|
||||
hostapd_disable_iface(iface);
|
||||
hostapd_enable_iface(iface);
|
||||
return 0;
|
||||
}
|
||||
|
||||
iface->freq = channel->freq;
|
||||
iface->conf->channel = channel->chan;
|
||||
iface->conf->secondary_channel = secondary_channel;
|
||||
hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
|
||||
oper_centr_freq_seg0_idx);
|
||||
hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
|
||||
oper_centr_freq_seg1_idx);
|
||||
|
||||
hostapd_disable_iface(iface);
|
||||
hostapd_enable_iface(iface);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d",
|
||||
|
@ -966,6 +1006,9 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
|
|||
"freq=%d chan=%d sec_chan=%d", channel->freq,
|
||||
channel->chan, secondary_channel);
|
||||
|
||||
new_vht_oper_chwidth = iface->conf->vht_oper_chwidth;
|
||||
iface->conf->vht_oper_chwidth = current_vht_oper_chwidth;
|
||||
|
||||
/* Setup CSA request */
|
||||
os_memset(&csa_settings, 0, sizeof(csa_settings));
|
||||
csa_settings.cs_count = 5;
|
||||
|
@ -980,7 +1023,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
|
|||
iface->conf->ieee80211ac,
|
||||
iface->conf->ieee80211ax,
|
||||
secondary_channel,
|
||||
hostapd_get_oper_chwidth(iface->conf),
|
||||
new_vht_oper_chwidth,
|
||||
oper_centr_freq_seg0_idx,
|
||||
oper_centr_freq_seg1_idx,
|
||||
cmode->vht_capab,
|
||||
|
@ -1004,6 +1047,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
|
|||
iface->freq = channel->freq;
|
||||
iface->conf->channel = channel->chan;
|
||||
iface->conf->secondary_channel = secondary_channel;
|
||||
iface->conf->vht_oper_chwidth = new_vht_oper_chwidth;
|
||||
hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
|
||||
oper_centr_freq_seg0_idx);
|
||||
hostapd_set_oper_centr_freq_seg1_idx(iface->conf,
|
||||
|
|
Loading…
Reference in a new issue