]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
hostapd: Use stations nsts capability in (Re)Association Response frame
authorTamizh chelvam <c_traja@qti.qualcomm.com>
Wed, 31 Aug 2016 14:15:47 +0000 (19:45 +0530)
committerJouni Malinen <j@w1.fi>
Mon, 5 Sep 2016 18:14:40 +0000 (21:14 +0300)
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>
hostapd/config_file.c
hostapd/hostapd.conf
src/ap/ap_config.h
src/ap/beacon.c
src/ap/ieee802_11.c
src/ap/ieee802_11.h
src/ap/ieee802_11_vht.c
wpa_supplicant/mesh_mpm.c

index 1b506a7afb46b2b7843fc2900aefe3882e743fc1..fa08234e688735c4c3e17f065997f7bb1ce27c52 100644 (file)
@@ -2895,6 +2895,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                conf->vht_oper_centr_freq_seg1_idx = atoi(pos);
        } else if (os_strcmp(buf, "vendor_vht") == 0) {
                bss->vendor_vht = atoi(pos);
+       } else if (os_strcmp(buf, "use_sta_nsts") == 0) {
+               bss->use_sta_nsts = atoi(pos);
 #endif /* CONFIG_IEEE80211AC */
        } else if (os_strcmp(buf, "max_listen_interval") == 0) {
                bss->max_listen_interval = atoi(pos);
index a310c057601354550fdf2f7a7f708ffd179baca6..4fc32786faf955fc41943638ad884c48e30a2908 100644 (file)
@@ -685,6 +685,13 @@ wmm_ac_vo_acm=0
 #
 #vht_oper_centr_freq_seg1_idx=159
 
+# Workaround to use station's nsts capability in (Re)Association Response frame
+# This may be needed with some deployed devices as an interoperability
+# workaround for beamforming if the AP's capability is greater than the
+# station's capability. This is disabled by default and can be enabled by
+# setting use_sta_nsts=1.
+#use_sta_nsts=0
+
 ##### IEEE 802.1X-2004 related configuration ##################################
 
 # Require IEEE 802.1X authorization
index 64daf4c814a021cc394492437f9974ad150ae3ce..b16286b581484d2ab3c3a0b784fb53b385f9ca5f 100644 (file)
@@ -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;
index 0570ab721fc6cb1af695f46ebdd571742e18c98d..202abe6de0e8e82aaa90bae7750836792249d313 100644 (file)
@@ -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);
index eed54836e44989bda85784073b69dc6f84aea05d..2ecd78f2506c9acf0ff32ee59d32a8f4949526be 100644 (file)
@@ -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 */
index 71b3b497ad12c2ecbb627c201f737de4d9d62682..0327dec2a2bc30bfde6e1de5368c92ee082c5a9d 100644 (file)
@@ -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);
index 08418980a29758d7e583989f7c0c0c7f3ba10cbe..f30f63bc5709418f30f73478c7f97c4f7d9e7f7f 100644 (file)
@@ -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;
index 7ffdefe217415c391de0a1ab6a18de92ee151bb7..d14c7e3b20458131c54d7da8f2087bcd0cdf5471 100644 (file)
@@ -348,7 +348,7 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
        if (type != PLINK_CLOSE && wpa_s->mesh_vht_enabled) {
                u8 vht_capa_oper[2 + 12 + 2 + 5];
 
-               pos = hostapd_eid_vht_capabilities(bss, vht_capa_oper);
+               pos = hostapd_eid_vht_capabilities(bss, vht_capa_oper, 0);
                pos = hostapd_eid_vht_operation(bss, pos);
                wpabuf_put_data(buf, vht_capa_oper, pos - vht_capa_oper);
        }