blob: d2b117cdad0414837b8a71cfc6279c50e030f861 [file] [log] [blame]
developer7e2761e2023-10-12 08:11:13 +08001From 88f5a4c1c67f8fc40c8294c498faa72e1ceea470 Mon Sep 17 00:00:00 2001
2From: "fancy.liu" <fancy.liu@mediatek.com>
3Date: Thu, 28 Sep 2023 18:03:08 +0800
4Subject: [PATCH] hostapd: mtk: [ACS] Add EHT320 and HT40- support, fix issue
5
61. Add 6G EHT320 support;
72. Add 2.4G HT40- support;
83. Fix issue: selected best channel is out of channels;
9
10Signed-off-by: fancy.liu <fancy.liu@mediatek.com>
11---
12 src/ap/acs.c | 222 +++++++++++++++++++++++++++++++--------------------
13 1 file changed, 136 insertions(+), 86 deletions(-)
14
15diff --git a/src/ap/acs.c b/src/ap/acs.c
16index af31405..ed6a47b 100644
17--- a/src/ap/acs.c
18+++ b/src/ap/acs.c
19@@ -245,6 +245,7 @@ enum bw_type {
20 ACS_BW40,
21 ACS_BW80,
22 ACS_BW160,
23+ ACS_BW320,
24 };
25
26 struct bw_item {
27@@ -286,10 +287,16 @@ static const struct bw_item bw_160[] = {
28 { 6435, 6575, 111 }, { 6595, 6735, 143 },
29 { 6755, 6895, 175 }, { 6915, 7055, 207 }, { -1, -1, -1 }
30 };
31+static const struct bw_item bw_320[] = {
32+ { 5955, 6255, 31 }, { 6115, 6415, 63 }, { 6275, 6575, 95 },
33+ { 6435, 6735, 127 }, { 6595, 6895, 159 }, { 6755, 7055, 191 },
34+ { -1, -1, -1 }
35+};
36 static const struct bw_item *bw_desc[] = {
37 [ACS_BW40] = bw_40,
38 [ACS_BW80] = bw_80,
39 [ACS_BW160] = bw_160,
40+ [ACS_BW320] = bw_320,
41 };
42
43
44@@ -583,12 +590,6 @@ static void acs_survey_mode_interference_factor(
45 iface->conf->acs_exclude_dfs)
46 continue;
47
48- if (!is_in_chanlist(iface, chan))
49- continue;
50-
51- if (!is_in_freqlist(iface, chan))
52- continue;
53-
54 if (chan->max_tx_power < iface->conf->min_tx_power)
55 continue;
56
57@@ -775,17 +776,29 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
58 struct hostapd_channel_data **ideal_chan,
59 long double *ideal_factor)
60 {
61- struct hostapd_channel_data *chan, *adj_chan = NULL, *best;
62+ struct hostapd_channel_data *chan, *adj_chan = NULL, *tmp_chan = NULL, *best;
63 long double factor;
64 int i, j;
65 unsigned int k;
66+ int ht40_plus = 1, sec_ch_factor = 1;
67+
68+ if (is_24ghz_mode(mode->mode)) {
69+ ht40_plus = (iface->conf->secondary_channel == -1) ? 0 : 1;
70+ sec_ch_factor = (iface->conf->secondary_channel == -1) ? -1 : 1;
71+ }
72+
73+ wpa_printf(MSG_INFO, "%s:%d, bw(%u), n_chans(%d), num_channels(%d), sec_ch(%d)",
74+ __func__, __LINE__, bw, n_chans, mode->num_channels, iface->conf->secondary_channel);
75
76 for (i = 0; i < mode->num_channels; i++) {
77 double total_weight;
78 struct acs_bias *bias, tmp_bias;
79- bool update_best = true;
80+ bool update_best = true, has_candidate = true;
81
82 best = chan = &mode->channels[i];
83+ wpa_printf(MSG_INFO,
84+ "ACS: Channel[%d] %d: interference_factor %Lg",
85+ i, chan->chan, chan->interference_factor);
86
87 /* Since in the current ACS implementation the first channel is
88 * always a primary channel, skip channels not available as
89@@ -804,11 +817,12 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
90 iface->conf->acs_exclude_dfs)
91 continue;
92
93- if (!is_in_chanlist(iface, chan))
94- continue;
95-
96- if (!is_in_freqlist(iface, chan))
97- continue;
98+ if (!is_in_chanlist(iface, chan) || !is_in_freqlist(iface, chan)) {
99+ if (is_24ghz_mode(mode->mode))
100+ continue;
101+ else
102+ has_candidate = false;
103+ }
104
105 if (chan->max_tx_power < iface->conf->min_tx_power)
106 continue;
107@@ -817,7 +831,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
108 iface->conf->country[2] == 0x4f)
109 continue;
110
111- if (!chan_bw_allowed(chan, bw, 1, 1)) {
112+ if (!chan_bw_allowed(chan, bw, ht40_plus, 1)) {
113 wpa_printf(MSG_DEBUG,
114 "ACS: Channel %d: BW %u is not supported",
115 chan->chan, bw);
116@@ -838,7 +852,8 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
117 }
118
119 if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
120- (iface->conf->ieee80211ac || iface->conf->ieee80211ax)) {
121+ (iface->conf->ieee80211ac || iface->conf->ieee80211ax ||
122+ iface->conf->ieee80211be)) {
123 if (hostapd_get_oper_chwidth(iface->conf) ==
124 CONF_OPER_CHWIDTH_80MHZ &&
125 !acs_usable_bw_chan(chan, ACS_BW80)) {
126@@ -856,63 +871,89 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
127 chan->chan);
128 continue;
129 }
130- }
131
132- factor = 0;
133- if (acs_usable_chan(chan))
134- factor = chan->interference_factor;
135- total_weight = 1;
136-
137- for (j = 1; j < n_chans; j++) {
138- adj_chan = acs_find_chan(iface, chan->freq + (j * 20));
139- if (!adj_chan)
140- break;
141-
142- if (!chan_bw_allowed(adj_chan, bw, 1, 0)) {
143+ if (iface->conf->ieee80211be &&
144+ hostapd_get_oper_chwidth(iface->conf) ==
145+ CONF_OPER_CHWIDTH_320MHZ &&
146+ !acs_usable_bw_chan(chan, ACS_BW320)) {
147 wpa_printf(MSG_DEBUG,
148- "ACS: PRI Channel %d: secondary channel %d BW %u is not supported",
149- chan->chan, adj_chan->chan, bw);
150- break;
151+ "ACS: Channel %d: not allowed as primary channel for 320 MHz bandwidth",
152+ chan->chan);
153+ continue;
154 }
155+ }
156+
157+ factor = 0;
158+ total_weight = 0;
159
160- if (acs_usable_chan(adj_chan)) {
161- factor += adj_chan->interference_factor;
162+ if (!is_24ghz_mode(mode->mode)) {
163+ /* If the AP is in the 5 GHz or 6 GHz band, lets prefer a less
164+ * crowded primary channel if one was found in the segment */
165+ if (acs_usable_chan(chan)) {
166+ factor += chan->interference_factor;
167 total_weight += 1;
168- } else {
169- update_best = false;
170 }
171
172- /* find the best channel in this segment */
173- if (update_best &&
174- adj_chan->interference_factor <
175- best->interference_factor)
176- best = adj_chan;
177- }
178+ for (j = 1; j < n_chans; j++) {
179+ adj_chan = acs_find_chan(iface, chan->freq + j * 20);
180+ if (!adj_chan)
181+ break;
182
183- if (j != n_chans) {
184- wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth",
185- chan->chan);
186- continue;
187- }
188+ if (!chan_bw_allowed(adj_chan, bw, 1, 0)) {
189+ wpa_printf(MSG_DEBUG,
190+ "ACS: PRI Channel %d: secondary channel %d BW %u is not supported",
191+ chan->chan, adj_chan->chan, bw);
192+ break;
193+ }
194
195- /* If the AP is in the 5 GHz or 6 GHz band, lets prefer a less
196- * crowded primary channel if one was found in the segment */
197- if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
198- chan != best) {
199- wpa_printf(MSG_DEBUG,
200- "ACS: promoting channel %d over %d (less interference %Lg/%Lg)",
201- best->chan, chan->chan,
202- chan->interference_factor,
203- best->interference_factor);
204- chan = best;
205- }
206+ update_best = true;
207+ if (acs_usable_chan(adj_chan)) {
208+ factor += adj_chan->interference_factor;
209+ total_weight += 1;
210+
211+ if (!is_in_chanlist(iface, adj_chan) ||
212+ !is_in_freqlist(iface, adj_chan))
213+ update_best = false;
214+ } else {
215+ update_best = false;
216+ }
217+
218+ /* find the best channel in this segment */
219+ if (update_best && (!has_candidate ||
220+ adj_chan->interference_factor < best->interference_factor)) {
221+ best = adj_chan;
222+ has_candidate = true;
223+ }
224+ }
225
226- /* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
227- * channel interference factor. */
228- if (is_24ghz_mode(mode->mode)) {
229+ if (j != n_chans || !has_candidate) {
230+ wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth",
231+ chan->chan);
232+ continue;
233+ }
234+
235+ if (chan != best) {
236+ wpa_printf(MSG_INFO,
237+ "ACS: promoting channel %d over %d (less interference %Lg/%Lg)",
238+ best->chan, chan->chan,
239+ chan->interference_factor,
240+ best->interference_factor);
241+ chan = best;
242+ }
243+ } else {
244 for (j = 0; j < n_chans; j++) {
245+ /* Will set primary_channel / secondary_channel(40M case) weight to 1 */
246+ tmp_chan = acs_find_chan(iface, chan->freq +
247+ (j * 20) * sec_ch_factor);
248+ if (tmp_chan && acs_usable_chan(tmp_chan)) {
249+ factor += tmp_chan->interference_factor;
250+ total_weight += 1;
251+ }
252+
253+ /* 2.4 GHz has overlapping 20 MHz channels. Include adjacent channel
254+ interference factor, separately for primary/secondary channel. */
255 adj_chan = acs_find_chan(iface, chan->freq +
256- (j * 20) - 5);
257+ ((j * 20) - 5) * sec_ch_factor);
258 if (adj_chan && acs_usable_chan(adj_chan)) {
259 factor += ACS_ADJ_WEIGHT *
260 adj_chan->interference_factor;
261@@ -920,7 +961,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
262 }
263
264 adj_chan = acs_find_chan(iface, chan->freq +
265- (j * 20) - 10);
266+ ((j * 20) - 10) * sec_ch_factor);
267 if (adj_chan && acs_usable_chan(adj_chan)) {
268 factor += ACS_NEXT_ADJ_WEIGHT *
269 adj_chan->interference_factor;
270@@ -928,7 +969,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
271 }
272
273 adj_chan = acs_find_chan(iface, chan->freq +
274- (j * 20) + 5);
275+ ((j * 20) + 5) * sec_ch_factor);
276 if (adj_chan && acs_usable_chan(adj_chan)) {
277 factor += ACS_ADJ_WEIGHT *
278 adj_chan->interference_factor;
279@@ -936,7 +977,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
280 }
281
282 adj_chan = acs_find_chan(iface, chan->freq +
283- (j * 20) + 10);
284+ ((j * 20) + 10) * sec_ch_factor);
285 if (adj_chan && acs_usable_chan(adj_chan)) {
286 factor += ACS_NEXT_ADJ_WEIGHT *
287 adj_chan->interference_factor;
288@@ -945,7 +986,8 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
289 }
290 }
291
292- factor /= total_weight;
293+ if (total_weight)
294+ factor /= total_weight;
295
296 bias = NULL;
297 if (iface->conf->acs_chan_bias) {
298@@ -964,11 +1006,11 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
299
300 if (bias) {
301 factor *= bias->bias;
302- wpa_printf(MSG_DEBUG,
303+ wpa_printf(MSG_INFO,
304 "ACS: * channel %d: total interference = %Lg (%f bias)",
305 chan->chan, factor, bias->bias);
306 } else {
307- wpa_printf(MSG_DEBUG,
308+ wpa_printf(MSG_INFO,
309 "ACS: * channel %d: total interference = %Lg",
310 chan->chan, factor);
311 }
312@@ -1021,19 +1063,12 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
313 goto bw_selected;
314 }
315
316- /* TODO: HT40- support */
317-
318- if (iface->conf->ieee80211n &&
319- iface->conf->secondary_channel == -1) {
320- wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
321- return NULL;
322- }
323-
324 if (iface->conf->ieee80211n &&
325 iface->conf->secondary_channel)
326 n_chans = 2;
327
328- if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
329+ if (iface->conf->ieee80211ac || iface->conf->ieee80211ax ||
330+ iface->conf->ieee80211be) {
331 switch (hostapd_get_oper_chwidth(iface->conf)) {
332 case CONF_OPER_CHWIDTH_80MHZ:
333 n_chans = 4;
334@@ -1043,6 +1078,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
335 break;
336 default:
337 break;
338+ /* 320 is supported only in 6GHz 11be mode */
339 }
340 }
341
342@@ -1063,7 +1099,7 @@ bw_selected:
343 }
344
345 if (ideal_chan) {
346- wpa_printf(MSG_DEBUG, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg",
347+ wpa_printf(MSG_INFO, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg",
348 ideal_chan->chan, ideal_chan->freq, ideal_factor);
349
350 #ifdef CONFIG_IEEE80211BE
351@@ -1078,6 +1114,21 @@ bw_selected:
352 return rand_chan;
353 }
354
355+static int acs_get_center_freq_320mhz(int channel)
356+{
357+ if (channel >= 1 && channel <= 45)
358+ return 31;
359+ else if (channel >= 49 && channel <= 77)
360+ return 63;
361+ else if (channel >= 81 && channel <= 109)
362+ return 95;
363+ else if (channel >= 113 && channel <= 141)
364+ return 127;
365+ else if (channel >= 145 && channel <= 173)
366+ return 159;
367+ else
368+ return 191;
369+}
370
371 static void acs_adjust_secondary(struct hostapd_iface *iface)
372 {
373@@ -1104,10 +1155,11 @@ static void acs_adjust_secondary(struct hostapd_iface *iface)
374 static void acs_adjust_center_freq(struct hostapd_iface *iface)
375 {
376 int center;
377+ u8 bw = hostapd_get_oper_chwidth(iface->conf);
378
379- wpa_printf(MSG_DEBUG, "ACS: Adjusting VHT center frequency");
380+ wpa_printf(MSG_DEBUG, "ACS: Adjusting center frequency");
381
382- switch (hostapd_get_oper_chwidth(iface->conf)) {
383+ switch (bw) {
384 case CONF_OPER_CHWIDTH_USE_HT:
385 if (iface->conf->secondary_channel &&
386 iface->freq >= 2400 && iface->freq < 2500)
387@@ -1121,6 +1173,9 @@ static void acs_adjust_center_freq(struct hostapd_iface *iface)
388 case CONF_OPER_CHWIDTH_80MHZ:
389 center = acs_get_bw_center_chan(iface->freq, ACS_BW80);
390 break;
391+ case CONF_OPER_CHWIDTH_320MHZ:
392+ center = acs_get_center_freq_320mhz(iface->conf->channel);
393+ break;
394 case CONF_OPER_CHWIDTH_160MHZ:
395 center = acs_get_bw_center_chan(iface->freq, ACS_BW160);
396 break;
397@@ -1128,7 +1183,7 @@ static void acs_adjust_center_freq(struct hostapd_iface *iface)
398 /* TODO: How can this be calculated? Adjust
399 * acs_find_ideal_chan() */
400 wpa_printf(MSG_INFO,
401- "ACS: Only VHT20/40/80/160 is supported now");
402+ "ACS: Only VHT20/40/80/160 EHT320 is supported now");
403 return;
404 }
405
406@@ -1191,7 +1246,8 @@ static void acs_study(struct hostapd_iface *iface)
407 iface->conf->punct_bitmap = ideal_chan->punct_bitmap;
408 #endif /* CONFIG_IEEE80211BE */
409
410- if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
411+ if (iface->conf->ieee80211ac || iface->conf->ieee80211ax ||
412+ iface->conf->ieee80211be) {
413 acs_adjust_secondary(iface);
414 acs_adjust_center_freq(iface);
415 }
416@@ -1270,12 +1326,6 @@ static int * acs_request_scan_add_freqs(struct hostapd_iface *iface,
417 iface->conf->acs_exclude_dfs))
418 continue;
419
420- if (!is_in_chanlist(iface, chan))
421- continue;
422-
423- if (!is_in_freqlist(iface, chan))
424- continue;
425-
426 if (chan->max_tx_power < iface->conf->min_tx_power)
427 continue;
428
429--
4302.25.1
431