From 636c02c6e9ec03b5f9424d0ebdcd56b6bcfc1c7a Mon Sep 17 00:00:00 2001 From: Haim Dreyfuss Date: Wed, 3 Apr 2019 19:07:51 +0300 Subject: [PATCH] nl80211: Add regulatory wmm_limit to hostapd_channel_data ETSI EN 301 893 v2.1.1 (2017-05) standard defines a new channel access mechanism that all devices (WLAN and LAA) need to comply with. In previous versions the device was allowed by ETSI to implement 802.11 channel access mechanism based on a set of priority classes which are taken from 802.11. According of the new standard there might be some exceptions which require ETSI countries to follow more restrictive rules. In such a case the AP's wmm IE need to comply with ETSI limitation. To be able to do so the regulatory domain passes the new limitation values if needed. Implement this, by storing it and use it to calculate the new WMM parameters. This commit adds determination of regulator limitations to NL80211_CMD_GET_WIPHY processing so that the information is available for upper layer implementation to use later when constructing WMM element. Signed-off-by: Haim Dreyfuss --- src/drivers/driver.h | 24 +++++++++++++++ src/drivers/driver_nl80211_capa.c | 51 +++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 6210fc2d9..5f870a1f2 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -101,6 +101,20 @@ enum reg_type { REGDOM_TYPE_INTERSECTION, }; +/** + * struct hostapd_wmm_rule - WMM regulatory rule + * @min_cwmin: Lower bound of CW_min value + * @min_cwmax: Lower bound of CW_max value + * @min_aifs: Lower bound of AIFS value + * @max_txop: Upper bound of TXOP, value in units of 32 usec + */ +struct hostapd_wmm_rule { + int min_cwmin; + int min_cwmax; + int min_aifs; + int max_txop; +}; + /** * struct hostapd_channel_data - Channel information */ @@ -156,6 +170,16 @@ struct hostapd_channel_data { * dfs_cac_ms - DFS CAC time in milliseconds */ unsigned int dfs_cac_ms; + + /** + * wmm_rules_valid - Indicates wmm_rules state + */ + int wmm_rules_valid; + + /** + * wmm_rules - WMM regulatory rules + */ + struct hostapd_wmm_rule wmm_rules[WMM_AC_NUM]; }; #define HE_MAX_MAC_CAPAB_SIZE 6 diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index a90a55db8..ab9b19f39 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -1394,6 +1394,57 @@ static void phy_info_freq(struct hostapd_hw_modes *mode, chan->dfs_cac_ms = nla_get_u32( tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME]); } + + chan->wmm_rules_valid = 0; + if (tb_freq[NL80211_FREQUENCY_ATTR_WMM]) { + static struct nla_policy wmm_policy[NL80211_WMMR_MAX + 1] = { + [NL80211_WMMR_CW_MIN] = { .type = NLA_U16 }, + [NL80211_WMMR_CW_MAX] = { .type = NLA_U16 }, + [NL80211_WMMR_AIFSN] = { .type = NLA_U8 }, + [NL80211_WMMR_TXOP] = { .type = NLA_U16 }, + }; + struct nlattr *nl_wmm; + struct nlattr *tb_wmm[NL80211_WMMR_MAX + 1]; + int rem_wmm, ac, count = 0; + + nla_for_each_nested(nl_wmm, tb_freq[NL80211_FREQUENCY_ATTR_WMM], + rem_wmm) { + if (nla_parse_nested(tb_wmm, NL80211_WMMR_MAX, nl_wmm, + wmm_policy)) { + wpa_printf(MSG_DEBUG, + "nl80211: Failed to parse WMM rules attribute"); + return; + } + if (!tb_wmm[NL80211_WMMR_CW_MIN] || + !tb_wmm[NL80211_WMMR_CW_MAX] || + !tb_wmm[NL80211_WMMR_AIFSN] || + !tb_wmm[NL80211_WMMR_TXOP]) { + wpa_printf(MSG_DEBUG, + "nl80211: Channel is missing WMM rule attribute"); + return; + } + ac = nl_wmm->nla_type; + if (ac < 0 || ac >= WMM_AC_NUM) { + wpa_printf(MSG_DEBUG, + "nl80211: Invalid AC value %d", ac); + return; + } + + chan->wmm_rules[ac].min_cwmin = + nla_get_u16(tb_wmm[NL80211_WMMR_CW_MIN]); + chan->wmm_rules[ac].min_cwmax = + nla_get_u16(tb_wmm[NL80211_WMMR_CW_MAX]); + chan->wmm_rules[ac].min_aifs = + nla_get_u8(tb_wmm[NL80211_WMMR_AIFSN]); + chan->wmm_rules[ac].max_txop = + nla_get_u16(tb_wmm[NL80211_WMMR_TXOP]) / 32; + count++; + } + + /* Set valid flag if all the AC rules are present */ + if (count == WMM_AC_NUM) + chan->wmm_rules_valid = 1; + } }