• 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 <math.h>
12 
13 #include "utils/common.h"
14 #include "utils/list.h"
15 #include "common/ieee802_11_defs.h"
16 #include "drivers/driver.h"
17 #include "hostapd.h"
18 #include "ap_drv_ops.h"
19 #include "ap_config.h"
20 #include "hw_features.h"
21 #include "acs.h"
22 
23 /*
24  * Automatic Channel Selection
25  * ===========================
26  *
27  * More info at
28  * ------------
29  * http://wireless.kernel.org/en/users/Documentation/acs
30  *
31  * How to use
32  * ----------
33  * - make sure you have CONFIG_ACS=y in hostapd's .config
34  * - use channel=0 or channel=acs to enable ACS
35  *
36  * How does it work
37  * ----------------
38  * 1. passive scans are used to collect survey data
39  *    (it is assumed that scan trigger collection of survey data in driver)
40  * 2. interference factor is calculated for each channel
41  * 3. ideal channel is picked depending on channel width by using adjacent
42  *    channel interference factors
43  *
44  * Known limitations
45  * -----------------
46  * - Current implementation depends heavily on the amount of time willing to
47  *   spend gathering survey data during hostapd startup. Short traffic bursts
48  *   may be missed and a suboptimal channel may be picked.
49  * - Ideal channel may end up overlapping a channel with 40 MHz intolerant BSS
50  *
51  * Todo / Ideas
52  * ------------
53  * - implement other interference computation methods
54  *   - BSS/RSSI based
55  *   - spectral scan based
56  *   (should be possibly to hook this up with current ACS scans)
57  * - add wpa_supplicant support (for P2P)
58  * - collect a histogram of interference over time allowing more educated
59  *   guess about an ideal channel (perhaps CSA could be used to migrate AP to a
60  *   new "better" channel while running)
61  * - include neighboring BSS scan to avoid conflicts with 40 MHz intolerant BSSs
62  *   when choosing the ideal channel
63  *
64  * Survey interference factor implementation details
65  * -------------------------------------------------
66  * Generic interference_factor in struct hostapd_channel_data is used.
67  *
68  * The survey interference factor is defined as the ratio of the
69  * observed busy time over the time we spent on the channel,
70  * this value is then amplified by the observed noise floor on
71  * the channel in comparison to the lowest noise floor observed
72  * on the entire band.
73  *
74  * This corresponds to:
75  * ---
76  * (busy time - tx time) / (active time - tx time) * 2^(chan_nf + band_min_nf)
77  * ---
78  *
79  * The coefficient of 2 reflects the way power in "far-field"
80  * radiation decreases as the square of distance from the antenna [1].
81  * What this does is it decreases the observed busy time ratio if the
82  * noise observed was low but increases it if the noise was high,
83  * proportionally to the way "far field" radiation changes over
84  * distance.
85  *
86  * If channel busy time is not available the fallback is to use channel RX time.
87  *
88  * Since noise floor is in dBm it is necessary to convert it into Watts so that
89  * combined channel interference (e.g., HT40, which uses two channels) can be
90  * calculated easily.
91  * ---
92  * (busy time - tx time) / (active time - tx time) *
93  *    2^(10^(chan_nf/10) + 10^(band_min_nf/10))
94  * ---
95  *
96  * However to account for cases where busy/rx time is 0 (channel load is then
97  * 0%) channel noise floor signal power is combined into the equation so a
98  * channel with lower noise floor is preferred. The equation becomes:
99  * ---
100  * 10^(chan_nf/5) + (busy time - tx time) / (active time - tx time) *
101  *    2^(10^(chan_nf/10) + 10^(band_min_nf/10))
102  * ---
103  *
104  * All this "interference factor" is purely subjective and only time
105  * will tell how usable this is. By using the minimum noise floor we
106  * remove any possible issues due to card calibration. The computation
107  * of the interference factor then is dependent on what the card itself
108  * picks up as the minimum noise, not an actual real possible card
109  * noise value.
110  *
111  * Total interference computation details
112  * --------------------------------------
113  * The above channel interference factor is calculated with no respect to
114  * target operational bandwidth.
115  *
116  * To find an ideal channel the above data is combined by taking into account
117  * the target operational bandwidth and selected band. E.g., on 2.4 GHz channels
118  * overlap with 20 MHz bandwidth, but there is no overlap for 20 MHz bandwidth
119  * on 5 GHz.
120  *
121  * Each valid and possible channel spec (i.e., channel + width) is taken and its
122  * interference factor is computed by summing up interferences of each channel
123  * it overlaps. The one with least total interference is picked up.
124  *
125  * Note: This implies base channel interference factor must be non-negative
126  * allowing easy summing up.
127  *
128  * Example ACS analysis printout
129  * -----------------------------
130  *
131  * ACS: Trying survey-based ACS
132  * ACS: Survey analysis for channel 1 (2412 MHz)
133  * ACS:  1: min_nf=-113 interference_factor=0.0802469 nf=-113 time=162 busy=0 rx=13
134  * ACS:  2: min_nf=-113 interference_factor=0.0745342 nf=-113 time=161 busy=0 rx=12
135  * ACS:  3: min_nf=-113 interference_factor=0.0679012 nf=-113 time=162 busy=0 rx=11
136  * ACS:  4: min_nf=-113 interference_factor=0.0310559 nf=-113 time=161 busy=0 rx=5
137  * ACS:  5: min_nf=-113 interference_factor=0.0248447 nf=-113 time=161 busy=0 rx=4
138  * ACS:  * interference factor average: 0.0557166
139  * ACS: Survey analysis for channel 2 (2417 MHz)
140  * ACS:  1: min_nf=-113 interference_factor=0.0185185 nf=-113 time=162 busy=0 rx=3
141  * ACS:  2: min_nf=-113 interference_factor=0.0246914 nf=-113 time=162 busy=0 rx=4
142  * ACS:  3: min_nf=-113 interference_factor=0.037037 nf=-113 time=162 busy=0 rx=6
143  * ACS:  4: min_nf=-113 interference_factor=0.149068 nf=-113 time=161 busy=0 rx=24
144  * ACS:  5: min_nf=-113 interference_factor=0.0248447 nf=-113 time=161 busy=0 rx=4
145  * ACS:  * interference factor average: 0.050832
146  * ACS: Survey analysis for channel 3 (2422 MHz)
147  * ACS:  1: min_nf=-113 interference_factor=2.51189e-23 nf=-113 time=162 busy=0 rx=0
148  * ACS:  2: min_nf=-113 interference_factor=0.0185185 nf=-113 time=162 busy=0 rx=3
149  * ACS:  3: min_nf=-113 interference_factor=0.0186335 nf=-113 time=161 busy=0 rx=3
150  * ACS:  4: min_nf=-113 interference_factor=0.0186335 nf=-113 time=161 busy=0 rx=3
151  * ACS:  5: min_nf=-113 interference_factor=0.0186335 nf=-113 time=161 busy=0 rx=3
152  * ACS:  * interference factor average: 0.0148838
153  * ACS: Survey analysis for channel 4 (2427 MHz)
154  * ACS:  1: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
155  * ACS:  2: min_nf=-114 interference_factor=0.0555556 nf=-114 time=162 busy=0 rx=9
156  * ACS:  3: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=161 busy=0 rx=0
157  * ACS:  4: min_nf=-114 interference_factor=0.0186335 nf=-114 time=161 busy=0 rx=3
158  * ACS:  5: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1
159  * ACS:  * interference factor average: 0.0160801
160  * ACS: Survey analysis for channel 5 (2432 MHz)
161  * ACS:  1: min_nf=-114 interference_factor=0.409938 nf=-113 time=161 busy=0 rx=66
162  * ACS:  2: min_nf=-114 interference_factor=0.0432099 nf=-113 time=162 busy=0 rx=7
163  * ACS:  3: min_nf=-114 interference_factor=0.0124224 nf=-113 time=161 busy=0 rx=2
164  * ACS:  4: min_nf=-114 interference_factor=0.677019 nf=-113 time=161 busy=0 rx=109
165  * ACS:  5: min_nf=-114 interference_factor=0.0186335 nf=-114 time=161 busy=0 rx=3
166  * ACS:  * interference factor average: 0.232244
167  * ACS: Survey analysis for channel 6 (2437 MHz)
168  * ACS:  1: min_nf=-113 interference_factor=0.552795 nf=-113 time=161 busy=0 rx=89
169  * ACS:  2: min_nf=-113 interference_factor=0.0807453 nf=-112 time=161 busy=0 rx=13
170  * ACS:  3: min_nf=-113 interference_factor=0.0310559 nf=-113 time=161 busy=0 rx=5
171  * ACS:  4: min_nf=-113 interference_factor=0.434783 nf=-112 time=161 busy=0 rx=70
172  * ACS:  5: min_nf=-113 interference_factor=0.0621118 nf=-113 time=161 busy=0 rx=10
173  * ACS:  * interference factor average: 0.232298
174  * ACS: Survey analysis for channel 7 (2442 MHz)
175  * ACS:  1: min_nf=-113 interference_factor=0.440994 nf=-112 time=161 busy=0 rx=71
176  * ACS:  2: min_nf=-113 interference_factor=0.385093 nf=-113 time=161 busy=0 rx=62
177  * ACS:  3: min_nf=-113 interference_factor=0.0372671 nf=-113 time=161 busy=0 rx=6
178  * ACS:  4: min_nf=-113 interference_factor=0.0372671 nf=-113 time=161 busy=0 rx=6
179  * ACS:  5: min_nf=-113 interference_factor=0.0745342 nf=-113 time=161 busy=0 rx=12
180  * ACS:  * interference factor average: 0.195031
181  * ACS: Survey analysis for channel 8 (2447 MHz)
182  * ACS:  1: min_nf=-114 interference_factor=0.0496894 nf=-112 time=161 busy=0 rx=8
183  * ACS:  2: min_nf=-114 interference_factor=0.0496894 nf=-114 time=161 busy=0 rx=8
184  * ACS:  3: min_nf=-114 interference_factor=0.0372671 nf=-113 time=161 busy=0 rx=6
185  * ACS:  4: min_nf=-114 interference_factor=0.12963 nf=-113 time=162 busy=0 rx=21
186  * ACS:  5: min_nf=-114 interference_factor=0.166667 nf=-114 time=162 busy=0 rx=27
187  * ACS:  * interference factor average: 0.0865885
188  * ACS: Survey analysis for channel 9 (2452 MHz)
189  * ACS:  1: min_nf=-114 interference_factor=0.0124224 nf=-114 time=161 busy=0 rx=2
190  * ACS:  2: min_nf=-114 interference_factor=0.0310559 nf=-114 time=161 busy=0 rx=5
191  * ACS:  3: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=161 busy=0 rx=0
192  * ACS:  4: min_nf=-114 interference_factor=0.00617284 nf=-114 time=162 busy=0 rx=1
193  * ACS:  5: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
194  * ACS:  * interference factor average: 0.00993022
195  * ACS: Survey analysis for channel 10 (2457 MHz)
196  * ACS:  1: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1
197  * ACS:  2: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1
198  * ACS:  3: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1
199  * ACS:  4: min_nf=-114 interference_factor=0.0493827 nf=-114 time=162 busy=0 rx=8
200  * ACS:  5: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
201  * ACS:  * interference factor average: 0.0136033
202  * ACS: Survey analysis for channel 11 (2462 MHz)
203  * ACS:  1: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=161 busy=0 rx=0
204  * ACS:  2: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=161 busy=0 rx=0
205  * ACS:  3: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=161 busy=0 rx=0
206  * ACS:  4: min_nf=-114 interference_factor=0.0432099 nf=-114 time=162 busy=0 rx=7
207  * ACS:  5: min_nf=-114 interference_factor=0.0925926 nf=-114 time=162 busy=0 rx=15
208  * ACS:  * interference factor average: 0.0271605
209  * ACS: Survey analysis for channel 12 (2467 MHz)
210  * ACS:  1: min_nf=-114 interference_factor=0.0621118 nf=-113 time=161 busy=0 rx=10
211  * ACS:  2: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1
212  * ACS:  3: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=162 busy=0 rx=0
213  * ACS:  4: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=162 busy=0 rx=0
214  * ACS:  5: min_nf=-114 interference_factor=0.00617284 nf=-113 time=162 busy=0 rx=1
215  * ACS:  * interference factor average: 0.0148992
216  * ACS: Survey analysis for channel 13 (2472 MHz)
217  * ACS:  1: min_nf=-114 interference_factor=0.0745342 nf=-114 time=161 busy=0 rx=12
218  * ACS:  2: min_nf=-114 interference_factor=0.0555556 nf=-114 time=162 busy=0 rx=9
219  * ACS:  3: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
220  * ACS:  4: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
221  * ACS:  5: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0
222  * ACS:  * interference factor average: 0.0260179
223  * ACS: Survey analysis for selected bandwidth 20MHz
224  * ACS:  * channel 1: total interference = 0.121432
225  * ACS:  * channel 2: total interference = 0.137512
226  * ACS:  * channel 3: total interference = 0.369757
227  * ACS:  * channel 4: total interference = 0.546338
228  * ACS:  * channel 5: total interference = 0.690538
229  * ACS:  * channel 6: total interference = 0.762242
230  * ACS:  * channel 7: total interference = 0.756092
231  * ACS:  * channel 8: total interference = 0.537451
232  * ACS:  * channel 9: total interference = 0.332313
233  * ACS:  * channel 10: total interference = 0.152182
234  * ACS:  * channel 11: total interference = 0.0916111
235  * ACS:  * channel 12: total interference = 0.0816809
236  * ACS:  * channel 13: total interference = 0.0680776
237  * ACS: Ideal channel is 13 (2472 MHz) with total interference factor of 0.0680776
238  *
239  * [1] http://en.wikipedia.org/wiki/Near_and_far_field
240  */
241 
242 
243 static int acs_request_scan(struct hostapd_iface *iface);
244 
245 
acs_clean_chan_surveys(struct hostapd_channel_data * chan)246 static void acs_clean_chan_surveys(struct hostapd_channel_data *chan)
247 {
248 	struct freq_survey *survey, *tmp;
249 
250 	if (dl_list_empty(&chan->survey_list))
251 		return;
252 
253 	dl_list_for_each_safe(survey, tmp, &chan->survey_list,
254 			      struct freq_survey, list) {
255 		dl_list_del(&survey->list);
256 		os_free(survey);
257 	}
258 }
259 
260 
acs_cleanup(struct hostapd_iface * iface)261 static void acs_cleanup(struct hostapd_iface *iface)
262 {
263 	int i;
264 	struct hostapd_channel_data *chan;
265 
266 	for (i = 0; i < iface->current_mode->num_channels; i++) {
267 		chan = &iface->current_mode->channels[i];
268 
269 		if (chan->flag & HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED)
270 			acs_clean_chan_surveys(chan);
271 
272 		dl_list_init(&chan->survey_list);
273 		chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED;
274 		chan->min_nf = 0;
275 	}
276 
277 	iface->chans_surveyed = 0;
278 	iface->acs_num_completed_scans = 0;
279 }
280 
281 
acs_fail(struct hostapd_iface * iface)282 void acs_fail(struct hostapd_iface *iface)
283 {
284 	wpa_printf(MSG_ERROR, "ACS: Failed to start");
285 	acs_cleanup(iface);
286 }
287 
288 
289 static long double
acs_survey_interference_factor(struct freq_survey * survey,s8 min_nf)290 acs_survey_interference_factor(struct freq_survey *survey, s8 min_nf)
291 {
292 	long double factor, busy, total;
293 
294 	if (survey->filled & SURVEY_HAS_CHAN_TIME_BUSY)
295 		busy = survey->channel_time_busy;
296 	else if (survey->filled & SURVEY_HAS_CHAN_TIME_RX)
297 		busy = survey->channel_time_rx;
298 	else {
299 		/* This shouldn't really happen as survey data is checked in
300 		 * acs_sanity_check() */
301 		wpa_printf(MSG_ERROR, "ACS: Survey data missing");
302 		return 0;
303 	}
304 
305 	total = survey->channel_time;
306 
307 	if (survey->filled & SURVEY_HAS_CHAN_TIME_TX) {
308 		busy -= survey->channel_time_tx;
309 		total -= survey->channel_time_tx;
310 	}
311 
312 	/* TODO: figure out the best multiplier for noise floor base */
313 	factor = pow(10, survey->nf / 5.0L) +
314 		(busy / total) *
315 		pow(2, pow(10, (long double) survey->nf / 10.0L) -
316 		    pow(10, (long double) min_nf / 10.0L));
317 
318 	return factor;
319 }
320 
321 
322 static void
acs_survey_chan_interference_factor(struct hostapd_iface * iface,struct hostapd_channel_data * chan)323 acs_survey_chan_interference_factor(struct hostapd_iface *iface,
324 				    struct hostapd_channel_data *chan)
325 {
326 	struct freq_survey *survey;
327 	unsigned int i = 0;
328 	long double int_factor = 0;
329 
330 	if (dl_list_empty(&chan->survey_list))
331 		return;
332 
333 	if (chan->flag & HOSTAPD_CHAN_DISABLED)
334 		return;
335 
336 	chan->interference_factor = 0;
337 
338 	dl_list_for_each(survey, &chan->survey_list, struct freq_survey, list)
339 	{
340 		int_factor = acs_survey_interference_factor(survey,
341 							    iface->lowest_nf);
342 		chan->interference_factor += int_factor;
343 		wpa_printf(MSG_DEBUG, "ACS: %d: min_nf=%d interference_factor=%Lg nf=%d time=%lu busy=%lu rx=%lu",
344 			   ++i, chan->min_nf, int_factor,
345 			   survey->nf, (unsigned long) survey->channel_time,
346 			   (unsigned long) survey->channel_time_busy,
347 			   (unsigned long) survey->channel_time_rx);
348 	}
349 
350 	chan->interference_factor = chan->interference_factor /
351 		dl_list_len(&chan->survey_list);
352 }
353 
354 
acs_usable_chan(struct hostapd_channel_data * chan)355 static int acs_usable_chan(struct hostapd_channel_data *chan)
356 {
357 	if (dl_list_empty(&chan->survey_list))
358 		return 0;
359 	if (chan->flag & HOSTAPD_CHAN_DISABLED)
360 		return 0;
361 	return 1;
362 }
363 
364 
acs_usable_ht40_chan(struct hostapd_channel_data * chan)365 static int acs_usable_ht40_chan(struct hostapd_channel_data *chan)
366 {
367 	const int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149,
368 				157, 184, 192 };
369 	unsigned int i;
370 
371 	for (i = 0; i < sizeof(allowed) / sizeof(allowed[0]); i++)
372 		if (chan->chan == allowed[i])
373 			return 1;
374 
375 	return 0;
376 }
377 
378 
acs_survey_is_sufficient(struct freq_survey * survey)379 static int acs_survey_is_sufficient(struct freq_survey *survey)
380 {
381 	if (!(survey->filled & SURVEY_HAS_NF)) {
382 		wpa_printf(MSG_ERROR, "ACS: Survey is missing noise floor");
383 		return 0;
384 	}
385 
386 	if (!(survey->filled & SURVEY_HAS_CHAN_TIME)) {
387 		wpa_printf(MSG_ERROR, "ACS: Survey is missing channel time");
388 		return 0;
389 	}
390 
391 	if (!(survey->filled & SURVEY_HAS_CHAN_TIME_BUSY) &&
392 	    !(survey->filled & SURVEY_HAS_CHAN_TIME_RX)) {
393 		wpa_printf(MSG_ERROR, "ACS: Survey is missing RX and busy time (at least one is required)");
394 		return 0;
395 	}
396 
397 	return 1;
398 }
399 
400 
acs_surveys_are_sufficient(struct hostapd_iface * iface)401 static int acs_surveys_are_sufficient(struct hostapd_iface *iface)
402 {
403 	int i;
404 	struct hostapd_channel_data *chan;
405 	struct freq_survey *survey;
406 
407 	for (i = 0; i < iface->current_mode->num_channels; i++) {
408 		chan = &iface->current_mode->channels[i];
409 		if (chan->flag & HOSTAPD_CHAN_DISABLED)
410 			continue;
411 
412 		dl_list_for_each(survey, &chan->survey_list,
413 				 struct freq_survey, list)
414 		{
415 			if (!acs_survey_is_sufficient(survey)) {
416 				wpa_printf(MSG_ERROR, "ACS: Channel %d has insufficient survey data",
417 					   chan->chan);
418 				return 0;
419 			}
420 		}
421 	}
422 
423 	return 1;
424 }
425 
426 
acs_survey_all_chans_intereference_factor(struct hostapd_iface * iface)427 static void acs_survey_all_chans_intereference_factor(
428 	struct hostapd_iface *iface)
429 {
430 	int i;
431 	struct hostapd_channel_data *chan;
432 
433 	for (i = 0; i < iface->current_mode->num_channels; i++) {
434 		chan = &iface->current_mode->channels[i];
435 
436 		if (!acs_usable_chan(chan))
437 			continue;
438 
439 		wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)",
440 			   chan->chan, chan->freq);
441 
442 		acs_survey_chan_interference_factor(iface, chan);
443 
444 		wpa_printf(MSG_DEBUG, "ACS:  * interference factor average: %Lg",
445 			   chan->interference_factor);
446 	}
447 }
448 
449 
acs_find_chan(struct hostapd_iface * iface,int freq)450 static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface,
451 						  int freq)
452 {
453 	struct hostapd_channel_data *chan;
454 	int i;
455 
456 	for (i = 0; i < iface->current_mode->num_channels; i++) {
457 		chan = &iface->current_mode->channels[i];
458 
459 		if (!acs_usable_chan(chan))
460 			continue;
461 
462 		if (chan->freq == freq)
463 			return chan;
464 	}
465 
466 	return NULL;
467 }
468 
469 
470 /*
471  * At this point it's assumed chan->interface_factor has been computed.
472  * This function should be reusable regardless of interference computation
473  * option (survey, BSS, spectral, ...). chan->interference factor must be
474  * summable (i.e., must be always greater than zero).
475  */
476 static struct hostapd_channel_data *
acs_find_ideal_chan(struct hostapd_iface * iface)477 acs_find_ideal_chan(struct hostapd_iface *iface)
478 {
479 	struct hostapd_channel_data *chan, *adj_chan, *ideal_chan = NULL;
480 	long double factor, ideal_factor = 0;
481 	int i, j;
482 	int n_chans = 1;
483 
484 	/* TODO: HT40- support */
485 
486 	if (iface->conf->ieee80211n &&
487 	    iface->conf->secondary_channel == -1) {
488 		wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+");
489 		return NULL;
490 	}
491 
492 	if (iface->conf->ieee80211n &&
493 	    iface->conf->secondary_channel)
494 		n_chans = 2;
495 
496 	if (iface->conf->ieee80211ac &&
497 	    iface->conf->vht_oper_chwidth == 1)
498 		n_chans = 4;
499 
500 	/* TODO: VHT80+80, VHT160. Update acs_adjust_vht_center_freq() too. */
501 
502 	wpa_printf(MSG_DEBUG, "ACS: Survey analysis for selected bandwidth %d MHz",
503 		   n_chans == 1 ? 20 :
504 		   n_chans == 2 ? 40 :
505 		   n_chans == 4 ? 80 :
506 		   -1);
507 
508 	for (i = 0; i < iface->current_mode->num_channels; i++) {
509 		chan = &iface->current_mode->channels[i];
510 
511 		if (!acs_usable_chan(chan))
512 			continue;
513 
514 		/* HT40 on 5 GHz has a limited set of primary channels as per
515 		 * 11n Annex J */
516 		if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
517 		    iface->conf->ieee80211n &&
518 		    iface->conf->secondary_channel &&
519 		    !acs_usable_ht40_chan(chan)) {
520 			wpa_printf(MSG_DEBUG, "ACS: Channel %d: not allowed as primary channel for HT40",
521 				   chan->chan);
522 			continue;
523 		}
524 
525 		factor = chan->interference_factor;
526 
527 		for (j = 1; j < n_chans; j++) {
528 			adj_chan = acs_find_chan(iface, chan->freq + (j * 20));
529 			if (!adj_chan)
530 				break;
531 
532 			factor += adj_chan->interference_factor;
533 		}
534 
535 		if (j != n_chans) {
536 			wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth",
537 				   chan->chan);
538 			continue;
539 		}
540 
541 		/* 2.4 GHz has overlapping 20 MHz channels. Include adjacent
542 		 * channel interference factor. */
543 		if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211B ||
544 		    iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) {
545 			for (j = 0; j < n_chans; j++) {
546 				/* TODO: perhaps a multiplier should be used
547 				 * here? */
548 
549 				adj_chan = acs_find_chan(iface, chan->freq +
550 							 (j * 20) - 5);
551 				if (adj_chan)
552 					factor += adj_chan->interference_factor;
553 
554 				adj_chan = acs_find_chan(iface, chan->freq +
555 							 (j * 20) - 10);
556 				if (adj_chan)
557 					factor += adj_chan->interference_factor;
558 
559 				adj_chan = acs_find_chan(iface, chan->freq +
560 							 (j * 20) + 5);
561 				if (adj_chan)
562 					factor += adj_chan->interference_factor;
563 
564 				adj_chan = acs_find_chan(iface, chan->freq +
565 							 (j * 20) + 10);
566 				if (adj_chan)
567 					factor += adj_chan->interference_factor;
568 			}
569 		}
570 
571 		wpa_printf(MSG_DEBUG, "ACS:  * channel %d: total interference = %Lg",
572 			   chan->chan, factor);
573 
574 		if (!ideal_chan || factor < ideal_factor) {
575 			ideal_factor = factor;
576 			ideal_chan = chan;
577 		}
578 	}
579 
580 	if (ideal_chan)
581 		wpa_printf(MSG_DEBUG, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg",
582 			   ideal_chan->chan, ideal_chan->freq, ideal_factor);
583 
584 	return ideal_chan;
585 }
586 
587 
acs_adjust_vht_center_freq(struct hostapd_iface * iface)588 static void acs_adjust_vht_center_freq(struct hostapd_iface *iface)
589 {
590 	wpa_printf(MSG_DEBUG, "ACS: Adjusting VHT center frequency");
591 
592 	switch (iface->conf->vht_oper_chwidth) {
593 	case VHT_CHANWIDTH_USE_HT:
594 		iface->conf->vht_oper_centr_freq_seg0_idx =
595 			iface->conf->channel + 2;
596 		break;
597 	case VHT_CHANWIDTH_80MHZ:
598 		iface->conf->vht_oper_centr_freq_seg0_idx =
599 			iface->conf->channel + 6;
600 		break;
601 	default:
602 		/* TODO: How can this be calculated? Adjust
603 		 * acs_find_ideal_chan() */
604 		wpa_printf(MSG_INFO, "ACS: Only VHT20/40/80 is supported now");
605 		break;
606 	}
607 }
608 
609 
acs_study_survey_based(struct hostapd_iface * iface)610 static int acs_study_survey_based(struct hostapd_iface *iface)
611 {
612 	wpa_printf(MSG_DEBUG, "ACS: Trying survey-based ACS");
613 
614 	if (!iface->chans_surveyed) {
615 		wpa_printf(MSG_ERROR, "ACS: Unable to collect survey data");
616 		return -1;
617 	}
618 
619 	if (!acs_surveys_are_sufficient(iface)) {
620 		wpa_printf(MSG_ERROR, "ACS: Surveys have insufficient data");
621 		return -1;
622 	}
623 
624 	acs_survey_all_chans_intereference_factor(iface);
625 	return 0;
626 }
627 
628 
acs_study_options(struct hostapd_iface * iface)629 static int acs_study_options(struct hostapd_iface *iface)
630 {
631 	int err;
632 
633 	err = acs_study_survey_based(iface);
634 	if (err == 0)
635 		return 0;
636 
637 	/* TODO: If no surveys are available/sufficient this is a good
638 	 * place to fallback to BSS-based ACS */
639 
640 	return -1;
641 }
642 
643 
acs_study(struct hostapd_iface * iface)644 static void acs_study(struct hostapd_iface *iface)
645 {
646 	struct hostapd_channel_data *ideal_chan;
647 	int err;
648 
649 	err = acs_study_options(iface);
650 	if (err < 0) {
651 		wpa_printf(MSG_ERROR, "ACS: All study options have failed");
652 		goto fail;
653 	}
654 
655 	ideal_chan = acs_find_ideal_chan(iface);
656 	if (!ideal_chan) {
657 		wpa_printf(MSG_ERROR, "ACS: Failed to compute ideal channel");
658 		goto fail;
659 	}
660 
661 	iface->conf->channel = ideal_chan->chan;
662 
663 	if (iface->conf->ieee80211ac)
664 		acs_adjust_vht_center_freq(iface);
665 
666 	/*
667 	 * hostapd_setup_interface_complete() will return -1 on failure,
668 	 * 0 on success and 0 is HOSTAPD_CHAN_VALID :)
669 	 */
670 	switch (hostapd_acs_completed(iface)) {
671 	case HOSTAPD_CHAN_VALID:
672 		acs_cleanup(iface);
673 		return;
674 	case HOSTAPD_CHAN_INVALID:
675 	case HOSTAPD_CHAN_ACS:
676 	default:
677 		/* This can possibly happen if channel parameters (secondary
678 		 * channel, center frequencies) are misconfigured */
679 		wpa_printf(MSG_ERROR, "ACS: Possibly channel configuration is invalid, please report this along with your config file.");
680 		goto fail;
681 	}
682 
683 fail:
684 	acs_fail(iface);
685 }
686 
687 
acs_scan_complete(struct hostapd_iface * iface)688 static void acs_scan_complete(struct hostapd_iface *iface)
689 {
690 	int err;
691 
692 	iface->scan_cb = NULL;
693 
694 	wpa_printf(MSG_DEBUG, "ACS: Using survey based algorithm (acs_num_scans=%d)",
695 		   iface->conf->acs_num_scans);
696 
697 	err = hostapd_drv_get_survey(iface->bss[0], 0);
698 	if (err) {
699 		wpa_printf(MSG_ERROR, "ACS: Failed to get survey data");
700 		acs_fail(iface);
701 	}
702 
703 	if (++iface->acs_num_completed_scans < iface->conf->acs_num_scans) {
704 		err = acs_request_scan(iface);
705 		if (err) {
706 			wpa_printf(MSG_ERROR, "ACS: Failed to request scan");
707 			acs_fail(iface);
708 			return;
709 		}
710 
711 		return;
712 	}
713 
714 	acs_study(iface);
715 }
716 
717 
acs_request_scan(struct hostapd_iface * iface)718 static int acs_request_scan(struct hostapd_iface *iface)
719 {
720 	struct wpa_driver_scan_params params;
721 	struct hostapd_channel_data *chan;
722 	int i, *freq;
723 
724 	os_memset(&params, 0, sizeof(params));
725 	params.freqs = os_calloc(iface->current_mode->num_channels + 1,
726 				 sizeof(params.freqs[0]));
727 	if (params.freqs == NULL)
728 		return -1;
729 
730 	freq = params.freqs;
731 	for (i = 0; i < iface->current_mode->num_channels; i++) {
732 		chan = &iface->current_mode->channels[i];
733 		if (chan->flag & HOSTAPD_CHAN_DISABLED)
734 			continue;
735 
736 		*freq++ = chan->freq;
737 	}
738 	*freq = 0;
739 
740 	iface->scan_cb = acs_scan_complete;
741 
742 	wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d",
743 		   iface->acs_num_completed_scans + 1,
744 		   iface->conf->acs_num_scans);
745 
746 	if (hostapd_driver_scan(iface->bss[0], &params) < 0) {
747 		wpa_printf(MSG_ERROR, "ACS: Failed to request initial scan");
748 		acs_cleanup(iface);
749 		return -1;
750 	}
751 
752 	os_free(params.freqs);
753 	return 0;
754 }
755 
756 
acs_init(struct hostapd_iface * iface)757 enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
758 {
759 	int err;
760 
761 	wpa_printf(MSG_INFO, "ACS: Automatic channel selection started, this may take a bit");
762 
763 	acs_cleanup(iface);
764 
765 	err = acs_request_scan(iface);
766 	if (err < 0)
767 		return HOSTAPD_CHAN_INVALID;
768 
769 	return HOSTAPD_CHAN_ACS;
770 }
771