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>
This commit is contained in:
John Crispin 2019-04-16 14:33:57 +02:00 committed by Jouni Malinen
parent 1b90aae929
commit 5b3940d0c2
2 changed files with 86 additions and 4 deletions

View file

@ -159,7 +159,9 @@ struct hostapd_channel_data {
}; };
#define HE_MAX_NUM_SS 8 #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 * struct he_ppe_threshold - IEEE 802.11ax HE PPE Threshold
@ -175,9 +177,9 @@ struct he_ppe_threshold {
*/ */
struct he_capabilities { struct he_capabilities {
u8 he_supported; u8 he_supported;
u32 phy_cap[HE_MAX_PHY_CAPAB_SIZE]; u8 phy_cap[HE_MAX_PHY_CAPAB_SIZE];
u32 mac_cap; u8 mac_cap[HE_MAX_MAC_CAPAB_SIZE];
u32 mcs; u8 mcs[HE_MAX_MCS_CAPAB_SIZE];
struct he_ppe_threshold ppet; struct he_ppe_threshold ppet;
}; };

View file

@ -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) static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band)
{ {
struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1]; 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; 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; return NL_OK;
} }