@@ -10,6 +10,7 @@
#include "utils/includes.h"
#include "utils/common.h"
+#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "common/hw_features_common.h"
#include "common/wpa_ctrl.h"
@@ -636,6 +637,34 @@ static unsigned int dfs_get_cac_time(struct hostapd_iface *iface,
return cac_time_ms;
}
+static int dfs_start_cac(struct hostapd_iface *iface)
+{
+ int res;
+
+ wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START
+ "freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d, cac_time=%ds",
+ iface->freq,
+ iface->conf->channel, iface->conf->secondary_channel,
+ iface->conf->vht_oper_chwidth,
+ iface->conf->vht_oper_centr_freq_seg0_idx,
+ iface->conf->vht_oper_centr_freq_seg1_idx,
+ iface->dfs_cac_ms / 1000);
+
+ res = hostapd_start_dfs_cac(iface, iface->conf->hw_mode,
+ iface->freq,
+ iface->conf->channel,
+ iface->conf->ieee80211n,
+ iface->conf->ieee80211ac,
+ iface->conf->secondary_channel,
+ iface->conf->vht_oper_chwidth,
+ iface->conf->vht_oper_centr_freq_seg0_idx,
+ iface->conf->vht_oper_centr_freq_seg1_idx);
+
+ if (res)
+ wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res);
+
+ return res;
+}
/*
* Main DFS handler
@@ -719,31 +748,8 @@ int hostapd_handle_dfs(struct hostapd_iface *iface)
/* Finally start CAC */
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, width=%d, seg0=%d, seg1=%d, cac_time=%ds",
- iface->freq,
- iface->conf->channel, iface->conf->secondary_channel,
- iface->conf->vht_oper_chwidth,
- iface->conf->vht_oper_centr_freq_seg0_idx,
- iface->conf->vht_oper_centr_freq_seg1_idx,
- iface->dfs_cac_ms / 1000);
- res = hostapd_start_dfs_cac(iface, iface->conf->hw_mode,
- iface->freq,
- iface->conf->channel,
- iface->conf->ieee80211n,
- iface->conf->ieee80211ac,
- iface->conf->secondary_channel,
- iface->conf->vht_oper_chwidth,
- iface->conf->vht_oper_centr_freq_seg0_idx,
- iface->conf->vht_oper_centr_freq_seg1_idx);
-
- if (res) {
- wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res);
- return -1;
- }
-
- return 0;
+ return dfs_start_cac(iface);
}
@@ -763,18 +769,43 @@ static int hostapd_config_dfs_chan_available(struct hostapd_iface *iface)
return dfs_check_chans_available(iface, start_chan_idx, n_chans);
}
+static void hostapd_dfs_cac_restart(void *eloop_data, void *user_ctx)
+{
+ struct hostapd_iface *iface = eloop_data;
+ int res;
+
+ if (iface->state != HAPD_IFACE_DFS || !iface->cac_started) {
+ wpa_printf(MSG_WARNING, "CAC restart in wrong state=%d; started=%d",
+ iface->state, iface->cac_started);
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "DFS restart CAC on %d MHz", iface->freq);
+ res = dfs_start_cac(iface);
+
+ if (res)
+ hostapd_setup_interface_complete(iface, res);
+}
int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
int ht_enabled, int chan_offset, int chan_width,
int cf1, int cf2)
{
+ int res = 0;
+ int dfs_offload = !!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD);
+
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_COMPLETED
"success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
+ if (!iface->cac_started) {
+ wpa_printf(MSG_ERROR, "CAC complete received in wrong state");
+ return 1;
+ }
+
if (success) {
/* Complete iface/ap configuration */
- if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
+ if (dfs_offload) {
/* Complete AP configuration for the first bring up. */
if (iface->state != HAPD_IFACE_ENABLED)
hostapd_setup_interface_complete(iface, 0);
@@ -800,9 +831,21 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
iface->cac_started = 0;
}
}
+ } else {
+ if (dfs_offload) {
+ if (iface->state == HAPD_IFACE_ENABLED)
+ iface->cac_started = 0;
+ } else if (iface->state == HAPD_IFACE_DFS) {
+ /* Schedule CAC restart in 1 second */
+ eloop_register_timeout(1, 0, hostapd_dfs_cac_restart,
+ iface, NULL);
+ } else {
+ wpa_printf(MSG_ERROR, "CAC aborted received in wrong state=%d offload=%d",
+ iface->state, dfs_offload);
+ }
}
- return 0;
+ return res;
}
@@ -1074,7 +1117,7 @@ int hostapd_is_dfs_required(struct hostapd_iface *iface)
}
-int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+int hostapd_dfs_cac_started(struct hostapd_iface *iface, int freq,
int ht_enabled, int chan_offset, int chan_width,
int cf1, int cf2)
{
@@ -25,7 +25,7 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
int ht_enabled,
int chan_offset, int chan_width, int cf1, int cf2);
int hostapd_is_dfs_required(struct hostapd_iface *iface);
-int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+int hostapd_dfs_cac_started(struct hostapd_iface *iface, int freq,
int ht_enabled, int chan_offset, int chan_width,
int cf1, int cf2);
int hostapd_handle_dfs_offload(struct hostapd_iface *iface);
@@ -1398,9 +1398,9 @@ static void hostapd_event_dfs_cac_started(struct hostapd_data *hapd,
struct dfs_event *radar)
{
wpa_printf(MSG_DEBUG, "DFS offload CAC started on %d MHz", radar->freq);
- hostapd_dfs_start_cac(hapd->iface, radar->freq, radar->ht_enabled,
- radar->chan_offset, radar->chan_width,
- radar->cf1, radar->cf2);
+ hostapd_dfs_cac_started(hapd->iface, radar->freq, radar->ht_enabled,
+ radar->chan_offset, radar->chan_width,
+ radar->cf1, radar->cf2);
}
#endif /* NEED_AP_MLME */