[RFC 2/6] hostapd: extend CSA driver API
Michal Kazior
michal.kazior
Mon Jan 20 22:57:24 PST 2014
This prepares CSA driver API to support multi-BSS.
Signed-hostap: Michal Kazior <michal.kazior at 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 ++++-
8 files changed, 60 insertions(+), 24 deletions(-)
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 72faeae..a73a1d5 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -1077,7 +1077,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 caf4092..6037951 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -708,6 +708,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,
@@ -728,7 +730,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 b0a859f..d4d032d 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -2169,9 +2169,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;
@@ -2225,25 +2225,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 db34ed1..3a9b82c 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1209,6 +1209,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
@@ -1218,6 +1220,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;
@@ -2618,13 +2623,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 8c8ad51..94c2164 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -11390,7 +11390,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;
@@ -11398,6 +11399,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 ea4e6bb..9dbe0b0 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -1068,7 +1068,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 */
--
1.8.4.rc3
More information about the Hostap
mailing list