hostapd: Use channel switch fallback on error
It's worth giving a try to fallback to re-starting BSSes at least once hoping it works out instead of just leaving BSSes disabled. Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
This commit is contained in:
parent
8974620e3e
commit
5841958f26
4 changed files with 83 additions and 6 deletions
|
@ -885,6 +885,20 @@ static void hostapd_event_get_survey(struct hostapd_data *hapd,
|
|||
|
||||
#ifdef NEED_AP_MLME
|
||||
|
||||
static void hostapd_event_iface_unavailable(struct hostapd_data *hapd)
|
||||
{
|
||||
wpa_printf(MSG_DEBUG, "Interface %s is unavailable -- stopped",
|
||||
hapd->conf->iface);
|
||||
|
||||
if (hapd->csa_in_progress) {
|
||||
wpa_printf(MSG_INFO, "CSA failed (%s was stopped)",
|
||||
hapd->conf->iface);
|
||||
hostapd_switch_channel_fallback(hapd->iface,
|
||||
&hapd->cs_freq_params);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void hostapd_event_dfs_radar_detected(struct hostapd_data *hapd,
|
||||
struct dfs_event *radar)
|
||||
{
|
||||
|
@ -1072,6 +1086,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|||
hostapd_event_get_survey(hapd, &data->survey_results);
|
||||
break;
|
||||
#ifdef NEED_AP_MLME
|
||||
case EVENT_INTERFACE_UNAVAILABLE:
|
||||
hostapd_event_iface_unavailable(hapd);
|
||||
break;
|
||||
case EVENT_DFS_RADAR_DETECTED:
|
||||
if (!data)
|
||||
break;
|
||||
|
|
|
@ -2280,13 +2280,13 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd,
|
|||
|
||||
if (!params->channel) {
|
||||
/* check if the new channel is supported by hw */
|
||||
channel = hostapd_hw_get_channel(hapd, params->freq);
|
||||
if (!channel)
|
||||
return -1;
|
||||
} else {
|
||||
channel = params->channel;
|
||||
params->channel = hostapd_hw_get_channel(hapd, params->freq);
|
||||
}
|
||||
|
||||
channel = params->channel;
|
||||
if (!channel)
|
||||
return -1;
|
||||
|
||||
/* if a pointer to old_params is provided we save previous state */
|
||||
if (old_params) {
|
||||
old_params->channel = conf->channel;
|
||||
|
@ -2381,4 +2381,60 @@ int hostapd_switch_channel(struct hostapd_data *hapd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
hostapd_switch_channel_fallback(struct hostapd_iface *iface,
|
||||
const struct hostapd_freq_params *freq_params)
|
||||
{
|
||||
int vht_seg0_idx = 0, vht_seg1_idx = 0, vht_bw = VHT_CHANWIDTH_USE_HT;
|
||||
unsigned int i;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Restarting all CSA-related BSSes");
|
||||
|
||||
if (freq_params->center_freq1)
|
||||
vht_seg0_idx = 36 + (freq_params->center_freq1 - 5180) / 5;
|
||||
if (freq_params->center_freq2)
|
||||
vht_seg1_idx = 36 + (freq_params->center_freq2 - 5180) / 5;
|
||||
|
||||
switch (freq_params->bandwidth) {
|
||||
case 0:
|
||||
case 20:
|
||||
case 40:
|
||||
vht_bw = VHT_CHANWIDTH_USE_HT;
|
||||
break;
|
||||
case 80:
|
||||
if (freq_params->center_freq2)
|
||||
vht_bw = VHT_CHANWIDTH_80P80MHZ;
|
||||
else
|
||||
vht_bw = VHT_CHANWIDTH_80MHZ;
|
||||
break;
|
||||
case 160:
|
||||
vht_bw = VHT_CHANWIDTH_160MHZ;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_WARNING, "Unknown CSA bandwidth: %d",
|
||||
freq_params->bandwidth);
|
||||
break;
|
||||
}
|
||||
|
||||
iface->freq = freq_params->freq;
|
||||
iface->conf->channel = freq_params->channel;
|
||||
iface->conf->secondary_channel = freq_params->sec_channel_offset;
|
||||
iface->conf->vht_oper_centr_freq_seg0_idx = vht_seg0_idx;
|
||||
iface->conf->vht_oper_centr_freq_seg1_idx = vht_seg1_idx;
|
||||
iface->conf->vht_oper_chwidth = vht_bw;
|
||||
iface->conf->ieee80211n = freq_params->ht_enabled;
|
||||
iface->conf->ieee80211ac = freq_params->vht_enabled;
|
||||
|
||||
/*
|
||||
* cs_params must not be cleared earlier because the freq_params
|
||||
* argument may actually point to one of these.
|
||||
*/
|
||||
for (i = 0; i < iface->num_bss; i++)
|
||||
hostapd_cleanup_cs_params(iface->bss[i]);
|
||||
|
||||
hostapd_disable_iface(iface);
|
||||
hostapd_enable_iface(iface);
|
||||
}
|
||||
|
||||
#endif /* NEED_AP_MLME */
|
||||
|
|
|
@ -397,6 +397,9 @@ void hostapd_set_state(struct hostapd_iface *iface, enum hostapd_iface_state s);
|
|||
const char * hostapd_state_text(enum hostapd_iface_state s);
|
||||
int hostapd_switch_channel(struct hostapd_data *hapd,
|
||||
struct csa_settings *settings);
|
||||
void
|
||||
hostapd_switch_channel_fallback(struct hostapd_iface *iface,
|
||||
const struct hostapd_freq_params *freq_params);
|
||||
void hostapd_cleanup_cs_params(struct hostapd_data *hapd);
|
||||
|
||||
/* utils.c */
|
||||
|
|
|
@ -3316,7 +3316,8 @@ enum wpa_event_type {
|
|||
* the driver does not support radar detection and another virtual
|
||||
* interfaces caused the operating channel to change. Other similar
|
||||
* resource conflicts could also trigger this for station mode
|
||||
* interfaces.
|
||||
* interfaces. This event can be propagated when channel switching
|
||||
* fails.
|
||||
*/
|
||||
EVENT_INTERFACE_UNAVAILABLE,
|
||||
|
||||
|
|
Loading…
Reference in a new issue