mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +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).
|
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.
|
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
|
* - 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.
|
- 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
|
* - 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::
|
A default configuration example::
|
||||||
|
|
||||||
|
|||||||
@@ -924,6 +924,7 @@ Wi-Fi 带宽模式
|
|||||||
|
|
||||||
1. 当 STA 连接到位于 DFS 信道的 AP 时,SoftAP 允许通过 CSA (Channel Switch Announcement) 切换至相同的 DFS 信道。
|
1. 当 STA 连接到位于 DFS 信道的 AP 时,SoftAP 允许通过 CSA (Channel Switch Announcement) 切换至相同的 DFS 信道。
|
||||||
2. 当 STA 断开连接后,SoftAP 将通过 CSA 切换回非 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
|
* - policy
|
||||||
- 国家/地区策略。当配置的国家/地区与连接 AP 的信息冲突时,此字段决定应使用哪一方的信息。详情见下文说明。
|
- 国家/地区策略。当配置的国家/地区与连接 AP 的信息冲突时,此字段决定应使用哪一方的信息。详情见下文说明。
|
||||||
* - wifi_5g_channel_mask
|
* - 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 SSID`.
|
||||||
* Set `WiFi Remote AP Password`.
|
* 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.
|
Optional: If necessary, modify the other choices to suit your needs.
|
||||||
|
|
||||||
### Build and Flash
|
### Build and Flash
|
||||||
|
|||||||
@@ -85,4 +85,28 @@ menu "Example Configuration"
|
|||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
endmenu
|
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
|
endmenu
|
||||||
|
|||||||
@@ -170,6 +170,86 @@ esp_netif_t *wifi_init_sta(void)
|
|||||||
return esp_netif_sta;
|
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)
|
void softap_set_dns_addr(esp_netif_t *esp_netif_ap,esp_netif_t *esp_netif_sta)
|
||||||
{
|
{
|
||||||
esp_netif_dns_info_t dns;
|
esp_netif_dns_info_t dns;
|
||||||
@@ -231,6 +311,9 @@ void app_main(void)
|
|||||||
/* Start WiFi */
|
/* Start WiFi */
|
||||||
ESP_ERROR_CHECK(esp_wifi_start() );
|
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
|
* Wait until either the connection is established (WIFI_CONNECTED_BIT) or
|
||||||
* connection failed for the maximum number of re-tries (WIFI_FAIL_BIT).
|
* connection failed for the maximum number of re-tries (WIFI_FAIL_BIT).
|
||||||
|
|||||||
Reference in New Issue
Block a user