diff mbox series

AP: ACS: Primary channel for 5 GHz band is now selected based on interference factor.

Message ID 591431601920918@mail.yandex.ru
State Superseded
Headers show
Series AP: ACS: Primary channel for 5 GHz band is now selected based on interference factor. | expand

Commit Message

Марков Михаил Oct. 5, 2020, 6:04 p.m. UTC

diff mbox series

Patch

From c920b7fe2e5076a8af543ccefdbccadb8bb152a0 Mon Sep 17 00:00:00 2001
From: Markov Mikhail <markov.mikhail@itmh.ru>
Date: Mon, 5 Oct 2020 22:31:00 +0500
Subject: [PATCH] AP: ACS: Primary channel for 5 GHz band is now selected based
  on interference factor.

This commit replaces former logic where primary channel was always the first one within bandwidth.

Signed-off-by: Markov Mikhail <markov.mikhail@itmh.ru>
---
 src/ap/acs.c       | 33 ++++++++++++++++++++++++++-------
 src/ap/ap_config.h |  1 +
 2 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/src/ap/acs.c b/src/ap/acs.c
index aa2ceb0d1..924678a64 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -642,6 +642,7 @@  acs_find_ideal_chan_mode(struct hostapd_iface *iface,
 			 int n_chans, u32 bw,
 			 struct hostapd_channel_data **rand_chan,
 			 struct hostapd_channel_data **ideal_chan,
+			 struct hostapd_channel_data **first_chan,
 			 long double *ideal_factor)
 {
 	struct hostapd_channel_data *chan, *adj_chan = NULL;
@@ -652,8 +653,9 @@  acs_find_ideal_chan_mode(struct hostapd_iface *iface,
 	for (i = 0; i < mode->num_channels; i++) {
 		double total_weight;
 		struct acs_bias *bias, tmp_bias;
+		struct hostapd_channel_data *pri_chan;
 
-		chan = &mode->channels[i];
+		pri_chan = chan = &mode->channels[i];
 
 		/* Since in the current ACS implementation the first channel is
 		 * always a primary channel, skip channels not available as
@@ -727,6 +729,10 @@  acs_find_ideal_chan_mode(struct hostapd_iface *iface,
 			if (acs_usable_chan(adj_chan)) {
 				factor += adj_chan->interference_factor;
 				total_weight += 1;
+
+				if (adj_chan->interference_factor < pri_chan->interference_factor) {
+					pri_chan = adj_chan;
+				}
 			}
 		}
 
@@ -805,7 +811,8 @@  acs_find_ideal_chan_mode(struct hostapd_iface *iface,
 		if (acs_usable_chan(chan) &&
 		    (!*ideal_chan || factor < *ideal_factor)) {
 			*ideal_factor = factor;
-			*ideal_chan = chan;
+			*ideal_chan = pri_chan;
+			*first_chan = chan;
 		}
 
 		/* This channel would at least be usable */
@@ -825,7 +832,7 @@  static struct hostapd_channel_data *
 acs_find_ideal_chan(struct hostapd_iface *iface)
 {
 	struct hostapd_channel_data *ideal_chan = NULL,
-		*rand_chan = NULL;
+		*rand_chan = NULL, *first_chan = NULL;
 	long double ideal_factor = 0;
 	int i;
 	int n_chans = 1;
@@ -866,14 +873,15 @@  acs_find_ideal_chan(struct hostapd_iface *iface)
 		mode = &iface->hw_features[i];
 		if (!hostapd_hw_skip_mode(iface, mode))
 			acs_find_ideal_chan_mode(iface, mode, n_chans, bw,
-						 &rand_chan, &ideal_chan,
+						 &rand_chan, &ideal_chan, &first_chan,
 						 &ideal_factor);
 	}
 
 	if (ideal_chan) {
 		wpa_printf(MSG_DEBUG, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg",
 			   ideal_chan->chan, ideal_chan->freq, ideal_factor);
-		return ideal_chan;
+		iface->conf->bw_first_chan = first_chan->chan;
+		return is_24ghz_mode(iface->current_mode->mode)? first_chan : ideal_chan;
 	}
 
 	return rand_chan;
@@ -905,7 +913,16 @@  static void acs_adjust_center_freq(struct hostapd_iface *iface)
 	}
 
 	hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
-					     iface->conf->channel + offset);
+						iface->conf->bw_first_chan + offset);
+}
+
+
+static void acs_adjust_sec_chan(struct hostapd_config *conf)
+{
+    const short center = hostapd_get_oper_centr_freq_seg0_idx(conf);
+
+    conf->secondary_channel =
+            (center > conf->channel)? 1 : -1;
 }
 
 
@@ -961,8 +978,10 @@  static void acs_study(struct hostapd_iface *iface)
 	iface->conf->channel = ideal_chan->chan;
 	iface->freq = ideal_chan->freq;
 
-	if (iface->conf->ieee80211ac || iface->conf->ieee80211ax)
+	if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
 		acs_adjust_center_freq(iface);
+		acs_adjust_sec_chan(iface->conf);
+	}
 
 	err = 0;
 fail:
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index bada04c3e..18d662c6e 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -909,6 +909,7 @@  struct hostapd_config {
 	int fragm_threshold;
 	u8 op_class;
 	u8 channel;
+	u8 bw_first_chan;
 	int enable_edmg;
 	u8 edmg_channel;
 	u8 acs;
-- 
2.28.0