Patchwork [RFC,v2,2/6] hostapd: extend CSA driver API

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

Comments

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

This prepares CSA driver API to support multi-BSS.

Signed-hostap: Michal Kazior <michal.kazior@tieto.com>
---
 hostapd/ctrl_iface.c         |    5 ++++-
 src/ap/ap_drv_ops.h          |   14 +++++++++++---
 src/ap/dfs.c                 |    4 +++-
 src/ap/hostapd.c             |   35 ++++++++++++++++++++++-------------
 src/ap/hostapd.h             |    3 +--
 src/drivers/driver.h         |   11 +++++++++--
 src/drivers/driver_nl80211.c |    7 ++++++-
 wpa_supplicant/ap.c          |    5 ++++-
 wpa_supplicant/driver_i.h    |    2 +-
 9 files changed, 61 insertions(+), 25 deletions(-)

Patch

diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 4a9da5f..df5c513 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -1138,7 +1138,10 @@  static int hostapd_ctrl_iface_chan_switch(struct hostapd_data *hapd, char *pos)
 	if (ret)
 		return ret;
 
-	return hostapd_switch_channel(hapd, &settings);
+	settings.hapd = hapd;
+	settings.priv = hapd->drv_priv;
+
+	return hostapd_switch_channel(&settings, 1);
 #else /* NEED_AP_MLME */
 	return -1;
 #endif /* NEED_AP_MLME */
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 15a4b26..a729d7c 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -263,13 +263,21 @@  static inline const char * hostapd_drv_get_radio_name(struct hostapd_data *hapd)
 	return hapd->driver->get_radio_name(hapd->drv_priv);
 }
 
-static inline int hostapd_drv_switch_channel(struct hostapd_data *hapd,
-					     struct csa_settings *settings)
+static inline int hostapd_drv_switch_channel(struct csa_settings *settings,
+					     int num_settings)
 {
+	struct hostapd_data *hapd;
+
+	if (num_settings < 1)
+		return -EINVAL;
+
+	hapd = settings[0].hapd;
+
 	if (hapd->driver == NULL || hapd->driver->switch_channel == NULL)
 		return -ENOTSUP;
 
-	return hapd->driver->switch_channel(hapd->drv_priv, settings);
+	return hapd->driver->switch_channel(hapd->drv_priv, settings,
+					    num_settings);
 }
 
 static inline int hostapd_drv_status(struct hostapd_data *hapd, char *buf,
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index fe69333..9e86925 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -724,6 +724,8 @@  static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
 
 	/* 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,
@@ -744,7 +746,7 @@  static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
 		return err;
 	}
 
-	err = hostapd_switch_channel(hapd, &csa_settings);
+	err = hostapd_switch_channel(&csa_settings, 1);
 	if (err) {
 		wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback",
 			   err);
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 3526049..b1817a8 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -2174,9 +2174,9 @@  static int hostapd_change_config_freq(struct hostapd_data *hapd,
 }
 
 
-static int hostapd_fill_csa_settings(struct hostapd_data *hapd,
-				     struct csa_settings *settings)
+static int hostapd_fill_csa_settings(struct csa_settings *settings)
 {
+	struct hostapd_data *hapd = settings->hapd;
 	struct hostapd_iface *iface = hapd->iface;
 	struct hostapd_freq_params old_freq;
 	int ret;
@@ -2230,25 +2230,34 @@  void hostapd_cleanup_cs_params(struct hostapd_data *hapd)
 }
 
 
-int hostapd_switch_channel(struct hostapd_data *hapd,
-			   struct csa_settings *settings)
+int hostapd_switch_channel(struct csa_settings *settings,
+			   int num_settings)
 {
-	int ret;
-	ret = hostapd_fill_csa_settings(hapd, settings);
-	if (ret)
-		return ret;
+	int i, ret;
+
+	for (i = 0; i < num_settings; i++) {
+		ret = hostapd_fill_csa_settings(&settings[i]);
+		if (ret)
+			return ret;
+	}
 
-	ret = hostapd_drv_switch_channel(hapd, settings);
-	free_beacon_data(&settings->beacon_csa);
-	free_beacon_data(&settings->beacon_after);
+	ret = hostapd_drv_switch_channel(settings, num_settings);
+
+	for (i = 0; i < num_settings; i++) {
+		free_beacon_data(&settings[i].beacon_csa);
+		free_beacon_data(&settings[i].beacon_after);
+	}
 
 	if (ret) {
 		/* if we failed, clean cs parameters */
-		hostapd_cleanup_cs_params(hapd);
+		for (i = 0; i < num_settings; i++)
+			hostapd_cleanup_cs_params(settings[i].hapd);
 		return ret;
 	}
 
