diff mbox series

[3/9] DFS: add capability select radar-only channels

Message ID 8ce98f32015291c8fd633bcf811f379bd0afc5ff.1640014128.git.lorenzo@kernel.org
State New
Headers show
Series introduce background radar detection support | expand

Commit Message

Lorenzo Bianconi Dec. 20, 2021, 3:48 p.m. UTC
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@mediatek.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 src/ap/dfs.c | 57 ++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 44 insertions(+), 13 deletions(-)
diff mbox series

Patch

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;