acs.c revision 391c59f0632df8db1c325da1d31d479b2eedce45
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 243static int acs_request_scan(struct hostapd_iface *iface); 244 245 246static 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 261static 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 282void acs_fail(struct hostapd_iface *iface) 283{ 284 wpa_printf(MSG_ERROR, "ACS: Failed to start"); 285 acs_cleanup(iface); 286} 287 288 289static long double 290acs_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 322static void 323acs_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 355static 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 365static 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 379static 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 401static 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 427static 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 450static 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 */ 476static struct hostapd_channel_data * 477acs_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 588static 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 610static 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 629static 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 644static 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 683fail: 684 acs_fail(iface); 685} 686 687 688static 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 718static 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(¶ms, 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], ¶ms) < 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 757enum 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