• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&params, 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], &params) < 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