aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTamizh chelvam <c_traja@qti.qualcomm.com>2016-08-31 14:15:47 (GMT)
committerJouni Malinen <j@w1.fi>2016-09-05 18:14:40 (GMT)
commitfc72a48a632146b042637f376f9c887f783f0a08 (patch)
tree0a97111b70fd33215605bba30c3c847d8eba8b24 /src
parent22950d0568fddd9fcd11562d5a38c8e595ab5c99 (diff)
downloadhostap-fc72a48a632146b042637f376f9c887f783f0a08.zip
hostap-fc72a48a632146b042637f376f9c887f783f0a08.tar.gz
hostap-fc72a48a632146b042637f376f9c887f783f0a08.tar.bz2
hostapd: Use stations nsts capability in (Re)Association Response frame
Some deployed stations incorrectly consider nsts capability in (Re)Association Response frame as required capability instead of maximum capability and if it is greater than station's capability then beamform will not happen in uplink traffic. This commit adds support for an optional workaround to use station's nsts capability in (Re)Association Response frame if the station's nsts is less than AP by using the use_sta_nsts=1 configuration parameter. This configuration is introduced in this commit and it is disabled by default. Signed-off-by: Tamizh chelvam <c_traja@qti.qualcomm.com>
Diffstat (limited to 'src')
-rw-r--r--src/ap/ap_config.h1
-rw-r--r--src/ap/beacon.c4
-rw-r--r--src/ap/ieee802_11.c18
-rw-r--r--src/ap/ieee802_11.h2
-rw-r--r--src/ap/ieee802_11_vht.c16
5 files changed, 35 insertions, 6 deletions
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 64daf4c..b16286b 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -582,6 +582,7 @@ struct hostapd_bss_config {
u8 radio_measurements[RRM_CAPABILITIES_IE_LEN];
int vendor_vht;
+ int use_sta_nsts;
char *no_probe_resp_if_seen_on;
char *no_auth_if_seen_on;
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 0570ab7..202abe6 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -485,7 +485,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
#ifdef CONFIG_IEEE80211AC
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
- pos = hostapd_eid_vht_capabilities(hapd, pos);
+ pos = hostapd_eid_vht_capabilities(hapd, pos, 0);
pos = hostapd_eid_vht_operation(hapd, pos);
pos = hostapd_eid_txpower_envelope(hapd, pos);
pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
@@ -1105,7 +1105,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
#ifdef CONFIG_IEEE80211AC
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
- tailpos = hostapd_eid_vht_capabilities(hapd, tailpos);
+ tailpos = hostapd_eid_vht_capabilities(hapd, tailpos, 0);
tailpos = hostapd_eid_vht_operation(hapd, tailpos);
tailpos = hostapd_eid_txpower_envelope(hapd, tailpos);
tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index eed5483..2ecd78f 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1944,7 +1944,23 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
#ifdef CONFIG_IEEE80211AC
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
- p = hostapd_eid_vht_capabilities(hapd, p);
+ u32 nsts = 0, sta_nsts;
+
+ if (hapd->conf->use_sta_nsts && sta->vht_capabilities) {
+ struct ieee80211_vht_capabilities *capa;
+
+ nsts = (hapd->iface->conf->vht_capab >>
+ VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7;
+ capa = sta->vht_capabilities;
+ sta_nsts = (le_to_host32(capa->vht_capabilities_info) >>
+ VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7;
+
+ if (nsts < sta_nsts)
+ nsts = 0;
+ else
+ nsts = sta_nsts;
+ }
+ p = hostapd_eid_vht_capabilities(hapd, p, nsts);
p = hostapd_eid_vht_operation(hapd, p);
}
#endif /* CONFIG_IEEE80211AC */
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index 71b3b49..0327dec 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -50,7 +50,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid);
-u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts);
u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid);
diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c
index 0841898..f30f63b 100644
--- a/src/ap/ieee802_11_vht.c
+++ b/src/ap/ieee802_11_vht.c
@@ -20,7 +20,7 @@
#include "dfs.h"
-u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid)
+u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts)
{
struct ieee80211_vht_capabilities *cap;
struct hostapd_hw_modes *mode = hapd->iface->current_mode;
@@ -50,6 +50,18 @@ u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid)
cap->vht_capabilities_info = host_to_le32(
hapd->iface->conf->vht_capab);
+ if (nsts != 0) {
+ u32 hapd_nsts;
+
+ hapd_nsts = le_to_host32(cap->vht_capabilities_info);
+ hapd_nsts = (hapd_nsts >> VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7;
+ cap->vht_capabilities_info &=
+ ~(host_to_le32(hapd_nsts <<
+ VHT_CAP_BEAMFORMEE_STS_OFFSET));
+ cap->vht_capabilities_info |=
+ host_to_le32(nsts << VHT_CAP_BEAMFORMEE_STS_OFFSET);
+ }
+
/* Supported MCS set comes from hw */
os_memcpy(&cap->vht_supported_mcs_set, mode->vht_mcs_set, 8);
@@ -398,7 +410,7 @@ u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid)
WPA_PUT_BE32(pos, (OUI_BROADCOM << 8) | VENDOR_VHT_TYPE);
pos += 4;
*pos++ = VENDOR_VHT_SUBTYPE;
- pos = hostapd_eid_vht_capabilities(hapd, pos);
+ pos = hostapd_eid_vht_capabilities(hapd, pos, 0);
pos = hostapd_eid_vht_operation(hapd, pos);
return pos;