From: Qiwei Cai Date: Wed, 9 Nov 2022 11:46:04 +0000 (+0800) Subject: Skip CAC if the driver switches channel to non-DFS X-Git-Tag: hostap_2_11~1505 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b6c38cee93e312635576d47fea87b86c78e553b8;p=thirdparty%2Fhostap.git Skip CAC if the driver switches channel to non-DFS If an AP is started on a DFS channel (or any channels within its bandwidth require DFS) and DFS is offloaded to the driver, hostapd needs to wait for CAC to complete. But the driver may not do CAC and just switches to a non-DFS channel instead. This would result in a failure to start the AP because hostapd fails to receive a CAC complete event and cannot finish interface setup. Skip CAC and complete AP setup in the channel switch event handler for this case. Signed-off-by: Jouni Malinen --- diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index a673fae09..19a3afcb8 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -862,14 +862,16 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, int finished) { #ifdef NEED_AP_MLME - int channel, chwidth, is_dfs; + int channel, chwidth, is_dfs0, is_dfs; u8 seg0_idx = 0, seg1_idx = 0; size_t i; hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, - "driver %s channel switch: freq=%d, ht=%d, vht_ch=0x%x, he_ch=0x%x, eht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d", + "driver %s channel switch: iface->freq=%d, freq=%d, ht=%d, vht_ch=0x%x, " + "he_ch=0x%x, eht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d", finished ? "had" : "starting", + hapd->iface->freq, freq, ht, hapd->iconf->ch_switch_vht_config, hapd->iconf->ch_switch_he_config, hapd->iconf->ch_switch_eht_config, offset, @@ -882,6 +884,8 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, return; } + /* Check if any of configured channels require DFS */ + is_dfs0 = hostapd_is_dfs_required(hapd->iface); hapd->iface->freq = freq; channel = hostapd_hw_get_channel(hapd, freq); @@ -997,11 +1001,11 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, hapd->iface->num_hw_features); wpa_msg(hapd->msg_ctx, MSG_INFO, - "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d dfs=%d", + "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d is_dfs0=%d dfs=%d", finished ? WPA_EVENT_CHANNEL_SWITCH : WPA_EVENT_CHANNEL_SWITCH_STARTED, freq, ht, offset, channel_width_to_string(width), - cf1, cf2, is_dfs); + cf1, cf2, is_dfs0, is_dfs); if (!finished) return; @@ -1013,6 +1017,14 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED "freq=%d dfs=%d", freq, is_dfs); } else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) { + /* Complete AP configuration for the first bring up. */ + if (is_dfs0 > 0 && + hostapd_is_dfs_required(hapd->iface) <= 0 && + hapd->iface->state != HAPD_IFACE_ENABLED) { + /* Fake a CAC start bit to skip setting channel */ + hapd->iface->cac_started = 1; + hostapd_setup_interface_complete(hapd->iface, 0); + } wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED "freq=%d dfs=%d", freq, is_dfs); } else if (is_dfs &&