diff --git a/src/ap/acs.c b/src/ap/acs.c index 2b7a43e14..7da95d6c2 100644 --- a/src/ap/acs.c +++ b/src/ap/acs.c @@ -245,7 +245,8 @@ enum bw_type { ACS_BW40, ACS_BW80, ACS_BW160, - ACS_BW320, + ACS_BW320_1, + ACS_BW320_2, }; struct bw_item { @@ -287,16 +288,20 @@ static const struct bw_item bw_160[] = { { 6435, 6575, 111 }, { 6595, 6735, 143 }, { 6755, 6895, 175 }, { 6915, 7055, 207 }, { -1, -1, -1 } }; -static const struct bw_item bw_320[] = { - { 5955, 6255, 31 }, { 6115, 6415, 63 }, { 6275, 6575, 95 }, - { 6435, 6735, 127 }, { 6595, 6895, 159}, { 6755, 7055, 191 }, +static const struct bw_item bw_320_1[] = { + { 5955, 6255, 31 }, { 6275, 6575, 95 }, { 6595, 6895, 159 }, + { -1, -1, -1 } +}; +static const struct bw_item bw_320_2[] = { + { 6115, 6415, 63 }, { 6435, 6735, 127 }, { 6755, 7055, 191 }, { -1, -1, -1 } }; static const struct bw_item *bw_desc[] = { [ACS_BW40] = bw_40, [ACS_BW80] = bw_80, [ACS_BW160] = bw_160, - [ACS_BW320] = bw_320, + [ACS_BW320_1] = bw_320_1, + [ACS_BW320_2] = bw_320_2, }; @@ -775,6 +780,42 @@ static void acs_update_puncturing_bitmap(struct hostapd_iface *iface, #endif /* CONFIG_IEEE80211BE */ +static bool +acs_usable_bw320_chan(struct hostapd_iface *iface, + struct hostapd_channel_data *chan, int *bw320_offset) +{ + const char *bw320_str[] = { "320 MHz", "320 MHz-1", "320 MHz-2" }; + int conf_bw320_offset = hostapd_get_bw320_offset(iface->conf); + + *bw320_offset = 0; + switch (conf_bw320_offset) { + case 1: + if (acs_usable_bw_chan(chan, ACS_BW320_1)) + *bw320_offset = 1; + break; + case 2: + if (acs_usable_bw_chan(chan, ACS_BW320_2)) + *bw320_offset = 2; + break; + case 0: + default: + conf_bw320_offset = 0; + if (acs_usable_bw_chan(chan, ACS_BW320_1)) + *bw320_offset = 1; + else if (acs_usable_bw_chan(chan, ACS_BW320_2)) + *bw320_offset = 2; + break; + } + + if (!*bw320_offset) + wpa_printf(MSG_DEBUG, + "ACS: Channel %d: not allowed as primary channel for %s bandwidth", + chan->chan, bw320_str[conf_bw320_offset]); + + return *bw320_offset != 0; +} + + static void acs_find_ideal_chan_mode(struct hostapd_iface *iface, struct hostapd_hw_modes *mode, @@ -786,6 +827,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface, struct hostapd_channel_data *chan, *adj_chan = NULL, *best; long double factor; int i, j; + int bw320_offset = 0, ideal_bw320_offset = 0; unsigned int k; int secondary_channel = 1, freq_offset; @@ -849,7 +891,8 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface, } if (mode->mode == HOSTAPD_MODE_IEEE80211A && - (iface->conf->ieee80211ac || iface->conf->ieee80211ax)) { + (iface->conf->ieee80211ac || iface->conf->ieee80211ax || + iface->conf->ieee80211be)) { if (hostapd_get_oper_chwidth(iface->conf) == CONF_OPER_CHWIDTH_80MHZ && !acs_usable_bw_chan(chan, ACS_BW80)) { @@ -873,12 +916,8 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface, iface->conf->ieee80211be) { if (hostapd_get_oper_chwidth(iface->conf) == CONF_OPER_CHWIDTH_320MHZ && - !acs_usable_bw_chan(chan, ACS_BW320)) { - wpa_printf(MSG_DEBUG, - "ACS: Channel %d: not allowed as primary channel for 320 MHz bandwidth", - chan->chan); + !acs_usable_bw320_chan(iface, chan, &bw320_offset)) continue; - } } factor = 0; @@ -1012,6 +1051,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface, *ideal_factor = factor; *ideal_chan = chan; + ideal_bw320_offset = bw320_offset; #ifdef CONFIG_IEEE80211BE if (iface->conf->ieee80211be) @@ -1022,9 +1062,13 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface, } /* This channel would at least be usable */ - if (!(*rand_chan)) + if (!(*rand_chan)) { *rand_chan = chan; + ideal_bw320_offset = bw320_offset; + } } + + hostapd_set_and_check_bw320_offset(iface->conf, ideal_bw320_offset); } @@ -1116,7 +1160,8 @@ static void acs_adjust_secondary(struct hostapd_iface *iface) acs_find_mode(iface, iface->freq) != HOSTAPD_MODE_IEEE80211A) return; - wpa_printf(MSG_DEBUG, "ACS: Adjusting HT/VHT/HE secondary frequency"); + wpa_printf(MSG_DEBUG, + "ACS: Adjusting HT/VHT/HE/EHT secondary frequency"); for (i = 0; bw_desc[ACS_BW40][i].first != -1; i++) { if (iface->freq == bw_desc[ACS_BW40][i].first) @@ -1131,7 +1176,7 @@ static void acs_adjust_center_freq(struct hostapd_iface *iface) { int center; - wpa_printf(MSG_DEBUG, "ACS: Adjusting VHT center frequency"); + wpa_printf(MSG_DEBUG, "ACS: Adjusting center frequency"); switch (hostapd_get_oper_chwidth(iface->conf)) { case CONF_OPER_CHWIDTH_USE_HT: @@ -1151,7 +1196,21 @@ static void acs_adjust_center_freq(struct hostapd_iface *iface) center = acs_get_bw_center_chan(iface->freq, ACS_BW160); break; case CONF_OPER_CHWIDTH_320MHZ: - center = acs_get_bw_center_chan(iface->freq, ACS_BW320); + switch (hostapd_get_bw320_offset(iface->conf)) { + case 1: + center = acs_get_bw_center_chan(iface->freq, + ACS_BW320_1); + break; + case 2: + center = acs_get_bw_center_chan(iface->freq, + ACS_BW320_2); + break; + default: + wpa_printf(MSG_INFO, + "ACS: BW320 offset is not selected"); + return; + } + break; default: /* TODO: How can this be calculated? Adjust