-	hapd->csa_in_progress = 1;
+	for (i = 0; i < num_settings; i++)
+		settings[i].hapd->csa_in_progress = 1;
+
 	return 0;
 }
 
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 993def0..3510911 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -391,8 +391,7 @@  int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf);
 void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator);
 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);
+int hostapd_switch_channel(struct csa_settings *settings, int num_settings);
 void hostapd_cleanup_cs_params(struct hostapd_data *hapd);
 
 /* utils.c */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 2f4536e..57bff4a 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1213,6 +1213,8 @@  struct beacon_data {
 
 /**
  * struct csa_settings - Settings for channel switch command
+ * @hapd: Pointer to hostapd context
+ * @priv: Pointer to driver-specific context.
  * @cs_count: Count in Beacon frames (TBTT) to perform the switch
  * @block_tx: 1 - block transmission for CSA period
  * @freq_params: Next channel frequency parameter
@@ -1222,6 +1224,9 @@  struct beacon_data {
  * @counter_offset_presp: Offset to the count field in probe resp.
  */
 struct csa_settings {
+	struct hostapd_data *hapd;
+	void *priv;
+
 	u8 cs_count;
 	u8 block_tx;
 
@@ -2622,13 +2627,15 @@  struct wpa_driver_ops {
 	 * switch_channel - Announce channel switch and migrate the GO to the
 	 * given frequency
 	 * @priv: Private driver interface data
-	 * @settings: Settings for CSA period and new channel
+	 * @settings: Settings for CSA period and new channel for multiple BSSes
+	 * @num_settings: Number of CSA settings for different BSSes
 	 * Returns: 0 on success, -1 on failure
 	 *
 	 * This function is used to move the GO to the legacy STA channel to
 	 * avoid frequency conflict in single channel concurrency.
 	 */
-	int (*switch_channel)(void *priv, struct csa_settings *settings);
+	int (*switch_channel)(void *priv, struct csa_settings *settings,
+			      int num_settings);
 
 	/**
 	 * start_dfs_cac - Listen for radar interference on the channel
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 5162ecd..f10bd1f 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -11558,7 +11558,8 @@  nla_put_failure:
 }
 
 
-static int nl80211_switch_channel(void *priv, struct csa_settings *settings)
+static int nl80211_switch_channel(void *priv, struct csa_settings *settings,
+				  int num_settings)
 {
 	struct nl_msg *msg;
 	struct i802_bss *bss = priv;
@@ -11566,6 +11567,10 @@  static int nl80211_switch_channel(void *priv, struct csa_settings *settings)
 	struct nlattr *beacon_csa;
 	int ret = -ENOBUFS;
 
+	/* multi-BSS not implemented yet */
+	if (num_settings != 1)
+		return -EOPNOTSUPP;
+
 	wpa_printf(MSG_DEBUG, "nl80211: Channel switch request (cs_count=%u block_tx=%u freq=%d width=%d cf1=%d cf2=%d)",
 		   settings->cs_count, settings->block_tx,
 		   settings->freq_params.freq, settings->freq_params.bandwidth,
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index ce3efcb..ba21f18 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -1094,7 +1094,10 @@  int ap_switch_channel(struct wpa_supplicant *wpa_s,
 	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
 		return -1;
 
-	return hostapd_switch_channel(wpa_s->ap_iface->bss[0], settings);
+	settings->hapd = wpa_s->ap_iface->bss[0];
+	settings->priv = wpa_s->ap_iface->bss[0]->drv_priv;
+
+	return hostapd_switch_channel(settings, 1);
 #else /* NEED_AP_MLME */
 	return -1;
 #endif /* NEED_AP_MLME */
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 0691b6c..c2a16fd 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -574,7 +574,7 @@  static inline int wpa_drv_switch_channel(struct wpa_supplicant *wpa_s,
 {
 	if (!wpa_s->driver->switch_channel)
 		return -1;
-	return wpa_s->driver->switch_channel(wpa_s->drv_priv, settings);
+	return wpa_s->driver->switch_channel(wpa_s->drv_priv, settings, 1);
 }
 
 static inline int wpa_drv_wnm_oper(struct wpa_supplicant *wpa_s,