| From 119b1e4f41d2b983150f5f0cb6dcb2c060c6c3c8 Mon Sep 17 00:00:00 2001 |
| From: dzou <dzou@company.com> |
| Date: Sun, 5 Jun 2022 23:13:20 +0800 |
| Subject: [PATCH 901/911] DFS: Add capability to select radar-only channels |
| |
| Introduce type parameter to dfs_get_valid_channel() routine to allow |
| selection of a 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@mediatek.com> |
| Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> |
| --- |
| src/ap/dfs.c | 50 ++++++++++++++++++++++++++++++++++++-------------- |
| 1 file changed, 36 insertions(+), 14 deletions(-) |
| |
| diff --git a/src/ap/dfs.c b/src/ap/dfs.c |
| index 09b2bb7d4..56564b901 100644 |
| --- a/src/ap/dfs.c |
| +++ b/src/ap/dfs.c |
| @@ -52,15 +52,33 @@ static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1) |
| } |
| |
| |
| +enum dfs_channel_type { |
| + DFS_ANY_CHANNEL, |
| + DFS_AVAILABLE, /* non-radar or radar-available */ |
| + DFS_NO_CAC_YET, /* radar-not-yet-available */ |
| +}; |
| + |
| +/* dfs_channel_available: select new channel according to type parameter */ |
| static int dfs_channel_available(struct hostapd_channel_data *chan, |
| - int skip_radar) |
| + enum dfs_channel_type type) |
| { |
| + if (type == DFS_NO_CAC_YET) { |
| + /* 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 (type == DFS_AVAILABLE && (chan->flag & HOSTAPD_CHAN_RADAR) && |
| ((chan->flag & HOSTAPD_CHAN_DFS_MASK) != |
| HOSTAPD_CHAN_DFS_AVAILABLE)) |
| return 0; |
| @@ -139,7 +157,7 @@ dfs_get_chan_data(struct hostapd_hw_modes *mode, int freq, int first_chan_idx) |
| |
| static int dfs_chan_range_available(struct hostapd_hw_modes *mode, |
| int first_chan_idx, int num_chans, |
| - int skip_radar) |
| + enum dfs_channel_type type) |
| { |
| struct hostapd_channel_data *first_chan, *chan; |
| int i; |
| @@ -178,7 +196,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, type)) { |
| wpa_printf(MSG_DEBUG, "DFS: channel not available %d", |
| first_chan->freq + i * 20); |
| return 0; |
| @@ -208,7 +226,7 @@ static int is_in_chanlist(struct hostapd_iface *iface, |
| */ |
| static int dfs_find_channel(struct hostapd_iface *iface, |
| struct hostapd_channel_data **ret_chan, |
| - int idx, int skip_radar) |
| + int idx, enum dfs_channel_type type) |
| { |
| struct hostapd_hw_modes *mode; |
| struct hostapd_channel_data *chan; |
| @@ -233,7 +251,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, type)) { |
| wpa_printf(MSG_DEBUG, |
| "DFS: range not available for %d (%d)", |
| chan->freq, chan->chan); |
| @@ -476,7 +494,7 @@ 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) |
| + enum dfs_channel_type type) |
| { |
| struct hostapd_hw_modes *mode; |
| struct hostapd_channel_data *chan = NULL; |
| @@ -505,7 +523,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, type); |
| wpa_printf(MSG_DEBUG, "DFS: num_available_chandefs=%d", |
| num_available_chandefs); |
| if (num_available_chandefs == 0) |
| @@ -526,7 +544,7 @@ dfs_get_valid_channel(struct hostapd_iface *iface, |
| return NULL; |
| |
| chan_idx = _rand % num_available_chandefs; |
| - dfs_find_channel(iface, &chan, chan_idx, skip_radar); |
| + dfs_find_channel(iface, &chan, chan_idx, type); |
| if (!chan) { |
| wpa_printf(MSG_DEBUG, "DFS: no random channel found"); |
| return NULL; |
| @@ -555,7 +573,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, type); |
| if (chan2 && abs(chan2->chan - chan->chan) > 12) { |
| /* two channels are not adjacent */ |
| sec_chan_idx_80p80 = chan2->chan; |
| @@ -593,7 +611,8 @@ static int dfs_set_valid_channel(struct hostapd_iface *iface, int skip_radar) |
| int sec = 0; |
| |
| channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2, |
| - skip_radar); |
| + skip_radar ? DFS_AVAILABLE : |
| + DFS_ANY_CHANNEL); |
| if (!channel) { |
| wpa_printf(MSG_ERROR, "could not get valid channel"); |
| return -1; |
| @@ -976,7 +995,8 @@ dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel, |
| channel = dfs_get_valid_channel(iface, secondary_channel, |
| oper_centr_freq_seg0_idx, |
| oper_centr_freq_seg1_idx, |
| - *skip_radar); |
| + *skip_radar ? DFS_AVAILABLE : |
| + DFS_ANY_CHANNEL); |
| if (channel) { |
| wpa_printf(MSG_DEBUG, "DFS: Selected channel: %d", |
| channel->chan); |
| @@ -1017,7 +1037,8 @@ static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface) |
| channel = dfs_get_valid_channel(iface, &secondary_channel, |
| &oper_centr_freq_seg0_idx, |
| &oper_centr_freq_seg1_idx, |
| - skip_radar); |
| + skip_radar ? DFS_AVAILABLE : |
| + DFS_ANY_CHANNEL); |
| |
| if (!channel) { |
| channel = dfs_downgrade_bandwidth(iface, &secondary_channel, |
| @@ -1088,7 +1109,8 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) |
| channel = dfs_get_valid_channel(iface, &secondary_channel, |
| &oper_centr_freq_seg0_idx, |
| &oper_centr_freq_seg1_idx, |
| - skip_radar); |
| + skip_radar ? DFS_AVAILABLE : |
| + DFS_ANY_CHANNEL); |
| |
| if (!channel) { |
| /* |
| -- |
| 2.29.2 |
| |