There are bandwidth 320 MHz-1 and 320 MHz-2 channelization in EHT mode. When using ACS, user might prefer one of the channelization or both, but original ACS was unable to take such perference. Another problem is that the original ACS returns only the ideal channel but no 320 MHz channelization. The function acs_get_bw_center_chan() also could not correctly returns the center frequency of bandwidth 320 MHz that is decided by ACS. For example, if ACS decide the ideal channel is channel 37 with channelization 320 MHz-2 (center frequency 6265 MHz), acs_get_bw_center_chan() returns 6105 MHz, which is 320 MHz-1. This patch extends the support for 320 MHz so that ACS can choose the best channel according to the user's preference. Also, after calling acs_find_ideal_chan_mode(), the best channel and bandwidth can be derived. The changes of this patch are: - bw_type ACS_BW320 is divided into ACS_BW320_1 and ACS_BW320_2 - in bandwidth 320 MHz, find the best channel and bandwidth according to user's perference (320 MHz-1, 320 Mhz-2 or both are OK) - before acs_find_ideal_chan_mode() returns, update bw320_offset in iface->conf so that the best channel's channelization is recorded. - get the best center frequency from bw320_offset Co-developed-by: Money Wang <money.wang@xxxxxxxxxxxx> Signed-off-by: Michael-CY Lee <michael-cy.lee@xxxxxxxxxxxx> --- src/ap/acs.c | 90 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 73 insertions(+), 17 deletions(-) diff --git a/src/ap/acs.c b/src/ap/acs.c index b571459af..a5a870c1b 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) +{ + 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 2: + if (acs_usable_bw_chan(chan, ACS_BW320_2)) + *bw320_offset = 2; + break; + case 1: + if (acs_usable_bw_chan(chan, ACS_BW320_1)) + *bw320_offset = 1; + 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, @@ -785,9 +826,9 @@ 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 i, j, secondary_channel = 1; + int freq_offset, bw320_offset = 0, ideal_bw320_offset = 0; unsigned int k; - int secondary_channel = 1, freq_offset; if (is_24ghz_mode(mode->mode)) secondary_channel = iface->conf->secondary_channel; @@ -849,7 +890,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 +915,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; @@ -1011,6 +1049,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) @@ -1021,9 +1060,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); } @@ -1115,7 +1158,7 @@ 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) @@ -1130,7 +1173,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: @@ -1150,7 +1193,20 @@ 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 2: + center = acs_get_bw_center_chan(iface->freq, + ACS_BW320_2); + break; + case 1: + center = acs_get_bw_center_chan(iface->freq, + ACS_BW320_1); + break; + default: + wpa_printf(MSG_INFO, "ACS: BW320 offset is not selected"); + break; + } + break; default: /* TODO: How can this be calculated? Adjust -- 2.25.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap