]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
hostapd: Mask out not-supported VHT capabilities
authorEliad Peller <eliad@wizery.com>
Sun, 27 Oct 2013 17:28:40 +0000 (19:28 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 27 Oct 2013 17:28:40 +0000 (19:28 +0200)
Mask the remote VHT capabilities with our own capabilities, similarly
to what is done for HT capabilities.

Signed-hostap: Eliad Peller <eliadx.peller@intel.com>

src/ap/ieee802_11_vht.c
src/common/ieee802_11_defs.h

index 0012c0ff890f03f282ee8c6f9823e94b1965f66f..38590a32b6da72df7d0ecc37682ddabf11d69871 100644 (file)
@@ -113,9 +113,60 @@ void hostapd_get_vht_capab(struct hostapd_data *hapd,
                           struct ieee80211_vht_capabilities *vht_cap,
                           struct ieee80211_vht_capabilities *neg_vht_cap)
 {
+       u32 cap, own_cap, sym_caps;
+
        if (vht_cap == NULL)
                return;
        os_memcpy(neg_vht_cap, vht_cap, sizeof(*neg_vht_cap));
 
-       /* TODO: mask own capabilities, like get_ht_capab() */
+       cap = le_to_host32(neg_vht_cap->vht_capabilities_info);
+       own_cap = hapd->iconf->vht_capab;
+
+       /* mask out symmetric VHT capabilities we don't support */
+       sym_caps = VHT_CAP_SHORT_GI_80 | VHT_CAP_SHORT_GI_160;
+       cap &= ~sym_caps | (own_cap & sym_caps);
+
+       /* mask out beamformer/beamformee caps if not supported */
+       if (!(own_cap & VHT_CAP_SU_BEAMFORMER_CAPABLE))
+               cap &= ~(VHT_CAP_SU_BEAMFORMEE_CAPABLE |
+                        VHT_CAP_BEAMFORMEE_STS_MAX);
+
+       if (!(own_cap & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
+               cap &= ~(VHT_CAP_SU_BEAMFORMER_CAPABLE |
+                        VHT_CAP_SOUNDING_DIMENSION_MAX);
+
+       if (!(own_cap & VHT_CAP_MU_BEAMFORMER_CAPABLE))
+               cap &= ~VHT_CAP_MU_BEAMFORMEE_CAPABLE;
+
+       if (!(own_cap & VHT_CAP_MU_BEAMFORMEE_CAPABLE))
+               cap &= ~VHT_CAP_MU_BEAMFORMER_CAPABLE;
+
+       /* mask channel widths we don't support */
+       switch (own_cap & VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
+       case VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
+               break;
+       case VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
+               if (cap & VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) {
+                       cap &= ~VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
+                       cap |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+               }
+               break;
+       default:
+               cap &= ~VHT_CAP_SUPP_CHAN_WIDTH_MASK;
+               break;
+       }
+
+       if (!(cap & VHT_CAP_SUPP_CHAN_WIDTH_MASK))
+               cap &= ~VHT_CAP_SHORT_GI_160;
+
+       /*
+        * if we don't support RX STBC, mask out TX STBC in the STA's HT caps
+        * if we don't support TX STBC, mask out RX STBC in the STA's HT caps
+        */
+       if (!(own_cap & VHT_CAP_RXSTBC_MASK))
+               cap &= ~VHT_CAP_TXSTBC;
+       if (!(own_cap & VHT_CAP_TXSTBC))
+               cap &= ~VHT_CAP_RXSTBC_MASK;
+
+       neg_vht_cap->vht_capabilities_info = host_to_le32(cap);
 }
index 4d60fc0a96d906d5afcfaaee0ee6c38aa955d0c8..8ce1bfb25e821d436cd343996529b2e9b224d097 100644 (file)
@@ -707,6 +707,7 @@ struct ieee80211_vht_operation {
 #define VHT_CAP_MAX_MPDU_LENGTH_MASK                ((u32) BIT(0) | BIT(1))
 #define VHT_CAP_SUPP_CHAN_WIDTH_160MHZ              ((u32) BIT(2))
 #define VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ     ((u32) BIT(3))
+#define VHT_CAP_SUPP_CHAN_WIDTH_MASK                ((u32) BIT(2) | BIT(3))
 #define VHT_CAP_RXLDPC                              ((u32) BIT(4))
 #define VHT_CAP_SHORT_GI_80                         ((u32) BIT(5))
 #define VHT_CAP_SHORT_GI_160                        ((u32) BIT(6))