Add Transmit Power Envelope element defined in IEEE P802.11-REVmc/D4.3, 8.4.2.161. Signed-off-by: Rajkumar Manoharan <rmanohar@xxxxxxxxxxxxxxxx> --- v2: * "VHT" removed from the name * removed channel switch conditions * handled 80+80/160 MHz case * corrected max tx power calculation src/ap/beacon.c | 2 + src/ap/ieee802_11.h | 1 + src/ap/ieee802_11_vht.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 5f65b7d..d4054cb 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -481,6 +481,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) { pos = hostapd_eid_vht_capabilities(hapd, pos); pos = hostapd_eid_vht_operation(hapd, pos); + pos = hostapd_eid_vht_txpwr_env(hapd, pos); pos = hostapd_eid_wb_chsw_wrapper(hapd, pos); } if (hapd->conf->vendor_vht) @@ -1096,6 +1097,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) { tailpos = hostapd_eid_vht_capabilities(hapd, tailpos); tailpos = hostapd_eid_vht_operation(hapd, tailpos); + tailpos = hostapd_eid_vht_txpwr_env(hapd, tailpos); tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos); } if (hapd->conf->vendor_vht) diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index a2dd132..4788e6b 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -54,6 +54,7 @@ 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_vendor_vht(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_vht_txpwr_env(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, diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c index 8d2c428..59522a7 100644 --- a/src/ap/ieee802_11_vht.c +++ b/src/ap/ieee802_11_vht.c @@ -17,6 +17,7 @@ #include "sta_info.h" #include "beacon.h" #include "ieee802_11.h" +#include "dfs.h" u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid) @@ -184,6 +185,108 @@ u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid) } +u8 * hostapd_eid_vht_txpwr_env(struct hostapd_data *hapd, u8 *eid) +{ + struct hostapd_iface *iface = hapd->iface; + struct hostapd_config *iconf = iface->conf; + struct hostapd_hw_modes *mode = iface->current_mode; + struct hostapd_channel_data *chan; + int dfs, i; + u8 channel, max_tx_power, tx_pwr_count, local_pwr_constraint; + + if (!mode) + return eid; + + if (ieee80211_freq_to_chan(iface->freq, &channel) == + NUM_HOSTAPD_MODES) + return eid; + + for (i = 0; i < mode->num_channels; i++) { + if (mode->channels[i].freq == iface->freq) + break; + } + if (i == mode->num_channels) + return eid; + + switch (iface->conf->vht_oper_chwidth) { + case VHT_CHANWIDTH_USE_HT: + if (iconf->secondary_channel == 0) { + /* Max Transmit Power count = 0 (20MHz) */ + tx_pwr_count = 0; + } else { + /* Max Transmit Power count = 1 (20, 40MHz) */ + tx_pwr_count = 1; + } + break; + case VHT_CHANWIDTH_80MHZ: + /* Max Transmit Power count = 2 (20, 40 and 80MHz) */ + tx_pwr_count = 2; + break; + case VHT_CHANWIDTH_80P80MHZ: + case VHT_CHANWIDTH_160MHZ: + /* Max Transmit Power count = 3 (20, 40, 80, 160/80+80MHz) */ + tx_pwr_count = 3; + break; + default: + return eid; + } + + /* + * Below local_pwr_constraint logic is referred from + * hostapd_eid_pwr_constraint. + * + * Check if DFS is required by regulatory. + */ + dfs = hostapd_is_dfs_required(hapd->iface); + if (dfs < 0) + dfs = 0; + + /* + * In order to meet regulations when TPC is not implemented using + * a transmit power that is below the legal maximum (including any + * mitigation factor) should help. In this case, indicate 3 dB below + * maximum allowed transmit power. + */ + if (hapd->iconf->local_pwr_constraint == -1) + local_pwr_constraint = (dfs == 0) ? 0 : 3; + else + local_pwr_constraint = hapd->iconf->local_pwr_constraint; + + /* + * A STA that is not an AP shall use a transmit power less than or + * equal to the local maximum transmit power level for the channel. + * The local maximum transmit power can be calculated from the formula: + * local max TX pwr = max TX pwr - local pwr constraint + * Where max TX pwr is maximum transmit power level specified for + * channel in Country element and local pwr constraint is specified + * for channel in this Power Constraint element. + */ + chan = &mode->channels[i]; + max_tx_power = chan->max_tx_power - local_pwr_constraint; + + /* + * Local Maximum Transmit power is encoded as 2's complement + * with a 0.5 dB step + */ + max_tx_power = ~(max_tx_power * 2) + 1; + + *eid++ = WLAN_EID_VHT_TRANSMIT_POWER_ENVELOPE; + *eid++ = 4; + + /* + * Max Transmit Power count and + * Max Transmit Power units = 0 (EIRP) + */ + *eid++ = tx_pwr_count; + + i = 0; + while (i++ <= tx_pwr_count) + *eid++ = max_tx_power; + + return eid; +} + + u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta, const u8 *vht_capab) { -- 2.6.2 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap