diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 3b7e40018..4b7bf8035 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -61,6 +61,7 @@ struct hostapd_channel_data { }; #define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0) +#define HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN BIT(1) /** * struct hostapd_hw_modes - Supported hardware mode information diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 5f7be2913..4c0c24d0f 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -5658,7 +5658,20 @@ static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band) mode = &phy_info->modes[*(phy_info->num_modes)]; os_memset(mode, 0, sizeof(*mode)); mode->mode = NUM_HOSTAPD_MODES; - mode->flags = HOSTAPD_MODE_FLAG_HT_INFO_KNOWN; + mode->flags = HOSTAPD_MODE_FLAG_HT_INFO_KNOWN | + HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN; + + /* + * Unsupported VHT MCS stream is defined as value 3, so the VHT + * MCS RX/TX map must be initialized with 0xffff to mark all 8 + * possible streams as unsupported. This will be overridden if + * driver advertises VHT support. + */ + mode->vht_mcs_set[0] = 0xff; + mode->vht_mcs_set[1] = 0xff; + mode->vht_mcs_set[4] = 0xff; + mode->vht_mcs_set[5] = 0xff; + *(phy_info->num_modes) += 1; phy_info->last_mode = nl_band->nla_type; phy_info->last_chan_idx = 0; diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index f757c7235..fcd0f7946 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -548,6 +548,24 @@ static int ht_supported(const struct hostapd_hw_modes *mode) } +static int vht_supported(const struct hostapd_hw_modes *mode) +{ + if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) { + /* + * The driver did not indicate whether it supports VHT. Assume + * it does to avoid connection issues. + */ + return 1; + } + + /* + * A VHT non-AP STA shall support MCS 0-7 for one spatial stream. + * TODO: Verify if this complies with the standard + */ + return (mode->vht_mcs_set[0] & 0x3) != 3; +} + + static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) { const struct hostapd_hw_modes *mode = NULL, *modes; @@ -613,6 +631,18 @@ static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) continue; } + /* There's also a VHT selector for 802.11ac */ + if (flagged && ((rate_ie[j] & 0x7f) == + BSS_MEMBERSHIP_SELECTOR_VHT_PHY)) { + if (!vht_supported(mode)) { + wpa_dbg(wpa_s, MSG_DEBUG, + " hardware does not support " + "VHT PHY"); + return 0; + } + continue; + } + if (!flagged) continue;