HE/VHT: Fix frequency setup with HE enabled

Some places in the code base were not using the wrappers like
hostapd_set_oper_centr_freq_seg0_idx and friends. This could lead to
errors, for example when joining 80 MHz mesh networks. Fix this, by
enforcing usage of these wrappers.

wpa_supplicant_conf_ap_ht() now checks for HE capability before dealing
with VHT in order for these wrappers to work, as they first check HE
support in the config.

While doing these changes, I've noticed that the extra channel setup
code for mesh networks in wpa_supplicant/mesh.c should not be necessary
anymore and dropped it. wpa_supplicant_conf_ap_ht() should handle this
setup already.

Acked-by: John Crispin <john@phrozen.org>
Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
This commit is contained in:
Markus Theil 2020-06-30 13:53:17 +02:00 committed by Jouni Malinen
parent 0f07230eb9
commit 7f8ac02e85
3 changed files with 27 additions and 45 deletions

View File

@ -1028,7 +1028,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
unsigned int i; unsigned int i;
int err = 1; int err = 1;
struct hostapd_hw_modes *cmode = iface->current_mode; struct hostapd_hw_modes *cmode = iface->current_mode;
u8 current_vht_oper_chwidth = iface->conf->vht_oper_chwidth; u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)", wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)",
__func__, iface->cac_started ? "yes" : "no", __func__, iface->cac_started ? "yes" : "no",
@ -1089,8 +1089,8 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
"freq=%d chan=%d sec_chan=%d", channel->freq, "freq=%d chan=%d sec_chan=%d", channel->freq,
channel->chan, secondary_channel); channel->chan, secondary_channel);
new_vht_oper_chwidth = iface->conf->vht_oper_chwidth; new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
iface->conf->vht_oper_chwidth = current_vht_oper_chwidth; hostapd_set_oper_chwidth(iface->conf, current_vht_oper_chwidth);
/* Setup CSA request */ /* Setup CSA request */
os_memset(&csa_settings, 0, sizeof(csa_settings)); os_memset(&csa_settings, 0, sizeof(csa_settings));
@ -1130,7 +1130,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
iface->freq = channel->freq; iface->freq = channel->freq;
iface->conf->channel = channel->chan; iface->conf->channel = channel->chan;
iface->conf->secondary_channel = secondary_channel; iface->conf->secondary_channel = secondary_channel;
iface->conf->vht_oper_chwidth = new_vht_oper_chwidth; hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth);
hostapd_set_oper_centr_freq_seg0_idx(iface->conf, hostapd_set_oper_centr_freq_seg0_idx(iface->conf,
oper_centr_freq_seg0_idx); oper_centr_freq_seg0_idx);
hostapd_set_oper_centr_freq_seg1_idx(iface->conf, hostapd_set_oper_centr_freq_seg1_idx(iface->conf,

View File

@ -52,6 +52,7 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_P2P #ifdef CONFIG_P2P
u8 center_chan = 0; u8 center_chan = 0;
u8 channel = conf->channel; u8 channel = conf->channel;
u8 freq_seg_idx;
#endif /* CONFIG_P2P */ #endif /* CONFIG_P2P */
if (!conf->secondary_channel) if (!conf->secondary_channel)
@ -59,19 +60,21 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
/* Use the maximum oper channel width if it's given. */ /* Use the maximum oper channel width if it's given. */
if (ssid->max_oper_chwidth) if (ssid->max_oper_chwidth)
conf->vht_oper_chwidth = ssid->max_oper_chwidth; hostapd_set_oper_chwidth(conf, ssid->max_oper_chwidth);
ieee80211_freq_to_chan(ssid->vht_center_freq2, ieee80211_freq_to_chan(ssid->vht_center_freq2,
&conf->vht_oper_centr_freq_seg1_idx); &freq_seg_idx);
hostapd_set_oper_centr_freq_seg1_idx(conf, freq_seg_idx);
if (!ssid->p2p_group) { if (!ssid->p2p_group) {
if (!ssid->vht_center_freq1 || if (!ssid->vht_center_freq1 ||
conf->vht_oper_chwidth == CHANWIDTH_USE_HT) hostapd_get_oper_chwidth(conf) == CHANWIDTH_USE_HT)
goto no_vht; goto no_vht;
ieee80211_freq_to_chan(ssid->vht_center_freq1, ieee80211_freq_to_chan(ssid->vht_center_freq1,
&conf->vht_oper_centr_freq_seg0_idx); &freq_seg_idx);
hostapd_set_oper_centr_freq_seg0_idx(conf, freq_seg_idx);
wpa_printf(MSG_DEBUG, "VHT seg0 index %d for AP", wpa_printf(MSG_DEBUG, "VHT seg0 index %d for AP",
conf->vht_oper_centr_freq_seg0_idx); hostapd_get_oper_centr_freq_seg0_idx(conf));
return; return;
} }
@ -96,14 +99,14 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
* try oper_cwidth 160 MHz first then VHT 80 MHz, if 160 MHz is * try oper_cwidth 160 MHz first then VHT 80 MHz, if 160 MHz is
* not supported. * not supported.
*/ */
conf->vht_oper_chwidth = CHANWIDTH_160MHZ; hostapd_set_oper_chwidth(conf, CHANWIDTH_160MHZ);
center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel); center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
if (center_chan) { if (center_chan) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"VHT center channel %u for auto-selected 160 MHz bandwidth", "VHT center channel %u for auto-selected 160 MHz bandwidth",
center_chan); center_chan);
} else { } else {
conf->vht_oper_chwidth = CHANWIDTH_80MHZ; hostapd_set_oper_chwidth(conf, CHANWIDTH_80MHZ);
center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, center_chan = wpas_p2p_get_vht80_center(wpa_s, mode,
channel); channel);
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
@ -115,9 +118,9 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
if (!center_chan) if (!center_chan)
goto no_vht; goto no_vht;
conf->vht_oper_centr_freq_seg0_idx = center_chan; hostapd_set_oper_centr_freq_seg0_idx(conf, center_chan);
wpa_printf(MSG_DEBUG, "VHT seg0 index %d for P2P GO", wpa_printf(MSG_DEBUG, "VHT seg0 index %d for P2P GO",
conf->vht_oper_centr_freq_seg0_idx); hostapd_get_oper_centr_freq_seg0_idx(conf));
return; return;
#endif /* CONFIG_P2P */ #endif /* CONFIG_P2P */
@ -125,9 +128,9 @@ no_vht:
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"No VHT higher bandwidth support for the selected channel %d", "No VHT higher bandwidth support for the selected channel %d",
conf->channel); conf->channel);
conf->vht_oper_centr_freq_seg0_idx = hostapd_set_oper_centr_freq_seg0_idx(
conf->channel + conf->secondary_channel * 2; conf, conf->channel + conf->secondary_channel * 2);
conf->vht_oper_chwidth = CHANWIDTH_USE_HT; hostapd_set_oper_chwidth(conf, CHANWIDTH_USE_HT);
} }
@ -231,16 +234,19 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
HT_CAP_INFO_TX_STBC | HT_CAP_INFO_TX_STBC |
HT_CAP_INFO_MAX_AMSDU_SIZE); HT_CAP_INFO_MAX_AMSDU_SIZE);
/* check this before VHT, because setting oper chan
* width and friends is the same call for HE and VHT
* and checks if conf->ieee8021ax == 1 */
if (mode->he_capab[wpas_mode_to_ieee80211_mode(
ssid->mode)].he_supported &&
ssid->he)
conf->ieee80211ax = 1;
if (mode->vht_capab && ssid->vht) { if (mode->vht_capab && ssid->vht) {
conf->ieee80211ac = 1; conf->ieee80211ac = 1;
conf->vht_capab |= mode->vht_capab; conf->vht_capab |= mode->vht_capab;
wpas_conf_ap_vht(wpa_s, ssid, conf, mode); wpas_conf_ap_vht(wpa_s, ssid, conf, mode);
} }
if (mode->he_capab[wpas_mode_to_ieee80211_mode(
ssid->mode)].he_supported &&
ssid->he)
conf->ieee80211ax = 1;
} }
} }

View File

@ -333,30 +333,6 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
frequency); frequency);
goto out_free; goto out_free;
} }
if (ssid->ht40)
conf->secondary_channel = ssid->ht40;
if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A && ssid->vht) {
if (ssid->max_oper_chwidth != DEFAULT_MAX_OPER_CHWIDTH)
conf->vht_oper_chwidth = ssid->max_oper_chwidth;
switch (conf->vht_oper_chwidth) {
case CHANWIDTH_80MHZ:
case CHANWIDTH_80P80MHZ:
ieee80211_freq_to_chan(
frequency,
&conf->vht_oper_centr_freq_seg0_idx);
conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2;
break;
case CHANWIDTH_160MHZ:
ieee80211_freq_to_chan(
frequency,
&conf->vht_oper_centr_freq_seg0_idx);
conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2;
conf->vht_oper_centr_freq_seg0_idx += 40 / 5;
break;
}
ieee80211_freq_to_chan(ssid->vht_center_freq2,
&conf->vht_oper_centr_freq_seg1_idx);
}
if (ssid->mesh_basic_rates == NULL) { if (ssid->mesh_basic_rates == NULL) {
/* /*