Patchwork hostapd: DFS add cac_time cli command

login
register
mail settings
Submitter Janusz.Dziedzic@tieto.com
Date March 3, 2014, 10:10 a.m.
Message ID <1393841453-3846-1-git-send-email-janusz.dziedzic@tieto.com>
Download mbox | patch
Permalink /patch/325756/
State Superseded
Headers show

Comments

Janusz.Dziedzic@tieto.com - March 3, 2014, 10:10 a.m.
Add cac_time cli command, that will display
currently configured and left CAC time.
Print cac_time also in status command.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
---
 hostapd/ctrl_iface.c         |    3 +++
 hostapd/hostapd_cli.c        |    7 +++++++
 src/ap/ap_drv_ops.c          |    4 +++-
 src/ap/ctrl_iface_ap.c       |   40 ++++++++++++++++++++++++++++++++++++++--
 src/ap/ctrl_iface_ap.h       |    3 ++-
 src/ap/dfs.c                 |   30 ++++++++++++++++++++++++++++--
 src/ap/hostapd.h             |    3 +++
 src/drivers/driver.h         |    3 +++
 src/drivers/driver_nl80211.c |    4 ++++
 9 files changed, 91 insertions(+), 6 deletions(-)
Jouni Malinen - March 4, 2014, 6:18 p.m.
On Mon, Mar 03, 2014 at 11:10:53AM +0100, Janusz Dziedzic wrote:
> Add cac_time cli command, that will display
> currently configured and left CAC time.
> Print cac_time also in status command.

> diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
> @@ -771,8 +771,10 @@ int hostapd_start_dfs_cac(struct hostapd_iface *iface, int mode, int freq,
> +	if (!res) {
>  		iface->cac_started = 1;
> +		os_get_time(&iface->dfs_cac_start);
> +	}

> diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
> @@ -508,3 +510,37 @@ int hostapd_parse_csa_settings(const char *pos,
> +int hostapd_ctrl_iface_cac_time(struct hostapd_data *hapd, char *buf,
> +	/* CAC started and CAC time set - calc left time */
> +	os_get_time(&now);
> +	left_time = iface->dfs_cac_ms/1000 - (now.sec - iface->dfs_cac_start.sec);

This should likely use os_reltime instead of os_time.

> diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
> @@ -6180,6 +6181,9 @@ static void phy_info_freq(struct hostapd_hw_modes *mode,
> +	if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME])
> +		chan->dfs_cac_ms = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME]);

This attribute does not seem to exist in wireless-testing.git, so I
cannot apply this yet.

Patch

diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index dbdc8c6..a56a068 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -1470,6 +1470,9 @@  static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx,
 	} else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
 		if (hostapd_ctrl_iface_chan_switch(hapd, buf + 12))
 			reply_len = -1;
+	} else if (os_strncmp(buf, "CAC_TIME", 8) == 0) {
+		reply_len = hostapd_ctrl_iface_cac_time(hapd, reply,
+							reply_size);
 	} else {
 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 		reply_len = 16;
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index 8caca4f..9431b58 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -940,6 +940,12 @@  static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
 }
 
 
+static int hostapd_cli_cmd_cac_time(struct wpa_ctrl *ctrl,
+				    int argc, char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "CAC_TIME");
+}
+
 struct hostapd_cli_cmd {
 	const char *cmd;
 	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
@@ -988,6 +994,7 @@  static struct hostapd_cli_cmd hostapd_cli_commands[] = {
 	{ "chan_switch", hostapd_cli_cmd_chan_switch },
 	{ "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
 	{ "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
+	{ "cac_time", hostapd_cli_cmd_cac_time },
 	{ NULL, NULL }
 };
 
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index b8b260a..21f88fa 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -771,8 +771,10 @@  int hostapd_start_dfs_cac(struct hostapd_iface *iface, int mode, int freq,
 		return -1;
 
 	res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data);
-	if (!res)
+	if (!res) {
 		iface->cac_started = 1;
+		os_get_time(&iface->dfs_cac_start);
+	}
 
 	return res;
 }
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 8c0cbab..dbdba36 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -409,7 +409,8 @@  int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
 			  "num_sta_no_ht=%d\n"
 			  "num_sta_ht_20_mhz=%d\n"
 			  "olbc_ht=%d\n"
-			  "ht_op_mode=0x%x\n",
+			  "ht_op_mode=0x%x\n"
+			  "dfs_cac_ms=%d\n",
 			  hostapd_state_text(iface->state),
 			  iface->phy,
 			  iface->freq,
@@ -421,7 +422,8 @@  int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
 			  iface->num_sta_no_ht,
 			  iface->num_sta_ht_20mhz,
 			  iface->olbc_ht,
-			  iface->ht_op_mode);
+			  iface->ht_op_mode,
+			  iface->dfs_cac_ms);
 	if (ret < 0 || (size_t) ret >= buflen - len)
 		return len;
 	len += ret;
@@ -508,3 +510,37 @@  int hostapd_parse_csa_settings(const char *pos,
 
 	return 0;
 }
