diff mbox

wpa_supplicant: support VHT capability overrides

Message ID 1362156322-30254-1-git-send-email-johannes@sipsolutions.net
State Accepted
Commit e9ee8dc394725adf83fdd44050e15db953554335
Headers show

Commit Message

Johannes Berg March 1, 2013, 4:45 p.m. UTC
From: Johannes Berg <johannes.berg@intel.com>

Add support for VHT capability overrides to allow testing connections
with a subset of the VHT capabilities that are actually supported by
the device. The only thing that isn't currently supported (by mac80211
and this code) is the RX/TX highest rate field.

Signed-hostap: Johannes Berg <johannes.berg@intel.com>
---
 src/drivers/driver.h               | 13 +++++++++++
 src/drivers/driver_nl80211.c       | 28 +++++++++++++++++++++++
 wpa_supplicant/Makefile            |  4 ++++
 wpa_supplicant/android.config      |  3 +++
 wpa_supplicant/config.c            | 39 ++++++++++++++++++++++++++++++++
 wpa_supplicant/config_ssid.h       | 29 ++++++++++++++++++++++++
 wpa_supplicant/defconfig           |  3 +++
 wpa_supplicant/sme.c               | 11 +++++++++
 wpa_supplicant/wpa_supplicant.c    | 46 ++++++++++++++++++++++++++++++++++++++
 wpa_supplicant/wpa_supplicant.conf | 14 ++++++++++++
 wpa_supplicant/wpa_supplicant_i.h  |  3 +++
 11 files changed, 193 insertions(+)

Comments

Ben Greear March 1, 2013, 5:52 p.m. UTC | #1
On 03/01/2013 08:45 AM, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> Add support for VHT capability overrides to allow testing connections
> with a subset of the VHT capabilities that are actually supported by
> the device. The only thing that isn't currently supported (by mac80211
> and this code) is the RX/TX highest rate field.
>
> Signed-hostap: Johannes Berg <johannes.berg@intel.com>

> +#define OVERRIDE_MCS(i)							\
> +	if (ssid->vht_tx_mcs_nss_ ##i >= 0) {				\
> +		vhtcaps_mask->vht_supported_mcs_set.tx_map |=		\
> +			3 << 2 * (i - 1);				\
> +		vhtcaps->vht_supported_mcs_set.tx_map |=		\
> +			ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1);	\
> +	}								\
> +	if (ssid->vht_rx_mcs_nss_ ##i >= 0) {				\
> +		vhtcaps_mask->vht_supported_mcs_set.rx_map |=		\
> +			3 << 2 * (i - 1);				\
> +		vhtcaps->vht_supported_mcs_set.rx_map |=		\
> +			ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1);	\
> +	}

Maybe some comments on the code above?

> +
> +	OVERRIDE_MCS(1);
> +	OVERRIDE_MCS(2);

...

> +# vht_rx_mcs_nss_1/2/3/4/5/6/7/8: override the MCS set for RX NSS 1-8
> +# vht_tx_mcs_nss_1/2/3/4/5/6/7/8: override the MCS set for TX NSS 1-8
> +#  0: MCS 0-7
> +#  1: MCS 0-8
> +#  2: MCS 0-9
> +#  3: not supported

I'm confused by this.  The MCS overrides I put in for
HT basically allowed setting each bit in the available
MCS rates.  Can you offer a bit more explanation on what
these VHT MCS settings allow/do?

Thanks,
Ben
Johannes Berg March 1, 2013, 5:56 p.m. UTC | #2
On Fri, 2013-03-01 at 09:52 -0800, Ben Greear wrote:

> > +# vht_rx_mcs_nss_1/2/3/4/5/6/7/8: override the MCS set for RX NSS 1-8
> > +# vht_tx_mcs_nss_1/2/3/4/5/6/7/8: override the MCS set for TX NSS 1-8
> > +#  0: MCS 0-7
> > +#  1: MCS 0-8
> > +#  2: MCS 0-9
> > +#  3: not supported
> 
> I'm confused by this.  The MCS overrides I put in for
> HT basically allowed setting each bit in the available
> MCS rates.  Can you offer a bit more explanation on what
> these VHT MCS settings allow/do?

