From 5b3940d0c250d786ba07bed5eca457bff234eceb Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 16 Apr 2019 14:33:57 +0200 Subject: [PATCH] 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 Signed-off-by: John Crispin --- src/drivers/driver.h | 10 ++-- src/drivers/driver_nl80211_capa.c | 80 +++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 095bfd96a..0acc0958a 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 fad290bdf..a90a55db8 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; }