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);
#
#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
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;
#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);
#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);
#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 */
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);
#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;
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);
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;
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);
}