dfs.c revision 9866086a955d00e237cc8df3722e7dff75c02532
1051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt/* 2051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * DFS - Dynamic Frequency Selection 3051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> 4051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * Copyright (c) 2013, Qualcomm Atheros, Inc. 5051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * 6051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 7051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * See README for more details. 8051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt */ 9051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 10051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#include "utils/includes.h" 11051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 12051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#include "utils/common.h" 13051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#include "common/ieee802_11_defs.h" 14cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#include "common/wpa_ctrl.h" 15051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#include "hostapd.h" 16051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#include "ap_drv_ops.h" 17051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#include "drivers/driver.h" 18051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#include "dfs.h" 19051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 20051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 21cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtstatic int dfs_get_used_n_chans(struct hostapd_iface *iface) 22051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 23051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int n_chans = 1; 24051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 25cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (iface->conf->ieee80211n && iface->conf->secondary_channel) 26051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt n_chans = 2; 27051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 28cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (iface->conf->ieee80211ac) { 29cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt switch (iface->conf->vht_oper_chwidth) { 30051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case VHT_CHANWIDTH_USE_HT: 31051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 32051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case VHT_CHANWIDTH_80MHZ: 33051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt n_chans = 4; 34051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 35051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case VHT_CHANWIDTH_160MHZ: 36051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt n_chans = 8; 37051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 38051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt default: 39051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 40051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 41051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 42051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 43051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return n_chans; 44051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 45051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 46051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 4704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidtstatic int dfs_channel_available(struct hostapd_channel_data *chan, 4804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt int skip_radar) 49051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 5004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt /* 5104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt * When radar detection happens, CSA is performed. However, there's no 5204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt * time for CAC, so radar channels must be skipped when finding a new 539866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt * channel for CSA, unless they are available for immediate use. 5404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt */ 559866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (skip_radar && (chan->flag & HOSTAPD_CHAN_RADAR) && 569866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt ((chan->flag & HOSTAPD_CHAN_DFS_MASK) != 579866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt HOSTAPD_CHAN_DFS_AVAILABLE)) 5804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return 0; 5904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 60051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (chan->flag & HOSTAPD_CHAN_DISABLED) 61051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 62051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if ((chan->flag & HOSTAPD_CHAN_RADAR) && 63051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt ((chan->flag & HOSTAPD_CHAN_DFS_MASK) == 64051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt HOSTAPD_CHAN_DFS_UNAVAILABLE)) 65051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 66051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 1; 67051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 68051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 69051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 7068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidtstatic int dfs_is_chan_allowed(struct hostapd_channel_data *chan, int n_chans) 71051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 7268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt /* 7368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt * The tables contain first valid channel number based on channel width. 7468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt * We will also choose this first channel as the control one. 7568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt */ 7668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt int allowed_40[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, 7768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 184, 192 }; 7868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt /* 7968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt * VHT80, valid channels based on center frequency: 8068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt * 42, 58, 106, 122, 138, 155 8168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt */ 8268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt int allowed_80[] = { 36, 52, 100, 116, 132, 149 }; 83f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* 84f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt * VHT160 valid channels based on center frequency: 85f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt * 50, 114 86f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt */ 87f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int allowed_160[] = { 36, 100 }; 8868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt int *allowed = allowed_40; 8968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt unsigned int i, allowed_no = 0; 9068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 9168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt switch (n_chans) { 9268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt case 2: 9368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt allowed = allowed_40; 9468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt allowed_no = ARRAY_SIZE(allowed_40); 9568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt break; 9668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt case 4: 9768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt allowed = allowed_80; 9868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt allowed_no = ARRAY_SIZE(allowed_80); 9968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt break; 100f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt case 8: 101f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt allowed = allowed_160; 102f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt allowed_no = ARRAY_SIZE(allowed_160); 103f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt break; 10468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt default: 10568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_printf(MSG_DEBUG, "Unknown width for %d channels", n_chans); 10668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt break; 10768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 108051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 10968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt for (i = 0; i < allowed_no; i++) { 110051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (chan->chan == allowed[i]) 111051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 1; 112051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 113051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 114051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 115051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 116051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 117051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 118cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtstatic int dfs_chan_range_available(struct hostapd_hw_modes *mode, 11904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt int first_chan_idx, int num_chans, 12004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt int skip_radar) 121cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt{ 122cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt struct hostapd_channel_data *first_chan, *chan; 123cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int i; 124cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 125cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (first_chan_idx + num_chans >= mode->num_channels) 126cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt return 0; 127cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 128cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt first_chan = &mode->channels[first_chan_idx]; 129cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 130cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt for (i = 0; i < num_chans; i++) { 131cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt chan = &mode->channels[first_chan_idx + i]; 132cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 133cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (first_chan->freq + i * 20 != chan->freq) 134cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt return 0; 135cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 13604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt if (!dfs_channel_available(chan, skip_radar)) 137cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt return 0; 138cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt } 139cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 140cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt return 1; 141cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt} 142cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 143cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 1449866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidtstatic int is_in_chanlist(struct hostapd_iface *iface, 1459866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt struct hostapd_channel_data *chan) 1469866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt{ 1479866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt int *entry; 1489866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 1499866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (!iface->conf->chanlist) 1509866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt return 1; 1519866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 1529866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt for (entry = iface->conf->chanlist; *entry != -1; entry++) { 1539866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (*entry == chan->chan) 1549866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt return 1; 1559866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt } 1569866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt return 0; 1579866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt} 1589866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 1599866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 160cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt/* 161cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt * The function assumes HT40+ operation. 162cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt * Make sure to adjust the following variables after calling this: 163cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt * - hapd->secondary_channel 164cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt * - hapd->vht_oper_centr_freq_seg0_idx 165cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt * - hapd->vht_oper_centr_freq_seg1_idx 166cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt */ 167cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtstatic int dfs_find_channel(struct hostapd_iface *iface, 168051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_channel_data **ret_chan, 16904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt int idx, int skip_radar) 170051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 171051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_hw_modes *mode; 172cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt struct hostapd_channel_data *chan; 173cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int i, channel_idx = 0, n_chans; 174051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 175cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt mode = iface->current_mode; 176cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt n_chans = dfs_get_used_n_chans(iface); 177051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 178051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "DFS new chan checking %d channels", n_chans); 179051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt for (i = 0; i < mode->num_channels; i++) { 180051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt chan = &mode->channels[i]; 181051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 182cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt /* Skip HT40/VHT incompatible channels */ 183cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (iface->conf->ieee80211n && 184cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->conf->secondary_channel && 185cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt !dfs_is_chan_allowed(chan, n_chans)) 186051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt continue; 187051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 188cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt /* Skip incompatible chandefs */ 18904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt if (!dfs_chan_range_available(mode, i, n_chans, skip_radar)) 190cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt continue; 191051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1929866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (!is_in_chanlist(iface, chan)) 1939866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt continue; 1949866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 195051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (ret_chan && idx == channel_idx) { 196051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Selected ch. #%d", chan->chan); 197051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt *ret_chan = chan; 198051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return idx; 199051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 200051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "Adding channel: %d", chan->chan); 201051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt channel_idx++; 202051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 203051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return channel_idx; 204051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 205051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 206051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 207cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtstatic void dfs_adjust_vht_center_freq(struct hostapd_iface *iface, 208cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt struct hostapd_channel_data *chan, 209344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt int secondary_channel, 210cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt u8 *vht_oper_centr_freq_seg0_idx, 211cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt u8 *vht_oper_centr_freq_seg1_idx) 212051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 213cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (!iface->conf->ieee80211ac) 214051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return; 215051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 216051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (!chan) 217051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return; 218051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 219cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt *vht_oper_centr_freq_seg1_idx = 0; 220cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 221cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt switch (iface->conf->vht_oper_chwidth) { 222051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case VHT_CHANWIDTH_USE_HT: 223344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (secondary_channel == 1) 224cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt *vht_oper_centr_freq_seg0_idx = chan->chan + 2; 225344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt else if (secondary_channel == -1) 226cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt *vht_oper_centr_freq_seg0_idx = chan->chan - 2; 22768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt else 228cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt *vht_oper_centr_freq_seg0_idx = chan->chan; 229051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 230051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case VHT_CHANWIDTH_80MHZ: 231cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt *vht_oper_centr_freq_seg0_idx = chan->chan + 6; 232051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 233051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case VHT_CHANWIDTH_160MHZ: 234cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt *vht_oper_centr_freq_seg0_idx = chan->chan + 14; 23568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt break; 236051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt default: 237051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_INFO, "DFS only VHT20/40/80/160 is supported now"); 2387d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt *vht_oper_centr_freq_seg0_idx = 0; 239051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 240051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 241051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 242cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_DEBUG, "DFS adjusting VHT center frequency: %d, %d", 243cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt *vht_oper_centr_freq_seg0_idx, 244cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt *vht_oper_centr_freq_seg1_idx); 245051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 246051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 247051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 248051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt/* Return start channel idx we will use for mode->channels[idx] */ 249cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtstatic int dfs_get_start_chan_idx(struct hostapd_iface *iface) 250051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 251051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_hw_modes *mode; 252051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_channel_data *chan; 253cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int channel_no = iface->conf->channel; 254051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int res = -1, i; 255051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 256051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* HT40- */ 257cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (iface->conf->ieee80211n && iface->conf->secondary_channel == -1) 258051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt channel_no -= 4; 259051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 260051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* VHT */ 261cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (iface->conf->ieee80211ac) { 262cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt switch (iface->conf->vht_oper_chwidth) { 263051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case VHT_CHANWIDTH_USE_HT: 264051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 265051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case VHT_CHANWIDTH_80MHZ: 266051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt channel_no = 267cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg0_idx - 6; 268051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 269051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case VHT_CHANWIDTH_160MHZ: 270051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt channel_no = 271cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg0_idx - 14; 272051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 273051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt default: 274051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_INFO, 275051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt "DFS only VHT20/40/80/160 is supported now"); 276051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt channel_no = -1; 277051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 278051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 279051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 280051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 281051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* Get idx */ 282cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt mode = iface->current_mode; 283051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt for (i = 0; i < mode->num_channels; i++) { 284051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt chan = &mode->channels[i]; 285051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (chan->chan == channel_no) { 286051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt res = i; 287051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 288051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 289051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 290051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 2919866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (res == -1) { 2929866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_printf(MSG_DEBUG, 2939866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt "DFS chan_idx seems wrong; num-ch: %d ch-no: %d conf-ch-no: %d 11n: %d sec-ch: %d vht-oper-width: %d", 2949866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt mode->num_channels, channel_no, iface->conf->channel, 2959866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt iface->conf->ieee80211n, 2969866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt iface->conf->secondary_channel, 2979866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt iface->conf->vht_oper_chwidth); 2989866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 2999866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt for (i = 0; i < mode->num_channels; i++) { 3009866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt wpa_printf(MSG_DEBUG, "Available channel: %d", 3019866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt mode->channels[i].chan); 3029866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt } 3039866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt } 304051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 305051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return res; 306051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 307051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 308051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 309051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt/* At least one channel have radar flag */ 310cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtstatic int dfs_check_chans_radar(struct hostapd_iface *iface, 311cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int start_chan_idx, int n_chans) 312051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 313051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_channel_data *channel; 314051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_hw_modes *mode; 315051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int i, res = 0; 316051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 317cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt mode = iface->current_mode; 318051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 319051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt for (i = 0; i < n_chans; i++) { 320051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt channel = &mode->channels[start_chan_idx + i]; 321051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (channel->flag & HOSTAPD_CHAN_RADAR) 322051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt res++; 323051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 324051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 325051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return res; 326051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 327051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 328051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 329051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt/* All channels available */ 330cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtstatic int dfs_check_chans_available(struct hostapd_iface *iface, 331051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int start_chan_idx, int n_chans) 332051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 333051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_channel_data *channel; 334051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_hw_modes *mode; 335051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int i; 336051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 337cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt mode = iface->current_mode; 338051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 339f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (i = 0; i < n_chans; i++) { 340051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt channel = &mode->channels[start_chan_idx + i]; 341f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 342f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (channel->flag & HOSTAPD_CHAN_DISABLED) 343f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt break; 344f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 345f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!(channel->flag & HOSTAPD_CHAN_RADAR)) 346f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt continue; 347f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 348051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if ((channel->flag & HOSTAPD_CHAN_DFS_MASK) != 349051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt HOSTAPD_CHAN_DFS_AVAILABLE) 350051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 351051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 352051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 353051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return i == n_chans; 354051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 355051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 356051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 357051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt/* At least one channel unavailable */ 358cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtstatic int dfs_check_chans_unavailable(struct hostapd_iface *iface, 359051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int start_chan_idx, 360051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int n_chans) 361051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 362051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_channel_data *channel; 363051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_hw_modes *mode; 364051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int i, res = 0; 365051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 366cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt mode = iface->current_mode; 367051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 368f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt for (i = 0; i < n_chans; i++) { 369051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt channel = &mode->channels[start_chan_idx + i]; 370051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (channel->flag & HOSTAPD_CHAN_DISABLED) 371051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt res++; 372051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if ((channel->flag & HOSTAPD_CHAN_DFS_MASK) == 373051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt HOSTAPD_CHAN_DFS_UNAVAILABLE) 374051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt res++; 375051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 376051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 377051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return res; 378051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 379051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 380051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 381cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtstatic struct hostapd_channel_data * 382cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtdfs_get_valid_channel(struct hostapd_iface *iface, 383cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int *secondary_channel, 384cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt u8 *vht_oper_centr_freq_seg0_idx, 38504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt u8 *vht_oper_centr_freq_seg1_idx, 38604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt int skip_radar) 387051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 388051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_hw_modes *mode; 389051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_channel_data *chan = NULL; 390cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int num_available_chandefs; 391cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int chan_idx; 392051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt u32 _rand; 393051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 394051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "DFS: Selecting random channel"); 3957d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt *secondary_channel = 0; 3967d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt *vht_oper_centr_freq_seg0_idx = 0; 3977d5c8f257a74ac0d12828962a492e8b84ef83923Dmitry Shmidt *vht_oper_centr_freq_seg1_idx = 0; 398051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 399cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (iface->current_mode == NULL) 400051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return NULL; 401051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 402cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt mode = iface->current_mode; 403051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (mode->mode != HOSTAPD_MODE_IEEE80211A) 404051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return NULL; 405051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 406cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt /* Get the count first */ 40704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt num_available_chandefs = dfs_find_channel(iface, NULL, 0, skip_radar); 408cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (num_available_chandefs == 0) 409cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt return NULL; 410051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 411cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt os_get_random((u8 *) &_rand, sizeof(_rand)); 412cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt chan_idx = _rand % num_available_chandefs; 41304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt dfs_find_channel(iface, &chan, chan_idx, skip_radar); 414cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 415cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt /* dfs_find_channel() calculations assume HT40+ */ 416cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (iface->conf->secondary_channel) 417cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt *secondary_channel = 1; 418cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt else 419cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt *secondary_channel = 0; 420cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 421cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt dfs_adjust_vht_center_freq(iface, chan, 422344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt *secondary_channel, 423cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt vht_oper_centr_freq_seg0_idx, 424cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt vht_oper_centr_freq_seg1_idx); 425051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 426051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return chan; 427051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 428051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 429051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 430cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtstatic int set_dfs_state_freq(struct hostapd_iface *iface, int freq, u32 state) 431051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 432051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_hw_modes *mode; 433051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_channel_data *chan = NULL; 434051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int i; 435051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 436cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt mode = iface->current_mode; 437051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (mode == NULL) 438051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 439051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 440051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "set_dfs_state 0x%X for %d MHz", state, freq); 441cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt for (i = 0; i < iface->current_mode->num_channels; i++) { 442cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt chan = &iface->current_mode->channels[i]; 443051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (chan->freq == freq) { 444051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (chan->flag & HOSTAPD_CHAN_RADAR) { 445051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt chan->flag &= ~HOSTAPD_CHAN_DFS_MASK; 446051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt chan->flag |= state; 447051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 1; /* Channel found */ 448051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 449051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 450051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 451051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_WARNING, "Can't set DFS state for freq %d MHz", freq); 452051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 453051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 454051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 455051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 456cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtstatic int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled, 457051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int chan_offset, int chan_width, int cf1, 458051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int cf2, u32 state) 459051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 460051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int n_chans = 1, i; 461051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_hw_modes *mode; 462051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int frequency = freq; 463051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int ret = 0; 464051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 465cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt mode = iface->current_mode; 466051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (mode == NULL) 467051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 468051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 469051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (mode->mode != HOSTAPD_MODE_IEEE80211A) { 470051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_WARNING, "current_mode != IEEE80211A"); 471051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 472051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 473051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 474051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* Seems cf1 and chan_width is enough here */ 475051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt switch (chan_width) { 476051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case CHAN_WIDTH_20_NOHT: 477051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case CHAN_WIDTH_20: 478051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt n_chans = 1; 479cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (frequency == 0) 480cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt frequency = cf1; 481051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 482051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case CHAN_WIDTH_40: 483051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt n_chans = 2; 484051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt frequency = cf1 - 10; 485051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 486051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case CHAN_WIDTH_80: 487051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt n_chans = 4; 488051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt frequency = cf1 - 30; 489051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 490051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case CHAN_WIDTH_160: 491051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt n_chans = 8; 492051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt frequency = cf1 - 70; 493051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 494051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt default: 495051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_INFO, "DFS chan_width %d not supported", 496051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt chan_width); 497051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 498051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 499051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 500051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "DFS freq: %dMHz, n_chans: %d", frequency, 501051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt n_chans); 502051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt for (i = 0; i < n_chans; i++) { 503cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt ret += set_dfs_state_freq(iface, frequency, state); 504051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt frequency = frequency + 20; 505051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 506051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 507051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return ret; 508051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 509051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 510051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 511cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtstatic int dfs_are_channels_overlapped(struct hostapd_iface *iface, int freq, 512051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int chan_width, int cf1, int cf2) 513051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 514051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int start_chan_idx; 515051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_hw_modes *mode; 516051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_channel_data *chan; 517051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int n_chans, i, j, frequency = freq, radar_n_chans = 1; 518051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt u8 radar_chan; 519051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int res = 0; 520051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 521051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* Our configuration */ 522cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt mode = iface->current_mode; 523cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt start_chan_idx = dfs_get_start_chan_idx(iface); 524cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt n_chans = dfs_get_used_n_chans(iface); 525051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 52668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt /* Check we are on DFS channel(s) */ 527cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (!dfs_check_chans_radar(iface, start_chan_idx, n_chans)) 52868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return 0; 52968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 530051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* Reported via radar event */ 531051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt switch (chan_width) { 532051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case CHAN_WIDTH_20_NOHT: 533051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case CHAN_WIDTH_20: 534051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt radar_n_chans = 1; 535cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (frequency == 0) 536cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt frequency = cf1; 537051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 538051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case CHAN_WIDTH_40: 539051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt radar_n_chans = 2; 540051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt frequency = cf1 - 10; 541051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 542051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case CHAN_WIDTH_80: 543051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt radar_n_chans = 4; 544051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt frequency = cf1 - 30; 545051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 546051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case CHAN_WIDTH_160: 547051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt radar_n_chans = 8; 548051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt frequency = cf1 - 70; 549051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 550051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt default: 551051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_INFO, "DFS chan_width %d not supported", 552051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt chan_width); 553051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 554051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 555051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 556051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt ieee80211_freq_to_chan(frequency, &radar_chan); 557051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 558051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt for (i = 0; i < n_chans; i++) { 559051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt chan = &mode->channels[start_chan_idx + i]; 56068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (!(chan->flag & HOSTAPD_CHAN_RADAR)) 56168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt continue; 562051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt for (j = 0; j < radar_n_chans; j++) { 563051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "checking our: %d, radar: %d", 564051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt chan->chan, radar_chan + j * 4); 565051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (chan->chan == radar_chan + j * 4) 566051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt res++; 567051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 568051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 569051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 570051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "overlapped: %d", res); 571051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 572051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return res; 573051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 574051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 575051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 576051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt/* 577051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * Main DFS handler 578051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * 1 - continue channel/ap setup 579051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * 0 - channel/ap setup will be continued after CAC 580051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * -1 - hit critical error 581051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt */ 582cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtint hostapd_handle_dfs(struct hostapd_iface *iface) 583051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 584051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_channel_data *channel; 585051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int res, n_chans, start_chan_idx; 58604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt int skip_radar = 0; 587051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 588cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->cac_started = 0; 589cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 590051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt do { 591051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* Get start (first) channel for current configuration */ 592cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt start_chan_idx = dfs_get_start_chan_idx(iface); 593051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (start_chan_idx == -1) 594051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return -1; 595051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 596051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* Get number of used channels, depend on width */ 597cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt n_chans = dfs_get_used_n_chans(iface); 598051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 599051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* Check if any of configured channels require DFS */ 600cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt res = dfs_check_chans_radar(iface, start_chan_idx, n_chans); 601051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, 602051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt "DFS %d channels required radar detection", 603051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt res); 604051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (!res) 605051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 1; 606051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 607051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* Check if all channels are DFS available */ 608cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt res = dfs_check_chans_available(iface, start_chan_idx, n_chans); 609051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, 610051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt "DFS all channels available, (SKIP CAC): %s", 611051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt res ? "yes" : "no"); 612051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (res) 613051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 1; 614051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 615051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* Check if any of configured channels is unavailable */ 616cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt res = dfs_check_chans_unavailable(iface, start_chan_idx, 617051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt n_chans); 618051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_DEBUG, "DFS %d chans unavailable - choose other channel: %s", 619051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt res, res ? "yes": "no"); 620051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (res) { 62196be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt int sec = 0; 62296be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt u8 cf1 = 0, cf2 = 0; 623cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 62404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2, 62504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt skip_radar); 626051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (!channel) { 627051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt wpa_printf(MSG_ERROR, "could not get valid channel"); 628051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return -1; 629051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 630cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 631cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->freq = channel->freq; 632cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->conf->channel = channel->chan; 633cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->conf->secondary_channel = sec; 634cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg0_idx = cf1; 635cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg1_idx = cf2; 636051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 637051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } while (res); 638051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 639051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* Finally start CAC */ 640cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt hostapd_set_state(iface, HAPD_IFACE_DFS); 641cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz", iface->freq); 642cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START 643a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt "freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d", 644cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->freq, 645a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt iface->conf->channel, iface->conf->secondary_channel, 646a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt iface->conf->vht_oper_chwidth, 647a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg0_idx, 648a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg1_idx); 649a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 650a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt res = hostapd_start_dfs_cac(iface, iface->conf->hw_mode, 651a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt iface->freq, 652a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt iface->conf->channel, 653a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt iface->conf->ieee80211n, 654a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt iface->conf->ieee80211ac, 655a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt iface->conf->secondary_channel, 656a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt iface->conf->vht_oper_chwidth, 657a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg0_idx, 658a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg1_idx); 659a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt 660a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt if (res) { 661a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res); 662051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return -1; 663051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 664051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 665051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 666051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 667051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 668051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 669cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtint hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq, 670051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int ht_enabled, int chan_offset, int chan_width, 671051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int cf1, int cf2) 672051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 673cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_COMPLETED 674cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt "success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", 675cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2); 676cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 677051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (success) { 678051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* Complete iface/ap configuration */ 679cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt set_dfs_state(iface, freq, ht_enabled, chan_offset, 680051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt chan_width, cf1, cf2, 681051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt HOSTAPD_CHAN_DFS_AVAILABLE); 682cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->cac_started = 0; 683cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt hostapd_setup_interface_complete(iface, 0); 684051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 685051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 686051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 687051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 688051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 689051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 69004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidtstatic int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface) 691051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 692051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt struct hostapd_channel_data *channel; 69304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt int secondary_channel; 69496be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt u8 vht_oper_centr_freq_seg0_idx = 0; 69596be6222df414a7dde5c5b1b72df22e67b1a77fcDmitry Shmidt u8 vht_oper_centr_freq_seg1_idx = 0; 69604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt int skip_radar = 0; 697051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int err = 1; 69804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 69904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt /* Radar detected during active CAC */ 70004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt iface->cac_started = 0; 70104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt channel = dfs_get_valid_channel(iface, &secondary_channel, 70204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt &vht_oper_centr_freq_seg0_idx, 70304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt &vht_oper_centr_freq_seg1_idx, 70404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt skip_radar); 70504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 70604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt if (!channel) { 70704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt wpa_printf(MSG_ERROR, "No valid channel available"); 70804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt hostapd_setup_interface_complete(iface, err); 70904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return err; 71004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt } 71104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 71204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", 71304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt channel->chan); 71404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL 71504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt "freq=%d chan=%d sec_chan=%d", channel->freq, 71604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt channel->chan, secondary_channel); 71704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 71804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt iface->freq = channel->freq; 71904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt iface->conf->channel = channel->chan; 72004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt iface->conf->secondary_channel = secondary_channel; 72104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg0_idx = 72204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt vht_oper_centr_freq_seg0_idx; 72304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg1_idx = 72404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt vht_oper_centr_freq_seg1_idx; 72504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt err = 0; 72604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 72704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt hostapd_setup_interface_complete(iface, err); 72804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return err; 72904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt} 73004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 73104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 73204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidtstatic int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) 73304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt{ 73404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt struct hostapd_channel_data *channel; 735cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int secondary_channel; 736cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt u8 vht_oper_centr_freq_seg0_idx; 737cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt u8 vht_oper_centr_freq_seg1_idx; 73804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt int skip_radar = 1; 73904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt struct csa_settings csa_settings; 74004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt struct hostapd_data *hapd = iface->bss[0]; 74104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt int err = 1; 74204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 743344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)", 744344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt __func__, iface->cac_started ? "yes" : "no", 745344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt iface->csa_in_progress ? "yes" : "no"); 746344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt 747344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt /* Check if CSA in progress */ 748344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt if (iface->csa_in_progress) 749344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt return 0; 750051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 75104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt /* Check if active CAC */ 75204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt if (iface->cac_started) 75304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return hostapd_dfs_start_channel_switch_cac(iface); 75404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 75504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt /* Perform channel switch/CSA */ 756cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt channel = dfs_get_valid_channel(iface, &secondary_channel, 757cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt &vht_oper_centr_freq_seg0_idx, 75804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt &vht_oper_centr_freq_seg1_idx, 75904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt skip_radar); 76004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 76104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt if (!channel) { 7629866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt /* 7639866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt * If there is no channel to switch immediately to, check if 7649866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt * there is another channel where we can switch even if it 7659866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt * requires to perform a CAC first. 7669866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt */ 7679866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt skip_radar = 0; 7689866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt channel = dfs_get_valid_channel(iface, &secondary_channel, 7699866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt &vht_oper_centr_freq_seg0_idx, 7709866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt &vht_oper_centr_freq_seg1_idx, 7719866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt skip_radar); 7729866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt if (!channel) { 7739866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt /* FIXME: Wait for channel(s) to become available */ 7749866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt hostapd_disable_iface(iface); 7759866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt return err; 7769866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt } 7779866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 7789866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt iface->freq = channel->freq; 7799866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt iface->conf->channel = channel->chan; 7809866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt iface->conf->secondary_channel = secondary_channel; 7819866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg0_idx = 7829866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt vht_oper_centr_freq_seg0_idx; 7839866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg1_idx = 7849866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt vht_oper_centr_freq_seg1_idx; 7859866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt 78604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt hostapd_disable_iface(iface); 7879866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt hostapd_enable_iface(iface); 7889866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt return 0; 78904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt } 79004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 79104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", 79204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt channel->chan); 79304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL 79404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt "freq=%d chan=%d sec_chan=%d", channel->freq, 79504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt channel->chan, secondary_channel); 79604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 79704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt /* Setup CSA request */ 79804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt os_memset(&csa_settings, 0, sizeof(csa_settings)); 79904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt csa_settings.cs_count = 5; 80004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt csa_settings.block_tx = 1; 80104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt err = hostapd_set_freq_params(&csa_settings.freq_params, 80204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt iface->conf->hw_mode, 80304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt channel->freq, 80404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt channel->chan, 80504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt iface->conf->ieee80211n, 80604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt iface->conf->ieee80211ac, 80704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt secondary_channel, 80804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt iface->conf->vht_oper_chwidth, 80904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt vht_oper_centr_freq_seg0_idx, 81004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt vht_oper_centr_freq_seg1_idx, 81104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt iface->current_mode->vht_capab); 81204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 81304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt if (err) { 81404f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params"); 81504f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt hostapd_disable_iface(iface); 81604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return err; 81704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt } 818cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 81904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt err = hostapd_switch_channel(hapd, &csa_settings); 82004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt if (err) { 82104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback", 82204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt err); 823cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->freq = channel->freq; 824cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->conf->channel = channel->chan; 825cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->conf->secondary_channel = secondary_channel; 826cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg0_idx = 827cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt vht_oper_centr_freq_seg0_idx; 828cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->conf->vht_oper_centr_freq_seg1_idx = 829cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt vht_oper_centr_freq_seg1_idx; 830051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 831cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt hostapd_disable_iface(iface); 83204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt hostapd_enable_iface(iface); 83304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt return 0; 83468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 835051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 83604f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt /* Channel configuration will be updated once CSA completes and 83704f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt * ch_switch_notify event is received */ 83804f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt 83904f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt wpa_printf(MSG_DEBUG, "DFS waiting channel switch event"); 840051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 841051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 842051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 843051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 844cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtint hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq, 845051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int ht_enabled, int chan_offset, int chan_width, 846051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int cf1, int cf2) 847051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 848051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int res; 849051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 850cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (!iface->conf->ieee80211h) 851051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 852051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 853cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_RADAR_DETECTED 854cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", 855cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt freq, ht_enabled, chan_offset, chan_width, cf1, cf2); 856cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 857051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* mark radar frequency as invalid */ 858cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt res = set_dfs_state(iface, freq, ht_enabled, chan_offset, 859051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt chan_width, cf1, cf2, 860051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt HOSTAPD_CHAN_DFS_UNAVAILABLE); 861051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 862051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* Skip if reported radar event not overlapped our channels */ 863cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2); 864051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if (!res) 865051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 866051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 867051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* radar detected while operating, switch the channel. */ 868cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt res = hostapd_dfs_start_channel_switch(iface); 869051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 870051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return res; 871051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 872051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 873051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 874cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtint hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq, 875051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int ht_enabled, int chan_offset, int chan_width, 876051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int cf1, int cf2) 877051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 878cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NOP_FINISHED 879cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", 880cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt freq, ht_enabled, chan_offset, chan_width, cf1, cf2); 881051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt /* TODO add correct implementation here */ 882cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, 883cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt cf1, cf2, HOSTAPD_CHAN_DFS_USABLE); 884051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return 0; 885051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 886f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 887f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 888f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidtint hostapd_is_dfs_required(struct hostapd_iface *iface) 889f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt{ 890f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int n_chans, start_chan_idx; 891f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 892f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (!iface->current_mode) 893f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return -1; 894f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 895f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* Get start (first) channel for current configuration */ 896f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt start_chan_idx = dfs_get_start_chan_idx(iface); 897f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (start_chan_idx == -1) 898f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return -1; 899f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 900f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* Get number of used channels, depend on width */ 901f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt n_chans = dfs_get_used_n_chans(iface); 902f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 903f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt /* Check if any of configured channels require DFS */ 904f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt return dfs_check_chans_radar(iface, start_chan_idx, n_chans); 905f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt} 906