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(-)
@@ -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:
@@ -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