mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-21 11:22:50 +00:00
Some checks failed
Build OpenWrt/uCentral images / build (cig_wf186h) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf186w) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf188n) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf189) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cig_wf196) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cybertan_eww631-a1) (push) Has been cancelled
Build OpenWrt/uCentral images / build (cybertan_eww631-b1) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap101) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap102) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap104) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap105) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap111) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_eap112) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101-6e) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101e) (push) Has been cancelled
Build OpenWrt/uCentral images / build (edgecore_oap101e-6e) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x_2) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x_3) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4x_w) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4xe) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4xi) (push) Has been cancelled
Build OpenWrt/uCentral images / build (hfcl_ion4xi_w) (push) Has been cancelled
Build OpenWrt/uCentral images / build (indio_um-305ax) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sercomm_ap72tip) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sonicfi_rap630c-311g) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sonicfi_rap630w-211g) (push) Has been cancelled
Build OpenWrt/uCentral images / build (sonicfi_rap630w-311g) (push) Has been cancelled
Build OpenWrt/uCentral images / build (udaya_a6-id2) (push) Has been cancelled
Build OpenWrt/uCentral images / build (udaya_a6-od2) (push) Has been cancelled
Build OpenWrt/uCentral images / build (wallys_dr5018) (push) Has been cancelled
Build OpenWrt/uCentral images / build (wallys_dr6018) (push) Has been cancelled
Build OpenWrt/uCentral images / build (wallys_dr6018-v4) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_ax820) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_ax840) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_fap640) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_fap650) (push) Has been cancelled
Build OpenWrt/uCentral images / build (yuncore_fap655) (push) Has been cancelled
Build OpenWrt/uCentral images / trigger-testing (push) Has been cancelled
Build OpenWrt/uCentral images / create-x64_vm-ami (push) Has been cancelled
Signed-off-by: John Crispin <john@phrozen.org>
566 lines
19 KiB
Diff
566 lines
19 KiB
Diff
From 404211da041eef5ddfc52515048b04c70ef8579c Mon Sep 17 00:00:00 2001
|
|
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
|
|
Date: Thu, 21 Oct 2021 12:51:38 +0530
|
|
Subject: [PATCH] hostapd: add support for 6GHz operation
|
|
|
|
6 GHz gives users ability to select the AP mode from LPI, SP and
|
|
VLP modes. This mode needs to be passed on to the cfg80211
|
|
for further processing during AP bring up. Also, the regulatory
|
|
rules received by hostapd contains psd values for 6G rules.
|
|
Hostapd needs to store these values in order to later advertise
|
|
it in the tx power element in the beacon.
|
|
|
|
This patch adds the support to send the user configured 6g power
|
|
type during set_channel command and as well to get and store the
|
|
psd values from reg rules which will be later on used in tpe
|
|
advertisement during beacon formation.
|
|
|
|
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
|
|
---
|
|
src/ap/ap_drv_ops.c | 9 ++++++---
|
|
src/ap/beacon.c | 9 +++++++--
|
|
src/ap/dfs.c | 6 ++++--
|
|
src/ap/hostapd.c | 2 +-
|
|
src/ap/ieee802_11.c | 13 ++++++++++++-
|
|
src/ap/ieee802_11_he.c | 10 ++++++++--
|
|
src/common/hw_features_common.c | 4 +++-
|
|
src/common/hw_features_common.h | 2 +-
|
|
src/common/ieee802_11_defs.h | 14 ++++++++++++++
|
|
src/drivers/driver.h | 20 +++++++++++++++++++-
|
|
src/drivers/driver_hostap.c | 3 ++-
|
|
src/drivers/driver_nl80211.c | 15 ++++++++++++++-
|
|
src/drivers/driver_nl80211.h | 2 +-
|
|
src/drivers/driver_nl80211_capa.c | 28 +++++++++++++++++++++++-----
|
|
src/drivers/driver_nl80211_event.c | 2 +-
|
|
src/drivers/nl80211_copy.h | 19 +++++++++++++++++++
|
|
wpa_supplicant/driver_i.h | 2 +-
|
|
wpa_supplicant/mesh.c | 2 +-
|
|
wpa_supplicant/wpa_supplicant.c | 2 +-
|
|
19 files changed, 138 insertions(+), 26 deletions(-)
|
|
|
|
--- a/hostapd/config_file.c
|
|
+++ b/hostapd/config_file.c
|
|
@@ -3580,6 +3580,15 @@ static int hostapd_config_fill(struct ho
|
|
}
|
|
} else if (os_strcmp(buf, "he_6ghz_reg_pwr_type") == 0) {
|
|
conf->he_6ghz_reg_pwr_type = atoi(pos);
|
|
+ if (conf->he_6ghz_reg_pwr_type > HE_6GHZ_VERY_LOW_POWER_AP ||
|
|
+ conf->he_6ghz_reg_pwr_type < HE_6GHZ_INDOOR_AP) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "Line %d: Invalid 6ghz regulatory power type('%s') "
|
|
+ "[min: %d and max: %d]",
|
|
+ line, pos, HE_6GHZ_INDOOR_AP,
|
|
+ HE_6GHZ_VERY_LOW_POWER_AP);
|
|
+ return 1;
|
|
+ }
|
|
} else if (os_strcmp(buf, "he_oper_chwidth") == 0) {
|
|
conf->he_oper_chwidth = atoi(pos);
|
|
} else if (os_strcmp(buf, "he_oper_centr_freq_seg0_idx") == 0) {
|
|
--- a/src/ap/ap_drv_ops.c
|
|
+++ b/src/ap/ap_drv_ops.c
|
|
@@ -588,7 +588,8 @@ int hostapd_set_freq(struct hostapd_data
|
|
&cmode->he_capab[IEEE80211_MODE_AP] : NULL,
|
|
cmode ?
|
|
&cmode->eht_capab[IEEE80211_MODE_AP] :
|
|
- NULL))
|
|
+ NULL,
|
|
+ hapd->iconf->he_6ghz_reg_pwr_type))
|
|
return -1;
|
|
|
|
if (hapd->driver == NULL)
|
|
@@ -681,7 +682,8 @@ hostapd_get_hw_feature_data(struct hosta
|
|
!hapd->drv_priv)
|
|
return NULL;
|
|
return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes,
|
|
- flags, dfs_domain);
|
|
+ flags, dfs_domain,
|
|
+ hapd->iconf->he_6ghz_reg_pwr_type);
|
|
}
|
|
|
|
|
|
@@ -905,7 +907,8 @@ int hostapd_start_dfs_cac(struct hostapd
|
|
center_segment1,
|
|
cmode->vht_capab,
|
|
&cmode->he_capab[IEEE80211_MODE_AP],
|
|
- &cmode->eht_capab[IEEE80211_MODE_AP])) {
|
|
+ &cmode->eht_capab[IEEE80211_MODE_AP],
|
|
+ hapd->iconf->he_6ghz_reg_pwr_type)) {
|
|
wpa_printf(MSG_ERROR, "Can't set freq params");
|
|
return -1;
|
|
}
|
|
--- a/src/ap/beacon.c
|
|
+++ b/src/ap/beacon.c
|
|
@@ -2183,7 +2183,8 @@ static int __ieee802_11_set_beacon(struc
|
|
hostapd_get_oper_centr_freq_seg1_idx(iconf),
|
|
cmode->vht_capab,
|
|
&cmode->he_capab[IEEE80211_MODE_AP],
|
|
- &cmode->eht_capab[IEEE80211_MODE_AP]) == 0)
|
|
+ &cmode->eht_capab[IEEE80211_MODE_AP],
|
|
+ iconf->he_6ghz_reg_pwr_type) == 0)
|
|
params.freq = &freq;
|
|
|
|
for (i = 0; i < hapd->iface->num_hw_features; i++) {
|
|
--- a/src/ap/dfs.c
|
|
+++ b/src/ap/dfs.c
|
|
@@ -1081,7 +1081,8 @@ static int hostapd_dfs_request_channel_s
|
|
oper_centr_freq_seg1_idx,
|
|
cmode->vht_capab,
|
|
&cmode->he_capab[ieee80211_mode],
|
|
- &cmode->eht_capab[ieee80211_mode]);
|
|
+ &cmode->eht_capab[ieee80211_mode],
|
|
+ iface->conf->he_6ghz_reg_pwr_type);
|
|
|
|
if (err) {
|
|
wpa_printf(MSG_ERROR,
|
|
@@ -1226,7 +1227,8 @@ static int hostapd_dfs_testmode_set_beac
|
|
vht_oper_centr_freq_seg1_idx,
|
|
iface->current_mode->vht_capab,
|
|
&iface->current_mode->he_capab[IEEE80211_MODE_AP],
|
|
- &iface->current_mode->eht_capab[IEEE80211_MODE_AP]);
|
|
+ &iface->current_mode->eht_capab[IEEE80211_MODE_AP],
|
|
+ iface->conf->he_6ghz_reg_pwr_type);
|
|
|
|
if (err) {
|
|
wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params");
|
|
--- a/src/ap/hostapd.c
|
|
+++ b/src/ap/hostapd.c
|
|
@@ -3889,7 +3889,8 @@ static int hostapd_change_config_freq(st
|
|
mode ? &mode->he_capab[IEEE80211_MODE_AP] :
|
|
NULL,
|
|
mode ? &mode->eht_capab[IEEE80211_MODE_AP] :
|
|
- NULL))
|
|
+ NULL,
|
|
+ hapd->iconf->he_6ghz_reg_pwr_type))
|
|
return -1;
|
|
|
|
switch (params->bandwidth) {
|
|
--- a/src/ap/ieee802_11.c
|
|
+++ b/src/ap/ieee802_11.c
|
|
@@ -6909,6 +6909,7 @@ void ieee802_11_rx_from_unknown(struct h
|
|
#define REG_APL1_PSD_MAX_TXPOWER_DEFAULT_SUBORDINATE_CLIENT_LPI 2 /* dBm/MHz */
|
|
#define REG_APL1_PSD_MAX_TXPOWER_DEFAULT_SUBORDINATE_CLIENT_VLP 1 /* dBm/MHz */
|
|
|
|
+#ifndef REG_DOM_SUPPORT_TX_POWER
|
|
static u8 hostapd_get_6g_tx_power(struct hostapd_data *hapd, u8 ap_type, u8 tx_pwr_cat)
|
|
{
|
|
char country[3];
|
|
@@ -6949,6 +6950,7 @@ static u8 hostapd_get_6g_tx_power(struct
|
|
ap_type, country);
|
|
return 0;
|
|
}
|
|
+#endif
|
|
|
|
static u8 * hostapd_add_tpe_info(u8 *eid, u8 tx_pwr_count,
|
|
enum max_tx_pwr_interpretation tx_pwr_intrpn,
|
|
@@ -6984,6 +6986,7 @@ u8 * hostapd_eid_txpower_envelope(struct
|
|
u8 channel, tx_pwr_count, local_pwr_constraint;
|
|
int max_tx_power;
|
|
u8 tx_pwr;
|
|
+ s8 psd;
|
|
|
|
if (!mode)
|
|
return eid;
|
|
@@ -7015,20 +7018,30 @@ u8 * hostapd_eid_txpower_envelope(struct
|
|
tx_pwr_count = 0;
|
|
tx_pwr_intrpn = REGULATORY_CLIENT_EIRP_PSD;
|
|
|
|
- /* Default Transmit Power Envelope for Global Operating Class */
|
|
- tx_pwr = (hostapd_get_6g_tx_power(hapd,
|
|
- iconf->he_6ghz_reg_pwr_type,
|
|
- REG_DEFAULT_CLIENT) * 2);
|
|
+ psd = mode->psd_values[NL80211_REG_REGULAR_CLIENT_LPI +
|
|
+ iconf->he_6ghz_reg_pwr_type];
|
|
+#ifdef REG_DOM_SUPPORT_TX_POWER
|
|
+ tx_pwr = psd * 2;
|
|
+#else
|
|
+ tx_pwr = (hostapd_get_6g_tx_power(hapd,
|
|
+ iconf->he_6ghz_reg_pwr_type,
|
|
+ REG_DEFAULT_CLIENT) * 2);
|
|
+#endif /* REG_DOM_SUPPORT_TX_POWER */
|
|
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 = (hostapd_get_6g_tx_power(hapd,
|
|
- iconf->he_6ghz_reg_pwr_type,
|
|
- REG_SUBORDINATE_CLIENT) * 2);
|
|
+ psd = mode->psd_values[NL80211_REG_SUBORDINATE_CLIENT_LPI +
|
|
+ iconf->he_6ghz_reg_pwr_type];
|
|
+#ifdef REG_DOM_SUPPORT_TX_POWER
|
|
+ tx_pwr = psd * 2;
|
|
+#else
|
|
+ tx_pwr = (hostapd_get_6g_tx_power(hapd,
|
|
+ iconf->he_6ghz_reg_pwr_type,
|
|
+ REG_SUBORDINATE_CLIENT) * 2);
|
|
+#endif /* REG_DOM_SUPPORT_TX_POWER */
|
|
eid = hostapd_add_tpe_info(eid, tx_pwr_count,
|
|
tx_pwr_intrpn,
|
|
REG_SUBORDINATE_CLIENT,
|
|
--- a/src/ap/ieee802_11_he.c
|
|
+++ b/src/ap/ieee802_11_he.c
|
|
@@ -255,7 +255,10 @@ u8 * hostapd_eid_he_operation(struct hos
|
|
control = 3;
|
|
else
|
|
control = center_idx_to_bw_6ghz(seg0);
|
|
- if (hapd->iconf->he_6ghz_reg_pwr_type == 1)
|
|
+ if (hapd->iconf->he_6ghz_reg_pwr_type == 2)
|
|
+ control |= HE_6GHZ_VERY_LOW_POWER_AP <<
|
|
+ HE_6GHZ_OPER_INFO_CTRL_REG_INFO_SHIFT;
|
|
+ else if (hapd->iconf->he_6ghz_reg_pwr_type == 1)
|
|
control |= HE_6GHZ_STANDARD_POWER_AP <<
|
|
HE_6GHZ_OPER_INFO_CTRL_REG_INFO_SHIFT;
|
|
else
|
|
--- a/src/common/hw_features_common.c
|
|
+++ b/src/common/hw_features_common.c
|
|
@@ -388,7 +388,8 @@ int hostapd_set_freq_params(struct hosta
|
|
int center_segment0,
|
|
int center_segment1, u32 vht_caps,
|
|
struct he_capabilities *he_cap,
|
|
- struct eht_capabilities *eht_cap)
|
|
+ struct eht_capabilities *eht_cap,
|
|
+ u8 reg_6g_pwr_mode)
|
|
{
|
|
if (!he_cap || !he_cap->he_supported)
|
|
he_enabled = 0;
|
|
@@ -484,6 +485,8 @@ int hostapd_set_freq_params(struct hosta
|
|
data->ht_enabled = 0;
|
|
data->vht_enabled = 0;
|
|
|
|
+ /* Append 6G reg power info */
|
|
+ data->he_6ghz_reg_pwr_type = reg_6g_pwr_mode;
|
|
return 0;
|
|
}
|
|
|
|
--- a/src/common/hw_features_common.h
|
|
+++ b/src/common/hw_features_common.h
|
|
@@ -45,7 +45,8 @@ int hostapd_set_freq_params(struct hosta
|
|
int center_segment0,
|
|
int center_segment1, u32 vht_caps,
|
|
struct he_capabilities *he_caps,
|
|
- struct eht_capabilities *eht_cap);
|
|
+ struct eht_capabilities *eht_cap,
|
|
+ u8 reg_6g_pwr_mode);
|
|
void set_disable_ht40(struct ieee80211_ht_capabilities *htcaps,
|
|
int disabled);
|
|
int ieee80211ac_cap_check(u32 hw, u32 conf);
|
|
--- a/src/common/ieee802_11_defs.h
|
|
+++ b/src/common/ieee802_11_defs.h
|
|
@@ -2009,6 +2009,16 @@ struct tpc_report {
|
|
} STRUCT_PACKED;
|
|
|
|
/*
|
|
+ * REG_DOM_SUPPORT_TX_POWER - regulatory domain
|
|
+ * supports tx power values or not.
|
|
+ *
|
|
+ * If this macro is undefined, tx-power macros will be used to
|
|
+ * get the tx-power, otherwise psd values from regulatory domain
|
|
+ * will be taken
|
|
+ */
|
|
+#define REG_DOM_SUPPORT_TX_POWER 1
|
|
+
|
|
+/*
|
|
* IEEE Std 802.11ax-2021, Table 9-275a - Maximum Transmit Power
|
|
* Interpretation subfield encoding
|
|
*/
|
|
@@ -2408,6 +2418,9 @@ enum he_6ghz_ap_type {
|
|
HE_6GHZ_VERY_LOW_POWER_AP = 2,
|
|
};
|
|
|
|
+#define IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO 0x38
|
|
+#define IEEE80211_HE_6GHZ_OPER_CTRL_REG_INFO_LSB 3
|
|
+
|
|
/* Spatial Reuse defines */
|
|
#define SPATIAL_REUSE_SRP_DISALLOWED BIT(0)
|
|
#define SPATIAL_REUSE_NON_SRG_OBSS_PD_SR_DISALLOWED BIT(1)
|
|
--- a/src/drivers/driver.h
|
|
+++ b/src/drivers/driver.h
|
|
@@ -309,6 +309,12 @@ struct hostapd_hw_modes {
|
|
* eht_capab - EHT (IEEE 802.11be) capabilities
|
|
*/
|
|
struct eht_capabilities eht_capab[IEEE80211_MODE_NUM];
|
|
+
|
|
+ /**
|
|
+ * This array is used to store the psd value of each power mode
|
|
+ * supported in 6G band.
|
|
+ */
|
|
+ s8 psd_values[NL80211_REG_NUM_POWER_MODES];
|
|
};
|
|
|
|
|
|
@@ -844,6 +850,17 @@ struct hostapd_freq_params {
|
|
bool eht_enabled;
|
|
|
|
/**
|
|
+ * he_6ghz_reg_pwr_type - 6G regulatory power mode
|
|
+ * Since many operation related to channel for 6G depends on the
|
|
+ * power mode, this parameter is added here.
|
|
+ *
|
|
+ * 0 - LPI_AP
|
|
+ * 1 - SP_AP
|
|
+ * 2 - VLP_AP
|
|
+ */
|
|
+ u8 he_6ghz_reg_pwr_type;
|
|
+
|
|
+ /**
|
|
* link_id: If >=0 indicates the link of the AP MLD to configure
|
|
*/
|
|
int link_id;
|
|
@@ -3280,12 +3297,13 @@ struct wpa_driver_ops {
|
|
* @num_modes: Variable for returning the number of returned modes
|
|
* flags: Variable for returning hardware feature flags
|
|
* @dfs: Variable for returning DFS region (HOSTAPD_DFS_REGION_*)
|
|
+ * @pwr_mode: Variable required for processing the support data for 6G
|
|
* Returns: Pointer to allocated hardware data on success or %NULL on
|
|
* failure. Caller is responsible for freeing this.
|
|
*/
|
|
struct hostapd_hw_modes * (*get_hw_feature_data)(void *priv,
|
|
u16 *num_modes,
|
|
- u16 *flags, u8 *dfs);
|
|
+ u16 *flags, u8 *dfs, u8 pwr_mode);
|
|
|
|
/**
|
|
* send_mlme - Send management frame from MLME
|
|
--- a/src/drivers/driver_hostap.c
|
|
+++ b/src/drivers/driver_hostap.c
|
|
@@ -1100,7 +1100,8 @@ static int hostap_sta_disassoc(void *pri
|
|
|
|
static struct hostapd_hw_modes * hostap_get_hw_feature_data(void *priv,
|
|
u16 *num_modes,
|
|
- u16 *flags, u8 *dfs)
|
|
+ u16 *flags, u8 *dfs,
|
|
+ u8 pwr_mode)
|
|
{
|
|
struct hostapd_hw_modes *mode;
|
|
int i, clen, rlen;
|
|
--- a/src/drivers/driver_nl80211.c
|
|
+++ b/src/drivers/driver_nl80211.c
|
|
@@ -5420,6 +5420,20 @@ static int nl80211_set_channel(struct i8
|
|
return -1;
|
|
}
|
|
|
|
+#ifdef CONFIG_IEEE80211AX
|
|
+ if (freq->freq && is_6ghz_freq(freq->freq)) {
|
|
+ wpa_printf(MSG_DEBUG, "%s: 6g_reg_pwr_mode=%d",
|
|
+ __func__, freq->he_6ghz_reg_pwr_type);
|
|
+ if (nla_put_u8(msg, NL80211_ATTR_6G_REG_POWER_MODE,
|
|
+ freq->he_6ghz_reg_pwr_type)) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "%s: Failed to put 6g_reg_pwr_mode", __func__);
|
|
+ nlmsg_free(msg);
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+#endif /* CONFIG_IEEE80211AX */
|
|
+
|
|
if (nl80211_link_valid(bss, freq->link_id)) {
|
|
wpa_printf(MSG_DEBUG, "nl80211: Set link_id=%u for freq",
|
|
freq->link_id);
|
|
@@ -9059,7 +9073,7 @@ static int wpa_driver_nl80211_send_actio
|
|
int i;
|
|
|
|
modes = nl80211_get_hw_feature_data(bss, &num_modes,
|
|
- &flags, &dfs_domain);
|
|
+ &flags, &dfs_domain, 0);
|
|
if (dfs_domain != HOSTAPD_DFS_REGION_ETSI &&
|
|
ieee80211_is_dfs(bss->flink->freq, modes, num_modes))
|
|
offchanok = 0;
|
|
--- a/src/drivers/driver_nl80211.h
|
|
+++ b/src/drivers/driver_nl80211.h
|
|
@@ -317,7 +317,7 @@ int nl80211_send_monitor(struct wpa_driv
|
|
int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv);
|
|
struct hostapd_hw_modes *
|
|
nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags,
|
|
- u8 *dfs_domain);
|
|
+ u8 *dfs_domain, u8 pwr_mode);
|
|
|
|
int process_global_event(struct nl_msg *msg, void *arg);
|
|
int process_bss_event(struct nl_msg *msg, void *arg);
|
|
--- a/src/drivers/driver_nl80211_capa.c
|
|
+++ b/src/drivers/driver_nl80211_capa.c
|
|
@@ -1574,6 +1574,7 @@ struct phy_info_arg {
|
|
int last_mode, last_chan_idx;
|
|
int failed;
|
|
u8 dfs_domain;
|
|
+ u8 pwr_mode;
|
|
};
|
|
|
|
static void phy_info_ht_capa(struct hostapd_hw_modes *mode, struct nlattr *capa,
|
|
@@ -2266,7 +2267,9 @@ static void nl80211_set_ht40_mode_sec(st
|
|
|
|
|
|
static void nl80211_reg_rule_max_eirp(u32 start, u32 end, u32 max_eirp,
|
|
- struct phy_info_arg *results)
|
|
+ struct phy_info_arg *results,
|
|
+ u8 config_pwr_mode, u8 pwr_mode,
|
|
+ s8 psd)
|
|
{
|
|
u16 m;
|
|
|
|
@@ -2276,10 +2279,16 @@ static void nl80211_reg_rule_max_eirp(u3
|
|
|
|
for (c = 0; c < mode->num_channels; c++) {
|
|
struct hostapd_channel_data *chan = &mode->channels[c];
|
|
+
|
|
+ if (is_6ghz_freq(chan->freq) && config_pwr_mode != pwr_mode)
|
|
+ continue;
|
|
+
|
|
if ((u32) chan->freq - 10 >= start &&
|
|
(u32) chan->freq + 10 <= end)
|
|
chan->max_tx_power = max_eirp;
|
|
}
|
|
+ /* Update the psd rules */
|
|
+ mode->psd_values[pwr_mode] = psd;
|
|
}
|
|
}
|
|
|
|
@@ -2424,6 +2433,7 @@ static int nl80211_get_reg(struct nl_msg
|
|
[NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 },
|
|
};
|
|
|
|
+ u8 config_pwr_mode = results->pwr_mode;
|
|
nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
|
|
genlmsg_attrlen(gnlh, 0), NULL);
|
|
if (!tb_msg[NL80211_ATTR_REG_ALPHA2] ||
|
|
@@ -2448,6 +2458,8 @@ static int nl80211_get_reg(struct nl_msg
|
|
nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
|
|
{
|
|
u32 start, end, max_eirp = 0, max_bw = 0, flags = 0;
|
|
+ u8 pwr_mode = 0;
|
|
+ s8 psd = 0;
|
|
nla_parse(tb_rule, NL80211_FREQUENCY_ATTR_MAX,
|
|
nla_data(nl_rule), nla_len(nl_rule), reg_policy);
|
|
if (tb_rule[NL80211_ATTR_FREQ_RANGE_START] == NULL ||
|
|
@@ -2461,9 +2473,13 @@ static int nl80211_get_reg(struct nl_msg
|
|
max_bw = nla_get_u32(tb_rule[NL80211_ATTR_FREQ_RANGE_MAX_BW]) / 1000;
|
|
if (tb_rule[NL80211_ATTR_REG_RULE_FLAGS])
|
|
flags = nla_get_u32(tb_rule[NL80211_ATTR_REG_RULE_FLAGS]);
|
|
+ if (tb_rule[NL80211_ATTR_REG_POWER_MODE])
|
|
+ pwr_mode = nla_get_u8(tb_rule[NL80211_ATTR_REG_POWER_MODE]);
|
|
+ if (tb_rule[NL80211_ATTR_POWER_RULE_PSD])
|
|
+ psd = (s8) nla_get_u8(tb_rule[NL80211_ATTR_POWER_RULE_PSD]);
|
|
|
|
- wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u MHz %u mBm%s%s%s%s%s%s%s%s",
|
|
- start, end, max_bw, max_eirp,
|
|
+ wpa_printf(MSG_DEBUG, "nl80211: %u-%u @ %u MHz %u mBm pwr_mode: %u psd: %d%s%s%s%s%s%s%s%s",
|
|
+ start, end, max_bw, max_eirp, pwr_mode, psd,
|
|
flags & NL80211_RRF_NO_OFDM ? " (no OFDM)" : "",
|
|
flags & NL80211_RRF_NO_CCK ? " (no CCK)" : "",
|
|
flags & NL80211_RRF_NO_INDOOR ? " (no indoor)" : "",
|
|
@@ -2477,7 +2493,8 @@ static int nl80211_get_reg(struct nl_msg
|
|
nl80211_reg_rule_ht40(start, end, results);
|
|
if (tb_rule[NL80211_ATTR_POWER_RULE_MAX_EIRP])
|
|
nl80211_reg_rule_max_eirp(start, end, max_eirp,
|
|
- results);
|
|
+ results, config_pwr_mode,
|
|
+ pwr_mode, psd);
|
|
}
|
|
|
|
nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule)
|
|
@@ -2581,7 +2598,7 @@ static void nl80211_dump_chan_list(struc
|
|
|
|
struct hostapd_hw_modes *
|
|
nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags,
|
|
- u8 *dfs_domain)
|
|
+ u8 *dfs_domain, u8 pwr_mode)
|
|
{
|
|
u32 feat;
|
|
struct i802_bss *bss = priv;
|
|
@@ -2594,6 +2611,7 @@ nl80211_get_hw_feature_data(void *priv,
|
|
.last_mode = -1,
|
|
.failed = 0,
|
|
.dfs_domain = 0,
|
|
+ .pwr_mode = pwr_mode
|
|
};
|
|
|
|
*num_modes = 0;
|
|
--- a/src/drivers/driver_nl80211_event.c
|
|
+++ b/src/drivers/driver_nl80211_event.c
|
|
@@ -2580,7 +2580,7 @@ static unsigned int chan_to_freq(struct
|
|
int i;
|
|
|
|
modes = nl80211_get_hw_feature_data(drv->first_bss, &num_modes,
|
|
- &flags, &dfs_domain);
|
|
+ &flags, &dfs_domain, 0);
|
|
if (!modes) {
|
|
wpa_printf(MSG_DEBUG,
|
|
"nl80211: Fetching hardware mode failed");
|
|
--- a/src/drivers/nl80211_copy.h
|
|
+++ b/src/drivers/nl80211_copy.h
|
|
@@ -3373,6 +3373,8 @@ enum nl80211_attrs {
|
|
|
|
NL80211_ATTR_AWGN_INTERFERENCE_BITMAP,
|
|
|
|
+ NL80211_ATTR_6G_REG_POWER_MODE,
|
|
+
|
|
/* add attributes here, update the policy in nl80211.c */
|
|
|
|
__NL80211_ATTR_AFTER_LAST,
|
|
@@ -4127,6 +4129,20 @@ enum nl80211_band_attr {
|
|
|
|
#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA
|
|
|
|
+enum nl80211_regulatory_power_modes {
|
|
+ NL80211_REG_AP_LPI,
|
|
+ NL80211_REG_AP_SP,
|
|
+ NL80211_REG_AP_VLP,
|
|
+ NL80211_REG_REGULAR_CLIENT_LPI,
|
|
+ NL80211_REG_REGULAR_CLIENT_SP,
|
|
+ NL80211_REG_REGULAR_CLIENT_VLP,
|
|
+ NL80211_REG_SUBORDINATE_CLIENT_LPI,
|
|
+ NL80211_REG_SUBORDINATE_CLIENT_SP,
|
|
+ NL80211_REG_SUBORDINATE_CLIENT_VLP,
|
|
+
|
|
+ NL80211_REG_NUM_POWER_MODES,
|
|
+};
|
|
+
|
|
/**
|
|
* enum nl80211_wmm_rule - regulatory wmm rule
|
|
*
|
|
@@ -4357,6 +4373,9 @@ enum nl80211_reg_type {
|
|
* a given frequency range. The value is in mBm (100 * dBm).
|
|
* @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds.
|
|
* If not present or 0 default CAC time will be used.
|
|
+ * @NL80211_ATTR_POWER_RULE_PSD: power spectral density (in dBm).
|
|
+ * This could be negative.
|
|
+ * @NL80211_ATTR_REG_POWER_MODE: the regulatory power mode for 6G rules
|
|
* @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number
|
|
* currently defined
|
|
* @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use
|
|
@@ -4374,6 +4393,10 @@ enum nl80211_reg_rule_attr {
|
|
|
|
NL80211_ATTR_DFS_CAC_TIME,
|
|
|
|
+ NL80211_ATTR_POWER_RULE_PSD,
|
|
+
|
|
+ NL80211_ATTR_REG_POWER_MODE,
|
|
+
|
|
/* keep last */
|
|
__NL80211_REG_RULE_ATTR_AFTER_LAST,
|
|
NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
|
|
--- a/wpa_supplicant/driver_i.h
|
|
+++ b/wpa_supplicant/driver_i.h
|
|
@@ -309,7 +309,7 @@ wpa_drv_get_hw_feature_data(struct wpa_s
|
|
if (wpa_s->driver->get_hw_feature_data)
|
|
return wpa_s->driver->get_hw_feature_data(wpa_s->drv_priv,
|
|
num_modes, flags,
|
|
- dfs_domain);
|
|
+ dfs_domain, 0);
|
|
return NULL;
|
|
}
|
|
|
|
--- a/wpa_supplicant/mesh.c
|
|
+++ b/wpa_supplicant/mesh.c
|
|
@@ -232,7 +232,8 @@ static int wpas_mesh_update_freq_params(
|
|
hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf),
|
|
hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf),
|
|
ifmsh->conf->vht_capab,
|
|
- he_capab, NULL)) {
|
|
+ he_capab, NULL,
|
|
+ ifmsh->conf->he_6ghz_reg_pwr_type)) {
|
|
wpa_printf(MSG_ERROR, "Error updating mesh frequency params");
|
|
wpa_supplicant_mesh_deinit(wpa_s, true);
|
|
return -1;
|