aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Crispin <john@phrozen.org>2019-04-16 12:33:57 (GMT)
committerJouni Malinen <j@w1.fi>2019-04-25 08:43:59 (GMT)
commit5b3940d0c250d786ba07bed5eca457bff234eceb (patch)
treebceca70f4fe79ec9365e6999e02ddba137daabbb
parent1b90aae9299f0a8618001b38882317787a690485 (diff)
downloadhostap-5b3940d0c250d786ba07bed5eca457bff234eceb.zip
hostap-5b3940d0c250d786ba07bed5eca457bff234eceb.tar.gz
hostap-5b3940d0c250d786ba07bed5eca457bff234eceb.tar.bz2
nl80211: Add driver HE capabilities parsing support
Add code to parse NL80211_BAND_ATTR_IFTYPE_DATA when reading the band info. This is needed to find out about the local HE capabilities in AP mode. Signed-off-by: Shashidhar Lakkavalli <slakkavalli@datto.com> Signed-off-by: John Crispin <john@phrozen.org>
-rw-r--r--src/drivers/driver.h10
-rw-r--r--src/drivers/driver_nl80211_capa.c80
2 files changed, 86 insertions, 4 deletions
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 095bfd9..0acc095 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -159,7 +159,9 @@ struct hostapd_channel_data {
};
#define HE_MAX_NUM_SS 8
-#define HE_MAX_PHY_CAPAB_SIZE 3
+#define HE_MAX_MAC_CAPAB_SIZE 6
+#define HE_MAX_PHY_CAPAB_SIZE 11
+#define HE_MAX_MCS_CAPAB_SIZE 12
/**
* struct he_ppe_threshold - IEEE 802.11ax HE PPE Threshold
@@ -175,9 +177,9 @@ struct he_ppe_threshold {
*/
struct he_capabilities {
u8 he_supported;
- u32 phy_cap[HE_MAX_PHY_CAPAB_SIZE];
- u32 mac_cap;
- u32 mcs;
+ u8 phy_cap[HE_MAX_PHY_CAPAB_SIZE];
+ u8 mac_cap[HE_MAX_MAC_CAPAB_SIZE];
+ u8 mcs[HE_MAX_MCS_CAPAB_SIZE];
struct he_ppe_threshold ppet;
};
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index fad290b..a90a55d 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -1500,6 +1500,73 @@ static int phy_info_rates(struct hostapd_hw_modes *mode, struct nlattr *tb)
}
+static int phy_info_iftype(struct hostapd_hw_modes *mode,
+ struct nlattr *nl_iftype)
+{
+ struct nlattr *tb[NL80211_BAND_IFTYPE_ATTR_MAX + 1];
+ struct he_capabilities *he_capab = &mode->he_capab;
+ struct nlattr *tb_flags[NL80211_IFTYPE_MAX + 1];
+ size_t len;
+
+ nla_parse(tb, NL80211_BAND_IFTYPE_ATTR_MAX,
+ nla_data(nl_iftype), nla_len(nl_iftype), NULL);
+
+ if (!tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES])
+ return NL_STOP;
+
+ if (nla_parse_nested(tb_flags, NL80211_IFTYPE_MAX,
+ tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES], NULL))
+ return NL_STOP;
+
+ if (!nla_get_flag(tb_flags[NL80211_IFTYPE_AP]))
+ return NL_OK;
+
+ he_capab->he_supported = 1;
+
+ if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]) {
+ len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]);
+
+ if (len > sizeof(he_capab->phy_cap))
+ len = sizeof(he_capab->phy_cap);
+ os_memcpy(he_capab->phy_cap,
+ nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]),
+ len);
+ }
+
+ if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]) {
+ len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]);
+
+ if (len > sizeof(he_capab->mac_cap))
+ len = sizeof(he_capab->mac_cap);
+ os_memcpy(he_capab->mac_cap,
+ nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]),
+ len);
+ }
+
+ if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]) {
+ len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]);
+
+ if (len > sizeof(he_capab->mcs))
+ len = sizeof(he_capab->mcs);
+ os_memcpy(he_capab->mcs,
+ nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]),
+ len);
+ }
+
+ if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]) {
+ len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]);
+
+ if (len > sizeof(he_capab->ppet))
+ len = sizeof(he_capab->ppet);
+ os_memcpy(&he_capab->ppet,
+ nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]),
+ len);
+ }
+
+ return NL_OK;
+}
+
+
static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band)
{
struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
@@ -1556,6 +1623,19 @@ static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band)
return ret;
}
+ if (tb_band[NL80211_BAND_ATTR_IFTYPE_DATA]) {
+ struct nlattr *nl_iftype;
+ int rem_band;
+
+ nla_for_each_nested(nl_iftype,
+ tb_band[NL80211_BAND_ATTR_IFTYPE_DATA],
+ rem_band) {
+ ret = phy_info_iftype(mode, nl_iftype);
+ if (ret != NL_OK)
+ return ret;
+ }
+ }
+
return NL_OK;
}