AP MLD: Track radar detection in offloaded DFS case

Add a new flag radar_detected which is used in the following cases
when setting up a link on a DFS channel while the interface is not yet
enabled:
    1. DFS link received CAC start event
    2. If no radar detected, link setup succeeeds after CAC end
       event is received. Else go to 3.
    3. Radar detected on this link -> set radar_detected bit
    4. CAC end received for the current freq -> Do not setup interface
       as radar already detected. Clear radar_detected bit.
    5. The driver sends channel switch event to switch to another channel
        a. Switch to another DFS channel -> go to 1
        b. Switch to non-DFS channel -> proceed to set up interface

Or when receiving a CAC start event when the interface is already set up:
    1. DFS link already set up successfully
    2. Radar detected on this link -> set radar_detected bit
       a. Switch to DFS channel
           a.1. CAC start -> clear radar_detected bit and partner RNR
           a.2. If radar detected, go to 2.
           a.3. CAC end -> clear radar_detected bit
           a.4. Link enabled successfully
       b. Switch to non-DFS channel
           b.1  No op and the driver handles this

Signed-off-by: Chenming Huang <quic_chenhuan@quicinc.com>
This commit is contained in:
Chenming Huang 2024-03-13 15:08:17 +05:30 committed by Jouni Malinen
parent aaf879ef20
commit f4b84ecaf7
2 changed files with 28 additions and 5 deletions

View file

@ -14,6 +14,7 @@
#include "common/hw_features_common.h" #include "common/hw_features_common.h"
#include "common/wpa_ctrl.h" #include "common/wpa_ctrl.h"
#include "hostapd.h" #include "hostapd.h"
#include "beacon.h"
#include "ap_drv_ops.h" #include "ap_drv_ops.h"
#include "drivers/driver.h" #include "drivers/driver.h"
#include "dfs.h" #include "dfs.h"
@ -1143,14 +1144,23 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
int cf1, int cf2) int cf1, int cf2)
{ {
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_COMPLETED 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=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d radar_detected=%d",
success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2); success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2,
iface->radar_detected);
if (success) { if (success) {
/* Complete iface/ap configuration */ /* Complete iface/ap configuration */
if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) { if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) {
/* Complete AP configuration for the first bring up. */ /* Complete AP configuration for the first bring up. If
if (iface->state != HAPD_IFACE_ENABLED) * a radar was detected in this channel, interface setup
* will be handled in
* 1. hostapd_event_ch_switch() if switching to a
* non-DFS channel
* 2. on next CAC complete event if switching to another
* DFS channel.
*/
if (iface->state != HAPD_IFACE_ENABLED &&
!iface->radar_detected)
hostapd_setup_interface_complete(iface, 0); hostapd_setup_interface_complete(iface, 0);
else else
iface->cac_started = 0; iface->cac_started = 0;
@ -1195,6 +1205,7 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
hostapd_dfs_update_background_chain(iface); hostapd_dfs_update_background_chain(iface);
} }
iface->radar_detected = false;
return 0; return 0;
} }
@ -1438,6 +1449,8 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
"freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
freq, ht_enabled, chan_offset, chan_width, cf1, cf2); freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
iface->radar_detected = true;
/* Proceed only if DFS is not offloaded to the driver */ /* Proceed only if DFS is not offloaded to the driver */
if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
return 0; return 0;
@ -1531,9 +1544,17 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
iface->radar_background.cac_started = 1; iface->radar_background.cac_started = 1;
} else { } else {
/* This is called when the driver indicates that an offloaded /* This is called when the driver indicates that an offloaded
* DFS has started CAC. */ * DFS has started CAC. radar_detected might be set for previous
* DFS channel. Clear it for this new CAC process. */
hostapd_set_state(iface, HAPD_IFACE_DFS); hostapd_set_state(iface, HAPD_IFACE_DFS);
iface->cac_started = 1; iface->cac_started = 1;
/* Clear radar_detected in case it is for the previous
* frequency. Also remove disabled link's information in RNR
* element from other links. */
iface->radar_detected = false;
if (iface->interfaces && iface->interfaces->count > 1)
ieee802_11_set_beacons(iface);
} }
/* TODO: How to check CAC time for ETSI weather channels? */ /* TODO: How to check CAC time for ETSI weather channels? */
iface->dfs_cac_ms = 60000; iface->dfs_cac_ms = 60000;

View file

@ -602,6 +602,8 @@ struct hostapd_iface {
int *basic_rates; int *basic_rates;
int freq; int freq;
bool radar_detected;
/* Background radar configuration */ /* Background radar configuration */
struct { struct {
int channel; int channel;