mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
feat(wifi): support disable dfs channels in apsta example
This commit is contained in:
@@ -924,6 +924,7 @@ Wi-Fi Bandwidth Mode
|
||||
|
||||
1. If the STA connects to an AP on a DFS channel, the SoftAP is allowed to switch to the same DFS channel using CSA (Channel Switch Announcement).
|
||||
2. When the STA disconnects, the SoftAP will switch back to a non-DFS channel via CSA to remain compliant with regulations.
|
||||
3. To completely prevent the SoftAP from operating on DFS channels, call :cpp:func:`esp_wifi_set_country()` to set ``policy`` to ``WIFI_COUNTRY_POLICY_MANUAL`` and restrict ``wifi_5g_channel_mask`` to the non-DFS channels of the current country/region. ``wifi_5g_channel_mask`` takes effect only when policy is ``WIFI_COUNTRY_POLICY_MANUAL``. Note: in this case, if the target AP operates on a DFS channel, the STA cannot connect to that AP. See :component_file:`esp_wifi/regulatory/esp_wifi_regulatory.txt` for the DFS channel range of each country/region.
|
||||
|
||||
..
|
||||
|
||||
@@ -1058,7 +1059,7 @@ Wi-Fi Country Code
|
||||
* - policy
|
||||
- Country/region policy. When the configured country/region conflicts with that of the connected AP, this field determines which information to use. Details are explained below.
|
||||
* - wifi_5g_channel_mask
|
||||
- Bitmask indicating allowed 5 GHz channels for the station/AP. The mapping between channel numbers and bits can be found in :cpp:enum:`wifi_5g_channel_bit_t`.
|
||||
- Bitmask indicating allowed 5 GHz channels for the station/AP. The mapping between channel numbers and bits can be found in :cpp:enum:`wifi_5g_channel_bit_t`. A mask of 0 means 5 GHz channels are allowed according to local regulatory rules. The configured mask takes effect only when ``policy`` is ``WIFI_COUNTRY_POLICY_MANUAL``. To disable DFS channels, restrict the mask to the non-DFS channels of the current country/region; the STA will then be unable to connect to an AP operating on a DFS channel.
|
||||
|
||||
A default configuration example::
|
||||
|
||||
|
||||
@@ -924,6 +924,7 @@ Wi-Fi 带宽模式
|
||||
|
||||
1. 当 STA 连接到位于 DFS 信道的 AP 时,SoftAP 允许通过 CSA (Channel Switch Announcement) 切换至相同的 DFS 信道。
|
||||
2. 当 STA 断开连接后,SoftAP 将通过 CSA 切换回非 DFS 信道,确保符合监管要求。
|
||||
3. 如需要完全禁止 SoftAP 工作在 DFS 信道上,可通过 :cpp:func:`esp_wifi_set_country()` 将 ``policy`` 设为 ``WIFI_COUNTRY_POLICY_MANUAL``,并将 ``wifi_5g_channel_mask`` 限制为当前国家/地区的非 DFS 信道。``wifi_5g_channel_mask`` 仅在 policy 为 ``WIFI_COUNTRY_POLICY_MANUAL`` 时生效。注意:此时若目标 AP 工作在 DFS 信道上,STA 将无法与该 AP 建立连接。各国 DFS 信道范围见 :component_file:`esp_wifi/regulatory/esp_wifi_regulatory.txt`。
|
||||
|
||||
..
|
||||
|
||||
@@ -1058,7 +1059,7 @@ Wi-Fi 国家/地区代码
|
||||
* - policy
|
||||
- 国家/地区策略。当配置的国家/地区与连接 AP 的信息冲突时,此字段决定应使用哪一方的信息。详情见下文说明。
|
||||
* - wifi_5g_channel_mask
|
||||
- 表示 station/AP 在 5 GHz 频段中可使用的信道掩码。信道值与位的对应关系详见 :cpp:enum:`wifi_5g_channel_bit_t`。
|
||||
- 表示 station/AP 在 5 GHz 频段中可使用的信道掩码。信道值与位的对应关系详见 :cpp:enum:`wifi_5g_channel_bit_t`。掩码为 0 时,5 GHz 信道按当地监管规则允许使用。配置的掩码仅在 ``policy`` 为 ``WIFI_COUNTRY_POLICY_MANUAL`` 时生效。如需禁用 DFS 信道,请将掩码限制为当前国家/地区的非 DFS 信道;此时 STA 也无法连接到工作在 DFS 信道上的 AP。
|
||||
|
||||
默认配置示例如下::
|
||||
|
||||
|
||||
@@ -23,6 +23,15 @@ In the `Example Configuration` menu:
|
||||
* Set `WiFi Remote AP SSID`.
|
||||
* Set `WiFi Remote AP Password`.
|
||||
|
||||
* (5 GHz capable chips only) Set the DFS channel configuration under `DFS Channel Configuration`.
|
||||
* Set `Country code` to select the regulatory domain (e.g. `US` for FCC, `DE` for CE, `01` for world safe mode).
|
||||
* Enable `Disable DFS channels` to forbid both the STA and the SoftAP from using any DFS channel of the
|
||||
selected regulatory domain. STA will not be able to connect to an AP that operates on a DFS channel.
|
||||
The non-DFS channels are looked up from the esp_wifi regulatory table for the configured country, and
|
||||
the 5 GHz channel bitmask (`wifi_country_t.wifi_5g_channel_mask`) is restricted to them with the
|
||||
country policy switched to manual. This is useful for certification setups (e.g. FCC, CE) where DFS
|
||||
channels must be avoided.
|
||||
|
||||
Optional: If necessary, modify the other choices to suit your needs.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
@@ -85,4 +85,28 @@ menu "Example Configuration"
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
|
||||
menu "DFS Channel Configuration"
|
||||
depends on SOC_WIFI_SUPPORT_5G
|
||||
comment "DFS Channel Configuration (5 GHz capable chips only)"
|
||||
|
||||
config ESP_WIFI_COUNTRY_CODE
|
||||
string "Country code"
|
||||
default "01"
|
||||
help
|
||||
Country code used to configure the regulatory domain (e.g. "US" for FCC, "DE" for CE,
|
||||
"01" for world safe mode). The set of DFS channels depends on this regulatory domain.
|
||||
|
||||
config ESP_WIFI_DISABLE_DFS_CHANNELS
|
||||
bool "Disable DFS channels"
|
||||
default n
|
||||
help
|
||||
If enabled, the device (both STA and SoftAP) will not use any DFS channel of the
|
||||
configured regulatory domain. As a result, STA cannot connect to an AP that operates
|
||||
on a DFS channel. The non-DFS channels are derived by looking up the country in the
|
||||
esp_wifi regulatory table, and the 5 GHz channel bitmask
|
||||
(wifi_country_t.wifi_5g_channel_mask) is restricted to them with the country policy
|
||||
switched to manual. This can be useful for certification setups (e.g. FCC, CE)
|
||||
where DFS channels must be avoided.
|
||||
endmenu
|
||||
endmenu
|
||||
|
||||
@@ -170,6 +170,86 @@ esp_netif_t *wifi_init_sta(void)
|
||||
return esp_netif_sta;
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_WIFI_DISABLE_DFS_CHANNELS
|
||||
extern const wifi_regdomain_t regdomain_table[];
|
||||
extern const wifi_regulatory_t regulatory_data[];
|
||||
|
||||
static const wifi_regulatory_t *wifi_lookup_regulatory(const char *cc)
|
||||
{
|
||||
for (int i = 0; regdomain_table[i].cn[0] != '#'; i++) {
|
||||
if (regdomain_table[i].cn[0] == cc[0] && regdomain_table[i].cn[1] == cc[1]) {
|
||||
return ®ulatory_data[regdomain_table[i].regulatory_type];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint32_t wifi_get_non_dfs_5g_channel_mask(const wifi_regulatory_t *reg)
|
||||
{
|
||||
uint32_t mask = 0;
|
||||
|
||||
for (int i = 0; i < reg->n_reg_rules; i++) {
|
||||
const wifi_reg_rule_t *rule = ®->reg_rules[i];
|
||||
if (rule->is_dfs || rule->start_channel <= 14) {
|
||||
continue;
|
||||
}
|
||||
for (uint8_t ch = rule->start_channel; ch <= rule->end_channel; ch += 4) {
|
||||
mask |= CHANNEL_TO_BIT(ch);
|
||||
}
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
// static uint32_t wifi_get_non_dfs_5g_channel_mask_by_type(uint8_t type)
|
||||
// {
|
||||
// return wifi_get_non_dfs_5g_channel_mask(®ulatory_data[type]);
|
||||
// }
|
||||
|
||||
static esp_err_t wifi_configure_country_without_dfs_channels(void)
|
||||
{
|
||||
const char *cc = CONFIG_ESP_WIFI_COUNTRY_CODE;
|
||||
const wifi_regulatory_t *reg = wifi_lookup_regulatory(cc);
|
||||
if (!reg) {
|
||||
ESP_LOGE(TAG_STA, "Unknown country code '%s'", cc);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
wifi_country_t country = {0};
|
||||
memcpy(country.cc, cc, 2);
|
||||
country.policy = WIFI_COUNTRY_POLICY_MANUAL;
|
||||
uint8_t schan = 0;
|
||||
uint8_t echan = 0;
|
||||
for (int i = 0; i < reg->n_reg_rules; i++) {
|
||||
const wifi_reg_rule_t *rule = ®->reg_rules[i];
|
||||
if (rule->start_channel > 14) {
|
||||
continue;
|
||||
}
|
||||
if (schan == 0 || rule->start_channel < schan) {
|
||||
schan = rule->start_channel;
|
||||
}
|
||||
if (rule->end_channel > echan) {
|
||||
echan = rule->end_channel;
|
||||
}
|
||||
}
|
||||
if (schan != 0) {
|
||||
country.schan = schan;
|
||||
country.nchan = echan - schan + 1;
|
||||
}
|
||||
|
||||
/* A zero mask does not mean "no 5 GHz channel allowed", it means "fall back to
|
||||
the local regulatory rules", which would leave the DFS channels usable. Some
|
||||
domains (AM for instance) mark every 5 GHz rule as DFS, so there the only way
|
||||
to stay off DFS is to stay off 5 GHz altogether. */
|
||||
country.wifi_5g_channel_mask = wifi_get_non_dfs_5g_channel_mask(reg);
|
||||
if (country.wifi_5g_channel_mask == 0) {
|
||||
ESP_ERROR_CHECK(esp_wifi_set_band_mode(WIFI_BAND_MODE_2G_ONLY));
|
||||
ESP_LOGW(TAG_STA, "'%s' has no non-DFS 5 GHz channel, restricting to 2.4 GHz", cc);
|
||||
}
|
||||
ESP_ERROR_CHECK(esp_wifi_set_country(&country));
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* CONFIG_ESP_WIFI_DISABLE_DFS_CHANNELS */
|
||||
|
||||
void softap_set_dns_addr(esp_netif_t *esp_netif_ap,esp_netif_t *esp_netif_sta)
|
||||
{
|
||||
esp_netif_dns_info_t dns;
|
||||
@@ -231,6 +311,9 @@ void app_main(void)
|
||||
/* Start WiFi */
|
||||
ESP_ERROR_CHECK(esp_wifi_start() );
|
||||
|
||||
#if CONFIG_ESP_WIFI_DISABLE_DFS_CHANNELS
|
||||
ESP_ERROR_CHECK(wifi_configure_country_without_dfs_channels());
|
||||
#endif
|
||||
/*
|
||||
* Wait until either the connection is established (WIFI_CONNECTED_BIT) or
|
||||
* connection failed for the maximum number of re-tries (WIFI_FAIL_BIT).
|
||||
|
||||
Reference in New Issue
Block a user