[PATCH v2 4/4] hostapd: Use channel switch fallback on error

Michal Kazior michal.kazior at tieto.com
Fri Jun 27 08:19:30 EDT 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