[PATCH 4/4] hostapd: Use channel switch fallback on error
Michal Kazior
michal.kazior
Wed Jun 25 04:20:26 PDT 2014
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 at tieto.com>
---
src/ap/drv_callbacks.c | 11 +++++++++++
src/ap/hostapd.c | 51 +++++++++++++++++++++++++++++++++++++++++++++-----
src/ap/hostapd.h | 8 ++++++++
src/drivers/driver.h | 3 ++-
4 files changed, 67 insertions(+), 6 deletions(-)
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index ac5732c..561cbf9 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -885,6 +885,14 @@ 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 is unavailable -- stopped");
+ hostapd_switch_channel_fallback(hapd);
+}
+
+
static void hostapd_event_dfs_radar_detected(struct hostapd_data *hapd,
struct dfs_event *radar)
{
@@ -1072,6 +1080,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;
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 4da5a3d..c504364 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -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;
@@ -2363,11 +2363,25 @@ void hostapd_cleanup_cs_params(struct hostapd_data *hapd)
int hostapd_switch_channel(struct hostapd_data *hapd,
struct csa_settings *settings)
{
+ struct hostapd_iface *iface = hapd->iface;
int ret;
+
ret = hostapd_fill_csa_settings(hapd, settings);
if (ret)
return ret;
+ iface->csa_freq = settings->freq_params.freq;
+ iface->csa_channel = settings->freq_params.channel;
+ iface->csa_secondary_channel = settings->freq_params.sec_channel_offset;
+
+ if (settings->freq_params.center_freq1)
+ iface->csa_vht_oper_centr_freq_seg0_idx =
+ 36 + (settings->freq_params.center_freq1 - 5180) / 5;
+
+ if (settings->freq_params.center_freq2)
+ iface->csa_vht_oper_centr_freq_seg1_idx =
+ 36 + (settings->freq_params.center_freq2 - 5180) / 5;
+
ret = hostapd_drv_switch_channel(hapd, settings);
free_beacon_data(&settings->beacon_csa);
free_beacon_data(&settings->beacon_after);
@@ -2382,4 +2396,31 @@ int hostapd_switch_channel(struct hostapd_data *hapd,
return 0;
}
+void hostapd_switch_channel_fallback(struct hostapd_data *hapd)
+{
+ struct hostapd_iface *iface = hapd->iface;
+ int i;
+
+ if (!hapd->csa_in_progress)
+ return;
+
+ for (i = 0; i < iface->num_bss; i++) {
+ iface->bss[i]->csa_in_progress = 0;
+ iface->bss[i]->cs_freq_params.freq = 0;
+ }
+
+ wpa_printf(MSG_WARNING, "CSA failed, trying fallback by toggling interface");
+
+ iface->freq = iface->csa_freq;
+ iface->conf->channel = iface->csa_channel;
+ iface->conf->secondary_channel = iface->csa_secondary_channel;
+ iface->conf->vht_oper_centr_freq_seg0_idx =
+ iface->csa_vht_oper_centr_freq_seg0_idx;
+ iface->conf->vht_oper_centr_freq_seg1_idx =
+ iface->csa_vht_oper_centr_freq_seg1_idx;
+
+ hostapd_disable_iface(iface);
+ hostapd_enable_iface(iface);
+}
+
#endif /* NEED_AP_MLME */
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index d413f7e..011dc51 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -362,6 +362,13 @@ struct hostapd_iface {
unsigned int acs_num_completed_scans;
#endif /* CONFIG_ACS */
+ /* channel switch parameters - used for fallback if CSA itself fails */
+ int csa_freq;
+ short csa_channel;
+ int csa_secondary_channel;
+ u8 csa_vht_oper_centr_freq_seg0_idx;
+ u8 csa_vht_oper_centr_freq_seg1_idx;
+
void (*scan_cb)(struct hostapd_iface *iface);
int num_ht40_scan_tries;
};
@@ -397,6 +404,7 @@ 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_data *hapd);
void hostapd_cleanup_cs_params(struct hostapd_data *hapd);
/* utils.c */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 33f53af..352c163 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -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,
--
1.8.5.3
More information about the Hostap
mailing list