From 2124a615e35737eeb21d9a038d189da882f68144 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 7 Mar 2017 18:20:57 +0200 Subject: [PATCH] wpa_supplicant: Allow explicit wide channel configuration for AP mode Instead of deducing the wide (HT, VHT) channel configuration only automatically in P2P mode, allow it to be configured in the network in non-P2P mode. Also allow all of these parameters to be configured through the control interface or the configuration file. Signed-off-by: Johannes Berg --- wpa_supplicant/ap.c | 44 ++++++++++++++++++++++++------------ wpa_supplicant/config.c | 4 ++++ wpa_supplicant/config_file.c | 4 ++++ wpa_supplicant/config_ssid.h | 1 + wpa_supplicant/wpa_cli.c | 3 ++- 5 files changed, 40 insertions(+), 16 deletions(-) diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index f2edb4f06..d6aac3e0e 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -46,16 +46,33 @@ static void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx); #ifdef CONFIG_IEEE80211N static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, struct hostapd_config *conf, struct hostapd_hw_modes *mode) { -#ifdef CONFIG_P2P u8 center_chan = 0; u8 channel = conf->channel; if (!conf->secondary_channel) goto no_vht; + /* Use the maximum oper channel width if it's given. */ + if (ssid->max_oper_chwidth) + conf->vht_oper_chwidth = ssid->max_oper_chwidth; + + ieee80211_freq_to_chan(ssid->vht_center_freq2, + &conf->vht_oper_centr_freq_seg1_idx); + + if (!ssid->p2p_group) { + if (!ssid->vht_center_freq1 || + conf->vht_oper_chwidth == VHT_CHANWIDTH_USE_HT) + goto no_vht; + ieee80211_freq_to_chan(ssid->vht_center_freq1, + &conf->vht_oper_centr_freq_seg0_idx); + return; + } + +#ifdef CONFIG_P2P switch (conf->vht_oper_chwidth) { case VHT_CHANWIDTH_80MHZ: case VHT_CHANWIDTH_80P80MHZ: @@ -84,14 +101,11 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, conf->vht_oper_centr_freq_seg0_idx = center_chan; return; +#endif /* CONFIG_P2P */ no_vht: - conf->vht_oper_centr_freq_seg0_idx = - channel + conf->secondary_channel * 2; -#else /* CONFIG_P2P */ conf->vht_oper_centr_freq_seg0_idx = conf->channel + conf->secondary_channel * 2; -#endif /* CONFIG_P2P */ conf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT; } #endif /* CONFIG_IEEE80211N */ @@ -141,17 +155,24 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, if (!no_ht && mode && mode->ht_capab) { conf->ieee80211n = 1; #ifdef CONFIG_P2P - if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A && + if (ssid->p2p_group && + conf->hw_mode == HOSTAPD_MODE_IEEE80211A && (mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) && ssid->ht40) conf->secondary_channel = wpas_p2p_get_ht40_mode(wpa_s, mode, conf->channel); +#endif /* CONFIG_P2P */ + + if (!ssid->p2p_group && + (mode->ht_capab & + HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) + conf->secondary_channel = ssid->ht40; + if (conf->secondary_channel) conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; -#endif /* CONFIG_P2P */ /* * white-list capabilities that won't cause issues @@ -169,7 +190,7 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, if (mode->vht_capab && ssid->vht) { conf->ieee80211ac = 1; conf->vht_capab |= mode->vht_capab; - wpas_conf_ap_vht(wpa_s, conf, mode); + wpas_conf_ap_vht(wpa_s, ssid, conf, mode); } } } @@ -693,13 +714,6 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, return -1; } - /* Use the maximum oper channel width if it's given. */ - if (ssid->max_oper_chwidth) - conf->vht_oper_chwidth = ssid->max_oper_chwidth; - - ieee80211_freq_to_chan(ssid->vht_center_freq2, - &conf->vht_oper_centr_freq_seg1_idx); - os_memcpy(wpa_s->ap_iface->conf->wmm_ac_params, wpa_s->conf->wmm_ac_params, sizeof(wpa_s->conf->wmm_ac_params)); diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index e3ce6bc1d..95971ea99 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -1995,8 +1995,12 @@ static const struct parse_data ssid_fields[] = { { FUNC(auth_alg) }, { FUNC(scan_freq) }, { FUNC(freq_list) }, + { INT_RANGE(vht, 0, 1) }, + { INT_RANGE(ht40, -1, 1) }, { INT_RANGE(max_oper_chwidth, VHT_CHANWIDTH_USE_HT, VHT_CHANWIDTH_80P80MHZ) }, + { INT(vht_center_freq1) }, + { INT(vht_center_freq2) }, #ifdef IEEE8021X_EAPOL { FUNC(eap) }, { STR_LENe(identity) }, diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 2b46fed4f..e5808612e 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -792,7 +792,11 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT(disabled); INT(peerkey); INT(mixed_cell); + INT(vht); + INT(ht40); INT(max_oper_chwidth); + INT(vht_center_freq1); + INT(vht_center_freq2); INT(pbss); INT(wps_disabled); #ifdef CONFIG_IEEE80211W diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index 69ace3780..a2482d4d6 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -476,6 +476,7 @@ struct wpa_ssid { u8 max_oper_chwidth; + unsigned int vht_center_freq1; unsigned int vht_center_freq2; /** diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 09050d0d0..8ef7f4673 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -1371,7 +1371,8 @@ static const char *network_fields[] = { "ssid", "scan_ssid", "bssid", "bssid_blacklist", "bssid_whitelist", "psk", "proto", "key_mgmt", "bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq", - "freq_list", "max_oper_chwidth", + "freq_list", "max_oper_chwidth", "ht40", "vht", "vht_center_freq1", + "vht_center_freq2", #ifdef IEEE8021X_EAPOL "eap", "identity", "anonymous_identity", "password", "ca_cert", "ca_path", "client_cert", "private_key", "private_key_passwd",