@@ -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;