blob: f5b5c24dea1ce6441dd9883419105b6d13702c87 [file] [log] [blame]
developerd243af02023-12-21 14:49:33 +08001From 1f6c4857cb55c8ba81a50f3fe0a1465efee10513 Mon Sep 17 00:00:00 2001
developere35b8e42023-10-16 11:04:00 +08002From: "fancy.liu" <fancy.liu@mediatek.com>
3Date: Thu, 28 Sep 2023 18:03:08 +0800
developerd243af02023-12-21 14:49:33 +08004Subject: [PATCH 52/54] mtk: hostapd: ACS: Add EHT320 and HT40- support, fix
5 issue
developere35b8e42023-10-16 11:04:00 +08006
71. Add 6G EHT320 support;
82. Add 2.4G HT40- support;
93. Fix issue: selected best channel is out of channels;
10
11Signed-off-by: fancy.liu <fancy.liu@mediatek.com>
12---
developerd243af02023-12-21 14:49:33 +080013 src/ap/acs.c | 191 +++++++++++++++++++++++++++++++++------------------
14 1 file changed, 124 insertions(+), 67 deletions(-)
developere35b8e42023-10-16 11:04:00 +080015
16diff --git a/src/ap/acs.c b/src/ap/acs.c
developerd243af02023-12-21 14:49:33 +080017index af3140542..e4871921f 100644
developere35b8e42023-10-16 11:04:00 +080018--- a/src/ap/acs.c
19+++ b/src/ap/acs.c
20@@ -245,6 +245,7 @@ enum bw_type {
21 ACS_BW40,
22 ACS_BW80,
23 ACS_BW160,
24+ ACS_BW320,
25 };
26
27 struct bw_item {
28@@ -286,10 +287,16 @@ static const struct bw_item bw_160[] = {
29 { 6435, 6575, 111 }, { 6595, 6735, 143 },
30 { 6755, 6895, 175 }, { 6915, 7055, 207 }, { -1, -1, -1 }
31 };
32+static const struct bw_item bw_320[] = {
33+ { 5955, 6255, 31 }, { 6115, 6415, 63 }, { 6275, 6575, 95 },
34+ { 6435, 6735, 127 }, { 6595, 6895, 159 }, { 6755, 7055, 191 },
35+ { -1, -1, -1 }
36+};
37 static const struct bw_item *bw_desc[] = {
38 [ACS_BW40] = bw_40,
39 [ACS_BW80] = bw_80,
40 [ACS_BW160] = bw_160,
41+ [ACS_BW320] = bw_320,
42 };
43
44
developerd243af02023-12-21 14:49:33 +080045@@ -775,10 +782,19 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developere35b8e42023-10-16 11:04:00 +080046 struct hostapd_channel_data **ideal_chan,
47 long double *ideal_factor)
48 {
49- struct hostapd_channel_data *chan, *adj_chan = NULL, *best;
50+ struct hostapd_channel_data *chan, *adj_chan = NULL, *tmp_chan = NULL, *best;
51 long double factor;
52 int i, j;
53 unsigned int k;
54+ int ht40_plus = 1, sec_ch_factor = 1;
55+
56+ if (is_24ghz_mode(mode->mode)) {
57+ ht40_plus = (iface->conf->secondary_channel == -1) ? 0 : 1;
58+ sec_ch_factor = (iface->conf->secondary_channel == -1) ? -1 : 1;
59+ }
60+
61+ wpa_printf(MSG_INFO, "%s:%d, bw(%u), n_chans(%d), num_channels(%d), sec_ch(%d)",
62+ __func__, __LINE__, bw, n_chans, mode->num_channels, iface->conf->secondary_channel);
63
64 for (i = 0; i < mode->num_channels; i++) {
65 double total_weight;
developerd243af02023-12-21 14:49:33 +080066@@ -786,6 +802,9 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
67 bool update_best = true;
developere35b8e42023-10-16 11:04:00 +080068
69 best = chan = &mode->channels[i];
70+ wpa_printf(MSG_INFO,
71+ "ACS: Channel[%d] %d: interference_factor %Lg",
72+ i, chan->chan, chan->interference_factor);
73
74 /* Since in the current ACS implementation the first channel is
75 * always a primary channel, skip channels not available as
developerd243af02023-12-21 14:49:33 +080076@@ -817,7 +836,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developere35b8e42023-10-16 11:04:00 +080077 iface->conf->country[2] == 0x4f)
78 continue;
79
80- if (!chan_bw_allowed(chan, bw, 1, 1)) {
81+ if (!chan_bw_allowed(chan, bw, ht40_plus, 1)) {
82 wpa_printf(MSG_DEBUG,
83 "ACS: Channel %d: BW %u is not supported",
84 chan->chan, bw);
developerd243af02023-12-21 14:49:33 +080085@@ -838,7 +857,8 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developere35b8e42023-10-16 11:04:00 +080086 }
87
88 if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
89- (iface->conf->ieee80211ac || iface->conf->ieee80211ax)) {
90+ (iface->conf->ieee80211ac || iface->conf->ieee80211ax ||
91+ iface->conf->ieee80211be)) {
92 if (hostapd_get_oper_chwidth(iface->conf) ==
93 CONF_OPER_CHWIDTH_80MHZ &&
94 !acs_usable_bw_chan(chan, ACS_BW80)) {
developerd243af02023-12-21 14:49:33 +080095@@ -856,63 +876,86 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developere35b8e42023-10-16 11:04:00 +080096 chan->chan);
97 continue;
98 }
99- }
100
101- factor = 0;
102- if (acs_usable_chan(chan))
103- factor = chan->interference_factor;
104- total_weight = 1;
105-
106- for (j = 1; j < n_chans; j++) {
107- adj_chan = acs_find_chan(iface, chan->freq + (j * 20));
108- if (!adj_chan)
109- break;
110-
111- if (!chan_bw_allowed(adj_chan, bw, 1, 0)) {
112+ if (iface->conf->ieee80211be &&
113+ hostapd_get_oper_chwidth(iface->conf) ==
114+ CONF_OPER_CHWIDTH_320MHZ &&
115+ !acs_usable_bw_chan(chan, ACS_BW320)) {
116 wpa_printf(MSG_DEBUG,
117- "ACS: PRI Channel %d: secondary channel %d BW %u is not supported",
118- chan->chan, adj_chan->chan, bw);
119- break;
120+ "ACS: Channel %d: not allowed as primary channel for 320 MHz bandwidth",
121+ chan->chan);
122+ continue;
123 }
124+ }
developere35b8e42023-10-16 11:04:00 +0800125
126- if (acs_usable_chan(adj_chan)) {
127- factor += adj_chan->interference_factor;
developerd243af02023-12-21 14:49:33 +0800128+ factor = 0;
129+ total_weight = 0;
130+
developere35b8e42023-10-16 11:04:00 +0800131+ if (!is_24ghz_mode(mode->mode)) {
132+ /* If the AP is in the 5 GHz or 6 GHz band, lets prefer a less
133+ * crowded primary channel if one was found in the segment */
134+ if (acs_usable_chan(chan)) {
135+ factor += chan->interference_factor;
136 total_weight += 1;
137- } else {
138- update_best = false;
139 }
140
141- /* find the best channel in this segment */
142- if (update_best &&
143- adj_chan->interference_factor <
144- best->interference_factor)
145- best = adj_chan;
146- }
147+ for (j = 1; j < n_chans; j++) {
148+ adj_chan = acs_find_chan(iface, chan->freq + j * 20);
149+ if (!adj_chan)
150+ break;
151
152- if (j != n_chans) {
153- wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth",
154- chan->chan);
155- continue;
156- }
developerd243af02023-12-21 14:49:33 +0800157+ if (!is_in_chanlist(iface, adj_chan) || !is_in_freqlist(iface, adj_chan))
developere35b8e42023-10-16 11:04:00 +0800158+ break;
developere35b8e42023-10-16 11:04:00 +0800159
160- /* If the AP is in the 5 GHz or 6 GHz band, lets prefer a less
161- * crowded primary channel if one was found in the segment */
162- if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
163- chan != best) {
164- wpa_printf(MSG_DEBUG,
165- "ACS: promoting channel %d over %d (less interference %Lg/%Lg)",
166- best->chan, chan->chan,
167- chan->interference_factor,
168- best->interference_factor);
169- chan = best;
170- }
developerd243af02023-12-21 14:49:33 +0800171+ if (!chan_bw_allowed(adj_chan, bw, 1, 0)) {
172+ wpa_printf(MSG_DEBUG,
173+ "ACS: PRI Channel %d: secondary channel %d BW %u is not supported",
174+ chan->chan, adj_chan->chan, bw);
175+ break;
176+ }
177+
developere35b8e42023-10-16 11:04:00 +0800178+ update_best = true;
179+ if (acs_usable_chan(adj_chan)) {
180+ factor += adj_chan->interference_factor;
181+ total_weight += 1;
developere35b8e42023-10-16 11:04:00 +0800182+ } else {
183+ update_best = false;
184+ }
developere35b8e42023-10-16 11:04:00 +0800185
186- /* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
187- * channel interference factor. */
188- if (is_24ghz_mode(mode->mode)) {
developerd243af02023-12-21 14:49:33 +0800189+ /* find the best channel in this segment */
190+ if (update_best &&
191+ adj_chan->interference_factor < best->interference_factor)
192+ best = adj_chan;
193+ }
194+
195+ if (j != n_chans) {
developere35b8e42023-10-16 11:04:00 +0800196+ wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth",
197+ chan->chan);
198+ continue;
199+ }
200+
201+ if (chan != best) {
202+ wpa_printf(MSG_INFO,
203+ "ACS: promoting channel %d over %d (less interference %Lg/%Lg)",
204+ best->chan, chan->chan,
205+ chan->interference_factor,
206+ best->interference_factor);
207+ chan = best;
208+ }
209+ } else {
210 for (j = 0; j < n_chans; j++) {
211+ /* Will set primary_channel / secondary_channel(40M case) weight to 1 */
212+ tmp_chan = acs_find_chan(iface, chan->freq +
developerd243af02023-12-21 14:49:33 +0800213+ (j * sec_ch_factor * 20));
developere35b8e42023-10-16 11:04:00 +0800214+ if (tmp_chan && acs_usable_chan(tmp_chan)) {
215+ factor += tmp_chan->interference_factor;
216+ total_weight += 1;
217+ }
218+
219+ /* 2.4 GHz has overlapping 20 MHz channels. Include adjacent channel
220+ interference factor, separately for primary/secondary channel. */
221 adj_chan = acs_find_chan(iface, chan->freq +
222- (j * 20) - 5);
developerd243af02023-12-21 14:49:33 +0800223+ (j * sec_ch_factor * 20) - 5);
developere35b8e42023-10-16 11:04:00 +0800224 if (adj_chan && acs_usable_chan(adj_chan)) {
225 factor += ACS_ADJ_WEIGHT *
226 adj_chan->interference_factor;
developerd243af02023-12-21 14:49:33 +0800227@@ -920,7 +963,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developere35b8e42023-10-16 11:04:00 +0800228 }
229
230 adj_chan = acs_find_chan(iface, chan->freq +
231- (j * 20) - 10);
developerd243af02023-12-21 14:49:33 +0800232+ (j * sec_ch_factor * 20) - 10);
developere35b8e42023-10-16 11:04:00 +0800233 if (adj_chan && acs_usable_chan(adj_chan)) {
234 factor += ACS_NEXT_ADJ_WEIGHT *
235 adj_chan->interference_factor;
developerd243af02023-12-21 14:49:33 +0800236@@ -928,7 +971,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developere35b8e42023-10-16 11:04:00 +0800237 }
238
239 adj_chan = acs_find_chan(iface, chan->freq +
240- (j * 20) + 5);
developerd243af02023-12-21 14:49:33 +0800241+ (j * sec_ch_factor * 20) + 5);
developere35b8e42023-10-16 11:04:00 +0800242 if (adj_chan && acs_usable_chan(adj_chan)) {
243 factor += ACS_ADJ_WEIGHT *
244 adj_chan->interference_factor;
developerd243af02023-12-21 14:49:33 +0800245@@ -936,7 +979,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developere35b8e42023-10-16 11:04:00 +0800246 }
247
248 adj_chan = acs_find_chan(iface, chan->freq +
249- (j * 20) + 10);
developerd243af02023-12-21 14:49:33 +0800250+ (j * sec_ch_factor * 20) + 10);
developere35b8e42023-10-16 11:04:00 +0800251 if (adj_chan && acs_usable_chan(adj_chan)) {
252 factor += ACS_NEXT_ADJ_WEIGHT *
253 adj_chan->interference_factor;
developerd243af02023-12-21 14:49:33 +0800254@@ -945,7 +988,8 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developere35b8e42023-10-16 11:04:00 +0800255 }
256 }
257
258- factor /= total_weight;
259+ if (total_weight)
260+ factor /= total_weight;
261
262 bias = NULL;
263 if (iface->conf->acs_chan_bias) {
developerd243af02023-12-21 14:49:33 +0800264@@ -964,11 +1008,11 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
developere35b8e42023-10-16 11:04:00 +0800265
266 if (bias) {
267 factor *= bias->bias;
268- wpa_printf(MSG_DEBUG,
269+ wpa_printf(MSG_INFO,
270 "ACS: * channel %d: total interference = %Lg (%f bias)",
271 chan->chan, factor, bias->bias);
272 } else {
273- wpa_printf(MSG_DEBUG,
274+ wpa_printf(MSG_INFO,
275 "ACS: * channel %d: total interference = %Lg",
276 chan->chan, factor);
277 }
developerd243af02023-12-21 14:49:33 +0800278@@ -1021,19 +1065,12 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
developere35b8e42023-10-16 11:04:00 +0800279 goto bw_selected;
280 }
281
282- /* TODO: HT40- support */
283-
284- if (iface->conf->ieee80211n &&
285- iface->conf->secondary_channel == -1) {
286- wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
287- return NULL;
288- }
289-
290 if (iface->conf->ieee80211n &&
291 iface->conf->secondary_channel)
292 n_chans = 2;
293
294- if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
295+ if (iface->conf->ieee80211ac || iface->conf->ieee80211ax ||
296+ iface->conf->ieee80211be) {
297 switch (hostapd_get_oper_chwidth(iface->conf)) {
298 case CONF_OPER_CHWIDTH_80MHZ:
299 n_chans = 4;
developerd243af02023-12-21 14:49:33 +0800300@@ -1043,6 +1080,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
developere35b8e42023-10-16 11:04:00 +0800301 break;
302 default:
303 break;
304+ /* 320 is supported only in 6GHz 11be mode */
305 }
306 }
307
developerd243af02023-12-21 14:49:33 +0800308@@ -1063,7 +1101,7 @@ bw_selected:
developere35b8e42023-10-16 11:04:00 +0800309 }
310
311 if (ideal_chan) {
312- wpa_printf(MSG_DEBUG, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg",
313+ wpa_printf(MSG_INFO, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg",
314 ideal_chan->chan, ideal_chan->freq, ideal_factor);
315
316 #ifdef CONFIG_IEEE80211BE
developerd243af02023-12-21 14:49:33 +0800317@@ -1078,6 +1116,21 @@ bw_selected:
developere35b8e42023-10-16 11:04:00 +0800318 return rand_chan;
319 }
320
321+static int acs_get_center_freq_320mhz(int channel)
322+{
323+ if (channel >= 1 && channel <= 45)
324+ return 31;
325+ else if (channel >= 49 && channel <= 77)
326+ return 63;
327+ else if (channel >= 81 && channel <= 109)
328+ return 95;
329+ else if (channel >= 113 && channel <= 141)
330+ return 127;
331+ else if (channel >= 145 && channel <= 173)
332+ return 159;
333+ else
334+ return 191;
335+}
336
337 static void acs_adjust_secondary(struct hostapd_iface *iface)
338 {
developerd243af02023-12-21 14:49:33 +0800339@@ -1105,7 +1158,7 @@ static void acs_adjust_center_freq(struct hostapd_iface *iface)
developere35b8e42023-10-16 11:04:00 +0800340 {
341 int center;
developere35b8e42023-10-16 11:04:00 +0800342
343- wpa_printf(MSG_DEBUG, "ACS: Adjusting VHT center frequency");
344+ wpa_printf(MSG_DEBUG, "ACS: Adjusting center frequency");
345
developerd243af02023-12-21 14:49:33 +0800346 switch (hostapd_get_oper_chwidth(iface->conf)) {
developere35b8e42023-10-16 11:04:00 +0800347 case CONF_OPER_CHWIDTH_USE_HT:
developerd243af02023-12-21 14:49:33 +0800348@@ -1121,6 +1174,9 @@ static void acs_adjust_center_freq(struct hostapd_iface *iface)
developere35b8e42023-10-16 11:04:00 +0800349 case CONF_OPER_CHWIDTH_80MHZ:
350 center = acs_get_bw_center_chan(iface->freq, ACS_BW80);
351 break;
352+ case CONF_OPER_CHWIDTH_320MHZ:
353+ center = acs_get_center_freq_320mhz(iface->conf->channel);
354+ break;
355 case CONF_OPER_CHWIDTH_160MHZ:
356 center = acs_get_bw_center_chan(iface->freq, ACS_BW160);
357 break;
developerd243af02023-12-21 14:49:33 +0800358@@ -1128,7 +1184,7 @@ static void acs_adjust_center_freq(struct hostapd_iface *iface)
developere35b8e42023-10-16 11:04:00 +0800359 /* TODO: How can this be calculated? Adjust
360 * acs_find_ideal_chan() */
361 wpa_printf(MSG_INFO,
362- "ACS: Only VHT20/40/80/160 is supported now");
363+ "ACS: Only VHT20/40/80/160 EHT320 is supported now");
364 return;
365 }
366
developerd243af02023-12-21 14:49:33 +0800367@@ -1191,7 +1247,8 @@ static void acs_study(struct hostapd_iface *iface)
developere35b8e42023-10-16 11:04:00 +0800368 iface->conf->punct_bitmap = ideal_chan->punct_bitmap;
369 #endif /* CONFIG_IEEE80211BE */
370
371- if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
372+ if (iface->conf->ieee80211ac || iface->conf->ieee80211ax ||
373+ iface->conf->ieee80211be) {
374 acs_adjust_secondary(iface);
375 acs_adjust_center_freq(iface);
376 }
developere35b8e42023-10-16 11:04:00 +0800377--
developerd243af02023-12-21 14:49:33 +08003782.18.0
developere35b8e42023-10-16 11:04:00 +0800379