Patchwork [RFC,v2,4/6] hostapd: submit multi-interface CSA requests for DFS

login
register
mail settings
Submitter Bartosz.Markowski@tieto.com
Date Jan. 31, 2014, 4:57 p.m.
Message ID <1391187424-5653-5-git-send-email-bartosz.markowski@tieto.com>
Download mbox | patch
Permalink /patch/315763/
State New
Headers show

Comments

Bartosz.Markowski@tieto.com - Jan. 31, 2014, 4:57 p.m.
From: Michal Kazior <michal.kazior@tieto.com>

When a radar is detecteed all BSSes sharing a
channel should switch. Switching a single
interface when multiple interfaces are running
wouldn't have worked with todays drivers anyway.

This also changes behaviour when CSA param setup
fails. Instead of disabling the hostapd_iface
fallback is tried (i.e. disable -> enable).

Signed-hostap: Michal Kazior <michal.kazior@tieto.com>
---
 src/ap/dfs.c |   85 +++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 61 insertions(+), 24 deletions(-)

Patch

diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 9e86925..d3d7356 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -681,6 +681,56 @@  static int hostapd_csa_in_progress(struct hostapd_iface *iface)
 }
 
 
+static struct csa_settings *
+hostapd_dfs_get_csa_settings(struct hostapd_iface *iface,
+			     struct hostapd_channel_data *channel,
+			     int secondary_channel,
+			     u8 vht_oper_centr_freq_seg0_idx,
+			     u8 vht_oper_centr_freq_seg1_idx)
+{
+	struct csa_settings *csa_settings;
+	int err, i;
+
+	csa_settings = os_malloc(sizeof(*csa_settings) * iface->num_bss);
+	if (!csa_settings)
+		return NULL;
+
+	memset(csa_settings, 0, sizeof(*csa_settings) * iface->num_bss);
+
+	for (i = 0; i < iface->num_bss; i++) {
+		struct hostapd_data *hapd = iface->bss[i];
+
+		csa_settings[i].hapd = hapd;
+		csa_settings[i].priv = hapd->drv_priv;
+		csa_settings[i].block_tx = 1;
+
+		/* FIXME: compute this depending on regulatory domain and
+		 * beacon interval to match regulatory quiescing requirements
+		 */
+		csa_settings[i].cs_count = 5;
+
+		err = hostapd_set_freq_params(&csa_settings[i].freq_params,
+					      iface->conf->hw_mode,
+					      channel->freq,
+					      channel->chan,
+					      hapd->iconf->ieee80211n,
+					      hapd->iconf->ieee80211ac,
+					      secondary_channel,
+					      hapd->iconf->vht_oper_chwidth,
+					      vht_oper_centr_freq_seg0_idx,
+					      vht_oper_centr_freq_seg1_idx,
+					      iface->current_mode->vht_capab);
+		if (err) {
+			wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
+			os_free(csa_settings);
+			return NULL;
+		}
+	}
+
+	return csa_settings;
+}
+
+
 static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
 {
 	struct hostapd_channel_data *channel;
@@ -688,8 +738,7 @@  static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
 	u8 vht_oper_centr_freq_seg0_idx;
 	u8 vht_oper_centr_freq_seg1_idx;
 	int skip_radar = 1;
-	struct csa_settings csa_settings;
-	struct hostapd_data *hapd = iface->bss[0];
+	struct csa_settings *csa_settings;
 	int err = 1;
 
 	wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)",
@@ -723,30 +772,18 @@  static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
 		channel->chan, secondary_channel);
 
 	/* Setup CSA request */
-	os_memset(&csa_settings, 0, sizeof(csa_settings));
-	csa_settings.hapd = hapd;
-	csa_settings.priv = hapd->drv_priv;
-	csa_settings.cs_count = 5;
-	csa_settings.block_tx = 1;
-	err = hostapd_set_freq_params(&csa_settings.freq_params,
-				      iface->conf->hw_mode,
-				      channel->freq,
-				      channel->chan,
-				      iface->conf->ieee80211n,
-				      iface->conf->ieee80211ac,
-				      secondary_channel,
-				      iface->conf->vht_oper_chwidth,
-				      vht_oper_centr_freq_seg0_idx,
-				      vht_oper_centr_freq_seg1_idx,
-				      iface->current_mode->vht_capab);
-
-	if (err) {
-		wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
-		hostapd_disable_iface(iface);
-		return err;
+	csa_settings = hostapd_dfs_get_csa_settings(iface, channel,
+						    secondary_channel,
+						    vht_oper_centr_freq_seg0_idx,
+						    vht_oper_centr_freq_seg1_idx);
+
+	if (csa_settings) {
+		err = hostapd_switch_channel(csa_settings, iface->num_bss);
+		os_free(csa_settings);
+	} else {
+		err = -1; /* just try fallback */
 	}
 
-	err = hostapd_switch_channel(&csa_settings, 1);
 	if (err) {
 		wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback",
 			   err);