[PATCH 3/9] hostapd: verify vht capabilities are supported by driver
eliad at wizery.com
eliad
Thu Oct 17 01:03:40 PDT 2013
From: Eliad Peller <eliad at wizery.com>
Make sure the defined vht capabilities are supported by
the driver.
Signed-hostap: Eliad Peller <eliadx.peller at intel.com>
---
src/ap/hw_features.c | 86 ++++++++++++++++++++++++++++++++++++++++++
src/common/ieee802_11_defs.h | 3 ++
src/utils/common.c | 12 ++++++
src/utils/common.h | 1 +
4 files changed, 102 insertions(+)
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 8a239f4..d76b569 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -613,6 +613,88 @@ static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
return 1;
}
+#ifdef CONFIG_IEEE80211AC
+static int ieee80211ac_cap_check(u32 hw, u32 conf, u32 cap, const char *name)
+{
+ u32 req_cap = conf & cap;
+
+ /*
+ * make sure we support all requested capabilities.
+ * NOTE: we assume that 'cap' represents a capability mask,
+ * not discrete value.
+ */
+ if ((hw & req_cap) != req_cap) {
+ wpa_printf(MSG_ERROR, "Driver does not support configured "
+ "VHT capability [%s]", name);
+ return 0;
+ }
+ return 1;
+}
+
+static int ieee80211ac_cap_check_max(u32 hw, u32 conf, u32 cap,
+ const char *name)
+{
+ u32 hw_max = hw & cap;
+ u32 conf_val = conf & cap;
+
+ if (conf_val > hw_max) {
+ int offset = find_first_bit(cap);
+ wpa_printf(MSG_ERROR, "Configured VHT capability [%s] exceeds "
+ "max value supported by the driver (%d > %d)",
+ name, conf_val >> offset, hw_max >> offset);
+ return 0;
+ }
+ return 1;
+}
+
+static int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface)
+{
+ u32 hw = iface->current_mode->vht_capab;
+ u32 conf = iface->conf->vht_capab;
+
+ wpa_printf(MSG_DEBUG, "hw vht capab: 0x%x, conf vht capab: 0x%x",
+ hw, conf);
+
+#define VHT_CAP_CHECK(cap) do {\
+ if (!ieee80211ac_cap_check(hw, conf, cap, #cap)) \
+ return 0; \
+ } while (0)
+
+#define VHT_CAP_CHECK_MAX(cap) do {\
+ if (!ieee80211ac_cap_check_max(hw, conf, cap, #cap)) \
+ return 0; \
+ } while (0)
+
+
+ VHT_CAP_CHECK_MAX(VHT_CAP_MAX_MPDU_LENGTH_MASK);
+ VHT_CAP_CHECK(VHT_CAP_SUPP_CHAN_WIDTH_160MHZ);
+ VHT_CAP_CHECK(VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ);
+ VHT_CAP_CHECK(VHT_CAP_RXLDPC);
+ VHT_CAP_CHECK(VHT_CAP_SHORT_GI_80);
+ VHT_CAP_CHECK(VHT_CAP_SHORT_GI_160);
+ VHT_CAP_CHECK(VHT_CAP_TXSTBC);
+ VHT_CAP_CHECK_MAX(VHT_CAP_RXSTBC_MASK);
+ VHT_CAP_CHECK(VHT_CAP_SU_BEAMFORMER_CAPABLE);
+ VHT_CAP_CHECK(VHT_CAP_SU_BEAMFORMEE_CAPABLE);
+ VHT_CAP_CHECK_MAX(VHT_CAP_BEAMFORMEE_STS_MAX);
+ VHT_CAP_CHECK_MAX(VHT_CAP_SOUNDING_DIMENSION_MAX);
+ VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMER_CAPABLE);
+ VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMEE_CAPABLE);
+ VHT_CAP_CHECK(VHT_CAP_VHT_TXOP_PS);
+ VHT_CAP_CHECK(VHT_CAP_HTC_VHT);
+ VHT_CAP_CHECK_MAX(VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT);
+ VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB);
+ VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB);
+ VHT_CAP_CHECK(VHT_CAP_RX_ANTENNA_PATTERN);
+ VHT_CAP_CHECK(VHT_CAP_TX_ANTENNA_PATTERN);
+
+#undef VHT_CAP_CHECK
+#undef VHT_CAP_CHECK_MAX
+
+ return 1;
+}
+#endif /* CONFIG_IEEE80211AC */
+
#endif /* CONFIG_IEEE80211N */
@@ -624,6 +706,10 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface)
return 0;
if (!ieee80211n_supported_ht_capab(iface))
return -1;
+#ifdef CONFIG_IEEE80211AC
+ if (!ieee80211ac_supported_vht_capab(iface))
+ return -1;
+#endif /* CONFIG_IEEE80211AC */
ret = ieee80211n_check_40mhz(iface);
if (ret)
return ret;
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index c51c46c..67f6451 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -702,6 +702,7 @@ struct ieee80211_vht_operation {
/* VHT Defines */
#define VHT_CAP_MAX_MPDU_LENGTH_7991 ((u32) BIT(0))
#define VHT_CAP_MAX_MPDU_LENGTH_11454 ((u32) BIT(1))
+#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_RXLDPC ((u32) BIT(4))
@@ -712,6 +713,8 @@ struct ieee80211_vht_operation {
#define VHT_CAP_RXSTBC_2 ((u32) BIT(9))
#define VHT_CAP_RXSTBC_3 ((u32) BIT(8) | BIT(9))
#define VHT_CAP_RXSTBC_4 ((u32) BIT(10))
+#define VHT_CAP_RXSTBC_MASK ((u32) BIT(8) | BIT(9) | \
+ BIT(10))
#define VHT_CAP_SU_BEAMFORMER_CAPABLE ((u32) BIT(11))
#define VHT_CAP_SU_BEAMFORMEE_CAPABLE ((u32) BIT(12))
#define VHT_CAP_BEAMFORMEE_STS_MAX ((u32) BIT(13) | \
diff --git a/src/utils/common.c b/src/utils/common.c
index 207d477..5494c79 100644
--- a/src/utils/common.c
+++ b/src/utils/common.c
@@ -577,6 +577,18 @@ int is_hex(const u8 *data, size_t len)
return 0;
}
+int find_first_bit(u32 value)
+{
+ int pos = 0;
+
+ while (value) {
+ if (value & 0x1)
+ return pos;
+ value >>= 1;
+ pos++;
+ }
+ return -1;
+}
size_t merge_byte_arrays(u8 *res, size_t res_len,
const u8 *src1, size_t src1_len,
diff --git a/src/utils/common.h b/src/utils/common.h
index 29f0b95..fad24fd 100644
--- a/src/utils/common.h
+++ b/src/utils/common.h
@@ -485,6 +485,7 @@ const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len);
char * wpa_config_parse_string(const char *value, size_t *len);
int is_hex(const u8 *data, size_t len);
+int find_first_bit(u32 value);
size_t merge_byte_arrays(u8 *res, size_t res_len,
const u8 *src1, size_t src1_len,
const u8 *src2, size_t src2_len);
--
1.7.10.4
More information about the Hostap
mailing list