1 /*
2 * ACS - Automatic Channel Selection module
3 * Copyright (c) 2011, Atheros Communications
4 * Copyright (c) 2013, Qualcomm Atheros, Inc.
5 *
6 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
8 */
9
10 #include "utils/includes.h"
11 #include <float.h>
12 #include <math.h>
13
14 #include "utils/common.h"
15 #include "utils/list.h"
16 #include "common/ieee802_11_defs.h"
17 #include "common/hw_features_common.h"
18 #include "common/wpa_ctrl.h"
19 #include "drivers/driver.h"
20 #include "hostapd.h"
21 #include "ap_drv_ops.h"
22 #include "ap_config.h"
23 #include "hw_features.h"
24 #include "acs.h"
25
26 /*
27 * Automatic Channel Selection
28 * ===========================
29 *
30 * More info at
31 * ------------
32 * http://wireless.kernel.org/en/users/Documentation/acs
33 *
34 * How to use
35 * ----------
36 * - make sure you have CONFIG_ACS=y in hostapd's .config
37 * - use channel=0 or channel=acs to enable ACS
38 *
39 * How does it work
40 * ----------------
41 * 1. passive scans are used to collect survey data
42 * (it is assumed that scan trigger collection of survey data in driver)
43 * 2. interference factor is calculated for each channel
44 * 3. ideal channel is picked depending on channel width by using adjacent
45 * channel interference factors
46 *
47 * Known limitations
48 * -----------------
49 * - Current implementation depends heavily on the amount of time willing to
50 * spend gathering survey data during hostapd startup. Short traffic bursts
51 * may be missed and a suboptimal channel may be picked.
52 * - Ideal channel may end up overlapping a channel with 40 MHz intolerant BSS
53 *
54 * Todo / Ideas
55 * ------------
56 * - implement other interference computation methods
57 * - BSS/RSSI based
58 * - spectral scan based
59 * (should be possibly to hook this up with current ACS scans)
60 * - add wpa_supplicant support (for P2P)
61 * - collect a histogram of interference over time allowing more educated
62 * guess about an ideal channel (perhaps CSA could be used to migrate AP to a
63 * new "better" channel while running)
64 * - include neighboring BSS scan to avoid conflicts with 40 MHz intolerant BSSs
65 * when choosing the ideal channel
66 *
67 * Survey interference factor implementation details
68 * -------------------------------------------------
69 * Generic interference_factor in struct hostapd_channel_data is used.
70 *
71 * The survey interference factor is defined as the ratio of the
72 * observed busy time over the time we spent on the channel,
73 * this value is then amplified by the observed noise floor on
74 * the channel in comparison to the lowest noise floor observed
75 * on the entire band.
76 *
77 * This corresponds to:
78 * ---
79 * (busy time - tx time) / (active time - tx time) * 2^(chan_nf + band_min_nf)
80 * ---
81 *
82 * The coefficient of 2 reflects the way power in "far-field"
83 * radiation decreases as the square of distance from the antenna [1].
84 * What this does is it decreases the observed busy time ratio if the
85 * noise observed was low but increases it if the noise was high,
86 * proportionally to the way "far field" radiation changes over
87 * distance.
88 *
89 * If channel busy time is not available the fallback is to use channel RX time.
90 *
91 * Since noise floor is in dBm it is necessary to convert it into Watts so that
92 * combined channel interference (e.g., HT40, which uses two channels) can be
93 * calculated easily.
94 * ---
95 * (busy time - tx time) / (active time - tx time) *
96 * 2^(10^(chan_nf/10) + 10^(band_min_nf/10))
97 * ---
98 *
99 * However to account for cases where busy/rx time is 0 (channel load is then
100 * 0%) channel noise floor signal power is combined into the equation so a
101 * channel with lower noise floor is preferred. The equation becomes:
102 * ---
103 * 10^(chan_nf/5) + (busy time - tx time) / (active time - tx time) *
104 * 2^(10^(chan_nf/10) + 10^(band_min_nf/10))
105 * ---
106 *
107 * All this "interference factor" is purely subjective and only time
108 * will tell how usable this is. By using the minimum noise floor we
109 * remove any possible issues due to card calibration. The computation
110 * of the interference factor then is dependent on what the card itself
111 * picks up as the minimum noise, not an actual real possible card
112 * noise value.
113 *
114 * Total interference computation details
115 * --------------------------------------
116 * The above channel interference factor is calculated with no respect to
117 * target operational bandwidth.
118 *
119 * To find an ideal channel the above data is combined by taking into account
120 * the target operational bandwidth and selected band. E.g., on 2.4 GHz channels
121 * overlap with 20 MHz bandwidth, but there is no overlap for 20 MHz bandwidth
122 * on 5 GHz.
123 *
124 * Each valid and possible channel spec (i.e., channel + width) is taken and its
125 * interference factor is computed by summing up interferences of each channel
126 * it overlaps. The one with least total interference is picked up.
127 *
128 * Note: This implies base channel interference factor must be non-negative
129 * allowing easy summing up.
130 *
131 * Example ACS analysis printout
132 * -----------------------------
133 *
134 * ACS: Trying survey-based ACS
135 * ACS: Survey analysis for channel 1 (2412 MHz)
136 * ACS: 1: min_nf=-113 interference_factor=0.0802469 nf=-113 time=162 busy=0 rx=13
137 * ACS: 2: min_nf=-113 interference_factor=0.0745342 nf=-113 time=161 busy=0 rx=12
138 * ACS: 3: min_nf=-113 interference_factor=0.0679012 nf=-113 time=162 busy=0 rx=11
139 * ACS: 4: min_nf=-113 interference_factor=0.0310559 nf=-113 time=161 busy=0 rx=5
140 * ACS: 5: min_nf=-113 interference_factor=0.0248447 nf=-113 time=161 busy=0 rx=4
141 * ACS: * interference factor average: 0.0557166
142 * ACS: Survey analysis for channel 2 (2417 MHz)
143 * ACS: 1: min_nf=-113 interference_factor=0.0185185 nf=-113 time=162 busy=0 rx=3
144 * ACS: 2: min_nf=-113 interference_factor=0.0246914 nf=-113 time=162 busy=0 rx=4
145 * ACS: 3: min_nf=-113 interference_factor=0.037037 nf=-113 time=162 busy=0 rx=6
146 * ACS: 4: min_nf=-113 interference_factor=0.149068 nf=-113 time=161 busy=0 rx=24
147 * ACS: 5: min_nf=-113 interference_factor=0.0248447 nf=-113 time=161 busy=0 rx=4
148 * ACS: * interference factor average: 0.050832
149 * ACS: Survey analysis for channel 3 (2422 MHz)
150 * ACS: 1: min_nf=-113 interference_factor=2.51189e-23 nf=-113 time=162 busy=0 rx=0
151 * ACS: 2: min_nf=-113 interference_factor=0.0185185 nf=-113 time=162 busy=0 rx=3
152 * ACS: 3: min_nf=-113 interference_factor=0.0186335 nf=-113 time=161 busy=0 rx=3
153 * ACS: 4: min_nf=-113 interference_factor=0.0186335 nf=-113 time=161 busy=0 rx=3
154 * ACS: 5: min_nf=-113 interference_factor=0.0186335 nf=-113 time=161 busy=0 rx=3
155 * ACS: * interference factor average: 0.0148838
156 * ACS: Survey analysis for channel 4 (2427 MHz)
157 * ACS: 1: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
158 * ACS: 2: min_nf=-114 interference_factor=0.0555556 nf=-114 time=162 busy=0 rx=9
159 * ACS: 3: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=161 busy=0 rx=0
160 * ACS: 4: min_nf=-114 interference_factor=0.0186335 nf=-114 time=161 busy=0 rx=3
161 * ACS: 5: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1
162 * ACS: * interference factor average: 0.0160801
163 * ACS: Survey analysis for channel 5 (2432 MHz)
164 * ACS: 1: min_nf=-114 interference_factor=0.409938 nf=-113 time=161 busy=0 rx=66
165 * ACS: 2: min_nf=-114 interference_factor=0.0432099 nf=-113 time=162 busy=0 rx=7
166 * ACS: 3: min_nf=-114 interference_factor=0.0124224 nf=-113 time=161 busy=0 rx=2
167 * ACS: 4: min_nf=-114 interference_factor=0.677019 nf=-113 time=161 busy=0 rx=109
168 * ACS: 5: min_nf=-114 interference_factor=0.0186335 nf=-114 time=161 busy=0 rx=3
169 * ACS: * interference factor average: 0.232244
170 * ACS: Survey analysis for channel 6 (2437 MHz)
171 * ACS: 1: min_nf=-113 interference_factor=0.552795 nf=-113 time=161 busy=0 rx=89
172 * ACS: 2: min_nf=-113 interference_factor=0.0807453 nf=-112 time=161 busy=0 rx=13
173 * ACS: 3: min_nf=-113 interference_factor=0.0310559 nf=-113 time=161 busy=0 rx=5
174 * ACS: 4: min_nf=-113 interference_factor=0.434783 nf=-112 time=161 busy=0 rx=70
175 * ACS: 5: min_nf=-113 interference_factor=0.0621118 nf=-113 time=161 busy=0 rx=10
176 * ACS: * interference factor average: 0.232298
177 * ACS: Survey analysis for channel 7 (2442 MHz)
178 * ACS: 1: min_nf=-113 interference_factor=0.440994 nf=-112 time=161 busy=0 rx=71
179 * ACS: 2: min_nf=-113 interference_factor=0.385093 nf=-113 time=161 busy=0 rx=62
180 * ACS: 3: min_nf=-113 interference_factor=0.0372671 nf=-113 time=161 busy=0 rx=6
181 * ACS: 4: min_nf=-113 interference_factor=0.0372671 nf=-113 time=161 busy=0 rx=6
182 * ACS: 5: min_nf=-113 interference_factor=0.0745342 nf=-113 time=161 busy=0 rx=12
183 * ACS: * interference factor average: 0.195031
184 * ACS: Survey analysis for channel 8 (2447 MHz)
185 * ACS: 1: min_nf=-114 interference_factor=0.0496894 nf=-112 time=161 busy=0 rx=8
186 * ACS: 2: min_nf=-114 interference_factor=0.0496894 nf=-114 time=161 busy=0 rx=8
187 * ACS: 3: min_nf=-114 interference_factor=0.0372671 nf=-113 time=161 busy=0 rx=6
188 * ACS: 4: min_nf=-114 interference_factor=0.12963 nf=-113 time=162 busy=0 rx=21
189 * ACS: 5: min_nf=-114 interference_factor=0.166667 nf=-114 time=162 busy=0 rx=27
190 * ACS: * interference factor average: 0.0865885
191 * ACS: Survey analysis for channel 9 (2452 MHz)
192 * ACS: 1: min_nf=-114 interference_factor=0.0124224 nf=-114 time=161 busy=0 rx=2
193 * ACS: 2: min_nf=-114 interference_factor=0.0310559 nf=-114 time=161 busy=0 rx=5
194 * ACS: 3: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=161 busy=0 rx=0
195 * ACS: 4: min_nf=-114 interference_factor=0.00617284 nf=-114 time=162 busy=0 rx=1
196 * ACS: 5: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
197 * ACS: * interference factor average: 0.00993022
198 * ACS: Survey analysis for channel 10 (2457 MHz)
199 * ACS: 1: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1
200 * ACS: 2: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1
201 * ACS: 3: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1
202 * ACS: 4: min_nf=-114 interference_factor=0.0493827 nf=-114 time=162 busy=0 rx=8
203 * ACS: 5: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
204 * ACS: * interference factor average: 0.0136033
205 * ACS: Survey analysis for channel 11 (2462 MHz)
206 * ACS: 1: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=161 busy=0 rx=0
207 * ACS: 2: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=161 busy=0 rx=0
208 * ACS: 3: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=161 busy=0 rx=0
209 * ACS: 4: min_nf=-114 interference_factor=0.0432099 nf=-114 time=162 busy=0 rx=7
210 * ACS: 5: min_nf=-114 interference_factor=0.0925926 nf=-114 time=162 busy=0 rx=15
211 * ACS: * interference factor average: 0.0271605
212 * ACS: Survey analysis for channel 12 (2467 MHz)
213 * ACS: 1: min_nf=-114 interference_factor=0.0621118 nf=-113 time=161 busy=0 rx=10
214 * ACS: 2: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1
215 * ACS: 3: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=162 busy=0 rx=0
216 * ACS: 4: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=162 busy=0 rx=0
217 * ACS: 5: min_nf=-114 interference_factor=0.00617284 nf=-113 time=162 busy=0 rx=1
218 * ACS: * interference factor average: 0.0148992
219 * ACS: Survey analysis for channel 13 (2472 MHz)
220 * ACS: 1: min_nf=-114 interference_factor=0.0745342 nf=-114 time=161 busy=0 rx=12
221 * ACS: 2: min_nf=-114 interference_factor=0.0555556 nf=-114 time=162 busy=0 rx=9
222 * ACS: 3: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
223 * ACS: 4: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
224 * ACS: 5: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
225 * ACS: * interference factor average: 0.0260179
226 * ACS: Survey analysis for selected bandwidth 20MHz
227 * ACS: * channel 1: total interference = 0.121432
228 * ACS: * channel 2: total interference = 0.137512
229 * ACS: * channel 3: total interference = 0.369757
230 * ACS: * channel 4: total interference = 0.546338
231 * ACS: * channel 5: total interference = 0.690538
232 * ACS: * channel 6: total interference = 0.762242
233 * ACS: * channel 7: total interference = 0.756092
234 * ACS: * channel 8: total interference = 0.537451
235 * ACS: * channel 9: total interference = 0.332313
236 * ACS: * channel 10: total interference = 0.152182
237 * ACS: * channel 11: total interference = 0.0916111
238 * ACS: * channel 12: total interference = 0.0816809
239 * ACS: * channel 13: total interference = 0.0680776
240 * ACS: Ideal channel is 13 (2472 MHz) with total interference factor of 0.0680776
241 *
242 * [1] http://en.wikipedia.org/wiki/Near_and_far_field
243 */
244 #define ACS_PRINT_FACTOR 1000000
245
246 static int acs_request_scan(struct hostapd_iface *iface);
247 static int acs_survey_is_sufficient(struct freq_survey *survey);
248
249
acs_clean_chan_surveys(struct hostapd_channel_data * chan)250 static void acs_clean_chan_surveys(struct hostapd_channel_data *chan)
251 {
252 struct freq_survey *survey, *tmp;
253
254 if (dl_list_empty(&chan->survey_list))
255 return;
256
257 dl_list_for_each_safe(survey, tmp, &chan->survey_list,
258 struct freq_survey, list) {
259 dl_list_del(&survey->list);
260 os_free(survey);
261 }
262 }
263
264
acs_cleanup_mode(struct hostapd_hw_modes * mode)265 static void acs_cleanup_mode(struct hostapd_hw_modes *mode)
266 {
267 int i;
268 struct hostapd_channel_data *chan;
269
270 for (i = 0; i < mode->num_channels; i++) {
271 chan = &mode->channels[i];
272
273 if (chan->flag & HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED)
274 acs_clean_chan_surveys(chan);
275
276 dl_list_init(&chan->survey_list);
277 chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED;
278 chan->min_nf = 0;
279 }
280 }
281
282
acs_cleanup(struct hostapd_iface * iface)283 void acs_cleanup(struct hostapd_iface *iface)
284 {
285 int i;
286
287 for (i = 0; i < iface->num_hw_features; i++)
288 acs_cleanup_mode(&iface->hw_features[i]);
289
290 iface->chans_surveyed = 0;
291 iface->acs_num_completed_scans = 0;
292 }
293
294
acs_fail(struct hostapd_iface * iface)295 static void acs_fail(struct hostapd_iface *iface)
296 {
297 wpa_printf(MSG_ERROR, "ACS: Failed to start");
298 acs_cleanup(iface);
299 hostapd_disable_iface(iface);
300 }
301
302 static float
acs_survey_interference_factor(struct freq_survey * survey,s8 min_nf)303 acs_survey_interference_factor(struct freq_survey *survey, s8 min_nf)
304 {
305 float factor, busy, total;
306
307 if (survey->filled & SURVEY_HAS_CHAN_TIME_BUSY)
308 busy = survey->channel_time_busy;
309 else if (survey->filled & SURVEY_HAS_CHAN_TIME_RX)
310 busy = survey->channel_time_rx;
311 else {
312 wpa_printf(MSG_ERROR, "ACS: Survey data missing");
313 return 0;
314 }
315
316 total = survey->channel_time;
317
318 if (survey->filled & SURVEY_HAS_CHAN_TIME_TX) {
319 busy -= survey->channel_time_tx;
320 total -= survey->channel_time_tx;
321 }
322
323 /* TODO: figure out the best multiplier for noise floor base */
324 factor = pow(10, survey->nf / 5.0L) +
325 ((fabs(total) > FLT_EPSILON) ? (busy / total) : 0) *
326 pow(2, pow(10, (float) survey->nf / 10.0L) -
327 pow(10, (float) min_nf / 10.0L));
328
329 return factor;
330 }
331
acs_get_raw_data(float acs_data)332 static int acs_get_raw_data(float acs_data)
333 {
334 int raw_acs_data;
335 (void)memcpy_s(&raw_acs_data, sizeof(float), &acs_data, sizeof(float));
336 return raw_acs_data;
337 }
338
339 static void
acs_survey_chan_interference_factor(struct hostapd_iface * iface,struct hostapd_channel_data * chan)340 acs_survey_chan_interference_factor(struct hostapd_iface *iface,
341 struct hostapd_channel_data *chan)
342 {
343 struct freq_survey *survey;
344 unsigned int i = 0;
345 float int_factor = 0;
346 unsigned count = 0;
347
348 if (dl_list_empty(&chan->survey_list) ||
349 (chan->flag & HOSTAPD_CHAN_DISABLED))
350 return;
351
352 chan->interference_factor = 0;
353
354 dl_list_for_each(survey, &chan->survey_list, struct freq_survey, list)
355 {
356 i++;
357
358 if (!acs_survey_is_sufficient(survey)) {
359 wpa_printf(MSG_DEBUG, "ACS: %d: insufficient data", i);
360 continue;
361 }
362
363 count++;
364 int_factor = acs_survey_interference_factor(survey,
365 iface->lowest_nf);
366 chan->interference_factor += int_factor;
367 osal_printk("ACS: %d: min_nf=%d interference_factor=0.%06d nf=%d time=%lu busy=%lu rx=%lu raw_factor[0x%X]\r\n",
368 i, chan->min_nf, (unsigned long)(int_factor * ACS_PRINT_FACTOR),
369 survey->nf, (unsigned long) survey->channel_time,
370 (unsigned long) survey->channel_time_busy,
371 (unsigned long) survey->channel_time_rx, acs_get_raw_data(int_factor));
372 }
373
374 if (count)
375 chan->interference_factor /= count;
376 }
377
378
acs_usable_bw40_chan(const struct hostapd_channel_data * chan)379 static int acs_usable_bw40_chan(const struct hostapd_channel_data *chan)
380 {
381 const int allowed[] = { 5180, 5220, 5260, 5300, 5500, 5540, 5580, 5620,
382 5660, 5745, 5785, 4920, 4960, 5955, 5995, 6035,
383 6075, 6115, 6155, 6195, 6235, 6275, 6315, 6355,
384 6395, 6435, 6475, 6515, 6555, 6595, 6635, 6675,
385 6715, 6755, 6795, 6835, 6875, 6915, 6955, 6995,
386 7035, 7075 };
387 unsigned int i;
388
389 for (i = 0; i < ARRAY_SIZE(allowed); i++)
390 if (chan->freq == allowed[i])
391 return 1;
392
393 return 0;
394 }
395
396
acs_usable_bw80_chan(const struct hostapd_channel_data * chan)397 static int acs_usable_bw80_chan(const struct hostapd_channel_data *chan)
398 {
399 const int allowed[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955, 6035,
400 6115, 6195, 6275, 6355, 6435, 6515, 6595, 6675,
401 6755, 6835, 6915, 6995 };
402 unsigned int i;
403
404 for (i = 0; i < ARRAY_SIZE(allowed); i++)
405 if (chan->freq == allowed[i])
406 return 1;
407
408 return 0;
409 }
410
411
acs_usable_bw160_chan(const struct hostapd_channel_data * chan)412 static int acs_usable_bw160_chan(const struct hostapd_channel_data *chan)
413 {
414 const int allowed[] = { 5180, 5500, 5955, 6115, 6275, 6435, 6595, 6755,
415 6915 };
416 unsigned int i;
417
418 for (i = 0; i < ARRAY_SIZE(allowed); i++)
419 if (chan->freq == allowed[i])
420 return 1;
421
422 return 0;
423 }
424
425
acs_survey_is_sufficient(struct freq_survey * survey)426 static int acs_survey_is_sufficient(struct freq_survey *survey)
427 {
428 if (!(survey->filled & SURVEY_HAS_NF)) {
429 wpa_printf(MSG_INFO, "ACS: Survey is missing noise floor");
430 return 0;
431 }
432
433 if (!(survey->filled & SURVEY_HAS_CHAN_TIME)) {
434 wpa_printf(MSG_INFO, "ACS: Survey is missing channel time");
435 return 0;
436 }
437
438 if (!(survey->filled & SURVEY_HAS_CHAN_TIME_BUSY) &&
439 !(survey->filled & SURVEY_HAS_CHAN_TIME_RX)) {
440 wpa_printf(MSG_INFO,
441 "ACS: Survey is missing RX and busy time (at least one is required)");
442 return 0;
443 }
444
445 return 1;
446 }
447
448
acs_survey_list_is_sufficient(struct hostapd_channel_data * chan)449 static int acs_survey_list_is_sufficient(struct hostapd_channel_data *chan)
450 {
451 struct freq_survey *survey;
452 int ret = -1;
453
454 dl_list_for_each(survey, &chan->survey_list, struct freq_survey, list)
455 {
456 if (acs_survey_is_sufficient(survey)) {
457 ret = 1;
458 break;
459 }
460 ret = 0;
461 }
462
463 if (ret == -1)
464 ret = 1; /* no survey list entries */
465
466 if (!ret) {
467 wpa_printf(MSG_INFO,
468 "ACS: Channel %d has insufficient survey data",
469 chan->chan);
470 }
471
472 return ret;
473 }
474
475
acs_surveys_are_sufficient_mode(struct hostapd_hw_modes * mode)476 static int acs_surveys_are_sufficient_mode(struct hostapd_hw_modes *mode)
477 {
478 int i;
479 struct hostapd_channel_data *chan;
480
481 for (i = 0; i < mode->num_channels; i++) {
482 chan = &mode->channels[i];
483 if (!(chan->flag & HOSTAPD_CHAN_DISABLED) &&
484 acs_survey_list_is_sufficient(chan))
485 return 1;
486 }
487
488 return 0;
489 }
490
491
acs_surveys_are_sufficient(struct hostapd_iface * iface)492 static int acs_surveys_are_sufficient(struct hostapd_iface *iface)
493 {
494 int i;
495 struct hostapd_hw_modes *mode;
496
497 for (i = 0; i < iface->num_hw_features; i++) {
498 mode = &iface->hw_features[i];
499 if (!hostapd_hw_skip_mode(iface, mode) &&
500 acs_surveys_are_sufficient_mode(mode))
501 return 1;
502 }
503
504 return 0;
505 }
506
507
acs_usable_chan(struct hostapd_channel_data * chan)508 static int acs_usable_chan(struct hostapd_channel_data *chan)
509 {
510 return !dl_list_empty(&chan->survey_list) &&
511 !(chan->flag & HOSTAPD_CHAN_DISABLED) &&
512 acs_survey_list_is_sufficient(chan);
513 }
514
515
is_in_chanlist(struct hostapd_iface * iface,struct hostapd_channel_data * chan)516 static int is_in_chanlist(struct hostapd_iface *iface,
517 struct hostapd_channel_data *chan)
518 {
519 if (!iface->conf->acs_ch_list.num)
520 return 1;
521
522 return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan);
523 }
524
525
is_in_freqlist(struct hostapd_iface * iface,struct hostapd_channel_data * chan)526 static int is_in_freqlist(struct hostapd_iface *iface,
527 struct hostapd_channel_data *chan)
528 {
529 if (!iface->conf->acs_freq_list.num)
530 return 1;
531
532 return freq_range_list_includes(&iface->conf->acs_freq_list,
533 chan->freq);
534 }
535
acs_survey_mode_interference_factor(struct hostapd_iface * iface,struct hostapd_hw_modes * mode)536 static void acs_survey_mode_interference_factor(
537 struct hostapd_iface *iface, struct hostapd_hw_modes *mode)
538 {
539 int i;
540 struct hostapd_channel_data *chan;
541
542 for (i = 0; i < mode->num_channels; i++) {
543 chan = &mode->channels[i];
544
545 if (!acs_usable_chan(chan))
546 continue;
547
548 if (!is_in_chanlist(iface, chan))
549 continue;
550
551 if (!is_in_freqlist(iface, chan))
552 continue;
553
554 if (chan->max_tx_power < iface->conf->min_tx_power)
555 continue;
556
557 wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)",
558 chan->chan, chan->freq);
559
560 acs_survey_chan_interference_factor(iface, chan);
561
562 osal_printk("ACS: * interference factor average: 0.%06d rawdata[0x%X]\r\n",
563 (unsigned long)(chan->interference_factor * ACS_PRINT_FACTOR), acs_get_raw_data(chan->interference_factor));
564 }
565 }
566
567
acs_survey_all_chans_interference_factor(struct hostapd_iface * iface)568 static void acs_survey_all_chans_interference_factor(
569 struct hostapd_iface *iface)
570 {
571 int i;
572 struct hostapd_hw_modes *mode;
573
574 for (i = 0; i < iface->num_hw_features; i++) {
575 mode = &iface->hw_features[i];
576 if (!hostapd_hw_skip_mode(iface, mode))
577 acs_survey_mode_interference_factor(iface, mode);
578 }
579 }
580
581
582 static struct hostapd_channel_data *
acs_find_chan_mode(struct hostapd_hw_modes * mode,int freq)583 acs_find_chan_mode(struct hostapd_hw_modes *mode, int freq)
584 {
585 struct hostapd_channel_data *chan;
586 int i;
587
588 for (i = 0; i < mode->num_channels; i++) {
589 chan = &mode->channels[i];
590
591 if (chan->flag & HOSTAPD_CHAN_DISABLED)
592 continue;
593
594 if (chan->freq == freq)
595 return chan;
596 }
597
598 return NULL;
599 }
600
601
602 static struct hostapd_channel_data *
acs_find_chan(struct hostapd_iface * iface,int freq)603 acs_find_chan(struct hostapd_iface *iface, int freq)
604 {
605 int i;
606 struct hostapd_hw_modes *mode;
607 struct hostapd_channel_data *chan;
608
609 for (i = 0; i < iface->num_hw_features; i++) {
610 mode = &iface->hw_features[i];
611 if (!hostapd_hw_skip_mode(iface, mode)) {
612 chan = acs_find_chan_mode(mode, freq);
613 if (chan)
614 return chan;
615 }
616 }
617
618 return NULL;
619 }
620
621
is_24ghz_mode(enum hostapd_hw_mode mode)622 static int is_24ghz_mode(enum hostapd_hw_mode mode)
623 {
624 return mode == HOSTAPD_MODE_IEEE80211B ||
625 mode == HOSTAPD_MODE_IEEE80211G;
626 }
627
628
is_common_24ghz_chan(int chan)629 static int is_common_24ghz_chan(int chan)
630 {
631 return chan == 1 || chan == 6 || chan == 11;
632 }
633
634
635 #ifndef ACS_ADJ_WEIGHT
636 #define ACS_ADJ_WEIGHT 0.85
637 #endif /* ACS_ADJ_WEIGHT */
638
639 #ifndef ACS_NEXT_ADJ_WEIGHT
640 #define ACS_NEXT_ADJ_WEIGHT 0.55
641 #endif /* ACS_NEXT_ADJ_WEIGHT */
642
643 #ifndef ACS_24GHZ_PREFER_1_6_11
644 /*
645 * Select commonly used channels 1, 6, 11 by default even if a neighboring
646 * channel has a smaller interference factor as long as it is not better by more
647 * than this multiplier.
648 */
649 #define ACS_24GHZ_PREFER_1_6_11 0.8
650 #endif /* ACS_24GHZ_PREFER_1_6_11 */
651
652 static void
acs_find_ideal_chan_mode(struct hostapd_iface * iface,struct hostapd_hw_modes * mode,int n_chans,u32 bw,struct hostapd_channel_data ** rand_chan,struct hostapd_channel_data ** ideal_chan,float * ideal_factor)653 acs_find_ideal_chan_mode(struct hostapd_iface *iface,
654 struct hostapd_hw_modes *mode,
655 int n_chans, u32 bw,
656 struct hostapd_channel_data **rand_chan,
657 struct hostapd_channel_data **ideal_chan,
658 float *ideal_factor)
659 {
660 struct hostapd_channel_data *chan, *adj_chan = NULL;
661 float factor;
662 int i, j;
663 unsigned int k;
664
665 for (i = 0; i < mode->num_channels; i++) {
666 float total_weight;
667 struct acs_bias *bias, tmp_bias;
668
669 chan = &mode->channels[i];
670
671 /* Since in the current ACS implementation the first channel is
672 * always a primary channel, skip channels not available as
673 * primary until more sophisticated channel selection is
674 * implemented. */
675 if (!chan_pri_allowed(chan))
676 continue;
677
678 if (!is_in_chanlist(iface, chan))
679 continue;
680
681 if (!is_in_freqlist(iface, chan))
682 continue;
683
684 if (chan->max_tx_power < iface->conf->min_tx_power)
685 continue;
686
687 if (!chan_bw_allowed(chan, bw, 1, 1)) {
688 wpa_printf(MSG_DEBUG,
689 "ACS: Channel %d: BW %u is not supported",
690 chan->chan, bw);
691 continue;
692 }
693
694 /* HT40 on 5 GHz has a limited set of primary channels as per
695 * 11n Annex J */
696 if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
697 ((iface->conf->ieee80211n &&
698 iface->conf->secondary_channel) ||
699 is_6ghz_freq(chan->freq)) &&
700 !acs_usable_bw40_chan(chan)) {
701 wpa_printf(MSG_DEBUG,
702 "ACS: Channel %d: not allowed as primary channel for 40 MHz bandwidth",
703 chan->chan);
704 continue;
705 }
706
707 if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
708 (iface->conf->ieee80211ac || iface->conf->ieee80211ax)) {
709 if (hostapd_get_oper_chwidth(iface->conf) ==
710 CHANWIDTH_80MHZ &&
711 !acs_usable_bw80_chan(chan)) {
712 wpa_printf(MSG_DEBUG,
713 "ACS: Channel %d: not allowed as primary channel for 80 MHz bandwidth",
714 chan->chan);
715 continue;
716 }
717
718 if (hostapd_get_oper_chwidth(iface->conf) ==
719 CHANWIDTH_160MHZ &&
720 !acs_usable_bw160_chan(chan)) {
721 wpa_printf(MSG_DEBUG,
722 "ACS: Channel %d: not allowed as primary channel for 160 MHz bandwidth",
723 chan->chan);
724 continue;
725 }
726 }
727
728 factor = 0;
729 if (acs_usable_chan(chan))
730 factor = chan->interference_factor;
731 total_weight = 1;
732
733 for (j = 1; j < n_chans; j++) {
734 adj_chan = acs_find_chan(iface, chan->freq + (j * 20));
735 if (!adj_chan)
736 break;
737
738 if (!chan_bw_allowed(adj_chan, bw, 1, 0)) {
739 wpa_printf(MSG_DEBUG,
740 "ACS: PRI Channel %d: secondary channel %d BW %u is not supported",
741 chan->chan, adj_chan->chan, bw);
742 break;
743 }
744
745 if (acs_usable_chan(adj_chan)) {
746 factor += adj_chan->interference_factor;
747 total_weight += 1;
748 }
749 }
750
751 if (j != n_chans) {
752 wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth",
753 chan->chan);
754 continue;
755 }
756
757 /* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
758 * channel interference factor. */
759 if (is_24ghz_mode(mode->mode)) {
760 for (j = 0; j < n_chans; j++) {
761 adj_chan = acs_find_chan(iface, chan->freq +
762 (j * 20) - 5);
763 if (adj_chan && acs_usable_chan(adj_chan)) {
764 factor += ACS_ADJ_WEIGHT *
765 adj_chan->interference_factor;
766 total_weight += ACS_ADJ_WEIGHT;
767 }
768
769 adj_chan = acs_find_chan(iface, chan->freq +
770 (j * 20) - 10);
771 if (adj_chan && acs_usable_chan(adj_chan)) {
772 factor += ACS_NEXT_ADJ_WEIGHT *
773 adj_chan->interference_factor;
774 total_weight += ACS_NEXT_ADJ_WEIGHT;
775 }
776
777 adj_chan = acs_find_chan(iface, chan->freq +
778 (j * 20) + 5);
779 if (adj_chan && acs_usable_chan(adj_chan)) {
780 factor += ACS_ADJ_WEIGHT *
781 adj_chan->interference_factor;
782 total_weight += ACS_ADJ_WEIGHT;
783 }
784
785 adj_chan = acs_find_chan(iface, chan->freq +
786 (j * 20) + 10);
787 if (adj_chan && acs_usable_chan(adj_chan)) {
788 factor += ACS_NEXT_ADJ_WEIGHT *
789 adj_chan->interference_factor;
790 total_weight += ACS_NEXT_ADJ_WEIGHT;
791 }
792 }
793 }
794
795 factor /= total_weight;
796
797 bias = NULL;
798 if (iface->conf->acs_chan_bias) {
799 for (k = 0; k < iface->conf->num_acs_chan_bias; k++) {
800 bias = &iface->conf->acs_chan_bias[k];
801 if (bias->channel == chan->chan)
802 break;
803 bias = NULL;
804 }
805 } else if (is_24ghz_mode(mode->mode) &&
806 is_common_24ghz_chan(chan->chan)) {
807 tmp_bias.channel = chan->chan;
808 tmp_bias.bias = ACS_24GHZ_PREFER_1_6_11;
809 bias = &tmp_bias;
810 }
811
812 if (bias) {
813 factor *= bias->bias;
814 osal_printk("ACS: * channel %d: total interference = 0.%06d (0.%06d bias) rawdata[0x%X]\r\n",
815 chan->chan, (unsigned long)(factor * ACS_PRINT_FACTOR), (unsigned long)(bias->bias * ACS_PRINT_FACTOR),
816 acs_get_raw_data(factor));
817 } else {
818 osal_printk("ACS: * channel %d: total interference = 0.%06d rawdata[0x%X]\r\n",
819 chan->chan, (unsigned long)(factor * ACS_PRINT_FACTOR), acs_get_raw_data(factor));
820 }
821
822 if (acs_usable_chan(chan) &&
823 #ifdef LOS_WPA_PATCH
824 ((chan->chan != 14)) &&
825 #endif
826 (!*ideal_chan || factor < *ideal_factor)) {
827 *ideal_factor = factor;
828 *ideal_chan = chan;
829 }
830
831 /* This channel would at least be usable */
832 if (!(*rand_chan))
833 *rand_chan = chan;
834 }
835 }
836
837
838 /*
839 * At this point it's assumed chan->interference_factor has been computed.
840 * This function should be reusable regardless of interference computation
841 * option (survey, BSS, spectral, ...). chan->interference factor must be
842 * summable (i.e., must be always greater than zero).
843 */
844 static struct hostapd_channel_data *
acs_find_ideal_chan(struct hostapd_iface * iface)845 acs_find_ideal_chan(struct hostapd_iface *iface)
846 {
847 struct hostapd_channel_data *ideal_chan = NULL,
848 *rand_chan = NULL;
849 float ideal_factor = 0;
850 int i;
851 int n_chans = 1;
852 u32 bw;
853 struct hostapd_hw_modes *mode;
854
855 if (is_6ghz_op_class(iface->conf->op_class)) {
856 bw = op_class_to_bandwidth(iface->conf->op_class);
857 n_chans = bw / 20;
858 goto bw_selected;
859 }
860
861 /* TODO: HT40- support */
862
863 if (iface->conf->ieee80211n &&
864 iface->conf->secondary_channel == -1) {
865 wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
866 return NULL;
867 }
868
869 if (iface->conf->ieee80211n &&
870 iface->conf->secondary_channel)
871 n_chans = 2;
872
873 if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
874 switch (hostapd_get_oper_chwidth(iface->conf)) {
875 case CHANWIDTH_80MHZ:
876 n_chans = 4;
877 break;
878 case CHANWIDTH_160MHZ:
879 n_chans = 8;
880 break;
881 }
882 }
883
884 bw = num_chan_to_bw(n_chans);
885
886 bw_selected:
887 /* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */
888
889 wpa_printf(MSG_DEBUG,
890 "ACS: Survey analysis for selected bandwidth %d MHz", bw);
891
892 for (i = 0; i < iface->num_hw_features; i++) {
893 mode = &iface->hw_features[i];
894 if (!hostapd_hw_skip_mode(iface, mode))
895 acs_find_ideal_chan_mode(iface, mode, n_chans, bw,
896 &rand_chan, &ideal_chan,
897 &ideal_factor);
898 }
899
900 if (ideal_chan) {
901 osal_printk("ACS: Ideal channel is %d (%d MHz) with total interference factor of 0.%06d rawdata[0x%X]\r\n",
902 ideal_chan->chan, ideal_chan->freq, (unsigned long)(ideal_factor * ACS_PRINT_FACTOR),
903 acs_get_raw_data(ideal_factor));
904 return ideal_chan;
905 }
906
907 return rand_chan;
908 }
909
910
acs_adjust_center_freq(struct hostapd_iface * iface)911 static void acs_adjust_center_freq(struct hostapd_iface *iface)
912 {
913 int offset;
914
915 wpa_printf(MSG_DEBUG, "ACS: Adjusting VHT center frequency");
916
917 switch (hostapd_get_oper_chwidth(iface->conf)) {
918 case CHANWIDTH_USE_HT:
919 offset = 2 * iface->conf->secondary_channel;
920 break;
921 case CHANWIDTH_80MHZ:
922 offset = 6;
923 break;
924 case CHANWIDTH_160MHZ:
925 offset = 14;
926 break;
927 default:
928 /* TODO: How can this be calculated? Adjust
929 * acs_find_ideal_chan() */
930 wpa_printf(MSG_INFO,
931 "ACS: Only VHT20/40/80/160 is supported now");
932 return;
933 }
934
935 hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
936 iface->conf->channel + offset);
937 }
938
939
acs_study_survey_based(struct hostapd_iface * iface)940 static int acs_study_survey_based(struct hostapd_iface *iface)
941 {
942 wpa_printf(MSG_DEBUG, "ACS: Trying survey-based ACS");
943
944 if (!iface->chans_surveyed) {
945 wpa_printf(MSG_ERROR, "ACS: Unable to collect survey data");
946 return -1;
947 }
948
949 if (!acs_surveys_are_sufficient(iface)) {
950 wpa_printf(MSG_ERROR, "ACS: Surveys have insufficient data");
951 return -1;
952 }
953
954 acs_survey_all_chans_interference_factor(iface);
955 return 0;
956 }
957
958
acs_study_options(struct hostapd_iface * iface)959 static int acs_study_options(struct hostapd_iface *iface)
960 {
961 if (acs_study_survey_based(iface) == 0)
962 return 0;
963
964 /* TODO: If no surveys are available/sufficient this is a good
965 * place to fallback to BSS-based ACS */
966
967 return -1;
968 }
969
970
acs_study(struct hostapd_iface * iface)971 static void acs_study(struct hostapd_iface *iface)
972 {
973 struct hostapd_channel_data *ideal_chan;
974 int err;
975
976 err = acs_study_options(iface);
977 if (err < 0) {
978 wpa_printf(MSG_ERROR, "ACS: All study options have failed");
979 goto fail;
980 }
981
982 ideal_chan = acs_find_ideal_chan(iface);
983 if (!ideal_chan) {
984 wpa_printf(MSG_ERROR, "ACS: Failed to compute ideal channel");
985 err = -1;
986 goto fail;
987 }
988
989 iface->conf->channel = ideal_chan->chan;
990 iface->freq = ideal_chan->freq;
991
992 if (iface->conf->ieee80211ac || iface->conf->ieee80211ax)
993 acs_adjust_center_freq(iface);
994
995 err = 0;
996 fail:
997 /*
998 * hostapd_setup_interface_complete() will return -1 on failure,
999 * 0 on success and 0 is HOSTAPD_CHAN_VALID :)
1000 */
1001 if (hostapd_acs_completed(iface, err) == HOSTAPD_CHAN_VALID) {
1002 acs_cleanup(iface);
1003 return;
1004 }
1005
1006 /* This can possibly happen if channel parameters (secondary
1007 * channel, center frequencies) are misconfigured */
1008 wpa_printf(MSG_ERROR, "ACS: Possibly channel configuration is invalid, please report this along with your config file.");
1009 acs_fail(iface);
1010 }
1011
1012
acs_scan_complete(struct hostapd_iface * iface)1013 static void acs_scan_complete(struct hostapd_iface *iface)
1014 {
1015 int err;
1016
1017 iface->scan_cb = NULL;
1018
1019 wpa_printf(MSG_DEBUG, "ACS: Using survey based algorithm (acs_num_scans=%d)",
1020 iface->conf->acs_num_scans);
1021
1022 err = hostapd_drv_get_survey(iface->bss[0], 0);
1023 if (err) {
1024 wpa_printf(MSG_ERROR, "ACS: Failed to get survey data");
1025 goto fail;
1026 }
1027
1028 if (++iface->acs_num_completed_scans < iface->conf->acs_num_scans) {
1029 err = acs_request_scan(iface);
1030 if (err) {
1031 wpa_printf(MSG_ERROR, "ACS: Failed to request scan");
1032 goto fail;
1033 }
1034
1035 return;
1036 }
1037
1038 acs_study(iface);
1039 return;
1040 fail:
1041 hostapd_acs_completed(iface, 1);
1042 acs_fail(iface);
1043 }
1044
1045
acs_request_scan_add_freqs(struct hostapd_iface * iface,struct hostapd_hw_modes * mode,int * freq)1046 static int * acs_request_scan_add_freqs(struct hostapd_iface *iface,
1047 struct hostapd_hw_modes *mode,
1048 int *freq)
1049 {
1050 struct hostapd_channel_data *chan;
1051 int i;
1052
1053 for (i = 0; i < mode->num_channels; i++) {
1054 chan = &mode->channels[i];
1055 if (chan->flag & HOSTAPD_CHAN_DISABLED)
1056 continue;
1057
1058 if (!is_in_chanlist(iface, chan))
1059 continue;
1060
1061 if (!is_in_freqlist(iface, chan))
1062 continue;
1063
1064 if (chan->max_tx_power < iface->conf->min_tx_power)
1065 continue;
1066
1067 *freq++ = chan->freq;
1068 }
1069
1070 return freq;
1071 }
1072
1073
acs_request_scan(struct hostapd_iface * iface)1074 static int acs_request_scan(struct hostapd_iface *iface)
1075 {
1076 struct wpa_driver_scan_params params;
1077 int i, *freq;
1078 int num_channels;
1079 struct hostapd_hw_modes *mode;
1080
1081 os_memset(¶ms, 0, sizeof(params));
1082
1083 num_channels = 0;
1084 for (i = 0; i < iface->num_hw_features; i++) {
1085 mode = &iface->hw_features[i];
1086 if (!hostapd_hw_skip_mode(iface, mode))
1087 num_channels += mode->num_channels;
1088 }
1089
1090 params.freqs = os_calloc(num_channels + 1, sizeof(params.freqs[0]));
1091 #ifdef CONFIG_ACS
1092 params.acs_scan_flag = 1;
1093 #endif
1094 if (params.freqs == NULL)
1095 return -1;
1096
1097 freq = params.freqs;
1098
1099 for (i = 0; i < iface->num_hw_features; i++) {
1100 mode = &iface->hw_features[i];
1101 if (!hostapd_hw_skip_mode(iface, mode))
1102 freq = acs_request_scan_add_freqs(iface, mode, freq);
1103 }
1104
1105 *freq = 0;
1106
1107 if (params.freqs == freq) {
1108 wpa_printf(MSG_ERROR, "ACS: No available channels found");
1109 os_free(params.freqs);
1110 return -1;
1111 }
1112
1113 iface->scan_cb = acs_scan_complete;
1114
1115 wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d",
1116 iface->acs_num_completed_scans + 1,
1117 iface->conf->acs_num_scans);
1118
1119 if (hostapd_driver_scan(iface->bss[0], ¶ms) < 0) {
1120 wpa_printf(MSG_ERROR, "ACS: Failed to request initial scan");
1121 acs_cleanup(iface);
1122 os_free(params.freqs);
1123 return -1;
1124 }
1125
1126 os_free(params.freqs);
1127 return 0;
1128 }
1129
1130
acs_init(struct hostapd_iface * iface)1131 enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
1132 {
1133 wpa_printf(MSG_INFO, "ACS: Automatic channel selection started, this may take a bit");
1134
1135 if (iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) {
1136 wpa_printf(MSG_INFO, "ACS: Offloading to driver");
1137 if (hostapd_drv_do_acs(iface->bss[0]))
1138 return HOSTAPD_CHAN_INVALID;
1139 return HOSTAPD_CHAN_ACS;
1140 }
1141
1142 if (!iface->current_mode &&
1143 iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY)
1144 return HOSTAPD_CHAN_INVALID;
1145
1146 acs_cleanup(iface);
1147
1148 if (acs_request_scan(iface) < 0)
1149 return HOSTAPD_CHAN_INVALID;
1150
1151 hostapd_set_state(iface, HAPD_IFACE_ACS);
1152 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_STARTED);
1153
1154 return HOSTAPD_CHAN_ACS;
1155 }
1156