From 420852ff044c804a6487ccc060f85c12bbdaac31 Mon Sep 17 00:00:00 2001
From: Seevalamuthu Mariappan <seevalam@codeaurora.org>
Date: Thu, 1 Jul 2021 10:15:29 +0530
Subject: [PATCH] hostap: Avoid selecting UNII-1 channel after DFS switch

Avoid UNII-1 band channel from getting selected after DFS when primary
channel is UNII-2 band with 80Mhz configuration.

To enable this, 'skip_unii1_dfs_switch' config should be enabled
in hostapd config.

Signed-off-by: Seevalamuthu Mariappan <seevalam@codeaurora.org>
---
 hostapd/config_file.c |  2 ++
 src/ap/ap_config.h    |  1 +
 src/ap/dfs.c          | 25 +++++++++++++++++++++++++
 3 files changed, 28 insertions(+)

--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3349,6 +3349,8 @@ static int hostapd_config_fill(struct ho
 		conf->require_ht = atoi(pos);
 	} else if (os_strcmp(buf, "obss_interval") == 0) {
 		conf->obss_interval = atoi(pos);
+	} else if (os_strcmp(buf, "skip_unii1_dfs_switch") == 0) {
+		conf->skip_unii1_dfs_switch = atoi(pos);
 #ifdef CONFIG_IEEE80211AC
 	} else if (os_strcmp(buf, "ieee80211ac") == 0) {
 		conf->ieee80211ac = atoi(pos);
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -1030,6 +1030,7 @@ struct hostapd_config {
 
 	/* Use driver-generated interface addresses when adding multiple BSSs */
 	u8 use_driver_iface_addr;
+	u8 skip_unii1_dfs_switch;
 
 #ifdef CONFIG_FST
 	struct fst_iface_cfg fst_cfg;
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -199,6 +199,24 @@ static int is_in_chanlist(struct hostapd
 	return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan);
 }
 
+static bool is_skip_unii1_dfs_switch_applicable(struct hostapd_iface *iface,
+				  		struct hostapd_channel_data *chan)
+{
+	if (!iface->conf->skip_unii1_dfs_switch)
+		return false;
+
+	/* Skip adjacent channel when below conditions are true
+	 * i) The primary channel of the AP is 52/56/60/64 & 80MHz mode.
+	 * ii) The AP moves to the adjacent channel 36/40/44/48 in 80MHz mode
+	 */
+
+	if ((hostapd_get_oper_chwidth(iface->conf) == CHANWIDTH_80MHZ) &&
+	    ((iface->conf->channel >= 52) && (iface->conf->channel <= 64)) &&
+	    ((chan->chan >= 36) && (chan->chan <= 48)))
+		return true;
+
+	return false;
+}
 
 /*
  * The function assumes HT40+ operation.
@@ -247,6 +265,13 @@ static int dfs_find_channel(struct hosta
 				   chan->freq, chan->chan);
 			continue;
 		}
+
+		if (is_skip_unii1_dfs_switch_applicable(iface, chan)) {
+			wpa_printf(MSG_DEBUG,
+				   "DFS: skip_unii1_dfs_switch enabled, skip adjacent channel: %d (%d)",
+				   chan->freq, chan->chan);
+			continue;
+		}
 
 		if (ret_chan && idx == channel_idx) {
 			wpa_printf(MSG_DEBUG, "Selected channel %d (%d)",