I think if you knew how VHT MCSes worked, it'd be obvious :)

For VHT, there are 10 MCSes (0-9), each of which has up to
configurations for the number of spatial streams (NSS). However, the VHT
capabilities only allow supporting one of 0-7, 0-8, 0-9 or none (see
also the example config file I included)

So a device could, for example, support

NSS 1: MCS 0-9
NSS 2: MCS 0-9
NSS 3-8: none

You could override this, e.g. by setting

vht_rx_mcs_nss_1=2
vht_rx_mcs_nss_2=3

and then you'd get

NSS 1: MCS 0-8
NSS 2-8: none

johannes
Ben Greear March 1, 2013, 6:04 p.m. UTC | #3
On 03/01/2013 09:56 AM, Johannes Berg wrote:
> On Fri, 2013-03-01 at 09:52 -0800, Ben Greear wrote:
>
>>> +# vht_rx_mcs_nss_1/2/3/4/5/6/7/8: override the MCS set for RX NSS 1-8
>>> +# vht_tx_mcs_nss_1/2/3/4/5/6/7/8: override the MCS set for TX NSS 1-8
>>> +#  0: MCS 0-7
>>> +#  1: MCS 0-8
>>> +#  2: MCS 0-9
>>> +#  3: not supported
>>
>> I'm confused by this.  The MCS overrides I put in for
>> HT basically allowed setting each bit in the available
>> MCS rates.  Can you offer a bit more explanation on what
>> these VHT MCS settings allow/do?
>
> I think if you knew how VHT MCSes worked, it'd be obvious :)

Well, yes, that is definitely my problem :)


> For VHT, there are 10 MCSes (0-9), each of which has up to
> configurations for the number of spatial streams (NSS). However, the VHT
> capabilities only allow supporting one of 0-7, 0-8, 0-9 or none (see
> also the example config file I included)
>
> So a device could, for example, support
>
> NSS 1: MCS 0-9
> NSS 2: MCS 0-9
> NSS 3-8: none
>
> You could override this, e.g. by setting
>
> vht_rx_mcs_nss_1=2
> vht_rx_mcs_nss_2=3
>
> and then you'd get
>
> NSS 1: MCS 0-8
> NSS 2-8: none

Ok, thanks.


Ben
Jouni Malinen March 10, 2013, 4:07 p.m. UTC | #4
On Fri, Mar 01, 2013 at 05:45:22PM +0100, Johannes Berg wrote:
> Add support for VHT capability overrides to allow testing connections
> with a subset of the VHT capabilities that are actually supported by
> the device. The only thing that isn't currently supported (by mac80211
> and this code) is the RX/TX highest rate field.

Thanks, applied.
diff mbox

Patch

diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index bb373be..16795d3 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -568,6 +568,19 @@  struct wpa_driver_associate_params {
 	 */
 	const u8 *htcaps;       /* struct ieee80211_ht_capabilities * */
 	const u8 *htcaps_mask;  /* struct ieee80211_ht_capabilities * */
+
+#ifdef CONFIG_VHT_OVERRIDES
+	/**
+	 * disable_vht - Disable VHT for this connection
+	 */
+	int disable_vht;
+
+	/**
+	 * VHT capability overrides.
+	 */
+	const struct ieee80211_vht_capabilities *vhtcaps;
+	const struct ieee80211_vht_capabilities *vhtcaps_mask;
+#endif
 };
 
 enum hide_ssid {
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 191e1d6..3b253b4 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -7043,6 +7043,20 @@  skip_auth_type:
 			params->htcaps_mask);
 	}
 
+#ifdef CONFIG_VHT_OVERRIDES
+	if (params->disable_vht) {
+		wpa_printf(MSG_DEBUG, "  * VHT disabled\n");
+		NLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_VHT);
+	}
+
+	if (params->vhtcaps && params->vhtcaps_mask) {
+		int sz = sizeof(struct ieee80211_vht_capabilities);
+		NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY, sz, params->vhtcaps);
+		NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, sz,
+			params->vhtcaps_mask);
+	}
+#endif
+
 	ret = nl80211_set_conn_keys(params, msg);
 	if (ret)
 		goto nla_put_failure;
