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 <haim.dreyfuss@intel.com>
This commit is contained in:
Haim Dreyfuss 2019-04-03 19:07:51 +03:00 committed by Jouni Malinen
parent bab3b7c5c7
commit 636c02c6e9
2 changed files with 75 additions and 0 deletions

View file

@ -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

View file

@ -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;
}
}