8e6f35a..06b57f0 100644
@@ -2508,6 +2508,18 @@ static int hostapd_config_fill(struct hostapd_config
*conf,
} else if (os_strcmp(buf, "vht_oper_centr_freq_seg1_idx") ==
0)
{
conf->vht_oper_centr_freq_seg1_idx = atoi(pos);
+ }
+ else if (os_strcmp(buf, "vht_tpe_lpc_20") == 0) {
+ conf->vht_tpe_lpc_20 = atoi(pos);
+ }
+ else if (os_strcmp(buf, "vht_tpe_lpc_40") == 0) {
+ conf->vht_tpe_lpc_40 = atoi(pos);
+ }
+ else if (os_strcmp(buf, "vht_tpe_lpc_80") == 0) {
+ conf->vht_tpe_lpc_80 = atoi(pos);
+ }
+ else if (os_strcmp(buf, "vht_tpe_lpc_160") == 0) {
+ conf->vht_tpe_lpc_160 = atoi(pos);
#endif /* CONFIG_IEEE80211AC */
} else if (os_strcmp(buf, "max_listen_interval") == 0) {
bss->max_listen_interval = atoi(pos); diff --git
a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 68c4069..054dad9 100644
@@ -589,6 +589,16 @@ wmm_ac_vo_acm=0
# which is channel 159 in 5G band
#
#vht_oper_centr_freq_seg1_idx=159
+#
+#IEEE802.11-ac-5.0: 8.4.2.164
+#VHT Transmit Power Envelope Requires 802.11h support #Local Maximum
+Power Constraints/Channel.
+#Valid Range: -64dBm to 53 dBm in 0.5 dB steps (63.5 dBM disables the
+Power Constraint) #Encoded Range: -128 to 126 (8-bit 2's Compliment)
+(127 disabled the Power Constraint)
+#vht_tpe_lpc_20=0
+#vht_tpe_lpc_40=0
+#vht_tpe_lpc_80=0
+#vht_tpe_lpc_160=0
##### IEEE 802.1X-2004 related configuration
##################################
100644
@@ -163,6 +163,15 @@ struct hostapd_config * hostapd_config_defaults(void)
conf->ap_table_max_size = 255;
conf->ap_table_expiration_time = 60;
+#ifdef CONFIG_IEEE80211AC
+ /* This will help us identify whether user has configured
+ * for a band or not */
+ conf->vht_tpe_lpc_20 = VHT_TPE_PWR_CONSTRAINT_DISABLE;
+ conf->vht_tpe_lpc_40 = VHT_TPE_PWR_CONSTRAINT_DISABLE;
+ conf->vht_tpe_lpc_80 = VHT_TPE_PWR_CONSTRAINT_DISABLE;
+ conf->vht_tpe_lpc_160 = VHT_TPE_PWR_CONSTRAINT_DISABLE; #endif
+
#ifdef CONFIG_TESTING_OPTIONS
conf->ignore_probe_probability = 0.0d;
conf->ignore_auth_probability = 0.0d;
100644
@@ -174,6 +174,14 @@ struct hostapd_nai_realm_data {
} eap_method[MAX_NAI_EAP_METHODS];
};
+/* 127 Means 63.5 dBm, meaning no local max power constraint
+ * So either User has not entered the power constraint for that BW
+ * (or) He configured to use no power constraint, in both cases
+ * For Mandaotry (20MHZ): We will use 127 values
+ * For Optional(40/80/160 MHz): we will skip those fields.
+ */
+#define VHT_TPE_PWR_CONSTRAINT_DISABLE 127
+
/**
* struct hostapd_bss_config - Per-BSS configuration
*/
@@ -465,6 +473,8 @@ struct hostapd_bss_config {
int *sae_groups;
};
+/* Default value for pwr constraint */
+#define DEFAULT_PWR_CONSTRAINT 0
/**
* struct hostapd_config - Per-radio interface configuration @@ -526,6
+536,13 @@ struct hostapd_config {
u8 vht_oper_centr_freq_seg0_idx;
u8 vht_oper_centr_freq_seg1_idx;
+#ifdef CONFIG_IEEE80211AC
+ s8 vht_tpe_lpc_20;
+ s8 vht_tpe_lpc_40;
+ s8 vht_tpe_lpc_80;
+ s8 vht_tpe_lpc_160;
+#endif
+
#ifdef CONFIG_TESTING_OPTIONS
double ignore_probe_probability;
double ignore_auth_probability;
@@ -92,6 +92,30 @@ static u8 * hostapd_eid_erp_info(struct hostapd_data
*hapd, u8 *eid)
return eid;
}
+static u8 * hostapd_eid_pwr_constraint(struct hostapd_data *hapd, u8
+*eid) {
+ u8 *pos = eid;
+
+ if (!hapd->iconf->ieee80211h ||
+ hapd->iface->current_mode == NULL ||
+ hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
+ return eid;
+
+ /* CRDA provides reduced TX power than actual regulatory max TX
power.
+ * * Value of 0 to the Local Power constraint provides an
opportunity
+ * * for the client devices to operate at Power Limit provided
by CRDA
+ * * (for client devices
+ * * "Local max TX pwr" = regul max TX pwr - Local pwr
constraint)*/
+
+ /* Element ID */
+ *pos++ = WLAN_EID_PWR_CONSTRAINT;
+ /* Length */
+ *pos++ = 1;
+ /* Local Power Constraint */
+ *pos++ = DEFAULT_PWR_CONSTRAINT;
+
+ return pos;
+}
static u8 * hostapd_eid_country_add(u8 *pos, u8 *end, int chan_spacing,
struct hostapd_channel_data *start, @@
-245,6 +269,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data
*hapd,
/* ERP Information element */
pos = hostapd_eid_erp_info(hapd, pos);
+ /* Power Constraint element */
+ pos = hostapd_eid_pwr_constraint(hapd, pos);
+
/* Extended supported rates */
pos = hostapd_eid_ext_supp_rates(hapd, pos);
@@ -268,6 +295,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data
*hapd, #ifdef CONFIG_IEEE80211AC
pos = hostapd_eid_vht_capabilities(hapd, pos);
pos = hostapd_eid_vht_operation(hapd, pos);
+ pos = hostapd_eid_vht_tpe(hapd, pos);
#endif /* CONFIG_IEEE80211AC */
/* Wi-Fi Alliance WMM */
@@ -655,6 +683,9 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
/* ERP Information element */
tailpos = hostapd_eid_erp_info(hapd, tailpos);
+ /* Power Constraint element */
+ pos = hostapd_eid_pwr_constraint(hapd, pos);
+
/* Extended supported rates */
tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos);
@@ -682,6 +713,7 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
#ifdef CONFIG_IEEE80211AC
tailpos = hostapd_eid_vht_capabilities(hapd, tailpos);
tailpos = hostapd_eid_vht_operation(hapd, tailpos);
+ tailpos = hostapd_eid_vht_tpe(hapd, tailpos);
#endif /* CONFIG_IEEE80211AC */
/* Wi-Fi Alliance WMM */
5503af1..e72b3e7 100644
@@ -175,6 +175,12 @@ u16 hostapd_own_capab_info(struct hostapd_data *hapd,
struct sta_info *sta,
hapd->iface->num_sta_no_short_slot_time == 0)
capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
+ /* To Do: Also consider driver support for DFS to set Spectrum
Mgmt*/
+ if (hapd->iface->current_mode &&
+ hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
+ hapd->iconf->ieee80211h)
+ capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
+
return capab;
}
2aab56d..e1b3b2d 100644
@@ -47,6 +47,7 @@ u8 * hostapd_eid_ht_capabilities(struct hostapd_data
*hapd, u8 *eid);
u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_vht_tpe(struct hostapd_data *hapd, u8 *eid);
int hostapd_ht_operation_update(struct hostapd_iface *iface); void
ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
const u8 *addr, const u8 *trans_id); diff
--git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c index
0012c0f..0241fbd 100644
@@ -81,6 +81,55 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd,
u8 *eid)
return pos;
}
+u8 * hostapd_eid_vht_tpe(struct hostapd_data *hapd, u8 *eid) {
+ #define PWR_IE_CNT_MASK 0x3
+ struct ieee80211_vht_tx_pwr_env *txenv;
+ u8 *pos = eid;
+ u8 pwr_ie_cnt = 0; /* Only 20MHZ info*/
+ u8 size = 0 ;
+
+ if (!hapd->iconf->ieee80211h || !hapd->iconf->ieee80211ac ||
hapd->conf->disable_11ac)
+ return eid;
+
+ size = sizeof(*txenv) +
+ ((hapd->iconf->vht_tpe_lpc_40 !=
VHT_TPE_PWR_CONSTRAINT_DISABLE) ? 1 : 0)
+ + ((hapd->iconf->vht_tpe_lpc_80 !=
VHT_TPE_PWR_CONSTRAINT_DISABLE) ? 1 : 0)
+ + ((hapd->iconf->vht_tpe_lpc_160 !=
VHT_TPE_PWR_CONSTRAINT_DISABLE) ?
+1 : 0);
+
+ *pos++ = WLAN_EID_VHT_TRANSMIT_POWER_ENVELOPE;
+ /* Variable Length Structure*/
+ *pos++ = size;
+
+ txenv = (struct ieee80211_vht_tx_pwr_env *) pos;
+ os_memset(txenv, 0 , size);
+
+ /* Mandatory Field*/
+ txenv->vht_local_max_tx_pwr_20 = hapd->iconf->vht_tpe_lpc_20;
+
+ /* Indent ignored to maintain readability and <80 chars */
+ if (hapd->iconf->vht_tpe_lpc_160 != VHT_TPE_PWR_CONSTRAINT_DISABLE)
{
+ txenv->vht_local_max_tx_pwr_opts[0] = hapd->iconf->vht_tpe_lpc_40;
+ txenv->vht_local_max_tx_pwr_opts[1] = hapd->iconf->vht_tpe_lpc_80;
+ txenv->vht_local_max_tx_pwr_opts[2] = hapd->iconf->vht_tpe_lpc_160;
+ pwr_ie_cnt = 3;
+ } else if (hapd->iconf->vht_tpe_lpc_80 !=
VHT_TPE_PWR_CONSTRAINT_DISABLE) {
+ txenv->vht_local_max_tx_pwr_opts[0] = hapd->iconf->vht_tpe_lpc_40;
+ txenv->vht_local_max_tx_pwr_opts[1] = hapd->iconf->vht_tpe_lpc_80;
+ pwr_ie_cnt = 2;
+ } else if (hapd->iconf->vht_tpe_lpc_40 !=
VHT_TPE_PWR_CONSTRAINT_DISABLE) {
+ txenv->vht_local_max_tx_pwr_opts[0] = hapd->iconf->vht_tpe_lpc_40;
+ pwr_ie_cnt = 1;
+ }
+
+ /* Ignore remaining like EIRP as they are by default reserved/0*/
+ txenv->vht_tx_pwr_info = (PWR_IE_CNT_MASK & pwr_ie_cnt);
+
+ pos += size;
+
+ return pos;
+
+}
u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *vht_capab, size_t vht_capab_len) diff --git
a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index
137c309..04fd195 100644
@@ -602,6 +602,14 @@ struct ieee80211_vht_operation {
le16 vht_basic_mcs_set;
} STRUCT_PACKED;
+
+struct ieee80211_vht_tx_pwr_env {
+ u8 vht_tx_pwr_info;
+ /* Valid Range -64 dBM to +63 dBm */
+ s8 vht_local_max_tx_pwr_20;
+ s8 vht_local_max_tx_pwr_opts[0];
+} STRUCT_PACKED;
+
#ifdef _MSC_VER
#pragma pack(pop)
#endif /* _MSC_VER */