diff options
Diffstat (limited to 'src/ap/acs.c')
-rw-r--r-- | src/ap/acs.c | 92 |
1 files changed, 74 insertions, 18 deletions
diff --git a/src/ap/acs.c b/src/ap/acs.c index 6d4c0416dd42..3b4507575328 100644 --- a/src/ap/acs.c +++ b/src/ap/acs.c @@ -13,6 +13,7 @@ #include "utils/common.h" #include "utils/list.h" #include "common/ieee802_11_defs.h" +#include "common/hw_features_common.h" #include "common/wpa_ctrl.h" #include "drivers/driver.h" #include "hostapd.h" @@ -362,7 +363,7 @@ acs_survey_chan_interference_factor(struct hostapd_iface *iface, } -static int acs_usable_ht40_chan(struct hostapd_channel_data *chan) +static int acs_usable_ht40_chan(const struct hostapd_channel_data *chan) { const int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, 184, 192 }; @@ -376,7 +377,7 @@ static int acs_usable_ht40_chan(struct hostapd_channel_data *chan) } -static int acs_usable_vht80_chan(struct hostapd_channel_data *chan) +static int acs_usable_vht80_chan(const struct hostapd_channel_data *chan) { const int allowed[] = { 36, 52, 100, 116, 132, 149 }; unsigned int i; @@ -389,6 +390,19 @@ static int acs_usable_vht80_chan(struct hostapd_channel_data *chan) } +static int acs_usable_vht160_chan(const struct hostapd_channel_data *chan) +{ + const int allowed[] = { 36, 100 }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(allowed); i++) + if (chan->chan == allowed[i]) + return 1; + + return 0; +} + + static int acs_survey_is_sufficient(struct freq_survey *survey) { if (!(survey->filled & SURVEY_HAS_NF)) { @@ -565,6 +579,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface) long double factor, ideal_factor = 0; int i, j; int n_chans = 1; + u32 bw; unsigned int k; /* TODO: HT40- support */ @@ -579,16 +594,23 @@ acs_find_ideal_chan(struct hostapd_iface *iface) iface->conf->secondary_channel) n_chans = 2; - if (iface->conf->ieee80211ac && - iface->conf->vht_oper_chwidth == 1) - n_chans = 4; + if (iface->conf->ieee80211ac) { + switch (iface->conf->vht_oper_chwidth) { + case VHT_CHANWIDTH_80MHZ: + n_chans = 4; + break; + case VHT_CHANWIDTH_160MHZ: + n_chans = 8; + break; + } + } + + bw = num_chan_to_bw(n_chans); - /* TODO: VHT80+80, VHT160. Update acs_adjust_vht_center_freq() too. */ + /* TODO: VHT80+80. Update acs_adjust_vht_center_freq() too. */ - wpa_printf(MSG_DEBUG, "ACS: Survey analysis for selected bandwidth %d MHz", - n_chans == 1 ? 20 : - n_chans == 2 ? 40 : - 80); + wpa_printf(MSG_DEBUG, + "ACS: Survey analysis for selected bandwidth %d MHz", bw); for (i = 0; i < iface->current_mode->num_channels; i++) { double total_weight; @@ -596,12 +618,23 @@ acs_find_ideal_chan(struct hostapd_iface *iface) chan = &iface->current_mode->channels[i]; - if (chan->flag & HOSTAPD_CHAN_DISABLED) + /* Since in the current ACS implementation the first channel is + * always a primary channel, skip channels not available as + * primary until more sophisticated channel selection is + * implemented. */ + if (!chan_pri_allowed(chan)) continue; if (!is_in_chanlist(iface, chan)) continue; + if (!chan_bw_allowed(chan, bw, 1, 1)) { + wpa_printf(MSG_DEBUG, + "ACS: Channel %d: BW %u is not supported", + chan->chan, bw); + continue; + } + /* HT40 on 5 GHz has a limited set of primary channels as per * 11n Annex J */ if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A && @@ -614,12 +647,24 @@ acs_find_ideal_chan(struct hostapd_iface *iface) } if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A && - iface->conf->ieee80211ac && - iface->conf->vht_oper_chwidth == 1 && - !acs_usable_vht80_chan(chan)) { - wpa_printf(MSG_DEBUG, "ACS: Channel %d: not allowed as primary channel for VHT80", - chan->chan); - continue; + iface->conf->ieee80211ac) { + if (iface->conf->vht_oper_chwidth == + VHT_CHANWIDTH_80MHZ && + !acs_usable_vht80_chan(chan)) { + wpa_printf(MSG_DEBUG, + "ACS: Channel %d: not allowed as primary channel for VHT80", + chan->chan); + continue; + } + + if (iface->conf->vht_oper_chwidth == + VHT_CHANWIDTH_160MHZ && + !acs_usable_vht160_chan(chan)) { + wpa_printf(MSG_DEBUG, + "ACS: Channel %d: not allowed as primary channel for VHT160", + chan->chan); + continue; + } } factor = 0; @@ -632,6 +677,13 @@ acs_find_ideal_chan(struct hostapd_iface *iface) if (!adj_chan) break; + if (!chan_bw_allowed(adj_chan, bw, 1, 0)) { + wpa_printf(MSG_DEBUG, + "ACS: PRI Channel %d: secondary channel %d BW %u is not supported", + chan->chan, adj_chan->chan, bw); + break; + } + if (acs_usable_chan(adj_chan)) { factor += adj_chan->interference_factor; total_weight += 1; @@ -744,10 +796,14 @@ static void acs_adjust_vht_center_freq(struct hostapd_iface *iface) case VHT_CHANWIDTH_80MHZ: offset = 6; break; + case VHT_CHANWIDTH_160MHZ: + offset = 14; + break; default: /* TODO: How can this be calculated? Adjust * acs_find_ideal_chan() */ - wpa_printf(MSG_INFO, "ACS: Only VHT20/40/80 is supported now"); + wpa_printf(MSG_INFO, + "ACS: Only VHT20/40/80/160 is supported now"); return; } |