[PATCH 1/2] hostapd: Add DFS feature structures
Janusz Dziedzic
janusz.dziedzic
Sun Sep 15 22:40:06 PDT 2013
Add DFS structures/events handlers.
Signed-hostap: Simon Wunderlich <siwu at hrz.tu-chemnitz.de>
---
src/ap/ap_drv_ops.c | 27 +++++++++++++++++
src/ap/ap_drv_ops.h | 1 +
src/ap/drv_callbacks.c | 56 ++++++++++++++++++++++++++++++++++
src/ap/hostapd.c | 5 ++++
src/ap/hostapd.h | 12 ++++++++
src/ap/hw_features.c | 78 +++++++++++++++++++++++++++++++++++++++++-------
src/ap/hw_features.h | 5 ++++
7 files changed, 174 insertions(+), 10 deletions(-)
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 3072562..d9df9cc 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -699,3 +699,30 @@ int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq,
hapd->own_addr, hapd->own_addr, data,
len, 0);
}
+
+
+int hostapd_start_dfs_cac(struct hostapd_data *hapd, int freq, int flags)
+{
+ if (!hapd->driver || !hapd->driver->start_dfs_cac)
+ return 0;
+
+ if (!(flags & HOSTAPD_CHAN_RADAR)) {
+ wpa_printf(MSG_ERROR, "Can't start DFS_CAC, the channel %u is "
+ "not DFS channel", hapd->iconf->channel);
+ return -1;
+ }
+
+ if (!(hapd->iface->dfs_state & DFS_ENABLED)) {
+ wpa_printf(MSG_ERROR, "Can't start DFS CAC, DFS functionality "
+ "is not enabled");
+ return -1;
+ }
+
+ if (hapd->iface->conf->secondary_channel) {
+ wpa_printf(MSG_ERROR, "Can't start DFS CAC, DFS functionality "
+ "on HT40 is not supported");
+ return -1;
+ }
+
+ return hapd->driver->start_dfs_cac(hapd->drv_priv, freq);
+}
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 23277b6..d56aa91 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -101,6 +101,7 @@ int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr,
int reassoc, u16 status, const u8 *ie, size_t len);
int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr,
u8 *tspec_ie, size_t tspec_ielen);
+int hostapd_start_dfs_cac(struct hostapd_data *hapd, int freq, int flags);
#include "drivers/driver.h"
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index d6bc98d..a54ab0c 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -785,6 +785,35 @@ static void hostapd_event_get_survey(struct hostapd_data *hapd,
}
+static void hostapd_event_dfs_radar_detected(struct hostapd_data *hapd,
+ struct dfs_event *radar)
+{
+ wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq);
+
+}
+
+
+static void hostapd_event_dfs_cac_finished(struct hostapd_data *hapd,
+ struct dfs_event *radar)
+{
+ wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq);
+}
+
+
+static void hostapd_event_dfs_cac_aborted(struct hostapd_data *hapd,
+ struct dfs_event *radar)
+{
+ wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq);
+}
+
+
+static void hostapd_event_dfs_nop_finished(struct hostapd_data *hapd,
+ struct dfs_event *radar)
+{
+ wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq);
+}
+
+
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
union wpa_event_data *data)
{
@@ -929,6 +958,33 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
case EVENT_SURVEY:
hostapd_event_get_survey(hapd, &data->survey_results);
break;
+ case EVENT_DFS_RADAR_DETECTED:
+ if (!data)
+ break;
+ hostapd_event_dfs_radar_detected(hapd, &data->dfs_event);
+ break;
+ case EVENT_DFS_CAC_FINISHED:
+ if (!data)
+ break;
+ hostapd_event_dfs_cac_finished(hapd, &data->dfs_event);
+ break;
+ case EVENT_DFS_CAC_ABORTED:
+ if (!data)
+ break;
+ hostapd_event_dfs_cac_aborted(hapd, &data->dfs_event);
+ break;
+ case EVENT_DFS_NOP_FINISHED:
+ if (!data)
+ break;
+ hostapd_event_dfs_nop_finished(hapd, &data->dfs_event);
+ break;
+ case EVENT_CHANNEL_LIST_CHANGED:
+ /* channel list changed (regulatory?), update channel list */
+ /* TODO: check this. hostapd_get_hw_features() initializes
+ * too much stuff. */
+ /* hostapd_get_hw_features(hapd->iface); */
+ break;
+
default:
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
break;
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index fd1ca2b..55e6c95 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -931,6 +931,11 @@ static int setup_interface(struct hostapd_iface *iface)
"be completed in a callback");
return 0;
}
+
+ if (iface->conf->ieee80211h) {
+ wpa_printf(MSG_DEBUG, "DFS support is enabled");
+ iface->dfs_state |= DFS_ENABLED;
+ }
}
return hostapd_setup_interface_complete(iface, 0);
}
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index dbf1b52..b5595e7 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -315,6 +315,18 @@ struct hostapd_iface {
/* lowest observed noise floor in dBm */
s8 lowest_nf;
+
+ /* DFS functionality is enabled. */
+#define DFS_ENABLED BIT(0)
+
+ /* DFS channel availability check during initialization. */
+#define DFS_CAC_ACTIVE BIT(1)
+
+ /* DFS channel availability check completed successfully. */
+#define DFS_CAC_SUCCESS BIT(2)
+
+ u8 dfs_state; /* DFS_* bitfield */
+
#ifdef CONFIG_ACS
unsigned int acs_num_completed_scans;
#endif /* CONFIG_ACS */
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 8a239f4..c3e2080 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -45,6 +45,36 @@ void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
}
+#ifndef CONFIG_NO_STDOUT_DEBUG
+static char * dfs_info(struct hostapd_channel_data *chan)
+{
+ static char info[256], *state;
+
+ switch (chan->flag & HOSTAPD_CHAN_DFS_MASK) {
+ case HOSTAPD_CHAN_DFS_UNKNOWN:
+ state = "unknown";
+ break;
+ case HOSTAPD_CHAN_DFS_USABLE:
+ state = "usable";
+ break;
+ case HOSTAPD_CHAN_DFS_UNAVAILABLE:
+ state = "unavailable";
+ break;
+ case HOSTAPD_CHAN_DFS_AVAILABLE:
+ state = "available";
+ break;
+ default:
+ return "";
+ }
+ os_snprintf(info, sizeof(info), " (DFS state = %s)",
+ state);
+ info[sizeof(info) - 1] = '\0';
+
+ return info;
+}
+#endif /* CONFIG_NO_STDOUT_DEBUG */
+
+
int hostapd_get_hw_features(struct hostapd_iface *iface)
{
struct hostapd_data *hapd = iface->bss[0];
@@ -71,30 +101,40 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
for (i = 0; i < num_modes; i++) {
struct hostapd_hw_modes *feature = &modes[i];
+ int dfs_enabled = hapd->iconf->ieee80211h &&
+ (iface->drv_flags & WPA_DRIVER_FLAGS_RADAR);
+
/* set flag for channels we can use in current regulatory
* domain */
for (j = 0; j < feature->num_channels; j++) {
+ int dfs = 0;
+
/*
* Disable all channels that are marked not to allow
- * IBSS operation or active scanning. In addition,
- * disable all channels that require radar detection,
- * since that (in addition to full DFS) is not yet
- * supported.
+ * IBSS operation or active scanning.
+ * Use radar channels only if the driver supports DFS.
*/
- if (feature->channels[j].flag &
- (HOSTAPD_CHAN_NO_IBSS |
- HOSTAPD_CHAN_PASSIVE_SCAN |
- HOSTAPD_CHAN_RADAR))
+ if ((feature->channels[j].flag &
+ HOSTAPD_CHAN_RADAR) && dfs_enabled) {
+ dfs = 1;
+ } else if (feature->channels[j].flag &
+ (HOSTAPD_CHAN_NO_IBSS |
+ HOSTAPD_CHAN_PASSIVE_SCAN |
+ HOSTAPD_CHAN_RADAR)) {
feature->channels[j].flag |=
HOSTAPD_CHAN_DISABLED;
+ }
+
if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED)
continue;
+
wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d "
- "chan=%d freq=%d MHz max_tx_power=%d dBm",
+ "chan=%d freq=%d MHz max_tx_power=%d dBm%s",
feature->mode,
feature->channels[j].chan,
feature->channels[j].freq,
- feature->channels[j].max_tx_power);
+ feature->channels[j].max_tx_power,
+ dfs ? dfs_info(&feature->channels[j]) : "");
}
}
@@ -849,3 +889,21 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
return 0;
}
+
+
+int hostapd_hw_get_channel_flag(struct hostapd_data *hapd, int chan)
+{
+ int i;
+
+ if (!hapd->iface->current_mode)
+ return 0;
+
+ for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
+ struct hostapd_channel_data *ch =
+ &hapd->iface->current_mode->channels[i];
+ if (ch->chan == chan)
+ return ch->flag;
+ }
+
+ return 0;
+}
diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h
index abadcd1..fe18d7c 100644
--- a/src/ap/hw_features.h
+++ b/src/ap/hw_features.h
@@ -28,6 +28,7 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
int hostapd_check_ht_capab(struct hostapd_iface *iface);
int hostapd_prepare_rates(struct hostapd_iface *iface,
struct hostapd_hw_modes *mode);
+int hostapd_hw_get_channel_flag(struct hostapd_data *hapd, int chan);
#else /* NEED_AP_MLME */
static inline void
hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
@@ -66,6 +67,10 @@ static inline int hostapd_prepare_rates(struct hostapd_iface *iface,
return 0;
}
+static inline int hostapd_get_channel_flag(struct hostapd_data *hapd, int chan)
+{
+ return 0;
+}
#endif /* NEED_AP_MLME */
#endif /* HW_FEATURES_H */
--
1.7.9.5
More information about the Hostap
mailing list