@@ -7229,6 +7243,20 @@  static int wpa_driver_nl80211_associate(
 			params->htcaps_mask);
 	}
 
+#ifdef CONFIG_VHT_OVERRIDES
+	if (params->disable_vht) {
+		wpa_printf(MSG_DEBUG, "  * VHT disabled\n");
+		NLA_PUT_FLAG(msg, NL80211_ATTR_DISABLE_VHT);
+	}
+
+	if (params->vhtcaps && params->vhtcaps_mask) {
+		int sz = sizeof(struct ieee80211_vht_capabilities);
+		NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY, sz, params->vhtcaps);
+		NLA_PUT(msg, NL80211_ATTR_VHT_CAPABILITY_MASK, sz,
+			params->vhtcaps_mask);
+	}
+#endif
+
 	if (params->p2p)
 		wpa_printf(MSG_DEBUG, "  * P2P group");
 
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index da2abfc..0634219 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -126,6 +126,10 @@  ifdef CONFIG_HT_OVERRIDES
 CFLAGS += -DCONFIG_HT_OVERRIDES
 endif
 
+ifdef CONFIG_VHT_OVERRIDES
+CFLAGS += -DCONFIG_VHT_OVERRIDES
+endif
+
 ifndef CONFIG_BACKEND
 CONFIG_BACKEND=file
 endif
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index 43881fe..df5efe2 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -224,6 +224,9 @@  CONFIG_SMARTCARD=y
 # Support HT overrides (disable HT/HT40, mask MCS rates, etc.)
 #CONFIG_HT_OVERRIDES=y
 
+# Support VHT overrides (disable VHT, mask MCS rates, etc.)
+#CONFIG_VHT_OVERRIDES=y
+
 # Development testing
 #CONFIG_EAPOL_TEST=y
 
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index ee634a5..5da2d56 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1543,6 +1543,27 @@  static const struct parse_data ssid_fields[] = {
 	{ INT_RANGE(ampdu_density, -1, 7) },
 	{ STR(ht_mcs) },
 #endif /* CONFIG_HT_OVERRIDES */
+#ifdef CONFIG_VHT_OVERRIDES
+	{ INT_RANGE(disable_vht, 0, 1) },
+	{ INT(vht_capa) },
+	{ INT(vht_capa_mask) },
+	{ INT_RANGE(vht_rx_mcs_nss_1, -1, 3) },
+	{ INT_RANGE(vht_rx_mcs_nss_2, -1, 3) },
+	{ INT_RANGE(vht_rx_mcs_nss_3, -1, 3) },
+	{ INT_RANGE(vht_rx_mcs_nss_4, -1, 3) },
+	{ INT_RANGE(vht_rx_mcs_nss_5, -1, 3) },
+	{ INT_RANGE(vht_rx_mcs_nss_6, -1, 3) },
+	{ INT_RANGE(vht_rx_mcs_nss_7, -1, 3) },
+	{ INT_RANGE(vht_rx_mcs_nss_8, -1, 3) },
+	{ INT_RANGE(vht_tx_mcs_nss_1, -1, 3) },
+	{ INT_RANGE(vht_tx_mcs_nss_2, -1, 3) },
+	{ INT_RANGE(vht_tx_mcs_nss_3, -1, 3) },
+	{ INT_RANGE(vht_tx_mcs_nss_4, -1, 3) },
+	{ INT_RANGE(vht_tx_mcs_nss_5, -1, 3) },
+	{ INT_RANGE(vht_tx_mcs_nss_6, -1, 3) },
+	{ INT_RANGE(vht_tx_mcs_nss_7, -1, 3) },
+	{ INT_RANGE(vht_tx_mcs_nss_8, -1, 3) },
+#endif /* CONFIG_VHT_OVERRIDES */
 	{ INT(ap_max_inactivity) },
 	{ INT(dtim_period) },
 };