+
+int hostapd_ctrl_iface_cac_time(struct hostapd_data *hapd, char *buf,
+				size_t buflen)
+{
+	struct hostapd_iface *iface = hapd->iface;
+	int ret;
+	struct os_time now;
+	int left_time = 0;
+
+	if (!iface->cac_started || !iface->dfs_cac_ms) {
+		ret = os_snprintf(buf, buflen,
+				  "cac_time: %us\n"
+				  "cac_left_time: N/A\n",
+				  iface->dfs_cac_ms/1000);
+		if (ret < 0 || (size_t) ret >= buflen)
+			return 0;
+		return ret;
+	}
+
+	/* CAC started and CAC time set - calc left time */
+	os_get_time(&now);
+	left_time = iface->dfs_cac_ms/1000 - (now.sec - iface->dfs_cac_start.sec);
+	if (left_time < 0)
+		left_time = 0;
+	ret = os_snprintf(buf, buflen,
+			  "cac_time: %us\n"
+			  "cac_left_time: %ds\n",
+			  iface->dfs_cac_ms/1000,
+			  left_time);
+	if (ret < 0 || (size_t) ret >= buflen)
+		return 0;
+
+	return ret;
+}
diff --git a/src/ap/ctrl_iface_ap.h b/src/ap/ctrl_iface_ap.h
index ee58b4c..eb7947f 100644
--- a/src/ap/ctrl_iface_ap.h
+++ b/src/ap/ctrl_iface_ap.h
@@ -23,6 +23,7 @@  int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf,
 			      size_t buflen);
 int hostapd_parse_csa_settings(const char *pos,
 			       struct csa_settings *settings);
-
+int hostapd_ctrl_iface_cac_time(struct hostapd_data *hapd, char *buf,
+				size_t buflen);
 
 #endif /* CTRL_IFACE_AP_H */
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
index 2b8b90f..af26c68 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -541,6 +541,28 @@  static int dfs_are_channels_overlapped(struct hostapd_iface *iface, int freq,
 }
 
 
+static unsigned int dfs_get_cac_time(struct hostapd_iface *iface,
+				     int start_chan_idx,
+				     int n_chans)
+{
+	struct hostapd_channel_data *channel;
+	struct hostapd_hw_modes *mode;
+	int i;
+	unsigned int cac_time_ms = 0;
+
+	mode = iface->current_mode;
+
+	for (i = 0; i < n_chans; i++) {
+		channel = &mode->channels[start_chan_idx + i];
+		if (!(channel->flag & HOSTAPD_CHAN_RADAR))
+			continue;
+		if (channel->dfs_cac_ms > cac_time_ms)
+			cac_time_ms = channel->dfs_cac_ms;
+	}
+
+	return cac_time_ms;
+}
+
 /*
  * Main DFS handler
  * 1 - continue channel/ap setup
@@ -564,6 +586,9 @@  int hostapd_handle_dfs(struct hostapd_iface *iface)
 		/* Get number of used channels, depend on width */
 		n_chans = dfs_get_used_n_chans(iface);
 
+		/* Setup CAC time */
+		iface->dfs_cac_ms = dfs_get_cac_time(iface, start_chan_idx, n_chans);
+
 		/* Check if any of configured channels require DFS */
 		res = dfs_check_chans_radar(iface, start_chan_idx, n_chans);
 		wpa_printf(MSG_DEBUG,
@@ -608,9 +633,10 @@  int hostapd_handle_dfs(struct hostapd_iface *iface)
 	hostapd_set_state(iface, HAPD_IFACE_DFS);
 	wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz", iface->freq);
 	wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
-		"freq=%d chan=%d sec_chan=%d",
+		"freq=%d chan=%d sec_chan=%d, cac_time: %ds",
 		iface->freq,
-		iface->conf->channel, iface->conf->secondary_channel);
+		iface->conf->channel, iface->conf->secondary_channel,
+		iface->dfs_cac_ms/1000);
 	if (hostapd_start_dfs_cac(iface, iface->conf->hw_mode,
 				  iface->freq,
 				  iface->conf->channel,
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 489ab16..e69e1d1 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -345,6 +345,9 @@  struct hostapd_iface {
 	unsigned int cs_c_off_proberesp;
 	int csa_in_progress;
 
+	u32 dfs_cac_ms;
+	struct os_time dfs_cac_start;
+
 #ifdef CONFIG_ACS
 	unsigned int acs_num_completed_scans;
 #endif /* CONFIG_ACS */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index d2aad24..2d84cac 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -93,6 +93,9 @@  struct hostapd_channel_data {
 	 */
 	long double interference_factor;
 #endif /* CONFIG_ACS */
+
+	/* DFS CAC time in milliseconds */
+	u32 dfs_cac_ms;
 };
 
 #define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0)
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index c509170..091559d 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -6154,6 +6154,7 @@  static void phy_info_freq(struct hostapd_hw_modes *mode,
 	u8 channel;
 	chan->freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
 	chan->flag = 0;
+	chan->dfs_cac_ms = 0;
 	if (ieee80211_freq_to_chan(chan->freq, &channel) != NUM_HOSTAPD_MODES)
 		chan->chan = channel;
 
@@ -6180,6 +6181,9 @@  static void phy_info_freq(struct hostapd_hw_modes *mode,
 			break;
 		}
 	}
+
+	if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME])
+		chan->dfs_cac_ms = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME]);
 }