]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Add Transmit Power Envelope element in 6 GHz
authorPradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
Thu, 7 Apr 2022 23:56:54 +0000 (16:56 -0700)
committerJouni Malinen <j@w1.fi>
Fri, 8 Apr 2022 16:50:26 +0000 (19:50 +0300)
Add Transmit Power Envelope element for 6 GHz per IEEE Std
802.11ax-2021.

Currently, this uses hard coded EIRP/PSD limits which are applicable to
6 GHz operation in United states, Japan, and Korea. Support to extract
power limits from kernel data will be added after complete regulatory
support is added for the 6 GHz band.

Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
src/ap/beacon.c
src/ap/ieee802_11.c
src/common/ieee802_11_defs.h

index 5ab44f64e15c3541e4ecb77f36cfa7ba5724c5cf..24ad61c4660a60cd343d188fdc0dab77a3482598 100644 (file)
@@ -497,9 +497,15 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
                        3 + sizeof(struct ieee80211_he_operation) +
                        3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) +
                        3 + sizeof(struct ieee80211_spatial_reuse);
-               if (is_6ghz_op_class(hapd->iconf->op_class))
+               if (is_6ghz_op_class(hapd->iconf->op_class)) {
                        buflen += sizeof(struct ieee80211_he_6ghz_oper_info) +
                                3 + sizeof(struct ieee80211_he_6ghz_band_cap);
+                        /* An additional Transmit Power Envelope element for
+                         * subordinate client */
+                       if (hapd->iconf->he_6ghz_reg_pwr_type ==
+                           HE_6GHZ_INDOOR_AP)
+                               buflen += 4;
+               }
        }
 #endif /* CONFIG_IEEE80211AX */
 
@@ -1353,6 +1359,15 @@ static u8 * hostapd_gen_fils_discovery(struct hostapd_data *hapd, size_t *len)
        buf_len = pos - buf;
        total_len += buf_len;
 
+#ifdef CONFIG_IEEE80211AX
+       /* Transmit Power Envelope element(s) */
+       if (is_6ghz_op_class(hapd->iconf->op_class)) {
+               total_len += 4;
+               if (hapd->iconf->he_6ghz_reg_pwr_type == HE_6GHZ_INDOOR_AP)
+                       total_len += 4;
+       }
+#endif /* CONFIG_IEEE80211AX */
+
        head = os_zalloc(total_len);
        if (!head)
                return NULL;
@@ -1425,6 +1440,9 @@ static u8 * hostapd_gen_fils_discovery(struct hostapd_data *hapd, size_t *len)
                pos += buf_len;
        }
 
+       if (is_6ghz_op_class(hapd->iconf->op_class))
+               pos = hostapd_eid_txpower_envelope(hapd, pos);
+
        *len = pos - (u8 *) head;
        wpa_hexdump(MSG_DEBUG, "FILS Discovery frame template",
                    head, pos - (u8 *) head);
@@ -1499,9 +1517,15 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
                        3 + sizeof(struct ieee80211_he_operation) +
                        3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) +
                        3 + sizeof(struct ieee80211_spatial_reuse);
-               if (is_6ghz_op_class(hapd->iconf->op_class))
+               if (is_6ghz_op_class(hapd->iconf->op_class)) {
                        tail_len += sizeof(struct ieee80211_he_6ghz_oper_info) +
                                3 + sizeof(struct ieee80211_he_6ghz_band_cap);
+                        /* An additional Transmit Power Envelope element for
+                         * subordinate client */
+                       if (hapd->iconf->he_6ghz_reg_pwr_type ==
+                           HE_6GHZ_INDOOR_AP)
+                               tail_len += 4;
+               }
        }
 #endif /* CONFIG_IEEE80211AX */
 
index d2b718974222cc2b3dc2cd0a24be1e30a4d43296..fa5f043187a7086c4aa14892ab94a5ebdcc68a15 100644 (file)
@@ -6904,6 +6904,38 @@ void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
 }
 
 
+static u8 * hostapd_add_tpe_info(u8 *eid, u8 tx_pwr_count,
+                                enum max_tx_pwr_interpretation tx_pwr_intrpn,
+                                u8 tx_pwr_cat, u8 tx_pwr)
+{
+       int i;
+
+       *eid++ = WLAN_EID_TRANSMIT_POWER_ENVELOPE; /* Element ID */
+       *eid++ = 2 + tx_pwr_count; /* Length */
+
+       /*
+        * Transmit Power Information field
+        *      bits 0-2 : Maximum Transmit Power Count
+        *      bits 3-5 : Maximum Transmit Power Interpretation
+        *      bits 6-7 : Maximum Transmit Power Category
+        */
+       *eid++ = tx_pwr_count | (tx_pwr_intrpn << 3) | (tx_pwr_cat << 6);
+
+       /* Maximum Transmit Power field */
+       for (i = 0; i <= tx_pwr_count; i++)
+               *eid++ = tx_pwr;
+
+       return eid;
+}
+
+
+/*
+ * TODO: Extract power limits from channel data after 6G regulatory
+ *     support.
+ */
+#define REG_PSD_MAX_TXPOWER_FOR_DEFAULT_CLIENT      (-1) /* dBm/MHz */
+#define REG_PSD_MAX_TXPOWER_FOR_SUBORDINATE_CLIENT  5    /* dBm/MHz */
+
 u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid)
 {
        struct hostapd_iface *iface = hapd->iface;
@@ -6928,6 +6960,43 @@ u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid)
        if (i == mode->num_channels)
                return eid;
 
