Patchwork [PATCHv2,3/3] hostap: add config option for dfs channels

login
register
mail settings
Submitter Simon Wunderlich
Date March 25, 2013, 5:16 p.m.
Message ID <1364231797-12569-4-git-send-email-siwu@hrz.tu-chemnitz.de>
Download mbox | patch
Permalink /patch/230761/
State Changes Requested
Headers show

Comments

Simon Wunderlich - March 25, 2013, 5:16 p.m.
Different channels allow different transmission power, at least in ETSI
countries. Also, ETSI requires a "channel plan" for DFS operation, and
channels should be randomly choosen from these channels.

Add a channel list configuration option for users to add channels
hostapd may pick from.

Signed-hostap: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
---
 hostapd/config_file.c |   21 +++++++++++++--------
 hostapd/hostapd.conf  |    6 ++++++
 src/ap/ap_config.c    |    1 +
 src/ap/ap_config.h    |    1 +
 src/ap/hostapd.c      |   19 +++++++++++++++++++
 5 files changed, 40 insertions(+), 8 deletions(-)

Patch

diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 9af5bd8..2b9d244 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -711,14 +711,14 @@  static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
 }
 
 
-static int hostapd_parse_rates(int **rate_list, char *val)
+static int hostapd_parse_intlist(int **int_list, char *val)
 {
 	int *list;
 	int count;
 	char *pos, *end;
 
-	os_free(*rate_list);
-	*rate_list = NULL;
+	os_free(*int_list);
+	*int_list = NULL;
 
 	pos = val;
 	count = 0;
@@ -745,11 +745,10 @@  static int hostapd_parse_rates(int **rate_list, char *val)
 	}
 	list[count] = -1;
 
-	*rate_list = list;
+	*int_list = list;
 	return 0;
 }
 
-
 static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname)
 {
 	struct hostapd_bss_config *bss;
@@ -2308,6 +2307,12 @@  static int hostapd_config_fill(struct hostapd_config *conf,
 			}
 		} else if (os_strcmp(buf, "channel") == 0) {
 			conf->channel = atoi(pos);
+		} else if (os_strcmp(buf, "dfs_chanlist") == 0) {
+			if (hostapd_parse_intlist(&conf->dfs_chanlist, pos)) {
+				wpa_printf(MSG_ERROR, "Line %d: invalid channel "
+					   "list", line);
+				errors++;
+			}
 		} else if (os_strcmp(buf, "beacon_int") == 0) {
 			int val = atoi(pos);
 			/* MIB defines range as 1..65535, but very small values
@@ -2357,13 +2362,13 @@  static int hostapd_config_fill(struct hostapd_config *conf,
 			} else
 				conf->send_probe_response = val;
 		} else if (os_strcmp(buf, "supported_rates") == 0) {
-			if (hostapd_parse_rates(&conf->supported_rates, pos)) {
+			if (hostapd_parse_intlist(&conf->supported_rates, pos)) {
 				wpa_printf(MSG_ERROR, "Line %d: invalid rate "
 					   "list", line);
 				errors++;
 			}
 		} else if (os_strcmp(buf, "basic_rates") == 0) {
-			if (hostapd_parse_rates(&conf->basic_rates, pos)) {
+			if (hostapd_parse_intlist(&conf->basic_rates, pos)) {
 				wpa_printf(MSG_ERROR, "Line %d: invalid rate "
 					   "list", line);
 				errors++;
@@ -2913,7 +2918,7 @@  static int hostapd_config_fill(struct hostapd_config *conf,
 		} else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0) {
 			bss->sae_anti_clogging_threshold = atoi(pos);
 		} else if (os_strcmp(buf, "sae_groups") == 0) {
-			if (hostapd_parse_rates(&bss->sae_groups, pos)) {
+			if (hostapd_parse_intlist(&bss->sae_groups, pos)) {
 				wpa_printf(MSG_ERROR, "Line %d: Invalid "
 					   "sae_groups value '%s'", line, pos);
 				return 1;
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 2826929..e29a1d8 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -123,6 +123,12 @@  hw_mode=g
 # channel will need to be configured separately with iwconfig.
 channel=1
 
+# DFS Channels. This option allows hostapd to select on of the provided
+# DFS Channels when the current channels becomes unavailable due to
+# radar interference. Only useful when ieee80211h=1 is set.
+# Default: not set
+#dfs_chanlist=100 104 108 112 116
+
 # Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
 beacon_int=100
 
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 922f564..3f22891 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -542,6 +542,7 @@  void hostapd_config_free(struct hostapd_config *conf)
 	os_free(conf->bss);
 	os_free(conf->supported_rates);
 	os_free(conf->basic_rates);
+	os_free(conf->dfs_chanlist);
 
 	os_free(conf);
 }
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 2c28371..7e6b273 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -474,6 +474,7 @@  struct hostapd_config {
 	int fragm_threshold;
 	u8 send_probe_response;
 	u8 channel;
+	int *dfs_chanlist;
 	enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
 	enum {
 		LONG_PREAMBLE = 0,
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 132641a..5426c65 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1435,6 +1435,22 @@  void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
 }
 
 
+int hostapd_is_in_dfs_chanlist(struct hostapd_data *hapd,
+			       struct hostapd_channel_data *chan)
+{
+	int *chan_entry;
+
+	if (!hapd->iface->conf->dfs_chanlist)
+		return 1;
+
+	for (chan_entry = hapd->iface->conf->dfs_chanlist; *chan_entry != -1; chan_entry++) {
+		if (*chan_entry == chan->chan)
+			return 1;
+	}
+	return 0;
+}
+
+
 /*
  * if ret_chan == NULL: returns the number of channels with this dfs state
  * if ret_chan != NULL: return channel at the supplied position.
@@ -1458,6 +1474,9 @@  static int hostapd_dfs_find_channel(struct hostapd_data *hapd, u32 state,
 		    ((chan->flag & HOSTAPD_CHAN_DFS_MASK) != state))
 			continue;
 
+		if (!hostapd_is_in_dfs_chanlist(hapd, chan))
+			continue;
+
 		if (ret_chan && idx == channel_idx) {
 			wpa_printf(MSG_DEBUG, "Selected ch. #%d", chan->chan);
 			*ret_chan = chan;