]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Add regulatory wmm_limit to hostapd_channel_data
authorHaim Dreyfuss <haim.dreyfuss@intel.com>
Wed, 3 Apr 2019 16:07:51 +0000 (19:07 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 28 May 2019 15:54:05 +0000 (18:54 +0300)
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>
src/drivers/driver.h
src/drivers/driver_nl80211_capa.c

index 6210fc2d989b5628f2f0c257a5362368f807a753..5f870a1f2f3895cf0ebcec925ecf891d09c84ae2 100644 (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
index a90a55db8616edb73bcaf5e07c25ff380fbfde62..ab9b19f393b3d85299db967f0edbcb36b95613d2 100644 (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;
+       }
 }