1391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt/* 2391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS - Automatic Channel Selection module 3391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Copyright (c) 2011, Atheros Communications 4391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Copyright (c) 2013, Qualcomm Atheros, Inc. 5391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 6391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 7391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * See README for more details. 8391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt */ 9391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 10391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "utils/includes.h" 11391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include <math.h> 12391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 13391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "utils/common.h" 14391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "utils/list.h" 15391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "common/ieee802_11_defs.h" 16391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "drivers/driver.h" 17391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "hostapd.h" 18391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "ap_drv_ops.h" 19391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "ap_config.h" 20391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "hw_features.h" 21391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "acs.h" 22391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 23391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt/* 24391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Automatic Channel Selection 25391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * =========================== 26391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 27391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * More info at 28391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ------------ 29391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * http://wireless.kernel.org/en/users/Documentation/acs 30391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 31391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * How to use 32391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ---------- 33391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - make sure you have CONFIG_ACS=y in hostapd's .config 34391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - use channel=0 or channel=acs to enable ACS 35391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 36391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * How does it work 37391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ---------------- 38391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 1. passive scans are used to collect survey data 39391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * (it is assumed that scan trigger collection of survey data in driver) 40391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 2. interference factor is calculated for each channel 41391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 3. ideal channel is picked depending on channel width by using adjacent 42391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * channel interference factors 43391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 44391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Known limitations 45391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ----------------- 46391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - Current implementation depends heavily on the amount of time willing to 47391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * spend gathering survey data during hostapd startup. Short traffic bursts 48391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * may be missed and a suboptimal channel may be picked. 49391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - Ideal channel may end up overlapping a channel with 40 MHz intolerant BSS 50391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 51391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Todo / Ideas 52391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ------------ 53391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - implement other interference computation methods 54391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - BSS/RSSI based 55391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - spectral scan based 56391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * (should be possibly to hook this up with current ACS scans) 57391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - add wpa_supplicant support (for P2P) 58391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - collect a histogram of interference over time allowing more educated 59391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * guess about an ideal channel (perhaps CSA could be used to migrate AP to a 60391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * new "better" channel while running) 61391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - include neighboring BSS scan to avoid conflicts with 40 MHz intolerant BSSs 62391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * when choosing the ideal channel 63391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 64391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Survey interference factor implementation details 65391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ------------------------------------------------- 66391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Generic interference_factor in struct hostapd_channel_data is used. 67391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 68391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * The survey interference factor is defined as the ratio of the 69391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * observed busy time over the time we spent on the channel, 70391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * this value is then amplified by the observed noise floor on 71391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * the channel in comparison to the lowest noise floor observed 72391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * on the entire band. 73391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 74391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * This corresponds to: 75391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * --- 76391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * (busy time - tx time) / (active time - tx time) * 2^(chan_nf + band_min_nf) 77391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * --- 78391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 79391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * The coefficient of 2 reflects the way power in "far-field" 80391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * radiation decreases as the square of distance from the antenna [1]. 81391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * What this does is it decreases the observed busy time ratio if the 82391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * noise observed was low but increases it if the noise was high, 83391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * proportionally to the way "far field" radiation changes over 84391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * distance. 85391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 86391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * If channel busy time is not available the fallback is to use channel RX time. 87391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 88391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Since noise floor is in dBm it is necessary to convert it into Watts so that 89391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * combined channel interference (e.g., HT40, which uses two channels) can be 90391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * calculated easily. 91391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * --- 92391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * (busy time - tx time) / (active time - tx time) * 93391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 2^(10^(chan_nf/10) + 10^(band_min_nf/10)) 94391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * --- 95391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 96391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * However to account for cases where busy/rx time is 0 (channel load is then 97391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 0%) channel noise floor signal power is combined into the equation so a 98391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * channel with lower noise floor is preferred. The equation becomes: 99391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * --- 100391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 10^(chan_nf/5) + (busy time - tx time) / (active time - tx time) * 101391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 2^(10^(chan_nf/10) + 10^(band_min_nf/10)) 102391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * --- 103391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 104391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * All this "interference factor" is purely subjective and only time 105391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * will tell how usable this is. By using the minimum noise floor we 106391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * remove any possible issues due to card calibration. The computation 107391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * of the interference factor then is dependent on what the card itself 108391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * picks up as the minimum noise, not an actual real possible card 109391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * noise value. 110391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 111391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Total interference computation details 112391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * -------------------------------------- 113391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * The above channel interference factor is calculated with no respect to 114391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * target operational bandwidth. 115391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 116391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * To find an ideal channel the above data is combined by taking into account 117391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * the target operational bandwidth and selected band. E.g., on 2.4 GHz channels 118391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * overlap with 20 MHz bandwidth, but there is no overlap for 20 MHz bandwidth 119391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * on 5 GHz. 120391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 121391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Each valid and possible channel spec (i.e., channel + width) is taken and its 122391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * interference factor is computed by summing up interferences of each channel 123391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * it overlaps. The one with least total interference is picked up. 124391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 125391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Note: This implies base channel interference factor must be non-negative 126391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * allowing easy summing up. 127391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 128391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Example ACS analysis printout 129391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ----------------------------- 130391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 131391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Trying survey-based ACS 132391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 1 (2412 MHz) 133391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-113 interference_factor=0.0802469 nf=-113 time=162 busy=0 rx=13 134391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-113 interference_factor=0.0745342 nf=-113 time=161 busy=0 rx=12 135391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-113 interference_factor=0.0679012 nf=-113 time=162 busy=0 rx=11 136391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-113 interference_factor=0.0310559 nf=-113 time=161 busy=0 rx=5 137391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-113 interference_factor=0.0248447 nf=-113 time=161 busy=0 rx=4 138391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.0557166 139391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 2 (2417 MHz) 140391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-113 interference_factor=0.0185185 nf=-113 time=162 busy=0 rx=3 141391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-113 interference_factor=0.0246914 nf=-113 time=162 busy=0 rx=4 142391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-113 interference_factor=0.037037 nf=-113 time=162 busy=0 rx=6 143391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-113 interference_factor=0.149068 nf=-113 time=161 busy=0 rx=24 144391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-113 interference_factor=0.0248447 nf=-113 time=161 busy=0 rx=4 145391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.050832 146391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 3 (2422 MHz) 147391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-113 interference_factor=2.51189e-23 nf=-113 time=162 busy=0 rx=0 148391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-113 interference_factor=0.0185185 nf=-113 time=162 busy=0 rx=3 149391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-113 interference_factor=0.0186335 nf=-113 time=161 busy=0 rx=3 150391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-113 interference_factor=0.0186335 nf=-113 time=161 busy=0 rx=3 151391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-113 interference_factor=0.0186335 nf=-113 time=161 busy=0 rx=3 152391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.0148838 153391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 4 (2427 MHz) 154391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0 155391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-114 interference_factor=0.0555556 nf=-114 time=162 busy=0 rx=9 156391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=161 busy=0 rx=0 157391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-114 interference_factor=0.0186335 nf=-114 time=161 busy=0 rx=3 158391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1 159391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.0160801 160391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 5 (2432 MHz) 161391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-114 interference_factor=0.409938 nf=-113 time=161 busy=0 rx=66 162391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-114 interference_factor=0.0432099 nf=-113 time=162 busy=0 rx=7 163391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-114 interference_factor=0.0124224 nf=-113 time=161 busy=0 rx=2 164391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-114 interference_factor=0.677019 nf=-113 time=161 busy=0 rx=109 165391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-114 interference_factor=0.0186335 nf=-114 time=161 busy=0 rx=3 166391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.232244 167391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 6 (2437 MHz) 168391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-113 interference_factor=0.552795 nf=-113 time=161 busy=0 rx=89 169391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-113 interference_factor=0.0807453 nf=-112 time=161 busy=0 rx=13 170391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-113 interference_factor=0.0310559 nf=-113 time=161 busy=0 rx=5 171391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-113 interference_factor=0.434783 nf=-112 time=161 busy=0 rx=70 172391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-113 interference_factor=0.0621118 nf=-113 time=161 busy=0 rx=10 173391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.232298 174391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 7 (2442 MHz) 175391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-113 interference_factor=0.440994 nf=-112 time=161 busy=0 rx=71 176391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-113 interference_factor=0.385093 nf=-113 time=161 busy=0 rx=62 177391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-113 interference_factor=0.0372671 nf=-113 time=161 busy=0 rx=6 178391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-113 interference_factor=0.0372671 nf=-113 time=161 busy=0 rx=6 179391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-113 interference_factor=0.0745342 nf=-113 time=161 busy=0 rx=12 180391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.195031 181391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 8 (2447 MHz) 182391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-114 interference_factor=0.0496894 nf=-112 time=161 busy=0 rx=8 183391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-114 interference_factor=0.0496894 nf=-114 time=161 busy=0 rx=8 184391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-114 interference_factor=0.0372671 nf=-113 time=161 busy=0 rx=6 185391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-114 interference_factor=0.12963 nf=-113 time=162 busy=0 rx=21 186391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-114 interference_factor=0.166667 nf=-114 time=162 busy=0 rx=27 187391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.0865885 188391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 9 (2452 MHz) 189391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-114 interference_factor=0.0124224 nf=-114 time=161 busy=0 rx=2 190391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-114 interference_factor=0.0310559 nf=-114 time=161 busy=0 rx=5 191391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=161 busy=0 rx=0 192391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-114 interference_factor=0.00617284 nf=-114 time=162 busy=0 rx=1 193391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0 194391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.00993022 195391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 10 (2457 MHz) 196391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1 197391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1 198391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1 199391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-114 interference_factor=0.0493827 nf=-114 time=162 busy=0 rx=8 200391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0 201391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.0136033 202391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 11 (2462 MHz) 203391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=161 busy=0 rx=0 204391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=161 busy=0 rx=0 205391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=161 busy=0 rx=0 206391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-114 interference_factor=0.0432099 nf=-114 time=162 busy=0 rx=7 207391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-114 interference_factor=0.0925926 nf=-114 time=162 busy=0 rx=15 208391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.0271605 209391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 12 (2467 MHz) 210391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-114 interference_factor=0.0621118 nf=-113 time=161 busy=0 rx=10 211391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1 212391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=162 busy=0 rx=0 213391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=162 busy=0 rx=0 214391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-114 interference_factor=0.00617284 nf=-113 time=162 busy=0 rx=1 215391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.0148992 216391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 13 (2472 MHz) 217391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-114 interference_factor=0.0745342 nf=-114 time=161 busy=0 rx=12 218391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-114 interference_factor=0.0555556 nf=-114 time=162 busy=0 rx=9 219391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0 220391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0 221391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0 222391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.0260179 223391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for selected bandwidth 20MHz 224391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 1: total interference = 0.121432 225391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 2: total interference = 0.137512 226391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 3: total interference = 0.369757 227391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 4: total interference = 0.546338 228391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 5: total interference = 0.690538 229391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 6: total interference = 0.762242 230391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 7: total interference = 0.756092 231391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 8: total interference = 0.537451 232391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 9: total interference = 0.332313 233391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 10: total interference = 0.152182 234391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 11: total interference = 0.0916111 235391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 12: total interference = 0.0816809 236391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 13: total interference = 0.0680776 237391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Ideal channel is 13 (2472 MHz) with total interference factor of 0.0680776 238391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 239391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * [1] http://en.wikipedia.org/wiki/Near_and_far_field 240391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt */ 241391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 242391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 243391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic int acs_request_scan(struct hostapd_iface *iface); 244391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 245391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 246391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void acs_clean_chan_surveys(struct hostapd_channel_data *chan) 247391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 248391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct freq_survey *survey, *tmp; 249391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 250391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (dl_list_empty(&chan->survey_list)) 251391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return; 252391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 253391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt dl_list_for_each_safe(survey, tmp, &chan->survey_list, 254391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct freq_survey, list) { 255391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt dl_list_del(&survey->list); 256391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt os_free(survey); 257391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 258391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 259391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 260391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 261391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void acs_cleanup(struct hostapd_iface *iface) 262391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 263391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int i; 264391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_channel_data *chan; 265391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 266391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (i = 0; i < iface->current_mode->num_channels; i++) { 267391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan = &iface->current_mode->channels[i]; 268391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 269391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (chan->flag & HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED) 270391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_clean_chan_surveys(chan); 271391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 272391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt dl_list_init(&chan->survey_list); 273391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED; 274391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->min_nf = 0; 275391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 276391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 277391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->chans_surveyed = 0; 278391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->acs_num_completed_scans = 0; 279391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 280391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 281391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 282391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtvoid acs_fail(struct hostapd_iface *iface) 283391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 284391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Failed to start"); 285391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_cleanup(iface); 286391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 287391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 288391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 289391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic long double 290391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtacs_survey_interference_factor(struct freq_survey *survey, s8 min_nf) 291391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 292391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt long double factor, busy, total; 293391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 294391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (survey->filled & SURVEY_HAS_CHAN_TIME_BUSY) 295391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt busy = survey->channel_time_busy; 296391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt else if (survey->filled & SURVEY_HAS_CHAN_TIME_RX) 297391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt busy = survey->channel_time_rx; 298391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt else { 299391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* This shouldn't really happen as survey data is checked in 300391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * acs_sanity_check() */ 301391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Survey data missing"); 302391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 303391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 304391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 305391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt total = survey->channel_time; 306391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 307391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (survey->filled & SURVEY_HAS_CHAN_TIME_TX) { 308391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt busy -= survey->channel_time_tx; 309391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt total -= survey->channel_time_tx; 310391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 311391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 312391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* TODO: figure out the best multiplier for noise floor base */ 313391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt factor = pow(10, survey->nf / 5.0L) + 314391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt (busy / total) * 315391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt pow(2, pow(10, (long double) survey->nf / 10.0L) - 316391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt pow(10, (long double) min_nf / 10.0L)); 317391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 318391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return factor; 319391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 320391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 321391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 322391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void 323391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtacs_survey_chan_interference_factor(struct hostapd_iface *iface, 324391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_channel_data *chan) 325391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 326391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct freq_survey *survey; 327391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt unsigned int i = 0; 328391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt long double int_factor = 0; 329391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 330391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (dl_list_empty(&chan->survey_list)) 331391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return; 332391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 333391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (chan->flag & HOSTAPD_CHAN_DISABLED) 334391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return; 335391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 336391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->interference_factor = 0; 337391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 338391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt dl_list_for_each(survey, &chan->survey_list, struct freq_survey, list) 339391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt { 340391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int_factor = acs_survey_interference_factor(survey, 341391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->lowest_nf); 342391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->interference_factor += int_factor; 343391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: %d: min_nf=%d interference_factor=%Lg nf=%d time=%lu busy=%lu rx=%lu", 344391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt ++i, chan->min_nf, int_factor, 345391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt survey->nf, (unsigned long) survey->channel_time, 346391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt (unsigned long) survey->channel_time_busy, 347391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt (unsigned long) survey->channel_time_rx); 348391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 349391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 350391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->interference_factor = chan->interference_factor / 351391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt dl_list_len(&chan->survey_list); 352391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 353391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 354391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 355391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic int acs_usable_chan(struct hostapd_channel_data *chan) 356391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 357391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (dl_list_empty(&chan->survey_list)) 358391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 359391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (chan->flag & HOSTAPD_CHAN_DISABLED) 360391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 361391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 1; 362391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 363391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 364391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 365391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic int acs_usable_ht40_chan(struct hostapd_channel_data *chan) 366391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 367391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt const int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 368391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 157, 184, 192 }; 369391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt unsigned int i; 370391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 371391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (i = 0; i < sizeof(allowed) / sizeof(allowed[0]); i++) 372391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (chan->chan == allowed[i]) 373391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 1; 374391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 375391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 376391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 377391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 378391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 379391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic int acs_survey_is_sufficient(struct freq_survey *survey) 380391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 381391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!(survey->filled & SURVEY_HAS_NF)) { 382391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Survey is missing noise floor"); 383391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 384391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 385391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 386391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!(survey->filled & SURVEY_HAS_CHAN_TIME)) { 387391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Survey is missing channel time"); 388391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 389391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 390391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 391391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!(survey->filled & SURVEY_HAS_CHAN_TIME_BUSY) && 392391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt !(survey->filled & SURVEY_HAS_CHAN_TIME_RX)) { 393391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Survey is missing RX and busy time (at least one is required)"); 394391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 395391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 396391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 397391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 1; 398391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 399391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 400391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 401391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic int acs_surveys_are_sufficient(struct hostapd_iface *iface) 402391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 403391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int i; 404391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_channel_data *chan; 405391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct freq_survey *survey; 406391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 407391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (i = 0; i < iface->current_mode->num_channels; i++) { 408391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan = &iface->current_mode->channels[i]; 409391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (chan->flag & HOSTAPD_CHAN_DISABLED) 410391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt continue; 411391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 412391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt dl_list_for_each(survey, &chan->survey_list, 413391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct freq_survey, list) 414391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt { 415391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!acs_survey_is_sufficient(survey)) { 416391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Channel %d has insufficient survey data", 417391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->chan); 418391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 419391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 420391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 421391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 422391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 423391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 1; 424391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 425391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 426391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 427391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void acs_survey_all_chans_intereference_factor( 428391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_iface *iface) 429391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 430391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int i; 431391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_channel_data *chan; 432391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 433391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (i = 0; i < iface->current_mode->num_channels; i++) { 434391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan = &iface->current_mode->channels[i]; 435391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 436391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!acs_usable_chan(chan)) 437391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt continue; 438391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 439391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)", 440391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->chan, chan->freq); 441391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 442391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_survey_chan_interference_factor(iface, chan); 443391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 444391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: * interference factor average: %Lg", 445391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->interference_factor); 446391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 447391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 448391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 449391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 450391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface, 451391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int freq) 452391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 453391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_channel_data *chan; 454391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int i; 455391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 456391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (i = 0; i < iface->current_mode->num_channels; i++) { 457391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan = &iface->current_mode->channels[i]; 458391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 459391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!acs_usable_chan(chan)) 460391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt continue; 461391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 462391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (chan->freq == freq) 463391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return chan; 464391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 465391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 466391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return NULL; 467391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 468391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 469391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 470391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt/* 471391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * At this point it's assumed chan->interface_factor has been computed. 472391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * This function should be reusable regardless of interference computation 473391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * option (survey, BSS, spectral, ...). chan->interference factor must be 474391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * summable (i.e., must be always greater than zero). 475391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt */ 476391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic struct hostapd_channel_data * 477391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtacs_find_ideal_chan(struct hostapd_iface *iface) 478391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 479391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_channel_data *chan, *adj_chan, *ideal_chan = NULL; 480391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt long double factor, ideal_factor = 0; 481391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int i, j; 482391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int n_chans = 1; 483391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 484391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* TODO: HT40- support */ 485391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 486391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (iface->conf->ieee80211n && 487391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->secondary_channel == -1) { 488391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+"); 489391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return NULL; 490391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 491391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 492391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (iface->conf->ieee80211n && 493391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->secondary_channel) 494391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt n_chans = 2; 495391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 496391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (iface->conf->ieee80211ac && 497391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->vht_oper_chwidth == 1) 498391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt n_chans = 4; 499391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 500391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* TODO: VHT80+80, VHT160. Update acs_adjust_vht_center_freq() too. */ 501391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 502391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Survey analysis for selected bandwidth %d MHz", 503391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt n_chans == 1 ? 20 : 504391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt n_chans == 2 ? 40 : 505391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt n_chans == 4 ? 80 : 506391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt -1); 507391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 508391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (i = 0; i < iface->current_mode->num_channels; i++) { 509391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan = &iface->current_mode->channels[i]; 510391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 511391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!acs_usable_chan(chan)) 512391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt continue; 513391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 514391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* HT40 on 5 GHz has a limited set of primary channels as per 515391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 11n Annex J */ 516391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A && 517391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->ieee80211n && 518391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->secondary_channel && 519391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt !acs_usable_ht40_chan(chan)) { 520391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Channel %d: not allowed as primary channel for HT40", 521391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->chan); 522391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt continue; 523391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 524391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 525391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt factor = chan->interference_factor; 526391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 527391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (j = 1; j < n_chans; j++) { 528391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt adj_chan = acs_find_chan(iface, chan->freq + (j * 20)); 529391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!adj_chan) 530391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt break; 531391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 532391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt factor += adj_chan->interference_factor; 533391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 534391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 535391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (j != n_chans) { 536391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth", 537391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->chan); 538391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt continue; 539391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 540391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 541391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* 2.4 GHz has overlapping 20 MHz channels. Include adjacent 542391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * channel interference factor. */ 543391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211B || 544391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) { 545391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (j = 0; j < n_chans; j++) { 546391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* TODO: perhaps a multiplier should be used 547391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * here? */ 548391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 549391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt adj_chan = acs_find_chan(iface, chan->freq + 550391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt (j * 20) - 5); 551391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (adj_chan) 552391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt factor += adj_chan->interference_factor; 553391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 554391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt adj_chan = acs_find_chan(iface, chan->freq + 555391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt (j * 20) - 10); 556391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (adj_chan) 557391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt factor += adj_chan->interference_factor; 558391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 559391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt adj_chan = acs_find_chan(iface, chan->freq + 560391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt (j * 20) + 5); 561391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (adj_chan) 562391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt factor += adj_chan->interference_factor; 563391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 564391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt adj_chan = acs_find_chan(iface, chan->freq + 565391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt (j * 20) + 10); 566391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (adj_chan) 567391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt factor += adj_chan->interference_factor; 568391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 569391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 570391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 571391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: * channel %d: total interference = %Lg", 572391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->chan, factor); 573391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 574391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!ideal_chan || factor < ideal_factor) { 575391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt ideal_factor = factor; 576391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt ideal_chan = chan; 577391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 578391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 579391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 580391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (ideal_chan) 581391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg", 582391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt ideal_chan->chan, ideal_chan->freq, ideal_factor); 583391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 584391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return ideal_chan; 585391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 586391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 587391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 588391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void acs_adjust_vht_center_freq(struct hostapd_iface *iface) 589391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 590391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Adjusting VHT center frequency"); 591391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 592391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt switch (iface->conf->vht_oper_chwidth) { 593391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case VHT_CHANWIDTH_USE_HT: 594391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg0_idx = 595391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->channel + 2; 596391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt break; 597391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case VHT_CHANWIDTH_80MHZ: 598391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg0_idx = 599391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->channel + 6; 600391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt break; 601391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt default: 602391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* TODO: How can this be calculated? Adjust 603391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * acs_find_ideal_chan() */ 604391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_INFO, "ACS: Only VHT20/40/80 is supported now"); 605391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt break; 606391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 607391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 608391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 609391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 610391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic int acs_study_survey_based(struct hostapd_iface *iface) 611391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 612391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Trying survey-based ACS"); 613391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 614391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!iface->chans_surveyed) { 615391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Unable to collect survey data"); 616391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return -1; 617391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 618391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 619391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!acs_surveys_are_sufficient(iface)) { 620391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Surveys have insufficient data"); 621391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return -1; 622391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 623391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 624391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_survey_all_chans_intereference_factor(iface); 625391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 626391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 627391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 628391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 629391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic int acs_study_options(struct hostapd_iface *iface) 630391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 631391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int err; 632391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 633391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt err = acs_study_survey_based(iface); 634391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (err == 0) 635391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 636391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 637391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* TODO: If no surveys are available/sufficient this is a good 638391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * place to fallback to BSS-based ACS */ 639391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 640391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return -1; 641391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 642391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 643391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 644391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void acs_study(struct hostapd_iface *iface) 645391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 646391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_channel_data *ideal_chan; 647391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int err; 648391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 649391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt err = acs_study_options(iface); 650391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (err < 0) { 651391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: All study options have failed"); 652391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt goto fail; 653391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 654391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 655391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt ideal_chan = acs_find_ideal_chan(iface); 656391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!ideal_chan) { 657391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Failed to compute ideal channel"); 658391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt goto fail; 659391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 660391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 661391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->channel = ideal_chan->chan; 662391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 663391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (iface->conf->ieee80211ac) 664391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_adjust_vht_center_freq(iface); 665391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 666391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* 667391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * hostapd_setup_interface_complete() will return -1 on failure, 668391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 0 on success and 0 is HOSTAPD_CHAN_VALID :) 669391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt */ 670391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt switch (hostapd_acs_completed(iface)) { 671391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_VALID: 672391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_cleanup(iface); 673391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return; 674391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_INVALID: 675391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_ACS: 676391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt default: 677391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* This can possibly happen if channel parameters (secondary 678391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * channel, center frequencies) are misconfigured */ 679391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Possibly channel configuration is invalid, please report this along with your config file."); 680391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt goto fail; 681391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 682391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 683391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtfail: 684391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_fail(iface); 685391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 686391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 687391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 688391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void acs_scan_complete(struct hostapd_iface *iface) 689391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 690391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int err; 691391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 692391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->scan_cb = NULL; 693391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 694391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Using survey based algorithm (acs_num_scans=%d)", 695391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->acs_num_scans); 696391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 697391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt err = hostapd_drv_get_survey(iface->bss[0], 0); 698391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (err) { 699391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Failed to get survey data"); 700391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_fail(iface); 701391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 702391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 703391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (++iface->acs_num_completed_scans < iface->conf->acs_num_scans) { 704391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt err = acs_request_scan(iface); 705391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (err) { 706391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Failed to request scan"); 707391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_fail(iface); 708391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return; 709391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 710391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 711391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return; 712391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 713391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 714391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_study(iface); 715391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 716391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 717391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 718391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic int acs_request_scan(struct hostapd_iface *iface) 719391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 720391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct wpa_driver_scan_params params; 721391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_channel_data *chan; 722391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int i, *freq; 723391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 724391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt os_memset(¶ms, 0, sizeof(params)); 725391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt params.freqs = os_calloc(iface->current_mode->num_channels + 1, 726391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt sizeof(params.freqs[0])); 727391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (params.freqs == NULL) 728391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return -1; 729391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 730391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt freq = params.freqs; 731391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (i = 0; i < iface->current_mode->num_channels; i++) { 732391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan = &iface->current_mode->channels[i]; 733391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (chan->flag & HOSTAPD_CHAN_DISABLED) 734391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt continue; 735391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 736391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt *freq++ = chan->freq; 737391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 738391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt *freq = 0; 739391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 740391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->scan_cb = acs_scan_complete; 741391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 742391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d", 743391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->acs_num_completed_scans + 1, 744391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->acs_num_scans); 745391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 746391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (hostapd_driver_scan(iface->bss[0], ¶ms) < 0) { 747391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Failed to request initial scan"); 748391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_cleanup(iface); 749391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return -1; 750391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 751391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 752391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt os_free(params.freqs); 753391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 754391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 755391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 756391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 757391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtenum hostapd_chan_status acs_init(struct hostapd_iface *iface) 758391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 759391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int err; 760391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 761391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_INFO, "ACS: Automatic channel selection started, this may take a bit"); 762391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 763391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_cleanup(iface); 764391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 765391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt err = acs_request_scan(iface); 766391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (err < 0) 767391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return HOSTAPD_CHAN_INVALID; 768391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 769391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return HOSTAPD_CHAN_ACS; 770391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 771