[PATCH v2 4/4] hostapd: Use channel switch fallback on error
Michal Kazior
michal.kazior
Fri Jun 27 05:19:30 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>
---
Notes:
v2:
* use cs_freq_params instead of storing cs params in
hostapd_iface [Andrei]
* use hostapd_cleanup_cs_params() [Andrei]
* rework how functions are called a bit [Andrei]
src/ap/drv_callbacks.c | 17 +++++++++++++
src/ap/hostapd.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++----
src/ap/hostapd.h | 3 +++
src/drivers/driver.h | 3 ++-
4 files changed, 82 insertions(+), 6 deletions(-)
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index ac5732c..4c5fe8e 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -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 is unavailable -- stopped");
+
+ if (hapd->csa_in_progress) {
+ wpa_printf(MSG_WARNING, "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;
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 4da5a3d..63884a6 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;
@@ -2382,4 +2382,59 @@ 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;
+ int i;
+
+ wpa_printf(MSG_INFO, "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 */
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index d413f7e..3c8727b 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -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 */
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