+#ifdef CONFIG_IEEE80211AX
+       /* IEEE Std 802.11ax-2021, Annex E.2.7 (6 GHz band in the United
+        * States): An AP that is an Indoor Access Point per regulatory rules
+        * shall send at least two Transmit Power Envelope elements in Beacon
+        * and Probe Response frames as follows:
+        *  - Maximum Transmit Power Category subfield = Default;
+        *      Unit interpretation = Regulatory client EIRP PSD
+        *  - Maximum Transmit Power Category subfield = Subordinate Device;
+        *      Unit interpretation = Regulatory client EIRP PSD
+        */
+       if (is_6ghz_op_class(iconf->op_class)) {
+               enum max_tx_pwr_interpretation tx_pwr_intrpn;
+
+               /* Same Maximum Transmit Power for all 20 MHz bands */
+               tx_pwr_count = 0;
+               tx_pwr_intrpn = REGULATORY_CLIENT_EIRP_PSD;
+
+               /* Default Transmit Power Envelope for Global Operating Class */
+               tx_pwr = REG_PSD_MAX_TXPOWER_FOR_DEFAULT_CLIENT * 2;
+               eid = hostapd_add_tpe_info(eid, tx_pwr_count, tx_pwr_intrpn,
+                                          REG_DEFAULT_CLIENT, tx_pwr);
+
+               /* Indoor Access Point must include an additional TPE for
+                * subordinate devices */
+               if (iconf->he_6ghz_reg_pwr_type == HE_6GHZ_INDOOR_AP) {
+                       /* TODO: Extract PSD limits from channel data */
+                       tx_pwr = REG_PSD_MAX_TXPOWER_FOR_SUBORDINATE_CLIENT * 2;
+                       eid = hostapd_add_tpe_info(eid, tx_pwr_count,
+                                                  tx_pwr_intrpn,
+                                                  REG_SUBORDINATE_CLIENT,
+                                                  tx_pwr);
+               }
+
+               return eid;
+       }
+#endif /* CONFIG_IEEE80211AX */
+
        switch (hostapd_get_oper_chwidth(iconf)) {
        case CHANWIDTH_USE_HT:
                if (iconf->secondary_channel == 0) {
@@ -7000,19 +7069,9 @@ u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid)
        else
                tx_pwr = max_tx_power;
 
-       *eid++ = WLAN_EID_TRANSMIT_POWER_ENVELOPE;
-       *eid++ = 2 + tx_pwr_count;
-
-       /*
-        * Max Transmit Power count and
-        * Max Transmit Power units = 0 (EIRP)
-        */
-       *eid++ = tx_pwr_count;
-
-       for (i = 0; i <= tx_pwr_count; i++)
-               *eid++ = tx_pwr;
-
-       return eid;
+       return hostapd_add_tpe_info(eid, tx_pwr_count, LOCAL_EIRP,
+                                   0 /* Reserved for bands other than 6 GHz */,
+                                   tx_pwr);
 }
 
 
index db41ba1f2ba39d105c6e90c8cdbc7fdc4d2eb2f2..2c85d3fba014bf3019c0a3da8064d8120222a48f 100644 (file)
@@ -1947,6 +1947,26 @@ struct tpc_report {
        u8 link_margin;
 } STRUCT_PACKED;
 
+/*
+ * IEEE Std 802.11ax-2021, Table 9-275a - Maximum Transmit Power
+ * Interpretation subfield encoding
+ */
+enum max_tx_pwr_interpretation {
+       LOCAL_EIRP = 0,
+       LOCAL_EIRP_PSD = 1,
+       REGULATORY_CLIENT_EIRP = 2,
+       REGULATORY_CLIENT_EIRP_PSD = 3,
+};
+
+/*
+ * IEEE Std 802.11ax-2021, Table E-13 - Maximum Transmit Power
+ * Category subfield encoding in the United States
+ */
+enum reg_6g_client_type {
+       REG_DEFAULT_CLIENT = 0,
+       REG_SUBORDINATE_CLIENT = 1,
+};
+
 #define RRM_CAPABILITIES_IE_LEN 5
 
 /* IEEE Std 802.11-2012, 8.5.7.4 - Link Measurement Request frame format */