Home | History | Annotate | Download | only in ap
      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 
    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 
    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 
    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
    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
    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 
    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 
    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 
    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 
    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 
    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 
    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 *
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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