Introduce flags parameter to dfs_get_valid_channel routine in order to select radar-only channel where the CAC detection has not been performed yet. This is a preliminary patch to enable background radar/CAC detection. Tested-by: Owen Peng <owen.peng@xxxxxxxxxxxx> Signed-off-by: Lorenzo Bianconi <lorenzo@xxxxxxxxxx> --- src/ap/dfs.c | 57 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/src/ap/dfs.c b/src/ap/dfs.c index a97403756..5ce5489b2 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -50,16 +50,32 @@ static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1) return n_chans; } - +/* dfs_channel_available: select new channel according to flags parameter + * + * flags: + * - 0: any channel + * - 1: non-radar channel or radar available one + * - 2: radar-only channel not yet available + */ static int dfs_channel_available(struct hostapd_channel_data *chan, - int skip_radar) + int flags) { + if (flags == 2) { + /* Select only radar channel where CAC has not been + * performed yet + */ + if ((chan->flag & HOSTAPD_CHAN_RADAR) && + (chan->flag & HOSTAPD_CHAN_DFS_MASK) == + HOSTAPD_CHAN_DFS_USABLE) + return 1; + return 0; + } /* * When radar detection happens, CSA is performed. However, there's no * time for CAC, so radar channels must be skipped when finding a new * channel for CSA, unless they are available for immediate use. */ - if (skip_radar && (chan->flag & HOSTAPD_CHAN_RADAR) && + if (flags && (chan->flag & HOSTAPD_CHAN_RADAR) && ((chan->flag & HOSTAPD_CHAN_DFS_MASK) != HOSTAPD_CHAN_DFS_AVAILABLE)) return 0; @@ -135,10 +151,15 @@ dfs_get_chan_data(struct hostapd_hw_modes *mode, int freq, int first_chan_idx) return NULL; } - +/* + * flags: + * - 0: any channel + * - 1: non-radar channel or radar available one + * - 2: radar-only channel not yet available + */ static int dfs_chan_range_available(struct hostapd_hw_modes *mode, int first_chan_idx, int num_chans, - int skip_radar) + int flags) { struct hostapd_channel_data *first_chan, *chan; int i; @@ -177,7 +198,7 @@ static int dfs_chan_range_available(struct hostapd_hw_modes *mode, return 0; } - if (!dfs_channel_available(chan, skip_radar)) { + if (!dfs_channel_available(chan, flags)) { wpa_printf(MSG_DEBUG, "DFS: channel not available %d", first_chan->freq + i * 20); return 0; @@ -204,10 +225,15 @@ static int is_in_chanlist(struct hostapd_iface *iface, * - hapd->secondary_channel * - hapd->vht/he_oper_centr_freq_seg0_idx * - hapd->vht/he_oper_centr_freq_seg1_idx + * + * flags: + * - 0: any channel + * - 1: non-radar channel or radar available one + * - 2: radar-only channel not yet available */ static int dfs_find_channel(struct hostapd_iface *iface, struct hostapd_channel_data **ret_chan, - int idx, int skip_radar) + int idx, int flags) { struct hostapd_hw_modes *mode; struct hostapd_channel_data *chan; @@ -232,7 +258,7 @@ static int dfs_find_channel(struct hostapd_iface *iface, } /* Skip incompatible chandefs */ - if (!dfs_chan_range_available(mode, i, n_chans, skip_radar)) { + if (!dfs_chan_range_available(mode, i, n_chans, flags)) { wpa_printf(MSG_DEBUG, "DFS: range not available for %d (%d)", chan->freq, chan->chan); @@ -469,13 +495,18 @@ static int dfs_check_chans_unavailable(struct hostapd_iface *iface, return res; } - +/* + * flags: + * - 0: any channel + * - 1: non-radar channel or radar available one + * - 2: radar-only channel not yet available + */ static struct hostapd_channel_data * dfs_get_valid_channel(struct hostapd_iface *iface, int *secondary_channel, u8 *oper_centr_freq_seg0_idx, u8 *oper_centr_freq_seg1_idx, - int skip_radar) + int flags) { struct hostapd_hw_modes *mode; struct hostapd_channel_data *chan = NULL; @@ -499,7 +530,7 @@ dfs_get_valid_channel(struct hostapd_iface *iface, return NULL; /* Get the count first */ - num_available_chandefs = dfs_find_channel(iface, NULL, 0, skip_radar); + num_available_chandefs = dfs_find_channel(iface, NULL, 0, flags); wpa_printf(MSG_DEBUG, "DFS: num_available_chandefs=%d", num_available_chandefs); if (num_available_chandefs == 0) @@ -508,7 +539,7 @@ dfs_get_valid_channel(struct hostapd_iface *iface, if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0) return NULL; chan_idx = _rand % num_available_chandefs; - dfs_find_channel(iface, &chan, chan_idx, skip_radar); + dfs_find_channel(iface, &chan, chan_idx, flags); if (!chan) { wpa_printf(MSG_DEBUG, "DFS: no random channel found"); return NULL; @@ -537,7 +568,7 @@ dfs_get_valid_channel(struct hostapd_iface *iface, for (i = 0; i < num_available_chandefs - 1; i++) { /* start from chan_idx + 1, end when chan_idx - 1 */ chan_idx2 = (chan_idx + 1 + i) % num_available_chandefs; - dfs_find_channel(iface, &chan2, chan_idx2, skip_radar); + dfs_find_channel(iface, &chan2, chan_idx2, flags); if (chan2 && abs(chan2->chan - chan->chan) > 12) { /* two channels are not adjacent */ sec_chan_idx_80p80 = chan2->chan; -- 2.33.1