@@ -1945,6 +1966,24 @@  void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
 	ssid->ampdu_factor = DEFAULT_AMPDU_FACTOR;
 	ssid->ampdu_density = DEFAULT_AMPDU_DENSITY;
 #endif /* CONFIG_HT_OVERRIDES */
+#ifdef CONFIG_VHT_OVERRIDES
+	ssid->vht_rx_mcs_nss_1 = -1;
+	ssid->vht_rx_mcs_nss_2 = -1;
+	ssid->vht_rx_mcs_nss_3 = -1;
+	ssid->vht_rx_mcs_nss_4 = -1;
+	ssid->vht_rx_mcs_nss_5 = -1;
+	ssid->vht_rx_mcs_nss_6 = -1;
+	ssid->vht_rx_mcs_nss_7 = -1;
+	ssid->vht_rx_mcs_nss_8 = -1;
+	ssid->vht_tx_mcs_nss_1 = -1;
+	ssid->vht_tx_mcs_nss_2 = -1;
+	ssid->vht_tx_mcs_nss_3 = -1;
+	ssid->vht_tx_mcs_nss_4 = -1;
+	ssid->vht_tx_mcs_nss_5 = -1;
+	ssid->vht_tx_mcs_nss_6 = -1;
+	ssid->vht_tx_mcs_nss_7 = -1;
+	ssid->vht_tx_mcs_nss_8 = -1;
+#endif /* CONFIG_VHT_OVERRIDES */
 	ssid->proactive_key_caching = -1;
 #ifdef CONFIG_IEEE80211W
 	ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT;
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 9ac67c7..e09139d 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -534,6 +534,35 @@  struct wpa_ssid {
 	char *ht_mcs;
 #endif /* CONFIG_HT_OVERRIDES */
 
+#ifdef CONFIG_VHT_OVERRIDES
+	/**
+	 * disable_vht - Disable VHT (IEEE 802.11ac) for this network
+	 *
+	 * By default, use it if it is available, but this can be configured
+	 * to 1 to have it disabled.
+	 */
+	int disable_vht;
+
+	/**
+	 * vht_capa - VHT capabilities to use
+	 */
+	unsigned int vht_capa;
+
+	/**
+	 * vht_capa_mask - mask for VHT capabilities
+	 */
+	unsigned int vht_capa_mask;
+
+	int vht_rx_mcs_nss_1, vht_rx_mcs_nss_2,
+	    vht_rx_mcs_nss_3, vht_rx_mcs_nss_4,
+	    vht_rx_mcs_nss_5, vht_rx_mcs_nss_6,
+	    vht_rx_mcs_nss_7, vht_rx_mcs_nss_8;
+	int vht_tx_mcs_nss_1, vht_tx_mcs_nss_2,
+	    vht_tx_mcs_nss_3, vht_tx_mcs_nss_4,
+	    vht_tx_mcs_nss_5, vht_tx_mcs_nss_6,
+	    vht_tx_mcs_nss_7, vht_tx_mcs_nss_8;
+#endif /* CONFIG_VHT_OVERRIDES */
+
 	/**
 	 * ap_max_inactivity - Timeout in seconds to detect STA's inactivity
 	 *
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index 711b407..e867bae 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -225,6 +225,9 @@  CONFIG_SMARTCARD=y
 # Support HT overrides (disable HT/HT40, mask MCS rates, etc.)
 #CONFIG_HT_OVERRIDES=y
 
+# Support VHT overrides (disable VHT, mask MCS rates, etc.)
+#CONFIG_VHT_OVERRIDES=y
+
 # Development testing
 #CONFIG_EAPOL_TEST=y
 
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 30f9779..92762ef 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -632,6 +632,10 @@  void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
 	struct ieee80211_ht_capabilities htcaps;
 	struct ieee80211_ht_capabilities htcaps_mask;
 #endif /* CONFIG_HT_OVERRIDES */
+#ifdef CONFIG_VHT_OVERRIDES
+	struct ieee80211_vht_capabilities vhtcaps;
+	struct ieee80211_vht_capabilities vhtcaps_mask;
+#endif /* CONFIG_VHT_OVERRIDES */
 
 	os_memset(&params, 0, sizeof(params));
 	params.bssid = bssid;
@@ -653,6 +657,13 @@  void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
 	params.htcaps_mask = (u8 *) &htcaps_mask;
 	wpa_supplicant_apply_ht_overrides(wpa_s, wpa_s->current_ssid, &params);
 #endif /* CONFIG_HT_OVERRIDES */
+#ifdef CONFIG_VHT_OVERRIDES
+	os_memset(&vhtcaps, 0, sizeof(vhtcaps));
+	os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
+	params.vhtcaps = &vhtcaps;
+	params.vhtcaps_mask = &vhtcaps_mask;
+	wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, &params);
+#endif /* CONFIG_VHT_OVERRIDES */
 #ifdef CONFIG_IEEE80211R
 	if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
 		params.wpa_ie = wpa_s->sme.ft_ies;
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index fc23c8c..6695d66 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2646,6 +2646,52 @@  void wpa_supplicant_apply_ht_overrides(
 
 #endif /* CONFIG_HT_OVERRIDES */
 
+#ifdef CONFIG_VHT_OVERRIDES
+void wpa_supplicant_apply_vht_overrides(
+	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+	struct wpa_driver_associate_params *params)
+{
+	struct ieee80211_vht_capabilities *vhtcaps;
+	struct ieee80211_vht_capabilities *vhtcaps_mask;
+
+	if (!ssid)
+		return;
+
+	params->disable_vht = ssid->disable_vht;
+
+	vhtcaps = (void *)params->vhtcaps;
+	vhtcaps_mask = (void *)params->vhtcaps_mask;
+
+	if (!vhtcaps || !vhtcaps_mask)
+		return;
+
+	vhtcaps->vht_capabilities_info = ssid->vht_capa;
+	vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
+
+#define OVERRIDE_MCS(i)							\
+	if (ssid->vht_tx_mcs_nss_ ##i >= 0) {				\
+		vhtcaps_mask->vht_supported_mcs_set.tx_map |=		\
+			3 << 2 * (i - 1);				\
+		vhtcaps->vht_supported_mcs_set.tx_map |=		\
+			ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1);	\
+	}								\
+	if (ssid->vht_rx_mcs_nss_ ##i >= 0) {				\
+		vhtcaps_mask->vht_supported_mcs_set.rx_map |=		\
+			3 << 2 * (i - 1);				\
+		vhtcaps->vht_supported_mcs_set.rx_map |=		\
+			ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1);	\
+	}
+
+	OVERRIDE_MCS(1);
+	OVERRIDE_MCS(2);
+	OVERRIDE_MCS(3);
+	OVERRIDE_MCS(4);
+	OVERRIDE_MCS(5);
+	OVERRIDE_MCS(6);
+	OVERRIDE_MCS(7);
+	OVERRIDE_MCS(8);
+}
+#endif /* CONFIG_VHT_OVERRIDES */
 
 static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
 {
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 18460b8..273281e 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -860,6 +860,20 @@  fast_reauth=1
 # -1 = Do not make any changes.
 # 0-3 = Set AMPDU density (aka factor) to specified value.
 
+# disable_vht: Whether VHT should be disabled.
+# 0 = VHT enabled (if AP supports it)
+# 1 = VHT disabled
+#
+# vht_capa: VHT capabilities to set in the override
+# vht_capa_mask: mask of VHT capabilities
+#
+# vht_rx_mcs_nss_1/2/3/4/5/6/7/8: override the MCS set for RX NSS 1-8
+# vht_tx_mcs_nss_1/2/3/4/5/6/7/8: override the MCS set for TX NSS 1-8
+#  0: MCS 0-7
+#  1: MCS 0-8
+#  2: MCS 0-9
+#  3: not supported
+
 # Example blocks:
 
 # Simple case: WPA-PSK, PSK as an ASCII passphrase, allow all valid ciphers
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 63808ab..9f278de 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -685,6 +685,9 @@  struct wpa_supplicant {
 void wpa_supplicant_apply_ht_overrides(
 	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
 	struct wpa_driver_associate_params *params);
+void wpa_supplicant_apply_vht_overrides(
+	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+	struct wpa_driver_associate_params *params);
 
 int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);