@@ -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;
@@ -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 }
};
@@ -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;
}
@@ -508,3 +508,43 @@ 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) {
+ ret = os_snprintf(buf, buflen,
+ "DFS CAC not started\n");
+ if (ret < 0 || (size_t) ret >= buflen)
+ return 0;
+ return ret;
+ }
+
+ if (!iface->dfs_cac_ms) {
+ ret = os_snprintf(buf, buflen,
+ "DFS CAC time unknown\n");
+ if (ret < 0 || (size_t) ret >= buflen)
+ return 0;
+ return ret;
+ }
+
+ 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,
+ "DFS CAC stat:\n"
+ "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;
+}
@@ -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 */
@@ -537,6 +537,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
@@ -548,8 +570,10 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
struct hostapd_channel_data *channel;
int res, n_chans, start_chan_idx;
int skip_radar = 0;
+ unsigned int cac_time_ms = 0;
iface->cac_started = 0;
+ iface->dfs_cac_ms = 0;
do {
/* Get start (first) channel for current configuration */
@@ -601,12 +625,14 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
} while (res);
/* Finally start CAC */
+ cac_time_ms = dfs_get_cac_time(iface, start_chan_idx, n_chans);
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_ms: %d",
iface->freq,
- iface->conf->channel, iface->conf->secondary_channel);
+ iface->conf->channel, iface->conf->secondary_channel,
+ cac_time_ms);
if (hostapd_start_dfs_cac(iface, iface->conf->hw_mode,
iface->freq,
iface->conf->channel,
@@ -620,6 +646,8 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
return -1;
}
+ iface->dfs_cac_ms = cac_time_ms;
+
return 0;
}
@@ -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 */
@@ -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)
@@ -6179,6 +6179,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]);
}
Add cac_time cli command, that will display currently configured and left CAC time. 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 | 32 ++++++++++++++++++++++++++++++-- src/ap/hostapd.h | 3 +++ src/drivers/driver.h | 3 +++ src/drivers/driver_nl80211.c | 3 +++ 9 files changed, 94 insertions(+), 4 deletions(-)