blob: d968859d82ebf053fedf1481be80768f91926a9f [file] [log] [blame]
developer29808952023-11-18 07:50:06 +08001From 920a20927f1537ae2a6ce9c7123ef189e83cd0a0 Mon Sep 17 00:00:00 2001
developerde226652023-11-11 12:19:01 +08002From: Evelyn Tsai <evelyn.tsai@mediatek.com>
3Date: Sat, 11 Nov 2023 11:42:59 +0800
4Subject: [PATCH] hostapd: mtk: ACS: Fix 2.4GHz HT40 case and channel switch
5 fail
6
7Issue#1. Add 2.4G HT40- support
81. Add 2.4G HT40- support
92. Fix issue: selected best channel is out of channels
10
11Issue#2. Fix chan_switch to usable DFS channel fail due to ACS
12
13Step and issue:
141. Enable ACS in hostapd config;
152. Bootup and then use hostapd_cli cmd switch channel to a DFS channel;
163. Will do ACS again, and no work on channel specified in step 2.
17
18Root cause:
19When need do DFS-CAC, hostapd will do intf disable, then set the new
20channel into running config settings, and finally enable intf;
21In the test case, new DFS channel is set to runnint config settings, but
22another param "acs" is still 1 (enable), caused the ACS running when
23intf enabled.
developerde226652023-11-11 12:19:01 +080024---
developer29808952023-11-18 07:50:06 +080025 src/ap/acs.c | 142 ++++++++++++++++++++++++++---------------------
developerde226652023-11-11 12:19:01 +080026 src/ap/hostapd.c | 3 +
developer29808952023-11-18 07:50:06 +080027 2 files changed, 83 insertions(+), 62 deletions(-)
developerde226652023-11-11 12:19:01 +080028
29diff --git a/src/ap/acs.c b/src/ap/acs.c
developer29808952023-11-18 07:50:06 +080030index 130e135..65573b9 100644
developerde226652023-11-11 12:19:01 +080031--- a/src/ap/acs.c
32+++ b/src/ap/acs.c
developer29808952023-11-18 07:50:06 +080033@@ -712,10 +712,19 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developerde226652023-11-11 12:19:01 +080034 struct hostapd_channel_data **ideal_chan,
35 long double *ideal_factor)
36 {
37- struct hostapd_channel_data *chan, *adj_chan = NULL, *best;
38+ struct hostapd_channel_data *chan, *adj_chan = NULL, *tmp_chan = NULL, *best;
39 long double factor;
40 int i, j;
41 unsigned int k;
42+ int ht40_plus = 1, sec_ch_factor = 1;
43+
44+ if (is_24ghz_mode(mode->mode)) {
45+ ht40_plus = (iface->conf->secondary_channel == -1) ? 0 : 1;
46+ sec_ch_factor = (iface->conf->secondary_channel == -1) ? -1 : 1;
47+ }
48+
49+ wpa_printf(MSG_INFO, "%s:%d, bw(%u), n_chans(%d), num_channels(%d), sec_ch(%d)",
50+ __func__, __LINE__, bw, n_chans, mode->num_channels, iface->conf->secondary_channel);
51
52 for (i = 0; i < mode->num_channels; i++) {
53 double total_weight;
developer29808952023-11-18 07:50:06 +080054@@ -723,6 +732,9 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
55 bool update_best = true;
developerde226652023-11-11 12:19:01 +080056
57 best = chan = &mode->channels[i];
58+ wpa_printf(MSG_INFO,
59+ "ACS: Channel[%d] %d: interference_factor %Lg",
60+ i, chan->chan, chan->interference_factor);
61
62 /* Since in the current ACS implementation the first channel is
63 * always a primary channel, skip channels not available as
developer29808952023-11-18 07:50:06 +080064@@ -747,7 +759,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developerde226652023-11-11 12:19:01 +080065 if (chan->flag & HOSTAPD_CHAN_INDOOR_ONLY && iface->conf->country[2] == 0x4f)
66 continue;
67
68- if (!chan_bw_allowed(chan, bw, 1, 1)) {
69+ if (!chan_bw_allowed(chan, bw, ht40_plus, 1)) {
70 wpa_printf(MSG_DEBUG,
71 "ACS: Channel %d: BW %u is not supported",
72 chan->chan, bw);
developer29808952023-11-18 07:50:06 +080073@@ -789,60 +801,73 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developerde226652023-11-11 12:19:01 +080074 }
75
76 factor = 0;
77- if (acs_usable_chan(chan))
78- factor = chan->interference_factor;
79- total_weight = 1;
developer29808952023-11-18 07:50:06 +080080-
developerde226652023-11-11 12:19:01 +080081- for (j = 1; j < n_chans; j++) {
82- adj_chan = acs_find_chan(iface, chan->freq + (j * 20));
83- if (!adj_chan)
84- break;
developer29808952023-11-18 07:50:06 +080085+ total_weight = 0;
86
developerde226652023-11-11 12:19:01 +080087- if (!chan_bw_allowed(adj_chan, bw, 1, 0)) {
88- wpa_printf(MSG_DEBUG,
89- "ACS: PRI Channel %d: secondary channel %d BW %u is not supported",
90- chan->chan, adj_chan->chan, bw);
91- break;
92- }
93-
94- if (acs_usable_chan(adj_chan)) {
95- factor += adj_chan->interference_factor;
96+ if (!is_24ghz_mode(mode->mode)) {
97+ /* If the AP is in the 5 GHz or 6 GHz band, lets prefer a less
98+ * crowded primary channel if one was found in the segment */
99+ if (acs_usable_chan(chan)) {
100+ factor += chan->interference_factor;
101 total_weight += 1;
102- } else {
103- update_best = false;
104 }
105
106- /* find the best channel in this segment */
107- if (update_best &&
108- adj_chan->interference_factor <
109- best->interference_factor)
110- best = adj_chan;
111- }
112+ for (j = 1; j < n_chans; j++) {
113+ adj_chan = acs_find_chan(iface, chan->freq + j * 20);
114+ if (!adj_chan)
115+ break;
116
117- if (j != n_chans) {
118- wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth",
119- chan->chan);
120- continue;
121- }
developer29808952023-11-18 07:50:06 +0800122+ if (!is_in_chanlist(iface, adj_chan) || !is_in_freqlist(iface, adj_chan))
developerde226652023-11-11 12:19:01 +0800123+ break;
developerde226652023-11-11 12:19:01 +0800124
125- /* If the AP is in the 5 GHz or 6 GHz band, lets prefer a less
126- * crowded primary channel if one was found in the segment */
127- if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
128- chan != best) {
129- wpa_printf(MSG_DEBUG,
130- "ACS: promoting channel %d over %d (less interference %Lg/%Lg)",
131- best->chan, chan->chan,
132- chan->interference_factor,
133- best->interference_factor);
134- chan = best;
135- }
developer29808952023-11-18 07:50:06 +0800136+ if (!chan_bw_allowed(adj_chan, bw, 1, 0)) {
137+ wpa_printf(MSG_DEBUG,
138+ "ACS: PRI Channel %d: secondary channel %d BW %u is not supported",
139+ chan->chan, adj_chan->chan, bw);
140+ break;
141+ }
142
143- /* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
144- * channel interference factor. */
145- if (is_24ghz_mode(mode->mode)) {
developerde226652023-11-11 12:19:01 +0800146+ update_best = true;
147+ if (acs_usable_chan(adj_chan)) {
148+ factor += adj_chan->interference_factor;
149+ total_weight += 1;
developerde226652023-11-11 12:19:01 +0800150+ } else {
151+ update_best = false;
152+ }
153+
154+ /* find the best channel in this segment */
developer29808952023-11-18 07:50:06 +0800155+ if (update_best &&
156+ adj_chan->interference_factor < best->interference_factor)
developerde226652023-11-11 12:19:01 +0800157+ best = adj_chan;
developerde226652023-11-11 12:19:01 +0800158+ }
developer29808952023-11-18 07:50:06 +0800159+
160+ if (j != n_chans) {
developerde226652023-11-11 12:19:01 +0800161+ wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth",
162+ chan->chan);
163+ continue;
164+ }
165+
166+ if (chan != best) {
167+ wpa_printf(MSG_INFO,
168+ "ACS: promoting channel %d over %d (less interference %Lg/%Lg)",
169+ best->chan, chan->chan,
170+ chan->interference_factor,
171+ best->interference_factor);
172+ chan = best;
173+ }
174+ } else {
175 for (j = 0; j < n_chans; j++) {
176+ /* Will set primary_channel / secondary_channel(40M case) weight to 1 */
177+ tmp_chan = acs_find_chan(iface, chan->freq +
developer29808952023-11-18 07:50:06 +0800178+ (j * sec_ch_factor * 20));
developerde226652023-11-11 12:19:01 +0800179+ if (tmp_chan && acs_usable_chan(tmp_chan)) {
180+ factor += tmp_chan->interference_factor;
181+ total_weight += 1;
182+ }
183+
184+ /* 2.4 GHz has overlapping 20 MHz channels. Include adjacent channel
185+ interference factor, separately for primary/secondary channel. */
186 adj_chan = acs_find_chan(iface, chan->freq +
187- (j * 20) - 5);
developer29808952023-11-18 07:50:06 +0800188+ (j * sec_ch_factor * 20) - 5);
developerde226652023-11-11 12:19:01 +0800189 if (adj_chan && acs_usable_chan(adj_chan)) {
190 factor += ACS_ADJ_WEIGHT *
191 adj_chan->interference_factor;
developer29808952023-11-18 07:50:06 +0800192@@ -850,7 +875,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developerde226652023-11-11 12:19:01 +0800193 }
194
195 adj_chan = acs_find_chan(iface, chan->freq +
196- (j * 20) - 10);
developer29808952023-11-18 07:50:06 +0800197+ (j * sec_ch_factor * 20) - 10);
developerde226652023-11-11 12:19:01 +0800198 if (adj_chan && acs_usable_chan(adj_chan)) {
199 factor += ACS_NEXT_ADJ_WEIGHT *
200 adj_chan->interference_factor;
developer29808952023-11-18 07:50:06 +0800201@@ -858,7 +883,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developerde226652023-11-11 12:19:01 +0800202 }
203
204 adj_chan = acs_find_chan(iface, chan->freq +
205- (j * 20) + 5);
developer29808952023-11-18 07:50:06 +0800206+ (j * sec_ch_factor * 20) + 5);
developerde226652023-11-11 12:19:01 +0800207 if (adj_chan && acs_usable_chan(adj_chan)) {
208 factor += ACS_ADJ_WEIGHT *
209 adj_chan->interference_factor;
developer29808952023-11-18 07:50:06 +0800210@@ -866,7 +891,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developerde226652023-11-11 12:19:01 +0800211 }
212
213 adj_chan = acs_find_chan(iface, chan->freq +
214- (j * 20) + 10);
developer29808952023-11-18 07:50:06 +0800215+ (j * sec_ch_factor * 20) + 10);
developerde226652023-11-11 12:19:01 +0800216 if (adj_chan && acs_usable_chan(adj_chan)) {
217 factor += ACS_NEXT_ADJ_WEIGHT *
218 adj_chan->interference_factor;
developer29808952023-11-18 07:50:06 +0800219@@ -875,7 +900,8 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developerde226652023-11-11 12:19:01 +0800220 }
221 }
222
223- factor /= total_weight;
224+ if (total_weight)
225+ factor /= total_weight;
226
227 bias = NULL;
228 if (iface->conf->acs_chan_bias) {
developer29808952023-11-18 07:50:06 +0800229@@ -894,11 +920,11 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developerde226652023-11-11 12:19:01 +0800230
231 if (bias) {
232 factor *= bias->bias;
233- wpa_printf(MSG_DEBUG,
234+ wpa_printf(MSG_INFO,
235 "ACS: * channel %d: total interference = %Lg (%f bias)",
236 chan->chan, factor, bias->bias);
237 } else {
238- wpa_printf(MSG_DEBUG,
239+ wpa_printf(MSG_INFO,
240 "ACS: * channel %d: total interference = %Lg",
241 chan->chan, factor);
242 }
developer29808952023-11-18 07:50:06 +0800243@@ -939,14 +965,6 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
developerde226652023-11-11 12:19:01 +0800244 goto bw_selected;
245 }
246
247- /* TODO: HT40- support */
248-
249- if (iface->conf->ieee80211n &&
250- iface->conf->secondary_channel == -1) {
251- wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
252- return NULL;
253- }
254-
255 if (iface->conf->ieee80211n &&
256 iface->conf->secondary_channel)
257 n_chans = 2;
developer29808952023-11-18 07:50:06 +0800258@@ -981,7 +999,7 @@ bw_selected:
developerde226652023-11-11 12:19:01 +0800259 }
260
261 if (ideal_chan) {
262- wpa_printf(MSG_DEBUG, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg",
263+ wpa_printf(MSG_INFO, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg",
264 ideal_chan->chan, ideal_chan->freq, ideal_factor);
265 return ideal_chan;
266 }
developerde226652023-11-11 12:19:01 +0800267diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
268index f2eb638..250c168 100644
269--- a/src/ap/hostapd.c
270+++ b/src/ap/hostapd.c
271@@ -3895,6 +3895,9 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface,
272
273 iface->freq = freq_params->freq;
274 iface->conf->channel = freq_params->channel;
275+ if (iface->conf->channel != 0) /* If channel not zero, will disable acs. */
276+ iface->conf->acs = 0;
277+
278 iface->conf->secondary_channel = freq_params->sec_channel_offset;
279 hostapd_set_oper_centr_freq_seg0_idx(iface->conf, seg0_idx);
280 hostapd_set_oper_centr_freq_seg1_idx(iface->conf, seg1_idx);
281--
2822.18.0
283