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" 16cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#include "common/wpa_ctrl.h" 17391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "drivers/driver.h" 18391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "hostapd.h" 19391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "ap_drv_ops.h" 20391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "ap_config.h" 21391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "hw_features.h" 22391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "acs.h" 23391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 24391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt/* 25391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Automatic Channel Selection 26391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * =========================== 27391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 28391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * More info at 29391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ------------ 30391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * http://wireless.kernel.org/en/users/Documentation/acs 31391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 32391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * How to use 33391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ---------- 34391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - make sure you have CONFIG_ACS=y in hostapd's .config 35391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - use channel=0 or channel=acs to enable ACS 36391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 37391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * How does it work 38391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ---------------- 39391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 1. passive scans are used to collect survey data 40391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * (it is assumed that scan trigger collection of survey data in driver) 41391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 2. interference factor is calculated for each channel 42391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 3. ideal channel is picked depending on channel width by using adjacent 43391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * channel interference factors 44391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 45391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Known limitations 46391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ----------------- 47391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - Current implementation depends heavily on the amount of time willing to 48391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * spend gathering survey data during hostapd startup. Short traffic bursts 49391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * may be missed and a suboptimal channel may be picked. 50391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - Ideal channel may end up overlapping a channel with 40 MHz intolerant BSS 51391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 52391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Todo / Ideas 53391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ------------ 54391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - implement other interference computation methods 55391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - BSS/RSSI based 56391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - spectral scan based 57391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * (should be possibly to hook this up with current ACS scans) 58391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - add wpa_supplicant support (for P2P) 59391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - collect a histogram of interference over time allowing more educated 60391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * guess about an ideal channel (perhaps CSA could be used to migrate AP to a 61391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * new "better" channel while running) 62391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * - include neighboring BSS scan to avoid conflicts with 40 MHz intolerant BSSs 63391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * when choosing the ideal channel 64391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 65391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Survey interference factor implementation details 66391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ------------------------------------------------- 67391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Generic interference_factor in struct hostapd_channel_data is used. 68391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 69391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * The survey interference factor is defined as the ratio of the 70391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * observed busy time over the time we spent on the channel, 71391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * this value is then amplified by the observed noise floor on 72391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * the channel in comparison to the lowest noise floor observed 73391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * on the entire band. 74391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 75391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * This corresponds to: 76391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * --- 77391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * (busy time - tx time) / (active time - tx time) * 2^(chan_nf + band_min_nf) 78391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * --- 79391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 80391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * The coefficient of 2 reflects the way power in "far-field" 81391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * radiation decreases as the square of distance from the antenna [1]. 82391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * What this does is it decreases the observed busy time ratio if the 83391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * noise observed was low but increases it if the noise was high, 84391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * proportionally to the way "far field" radiation changes over 85391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * distance. 86391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 87391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * If channel busy time is not available the fallback is to use channel RX time. 88391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 89391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Since noise floor is in dBm it is necessary to convert it into Watts so that 90391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * combined channel interference (e.g., HT40, which uses two channels) can be 91391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * calculated easily. 92391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * --- 93391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * (busy time - tx time) / (active time - tx time) * 94391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 2^(10^(chan_nf/10) + 10^(band_min_nf/10)) 95391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * --- 96391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 97391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * However to account for cases where busy/rx time is 0 (channel load is then 98391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 0%) channel noise floor signal power is combined into the equation so a 99391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * channel with lower noise floor is preferred. The equation becomes: 100391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * --- 101391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 10^(chan_nf/5) + (busy time - tx time) / (active time - tx time) * 102391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 2^(10^(chan_nf/10) + 10^(band_min_nf/10)) 103391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * --- 104391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 105391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * All this "interference factor" is purely subjective and only time 106391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * will tell how usable this is. By using the minimum noise floor we 107391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * remove any possible issues due to card calibration. The computation 108391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * of the interference factor then is dependent on what the card itself 109391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * picks up as the minimum noise, not an actual real possible card 110391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * noise value. 111391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 112391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Total interference computation details 113391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * -------------------------------------- 114391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * The above channel interference factor is calculated with no respect to 115391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * target operational bandwidth. 116391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 117391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * To find an ideal channel the above data is combined by taking into account 118391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * the target operational bandwidth and selected band. E.g., on 2.4 GHz channels 119391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * overlap with 20 MHz bandwidth, but there is no overlap for 20 MHz bandwidth 120391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * on 5 GHz. 121391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 122391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Each valid and possible channel spec (i.e., channel + width) is taken and its 123391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * interference factor is computed by summing up interferences of each channel 124391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * it overlaps. The one with least total interference is picked up. 125391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 126391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Note: This implies base channel interference factor must be non-negative 127391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * allowing easy summing up. 128391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 129391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Example ACS analysis printout 130391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ----------------------------- 131391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 132391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Trying survey-based ACS 133391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 1 (2412 MHz) 134391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-113 interference_factor=0.0802469 nf=-113 time=162 busy=0 rx=13 135391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-113 interference_factor=0.0745342 nf=-113 time=161 busy=0 rx=12 136391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-113 interference_factor=0.0679012 nf=-113 time=162 busy=0 rx=11 137391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-113 interference_factor=0.0310559 nf=-113 time=161 busy=0 rx=5 138391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-113 interference_factor=0.0248447 nf=-113 time=161 busy=0 rx=4 139391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.0557166 140391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 2 (2417 MHz) 141391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-113 interference_factor=0.0185185 nf=-113 time=162 busy=0 rx=3 142391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-113 interference_factor=0.0246914 nf=-113 time=162 busy=0 rx=4 143391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-113 interference_factor=0.037037 nf=-113 time=162 busy=0 rx=6 144391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-113 interference_factor=0.149068 nf=-113 time=161 busy=0 rx=24 145391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-113 interference_factor=0.0248447 nf=-113 time=161 busy=0 rx=4 146391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.050832 147391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 3 (2422 MHz) 148391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-113 interference_factor=2.51189e-23 nf=-113 time=162 busy=0 rx=0 149391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-113 interference_factor=0.0185185 nf=-113 time=162 busy=0 rx=3 150391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-113 interference_factor=0.0186335 nf=-113 time=161 busy=0 rx=3 151391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-113 interference_factor=0.0186335 nf=-113 time=161 busy=0 rx=3 152391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-113 interference_factor=0.0186335 nf=-113 time=161 busy=0 rx=3 153391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.0148838 154391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 4 (2427 MHz) 155391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0 156391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-114 interference_factor=0.0555556 nf=-114 time=162 busy=0 rx=9 157391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=161 busy=0 rx=0 158391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-114 interference_factor=0.0186335 nf=-114 time=161 busy=0 rx=3 159391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1 160391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.0160801 161391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 5 (2432 MHz) 162391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-114 interference_factor=0.409938 nf=-113 time=161 busy=0 rx=66 163391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-114 interference_factor=0.0432099 nf=-113 time=162 busy=0 rx=7 164391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-114 interference_factor=0.0124224 nf=-113 time=161 busy=0 rx=2 165391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-114 interference_factor=0.677019 nf=-113 time=161 busy=0 rx=109 166391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-114 interference_factor=0.0186335 nf=-114 time=161 busy=0 rx=3 167391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.232244 168391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 6 (2437 MHz) 169391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-113 interference_factor=0.552795 nf=-113 time=161 busy=0 rx=89 170391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-113 interference_factor=0.0807453 nf=-112 time=161 busy=0 rx=13 171391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-113 interference_factor=0.0310559 nf=-113 time=161 busy=0 rx=5 172391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-113 interference_factor=0.434783 nf=-112 time=161 busy=0 rx=70 173391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-113 interference_factor=0.0621118 nf=-113 time=161 busy=0 rx=10 174391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.232298 175391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 7 (2442 MHz) 176391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-113 interference_factor=0.440994 nf=-112 time=161 busy=0 rx=71 177391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-113 interference_factor=0.385093 nf=-113 time=161 busy=0 rx=62 178391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-113 interference_factor=0.0372671 nf=-113 time=161 busy=0 rx=6 179391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-113 interference_factor=0.0372671 nf=-113 time=161 busy=0 rx=6 180391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-113 interference_factor=0.0745342 nf=-113 time=161 busy=0 rx=12 181391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.195031 182391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 8 (2447 MHz) 183391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-114 interference_factor=0.0496894 nf=-112 time=161 busy=0 rx=8 184391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-114 interference_factor=0.0496894 nf=-114 time=161 busy=0 rx=8 185391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-114 interference_factor=0.0372671 nf=-113 time=161 busy=0 rx=6 186391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-114 interference_factor=0.12963 nf=-113 time=162 busy=0 rx=21 187391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-114 interference_factor=0.166667 nf=-114 time=162 busy=0 rx=27 188391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.0865885 189391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 9 (2452 MHz) 190391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-114 interference_factor=0.0124224 nf=-114 time=161 busy=0 rx=2 191391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-114 interference_factor=0.0310559 nf=-114 time=161 busy=0 rx=5 192391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=161 busy=0 rx=0 193391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-114 interference_factor=0.00617284 nf=-114 time=162 busy=0 rx=1 194391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0 195391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.00993022 196391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 10 (2457 MHz) 197391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1 198391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1 199391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1 200391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-114 interference_factor=0.0493827 nf=-114 time=162 busy=0 rx=8 201391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0 202391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.0136033 203391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 11 (2462 MHz) 204391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=161 busy=0 rx=0 205391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=161 busy=0 rx=0 206391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=161 busy=0 rx=0 207391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-114 interference_factor=0.0432099 nf=-114 time=162 busy=0 rx=7 208391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-114 interference_factor=0.0925926 nf=-114 time=162 busy=0 rx=15 209391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.0271605 210391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 12 (2467 MHz) 211391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-114 interference_factor=0.0621118 nf=-113 time=161 busy=0 rx=10 212391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-114 interference_factor=0.00621118 nf=-114 time=161 busy=0 rx=1 213391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=162 busy=0 rx=0 214391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-114 interference_factor=2.51189e-23 nf=-113 time=162 busy=0 rx=0 215391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-114 interference_factor=0.00617284 nf=-113 time=162 busy=0 rx=1 216391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.0148992 217391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for channel 13 (2472 MHz) 218391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 1: min_nf=-114 interference_factor=0.0745342 nf=-114 time=161 busy=0 rx=12 219391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 2: min_nf=-114 interference_factor=0.0555556 nf=-114 time=162 busy=0 rx=9 220391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 3: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0 221391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 4: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0 222391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: 5: min_nf=-114 interference_factor=1.58489e-23 nf=-114 time=162 busy=0 rx=0 223391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * interference factor average: 0.0260179 224391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Survey analysis for selected bandwidth 20MHz 225391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 1: total interference = 0.121432 226391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 2: total interference = 0.137512 227391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 3: total interference = 0.369757 228391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 4: total interference = 0.546338 229391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 5: total interference = 0.690538 230391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 6: total interference = 0.762242 231391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 7: total interference = 0.756092 232391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 8: total interference = 0.537451 233391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 9: total interference = 0.332313 234391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 10: total interference = 0.152182 235391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 11: total interference = 0.0916111 236391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 12: total interference = 0.0816809 237391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: * channel 13: total interference = 0.0680776 238391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * ACS: Ideal channel is 13 (2472 MHz) with total interference factor of 0.0680776 239391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 240391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * [1] http://en.wikipedia.org/wiki/Near_and_far_field 241391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt */ 242391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 243391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 244391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic int acs_request_scan(struct hostapd_iface *iface); 2457f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidtstatic int acs_survey_is_sufficient(struct freq_survey *survey); 246391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 247391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 248391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void acs_clean_chan_surveys(struct hostapd_channel_data *chan) 249391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 250391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct freq_survey *survey, *tmp; 251391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 252391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (dl_list_empty(&chan->survey_list)) 253391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return; 254391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 255391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt dl_list_for_each_safe(survey, tmp, &chan->survey_list, 256391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct freq_survey, list) { 257391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt dl_list_del(&survey->list); 258391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt os_free(survey); 259391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 260391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 261391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 262391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 263391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void acs_cleanup(struct hostapd_iface *iface) 264391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 265391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int i; 266391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_channel_data *chan; 267391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 268391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (i = 0; i < iface->current_mode->num_channels; i++) { 269391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan = &iface->current_mode->channels[i]; 270391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 271391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (chan->flag & HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED) 272391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_clean_chan_surveys(chan); 273391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 274391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt dl_list_init(&chan->survey_list); 275391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED; 276391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->min_nf = 0; 277391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 278391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 279391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->chans_surveyed = 0; 280391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->acs_num_completed_scans = 0; 281391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 282391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 283391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 284fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtstatic void acs_fail(struct hostapd_iface *iface) 285391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 286391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Failed to start"); 287391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_cleanup(iface); 2882ac5f6049e74103a8fe8e9c78b330020081d7df4Dmitry Shmidt hostapd_disable_iface(iface); 289391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 290391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 291391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 292391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic long double 293391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtacs_survey_interference_factor(struct freq_survey *survey, s8 min_nf) 294391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 295391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt long double factor, busy, total; 296391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 297391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (survey->filled & SURVEY_HAS_CHAN_TIME_BUSY) 298391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt busy = survey->channel_time_busy; 299391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt else if (survey->filled & SURVEY_HAS_CHAN_TIME_RX) 300391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt busy = survey->channel_time_rx; 301391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt else { 302391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* This shouldn't really happen as survey data is checked in 303391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * acs_sanity_check() */ 304391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Survey data missing"); 305391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 306391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 307391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 308391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt total = survey->channel_time; 309391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 310391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (survey->filled & SURVEY_HAS_CHAN_TIME_TX) { 311391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt busy -= survey->channel_time_tx; 312391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt total -= survey->channel_time_tx; 313391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 314391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 315391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* TODO: figure out the best multiplier for noise floor base */ 316391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt factor = pow(10, survey->nf / 5.0L) + 317391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt (busy / total) * 318391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt pow(2, pow(10, (long double) survey->nf / 10.0L) - 319391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt pow(10, (long double) min_nf / 10.0L)); 320391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 321391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return factor; 322391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 323391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 324391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 325391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void 326391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtacs_survey_chan_interference_factor(struct hostapd_iface *iface, 327391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_channel_data *chan) 328391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 329391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct freq_survey *survey; 330391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt unsigned int i = 0; 331391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt long double int_factor = 0; 3327f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt unsigned count = 0; 333391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 334391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (dl_list_empty(&chan->survey_list)) 335391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return; 336391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 337391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (chan->flag & HOSTAPD_CHAN_DISABLED) 338391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return; 339391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 340391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->interference_factor = 0; 341391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 342391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt dl_list_for_each(survey, &chan->survey_list, struct freq_survey, list) 343391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt { 3447f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt i++; 3457f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 3467f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (!acs_survey_is_sufficient(survey)) { 3477f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: %d: insufficient data", i); 3487f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt continue; 3497f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 3507f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 3517f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt count++; 352391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int_factor = acs_survey_interference_factor(survey, 353391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->lowest_nf); 354391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->interference_factor += int_factor; 355391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: %d: min_nf=%d interference_factor=%Lg nf=%d time=%lu busy=%lu rx=%lu", 3567f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt i, chan->min_nf, int_factor, 357391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt survey->nf, (unsigned long) survey->channel_time, 358391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt (unsigned long) survey->channel_time_busy, 359391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt (unsigned long) survey->channel_time_rx); 360391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 361391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 3627f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (!count) 3637f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return; 3647f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt chan->interference_factor /= count; 365391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 366391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 367391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 368391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic int acs_usable_ht40_chan(struct hostapd_channel_data *chan) 369391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 370391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt const int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 371391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 157, 184, 192 }; 372391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt unsigned int i; 373391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 37468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt for (i = 0; i < ARRAY_SIZE(allowed); i++) 375391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (chan->chan == allowed[i]) 376391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 1; 377391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 378391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 379391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 380391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 381391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 382a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidtstatic int acs_usable_vht80_chan(struct hostapd_channel_data *chan) 383a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt{ 384a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt const int allowed[] = { 36, 52, 100, 116, 132, 149 }; 385a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt unsigned int i; 386a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 387a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt for (i = 0; i < ARRAY_SIZE(allowed); i++) 388a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt if (chan->chan == allowed[i]) 389a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt return 1; 390a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 391a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt return 0; 392a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt} 393a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 394a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 395391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic int acs_survey_is_sufficient(struct freq_survey *survey) 396391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 397391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!(survey->filled & SURVEY_HAS_NF)) { 3987f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_INFO, "ACS: Survey is missing noise floor"); 399391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 400391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 401391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 402391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!(survey->filled & SURVEY_HAS_CHAN_TIME)) { 4037f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_INFO, "ACS: Survey is missing channel time"); 404391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 405391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 406391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 407391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!(survey->filled & SURVEY_HAS_CHAN_TIME_BUSY) && 408391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt !(survey->filled & SURVEY_HAS_CHAN_TIME_RX)) { 4097f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_INFO, 4107f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt "ACS: Survey is missing RX and busy time (at least one is required)"); 411391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 412391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 413391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 414391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 1; 415391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 416391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 417391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 4184ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidtstatic int acs_survey_list_is_sufficient(struct hostapd_channel_data *chan) 4194ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt{ 4204ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt struct freq_survey *survey; 4217f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt int ret = -1; 4224ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 4234ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt dl_list_for_each(survey, &chan->survey_list, struct freq_survey, list) 4244ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt { 4257f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (acs_survey_is_sufficient(survey)) { 4267f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt ret = 1; 4277f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt break; 4284ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt } 4297f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt ret = 0; 4304ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt } 4314ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 4327f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (ret == -1) 4337f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt ret = 1; /* no survey list entries */ 4347f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 4357f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (!ret) { 4367f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_INFO, 4377f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt "ACS: Channel %d has insufficient survey data", 4387f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt chan->chan); 4397f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 4404ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 4417f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return ret; 4424ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt} 4434ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 4444ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 445391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic int acs_surveys_are_sufficient(struct hostapd_iface *iface) 446391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 447391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int i; 448391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_channel_data *chan; 4494ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt int valid = 0; 450391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 451391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (i = 0; i < iface->current_mode->num_channels; i++) { 452391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan = &iface->current_mode->channels[i]; 453391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (chan->flag & HOSTAPD_CHAN_DISABLED) 454391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt continue; 455391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 4564ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt if (!acs_survey_list_is_sufficient(chan)) 4574ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt continue; 4584ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 4594ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt valid++; 460391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 461391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 4624ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt /* We need at least survey data for one channel */ 4634ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt return !!valid; 4644ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt} 4654ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 4664ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 4674ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidtstatic int acs_usable_chan(struct hostapd_channel_data *chan) 4684ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt{ 4694ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt if (dl_list_empty(&chan->survey_list)) 4704ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt return 0; 4714ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt if (chan->flag & HOSTAPD_CHAN_DISABLED) 4724ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt return 0; 4734ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt if (!acs_survey_list_is_sufficient(chan)) 4744ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt return 0; 475391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 1; 476391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 477391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 478391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 4792f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidtstatic int is_in_chanlist(struct hostapd_iface *iface, 4802f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt struct hostapd_channel_data *chan) 4812f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt{ 482dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt if (!iface->conf->acs_ch_list.num) 4832f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt return 1; 4842f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 485dda10c2afb8378747491ea5d329a1de635d6d58eDmitry Shmidt return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan); 4862f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt} 4872f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 4882f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 489391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void acs_survey_all_chans_intereference_factor( 490391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_iface *iface) 491391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 492391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int i; 493391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_channel_data *chan; 494391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 495391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (i = 0; i < iface->current_mode->num_channels; i++) { 496391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan = &iface->current_mode->channels[i]; 497391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 498391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!acs_usable_chan(chan)) 499391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt continue; 500391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 5012f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (!is_in_chanlist(iface, chan)) 5022f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt continue; 5032f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 504391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)", 505391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->chan, chan->freq); 506391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 507391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_survey_chan_interference_factor(iface, chan); 508391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 509391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: * interference factor average: %Lg", 510391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->interference_factor); 511391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 512391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 513391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 514391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 515391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface, 516391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int freq) 517391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 518391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_channel_data *chan; 519391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int i; 520391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 521391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (i = 0; i < iface->current_mode->num_channels; i++) { 522391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan = &iface->current_mode->channels[i]; 523391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 5244ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt if (chan->flag & HOSTAPD_CHAN_DISABLED) 525391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt continue; 526391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 527391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (chan->freq == freq) 528391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return chan; 529391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 530391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 531391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return NULL; 532391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 533391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 534391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 5357f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidtstatic int is_24ghz_mode(enum hostapd_hw_mode mode) 5367f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt{ 5377f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return mode == HOSTAPD_MODE_IEEE80211B || 5387f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt mode == HOSTAPD_MODE_IEEE80211G; 5397f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt} 5407f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 5417f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 5427f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidtstatic int is_common_24ghz_chan(int chan) 5437f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt{ 5447f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt return chan == 1 || chan == 6 || chan == 11; 5457f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt} 5467f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 5477f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 5487f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#ifndef ACS_ADJ_WEIGHT 5497f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#define ACS_ADJ_WEIGHT 0.85 5507f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#endif /* ACS_ADJ_WEIGHT */ 5517f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 5527f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#ifndef ACS_NEXT_ADJ_WEIGHT 5537f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#define ACS_NEXT_ADJ_WEIGHT 0.55 5547f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#endif /* ACS_NEXT_ADJ_WEIGHT */ 5557f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 5567f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#ifndef ACS_24GHZ_PREFER_1_6_11 5577f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt/* 5587f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * Select commonly used channels 1, 6, 11 by default even if a neighboring 5597f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * channel has a smaller interference factor as long as it is not better by more 5607f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt * than this multiplier. 5617f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt */ 5627f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#define ACS_24GHZ_PREFER_1_6_11 0.8 5637f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt#endif /* ACS_24GHZ_PREFER_1_6_11 */ 5647f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 565391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt/* 566391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * At this point it's assumed chan->interface_factor has been computed. 567391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * This function should be reusable regardless of interference computation 568391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * option (survey, BSS, spectral, ...). chan->interference factor must be 569391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * summable (i.e., must be always greater than zero). 570391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt */ 571391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic struct hostapd_channel_data * 572391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtacs_find_ideal_chan(struct hostapd_iface *iface) 573391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 5744ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt struct hostapd_channel_data *chan, *adj_chan, *ideal_chan = NULL, 5754ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt *rand_chan = NULL; 576391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt long double factor, ideal_factor = 0; 577391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int i, j; 578391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int n_chans = 1; 5797f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt unsigned int k; 580391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 581391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* TODO: HT40- support */ 582391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 583391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (iface->conf->ieee80211n && 584391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->secondary_channel == -1) { 585391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+"); 586391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return NULL; 587391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 588391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 589391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (iface->conf->ieee80211n && 590391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->secondary_channel) 591391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt n_chans = 2; 592391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 593391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (iface->conf->ieee80211ac && 594391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->vht_oper_chwidth == 1) 595391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt n_chans = 4; 596391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 597391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* TODO: VHT80+80, VHT160. Update acs_adjust_vht_center_freq() too. */ 598391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 599391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Survey analysis for selected bandwidth %d MHz", 600391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt n_chans == 1 ? 20 : 601391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt n_chans == 2 ? 40 : 602de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt 80); 603391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 604391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (i = 0; i < iface->current_mode->num_channels; i++) { 6057f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt double total_weight; 6067f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt struct acs_bias *bias, tmp_bias; 6077f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 608391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan = &iface->current_mode->channels[i]; 609391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 6104ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt if (chan->flag & HOSTAPD_CHAN_DISABLED) 611391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt continue; 612391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 6132f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (!is_in_chanlist(iface, chan)) 6142f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt continue; 6154ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 616391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* HT40 on 5 GHz has a limited set of primary channels as per 617391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 11n Annex J */ 618391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A && 619391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->ieee80211n && 620391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->secondary_channel && 621391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt !acs_usable_ht40_chan(chan)) { 622391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Channel %d: not allowed as primary channel for HT40", 623391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->chan); 624391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt continue; 625391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 626391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 627a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A && 628a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt iface->conf->ieee80211ac && 629a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt iface->conf->vht_oper_chwidth == 1 && 630a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt !acs_usable_vht80_chan(chan)) { 631a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Channel %d: not allowed as primary channel for VHT80", 632a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt chan->chan); 633a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt continue; 634a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt } 635a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 6364ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt factor = 0; 6374ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt if (acs_usable_chan(chan)) 6384ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt factor = chan->interference_factor; 6397f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt total_weight = 1; 640391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 641391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (j = 1; j < n_chans; j++) { 642391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt adj_chan = acs_find_chan(iface, chan->freq + (j * 20)); 643391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!adj_chan) 644391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt break; 645391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 6467f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (acs_usable_chan(adj_chan)) { 6474ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt factor += adj_chan->interference_factor; 6487f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt total_weight += 1; 6497f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 650391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 651391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 652391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (j != n_chans) { 653391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Channel %d: not enough bandwidth", 654391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan->chan); 655391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt continue; 656391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 657391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 658391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* 2.4 GHz has overlapping 20 MHz channels. Include adjacent 659391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * channel interference factor. */ 6607f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (is_24ghz_mode(iface->current_mode->mode)) { 661391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (j = 0; j < n_chans; j++) { 662391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt adj_chan = acs_find_chan(iface, chan->freq + 663391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt (j * 20) - 5); 6647f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (adj_chan && acs_usable_chan(adj_chan)) { 6657f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt factor += ACS_ADJ_WEIGHT * 6667f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt adj_chan->interference_factor; 6677f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt total_weight += ACS_ADJ_WEIGHT; 6687f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 669391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 670391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt adj_chan = acs_find_chan(iface, chan->freq + 671391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt (j * 20) - 10); 6727f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (adj_chan && acs_usable_chan(adj_chan)) { 6737f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt factor += ACS_NEXT_ADJ_WEIGHT * 6747f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt adj_chan->interference_factor; 6757f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt total_weight += ACS_NEXT_ADJ_WEIGHT; 6767f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 677391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 678391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt adj_chan = acs_find_chan(iface, chan->freq + 679391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt (j * 20) + 5); 6807f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (adj_chan && acs_usable_chan(adj_chan)) { 6817f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt factor += ACS_ADJ_WEIGHT * 6827f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt adj_chan->interference_factor; 6837f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt total_weight += ACS_ADJ_WEIGHT; 6847f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 685391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 686391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt adj_chan = acs_find_chan(iface, chan->freq + 687391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt (j * 20) + 10); 6887f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (adj_chan && acs_usable_chan(adj_chan)) { 6897f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt factor += ACS_NEXT_ADJ_WEIGHT * 6907f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt adj_chan->interference_factor; 6917f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt total_weight += ACS_NEXT_ADJ_WEIGHT; 6927f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 6937f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 6947f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 6957f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 6967f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt factor /= total_weight; 6977f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt 6987f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt bias = NULL; 6997f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (iface->conf->acs_chan_bias) { 7007f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt for (k = 0; k < iface->conf->num_acs_chan_bias; k++) { 7017f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt bias = &iface->conf->acs_chan_bias[k]; 7027f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (bias->channel == chan->chan) 7037f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt break; 7047f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt bias = NULL; 705391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 7067f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } else if (is_24ghz_mode(iface->current_mode->mode) && 7077f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt is_common_24ghz_chan(chan->chan)) { 7087f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt tmp_bias.channel = chan->chan; 7097f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt tmp_bias.bias = ACS_24GHZ_PREFER_1_6_11; 7107f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt bias = &tmp_bias; 711391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 712391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 7137f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt if (bias) { 7147f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt factor *= bias->bias; 7157f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, 7167f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt "ACS: * channel %d: total interference = %Lg (%f bias)", 7177f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt chan->chan, factor, bias->bias); 7187f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } else { 7197f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt wpa_printf(MSG_DEBUG, 7207f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt "ACS: * channel %d: total interference = %Lg", 7217f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt chan->chan, factor); 7227f65602d49069f96a7bb44da8bd79ffe8d4c6a98Dmitry Shmidt } 723391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 7244ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt if (acs_usable_chan(chan) && 7254ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt (!ideal_chan || factor < ideal_factor)) { 726391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt ideal_factor = factor; 727391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt ideal_chan = chan; 728391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 7294ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 7304ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt /* This channel would at least be usable */ 7314ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt if (!rand_chan) 7324ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt rand_chan = chan; 733391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 734391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 7354ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt if (ideal_chan) { 736391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg", 737391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt ideal_chan->chan, ideal_chan->freq, ideal_factor); 7384ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt return ideal_chan; 7394ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt } 740391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 7414ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt return rand_chan; 742391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 743391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 744391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 745391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void acs_adjust_vht_center_freq(struct hostapd_iface *iface) 746391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 747b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt int offset; 748b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 749391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Adjusting VHT center frequency"); 750391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 751391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt switch (iface->conf->vht_oper_chwidth) { 752391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case VHT_CHANWIDTH_USE_HT: 753b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt offset = 2 * iface->conf->secondary_channel; 754391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt break; 755391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case VHT_CHANWIDTH_80MHZ: 756b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt offset = 6; 757391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt break; 758391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt default: 759391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* TODO: How can this be calculated? Adjust 760391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * acs_find_ideal_chan() */ 761391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_INFO, "ACS: Only VHT20/40/80 is supported now"); 762b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt return; 763391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 764b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt 765b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg0_idx = 766b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt iface->conf->channel + offset; 767391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 768391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 769391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 770391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic int acs_study_survey_based(struct hostapd_iface *iface) 771391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 772391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Trying survey-based ACS"); 773391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 774391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!iface->chans_surveyed) { 775391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Unable to collect survey data"); 776391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return -1; 777391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 778391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 779391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!acs_surveys_are_sufficient(iface)) { 780391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Surveys have insufficient data"); 781391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return -1; 782391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 783391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 784391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_survey_all_chans_intereference_factor(iface); 785391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 786391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 787391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 788391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 789391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic int acs_study_options(struct hostapd_iface *iface) 790391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 791391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int err; 792391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 793391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt err = acs_study_survey_based(iface); 794391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (err == 0) 795391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 796391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 797391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* TODO: If no surveys are available/sufficient this is a good 798391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * place to fallback to BSS-based ACS */ 799391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 800391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return -1; 801391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 802391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 803391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 804391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void acs_study(struct hostapd_iface *iface) 805391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 806391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_channel_data *ideal_chan; 807391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int err; 808391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 809391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt err = acs_study_options(iface); 810391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (err < 0) { 811391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: All study options have failed"); 812391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt goto fail; 813391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 814391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 815391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt ideal_chan = acs_find_ideal_chan(iface); 816391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (!ideal_chan) { 817391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Failed to compute ideal channel"); 8184ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt err = -1; 819391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt goto fail; 820391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 821391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 822391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->channel = ideal_chan->chan; 823391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 824391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (iface->conf->ieee80211ac) 825391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_adjust_vht_center_freq(iface); 826391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 8274ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt err = 0; 8284ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidtfail: 829391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt /* 830391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * hostapd_setup_interface_complete() will return -1 on failure, 831391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * 0 on success and 0 is HOSTAPD_CHAN_VALID :) 832391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt */ 8334ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt if (hostapd_acs_completed(iface, err) == HOSTAPD_CHAN_VALID) { 834391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_cleanup(iface); 835391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return; 836391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 837391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 8384ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt /* This can possibly happen if channel parameters (secondary 8394ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt * channel, center frequencies) are misconfigured */ 8404ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Possibly channel configuration is invalid, please report this along with your config file."); 841391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_fail(iface); 842391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 843391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 844391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 845391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic void acs_scan_complete(struct hostapd_iface *iface) 846391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 847391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int err; 848391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 849391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->scan_cb = NULL; 850391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 851391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Using survey based algorithm (acs_num_scans=%d)", 852391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->acs_num_scans); 853391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 854391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt err = hostapd_drv_get_survey(iface->bss[0], 0); 855391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (err) { 856391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Failed to get survey data"); 85715907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt goto fail; 858391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 859391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 860391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (++iface->acs_num_completed_scans < iface->conf->acs_num_scans) { 861391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt err = acs_request_scan(iface); 862391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (err) { 863391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Failed to request scan"); 864cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt goto fail; 865391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 866391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 867391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return; 868391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 869391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 870391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_study(iface); 871cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt return; 872cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtfail: 873cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt hostapd_acs_completed(iface, 1); 874cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt acs_fail(iface); 875391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 876391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 877391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 878391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtstatic int acs_request_scan(struct hostapd_iface *iface) 879391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 880391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct wpa_driver_scan_params params; 881391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt struct hostapd_channel_data *chan; 882391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int i, *freq; 883391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 884391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt os_memset(¶ms, 0, sizeof(params)); 885391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt params.freqs = os_calloc(iface->current_mode->num_channels + 1, 886391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt sizeof(params.freqs[0])); 887391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (params.freqs == NULL) 888391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return -1; 889391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 890391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt freq = params.freqs; 891391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt for (i = 0; i < iface->current_mode->num_channels; i++) { 892391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt chan = &iface->current_mode->channels[i]; 893391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (chan->flag & HOSTAPD_CHAN_DISABLED) 894391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt continue; 895391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 8968bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt if (!is_in_chanlist(iface, chan)) 8978bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt continue; 8988bd70b7d6ba220544ee2f0e201e5df23e277fa1dDmitry Shmidt 899391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt *freq++ = chan->freq; 900391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 901391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt *freq = 0; 902391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 903391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->scan_cb = acs_scan_complete; 904391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 905391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d", 906391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->acs_num_completed_scans + 1, 907391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt iface->conf->acs_num_scans); 908391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 909391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (hostapd_driver_scan(iface->bss[0], ¶ms) < 0) { 910391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS: Failed to request initial scan"); 911391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_cleanup(iface); 91215907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt os_free(params.freqs); 913391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return -1; 914391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 915391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 916391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt os_free(params.freqs); 917391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 918391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 919391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 920391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 921391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidtenum hostapd_chan_status acs_init(struct hostapd_iface *iface) 922391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 923391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt int err; 924391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 925391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_INFO, "ACS: Automatic channel selection started, this may take a bit"); 926391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 9276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) { 9286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_INFO, "ACS: Offloading to driver"); 9296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt err = hostapd_drv_do_acs(iface->bss[0]); 9306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (err) 9316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return HOSTAPD_CHAN_INVALID; 9326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return HOSTAPD_CHAN_ACS; 9336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 9346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt 935de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt if (!iface->current_mode) 936de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt return HOSTAPD_CHAN_INVALID; 937de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt 938391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt acs_cleanup(iface); 939391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 940391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt err = acs_request_scan(iface); 941391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (err < 0) 942391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return HOSTAPD_CHAN_INVALID; 943391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 944cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt hostapd_set_state(iface, HAPD_IFACE_ACS); 945cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_STARTED); 946cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 947391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return HOSTAPD_CHAN_ACS; 948391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 949