Merge branch 'feature/bss_max_idle' into 'master'

feat(wifi): Improve and enable bss max idle support on all chips

See merge request espressif/esp-idf!34656
This commit is contained in:
Jiang Jiang Jian
2025-04-08 22:44:33 +08:00
11 changed files with 288 additions and 25 deletions

View File

@ -92,7 +92,7 @@ ieee80211_deauth_construct = 0x40002040;
ieee80211_disassoc_construct = 0x40002044; ieee80211_disassoc_construct = 0x40002044;
//ieee80211_add_xrates = 0x40002058; //ieee80211_add_xrates = 0x40002058;
//ieee80211_assoc_req_construct = 0x40002060; //ieee80211_assoc_req_construct = 0x40002060;
ieee80211_assoc_resp_construct = 0x40002064; //ieee80211_assoc_resp_construct = 0x40002064;
//ieee80211_timer_process = 0x4000208c; //ieee80211_timer_process = 0x4000208c;
cnx_coexist_timeout = 0x40002090; cnx_coexist_timeout = 0x40002090;
//sta_recv_mgmt = 0x40002094; //sta_recv_mgmt = 0x40002094;

View File

@ -209,7 +209,7 @@ ppDisableQueue = 0x40000ed4;
ppCalVHTDeliNum = 0x40000ed8; ppCalVHTDeliNum = 0x40000ed8;
ppCalTxVHTSMPDULength = 0x40000edc; ppCalTxVHTSMPDULength = 0x40000edc;
ppCheckTxRTS = 0x40000ee0; ppCheckTxRTS = 0x40000ee0;
ppProcessLifeTime = 0x40000ee4; /*ppProcessLifeTime = 0x40000ee4;*/
ppProcTxCallback = 0x40000ee8; ppProcTxCallback = 0x40000ee8;
ppCalPreFecPaddingFactor = 0x40000eec; ppCalPreFecPaddingFactor = 0x40000eec;
ppCalDeliNum = 0x40000ef0; ppCalDeliNum = 0x40000ef0;

View File

@ -214,7 +214,7 @@ ppMapWaitTxq = 0x40000e44;
ppProcessWaitingQueue = 0x40000e48; ppProcessWaitingQueue = 0x40000e48;
ppDisableQueue = 0x40000e4c; ppDisableQueue = 0x40000e4c;
ppCheckTxRTS = 0x40000e50; ppCheckTxRTS = 0x40000e50;
ppProcessLifeTime = 0x40000e54; /*ppProcessLifeTime = 0x40000e54;*/
ppProcTxCallback = 0x40000e58; ppProcTxCallback = 0x40000e58;
ppCalPreFecPaddingFactor = 0x40000e5c; ppCalPreFecPaddingFactor = 0x40000e5c;
ppCalDeliNum = 0x40000e60; ppCalDeliNum = 0x40000e60;

View File

@ -363,14 +363,24 @@ menu "Wi-Fi"
during this period, the time will be refreshed. If the time is up, but the station still has packets during this period, the time will be refreshed. If the time is up, but the station still has packets
to receive or send, the time will also be refreshed. unit: milliseconds. to receive or send, the time will also be refreshed. unit: milliseconds.
config ESP_WIFI_BSS_MAX_IDLE_SUPPORT
bool "Enable bss max idle support"
default y if (SOC_WIFI_HE_SUPPORT || ESP_WIFI_WNM_SUPPORT)
help
Enables bss max idle support for Station and SoftAP. BSS max idle period enables an SoftAP to indicate
a time period during which the AP does not disassociate a STA due to nonreceipt of frames from the STA.
For station, max idle period is default 10 (1000TUs) and can be set through
ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME. For softap, bss max idle parameters will be set through
bss_max_idle_cfg in wifi_ap_config_t.
config ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME config ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME
int "Maximum keep alive time" int "Maximum keep alive time"
range 10 60 range 10 60
default 10 default 10
help help
Only for station in WIFI_PS_MIN_MODEM or WIFI_PS_MAX_MODEM. If no packet has been Only for station. If no packet has been sent within ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME, a null data
sent within ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME, a null data packet will be sent packet will be sent to maintain the connection with the AP. If ESP_WIFI_BSS_MAX_IDLE_SUPPORT is set,
to maintain the connection with the AP. unit: seconds. it will be sent as bss max idle period in association request. unit: seconds.
config ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME config ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME
int "Minimum wait broadcast data time" int "Minimum wait broadcast data time"

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -165,21 +165,6 @@ esp_err_t esp_wifi_get_tx_tb_statistics(esp_wifi_aci_t aci, esp_test_tx_tb_stati
*/ */
esp_err_t esp_wifi_softap_add_color_change_announcement(uint8_t color); esp_err_t esp_wifi_softap_add_color_change_announcement(uint8_t color);
/**
* @brief Add bss max idle ie
*
* @attention This API should be called after esp_wifi_start().
*
* @param[in] bss_max_idle_enable enable bss max idle
* @param[in] bss_max_idle_period_secs bss max idle period, unit seconds
* @param[in] protected_keep_alive using protected/unprotected frame to keep alive
*
* @return
* - ESP_OK: succeed
* - others: failed
*/
esp_err_t esp_wifi_softap_set_bss_max_idle(bool bss_max_idle_enable, uint16_t bss_max_idle_period_secs, bool protected_keep_alive);
/** /**
* @brief Reset MU EDCA Timer * @brief Reset MU EDCA Timer
* *

View File

@ -278,6 +278,12 @@ extern wifi_osi_funcs_t g_wifi_osi_funcs;
#define WIFI_TX_HETB_QUEUE_NUM 1 #define WIFI_TX_HETB_QUEUE_NUM 1
#endif #endif
#if CONFIG_ESP_WIFI_BSS_MAX_IDLE_SUPPORT
#define WIFI_ENABLE_BSS_MAX_IDLE (1<<8)
#else
#define WIFI_ENABLE_BSS_MAX_IDLE 0
#endif
#define CONFIG_FEATURE_WPA3_SAE_BIT (1<<0) #define CONFIG_FEATURE_WPA3_SAE_BIT (1<<0)
#define CONFIG_FEATURE_CACHE_TX_BUF_BIT (1<<1) #define CONFIG_FEATURE_CACHE_TX_BUF_BIT (1<<1)
#define CONFIG_FEATURE_FTM_INITIATOR_BIT (1<<2) #define CONFIG_FEATURE_FTM_INITIATOR_BIT (1<<2)
@ -286,6 +292,7 @@ extern wifi_osi_funcs_t g_wifi_osi_funcs;
#define CONFIG_FEATURE_GMAC_BIT (1<<5) #define CONFIG_FEATURE_GMAC_BIT (1<<5)
#define CONFIG_FEATURE_11R_BIT (1<<6) #define CONFIG_FEATURE_11R_BIT (1<<6)
#define CONFIG_FEATURE_WIFI_ENT_BIT (1<<7) #define CONFIG_FEATURE_WIFI_ENT_BIT (1<<7)
#define CONFIG_FEATURE_BSS_MAX_IDLE_BIT (1<<8)
/* Set additional WiFi features and capabilities */ /* Set additional WiFi features and capabilities */
#define WIFI_FEATURE_CAPS (WIFI_ENABLE_WPA3_SAE | \ #define WIFI_FEATURE_CAPS (WIFI_ENABLE_WPA3_SAE | \
@ -295,7 +302,8 @@ extern wifi_osi_funcs_t g_wifi_osi_funcs;
WIFI_ENABLE_GCMP | \ WIFI_ENABLE_GCMP | \
WIFI_ENABLE_GMAC | \ WIFI_ENABLE_GMAC | \
WIFI_ENABLE_11R | \ WIFI_ENABLE_11R | \
WIFI_ENABLE_ENTERPRISE) WIFI_ENABLE_ENTERPRISE | \
WIFI_ENABLE_BSS_MAX_IDLE)
#define WIFI_INIT_CONFIG_DEFAULT() { \ #define WIFI_INIT_CONFIG_DEFAULT() { \
.osi_funcs = &g_wifi_osi_funcs, \ .osi_funcs = &g_wifi_osi_funcs, \

View File

@ -17,6 +17,8 @@
extern "C" { extern "C" {
#endif #endif
#define WIFI_AP_DEFAULT_MAX_IDLE_PERIOD 292 /**< Default timeout for SoftAP BSS Max Idle. Unit: 1000TUs >**/
/** /**
* @brief Wi-Fi mode type * @brief Wi-Fi mode type
*/ */
@ -507,6 +509,14 @@ typedef enum {
WPA3_SAE_PK_MODE_DISABLED = 2, WPA3_SAE_PK_MODE_DISABLED = 2,
} wifi_sae_pk_mode_t; } wifi_sae_pk_mode_t;
/**
* @brief Configuration structure for BSS max idle
*/
typedef struct {
uint16_t period; /**< Sets BSS Max idle period (1 Unit = 1000TUs OR 1.024 Seconds). If there are no frames for this period from a STA, SoftAP will disassociate due to inactivity. Setting it to 0 disables the feature */
bool protected_keep_alive; /**< Requires clients to use protected keep alive frames for BSS Max Idle period */
} wifi_bss_max_idle_config_t;
/** /**
* @brief Soft-AP configuration settings for the device * @brief Soft-AP configuration settings for the device
*/ */
@ -527,6 +537,7 @@ typedef struct {
wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */ wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */
uint8_t transition_disable; /**< Whether to enable transition disable feature */ uint8_t transition_disable; /**< Whether to enable transition disable feature */
uint8_t sae_ext; /**< Enable SAE EXT feature. SOC_GCMP_SUPPORT is required for this feature. */ uint8_t sae_ext; /**< Enable SAE EXT feature. SOC_GCMP_SUPPORT is required for this feature. */
wifi_bss_max_idle_config_t bss_max_idle_cfg; /**< Configuration for bss max idle, effective if CONFIG_WIFI_BSS_MAX_IDLE_SUPPORT is enabled */
} wifi_ap_config_t; } wifi_ap_config_t;
#define SAE_H2E_IDENTIFIER_LEN 32 /**< Length of the password identifier for H2E */ #define SAE_H2E_IDENTIFIER_LEN 32 /**< Length of the password identifier for H2E */

View File

@ -0,0 +1,242 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#ifdef CONFIG_ESP_WIFI_BSS_MAX_IDLE_SUPPORT
#include <string.h>
#include "unity.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "test_utils.h"
#include "freertos/event_groups.h"
#include "unity_test_utils.h"
#include "esp_private/wifi.h"
#ifdef __CHECKER__
#define __force __attribute__((force))
#define __bitwise __attribute__((bitwise))
#else
#define __force
#define __bitwise
#endif
#if defined(__linux__) || defined(__GLIBC__)
#include <endian.h>
#include <byteswap.h>
#else
#include <machine/endian.h>
#define __BYTE_ORDER BYTE_ORDER
#define __LITTLE_ENDIAN LITTLE_ENDIAN
#endif /* __linux__ */
#ifndef __BYTE_ORDER
#ifndef __LITTLE_ENDIAN
#define __LITTLE_ENDIAN 1234
#endif
#endif
typedef uint16_t u16;
typedef uint8_t u8;
typedef u16 __bitwise be16;
#define host_to_be16(n) ((__force be16) __builtin_bswap16((n)))
#ifndef TEST_SUFFIX_STR
#define TEST_SUFFIX_STR "_0000"
#endif
#define TEST_DEFAULT_SSID "SSID_" CONFIG_IDF_TARGET TEST_SUFFIX_STR
#define TEST_DEFAULT_PWD "PASS_" CONFIG_IDF_TARGET TEST_SUFFIX_STR
#define TEST_DEFAULT_CHANNEL (6)
#define CONNECT_TIMEOUT_MS (8000)
#define MAXIMUM_RETRY (5)
#define WIFI_DISCONNECT_EVENT (1)
#define WIFI_STA_CONNECTED (1<<1)
#define WIFI_AP_STA_CONNECTED (1<<2)
#define WIFI_FAIL (1<<3)
#define EMPH_STR(s) "****** "s" ******"
#define MAX_IDLE_PERIOD (5)
#define ETHTYPE_IP 0x0800
static const char* TAG = "test_bss_max_idle";
static bool s_sta_conn_first = false;
static bool s_keep_alive_received = false;
static int s_retry_num = 0;
static EventGroupHandle_t wifi_events;
struct eth_header {
u8 dest_mac[6];
u8 src_mac[6];
be16 ethertype;
};
static esp_err_t wifi_ap_receive_test(void *buffer, uint16_t len, void *eb)
{
struct eth_header *pac = (struct eth_header *)buffer;
if ((host_to_be16(pac->ethertype) == ETHTYPE_IP) && (len < 48)) {
ESP_LOGI(TAG, "KEEP ALIVE RECEIVED");
s_keep_alive_received = true;
esp_wifi_deauth_sta(0);
}
esp_wifi_internal_free_rx_buffer(eb);
return ESP_OK;
}
static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
ESP_LOGI(TAG, "wifi event handler: %"PRIi32, event_id);
switch (event_id) {
case WIFI_EVENT_AP_START:
ESP_LOGI(TAG, "WIFI_EVENT_AP_START");
esp_wifi_internal_reg_rxcb(WIFI_IF_AP, wifi_ap_receive_test);
break;
case WIFI_EVENT_STA_START:
ESP_LOGI(TAG, "WIFI_EVENT_STA_START");
break;
case WIFI_EVENT_AP_STACONNECTED:
ESP_LOGI(TAG, "Wi-Fi AP got a station connected");
break;
case WIFI_EVENT_STA_CONNECTED:
ESP_LOGI(TAG, "WIFI_EVENT_STA_CONNECTED");
if (wifi_events) {
xEventGroupSetBits(wifi_events, WIFI_STA_CONNECTED);
s_sta_conn_first = true;
}
break;
case WIFI_EVENT_STA_DISCONNECTED:
if ((s_retry_num < MAXIMUM_RETRY) && !s_sta_conn_first) {
esp_wifi_connect();
s_retry_num++;
ESP_LOGI(TAG, "retry to connect to AP");
} else {
xEventGroupSetBits(wifi_events, WIFI_DISCONNECT_EVENT);
ESP_LOGI(TAG, "WIFI_EVENT_STA_DISCONNECTED");
wifi_event_sta_disconnected_t *event = (wifi_event_sta_disconnected_t *)event_data;
ESP_LOGI(TAG, "disconnect reason: %u", event->reason);
}
break;
default:
break;
}
return;
}
static esp_err_t event_init(void)
{
ESP_ERROR_CHECK(esp_event_loop_create_default());
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
return ESP_OK;
}
static esp_err_t event_deinit(void)
{
ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler));
ESP_ERROR_CHECK(esp_event_loop_delete_default());
return ESP_OK;
}
static void start_wifi_as_softap(void)
{
wifi_config_t w_config = {
.ap.ssid = TEST_DEFAULT_SSID,
.ap.password = TEST_DEFAULT_PWD,
.ap.ssid_len = strlen(TEST_DEFAULT_SSID),
.ap.channel = TEST_DEFAULT_CHANNEL,
.ap.authmode = WIFI_AUTH_WPA3_PSK,
.ap.ssid_hidden = false,
.ap.max_connection = 4,
.ap.beacon_interval = 100,
.ap.bss_max_idle_cfg = {
.period = MAX_IDLE_PERIOD,
.protected_keep_alive = true,
},
};
event_init();
if (wifi_events == NULL) {
wifi_events = xEventGroupCreate();
}
xEventGroupClearBits(wifi_events, 0x00ffffff);
TEST_ESP_OK(esp_wifi_set_mode(WIFI_MODE_AP));
TEST_ESP_OK(esp_wifi_set_config(WIFI_IF_AP, &w_config));
TEST_ESP_OK(esp_wifi_start());
ESP_LOGI(TAG, "start wifi softap: %s", TEST_DEFAULT_SSID);
}
static void start_wifi_as_sta(void)
{
event_init();
if (wifi_events == NULL) {
wifi_events = xEventGroupCreate();
}
xEventGroupClearBits(wifi_events, 0x00ffffff);
TEST_ESP_OK(esp_wifi_set_mode(WIFI_MODE_STA));
TEST_ESP_OK(esp_wifi_start());
}
static void stop_wifi(void)
{
TEST_ESP_OK(esp_wifi_stop());
event_deinit();
if (wifi_events) {
vEventGroupDelete(wifi_events);
wifi_events = NULL;
}
vTaskDelay(500 / portTICK_PERIOD_MS);
}
static void wifi_connect(void)
{
wifi_config_t w_config = {
.sta.ssid = TEST_DEFAULT_SSID,
.sta.password = TEST_DEFAULT_PWD,
.sta.channel = TEST_DEFAULT_CHANNEL,
};
TEST_ESP_OK(esp_wifi_set_config(WIFI_IF_STA, &w_config));
TEST_ESP_OK(esp_wifi_connect());
ESP_LOGI(TAG, "start esp_wifi_connect: %s", TEST_DEFAULT_SSID);
}
static void test_bss_max_idle_sta(void)
{
start_wifi_as_sta();
wifi_connect();
// Waiting untill connection est or failed
EventBits_t bits = xEventGroupWaitBits(wifi_events,
WIFI_STA_CONNECTED | WIFI_FAIL,
pdFALSE,
pdFALSE,
portMAX_DELAY);
TEST_ASSERT(bits & WIFI_STA_CONNECTED);
if (bits != WIFI_FAIL) {
bits = xEventGroupWaitBits(wifi_events,
WIFI_DISCONNECT_EVENT,
pdFALSE,
pdFALSE,
portMAX_DELAY);
}
stop_wifi();
}
static void test_bss_max_idle_softap(void)
{
start_wifi_as_softap();
vTaskDelay((CONNECT_TIMEOUT_MS + MAX_IDLE_PERIOD * 1000) / portTICK_PERIOD_MS);
TEST_ASSERT(s_keep_alive_received);
stop_wifi();
}
TEST_CASE_MULTIPLE_DEVICES("Connection with bss max idle enabled", "[wifi][bss max idle]", test_bss_max_idle_sta, test_bss_max_idle_softap);
#endif /* CONFIG_ESP_WIFI_BSS_MAX_IDLE_SUPPORT */

View File

@ -1,3 +1,4 @@
# ignore task watchdog triggered by unity_run_menu # ignore task watchdog triggered by unity_run_menu
CONFIG_ESP_TASK_WDT=n CONFIG_ESP_TASK_WDT_EN=n
CONFIG_ESP_WIFI_BSS_MAX_IDLE_SUPPORT=y

View File

@ -75,6 +75,12 @@ void wifi_init_softap(void)
.pmf_cfg = { .pmf_cfg = {
.required = true, .required = true,
}, },
#ifdef CONFIG_ESP_WIFI_BSS_MAX_IDLE_SUPPORT
.bss_max_idle_cfg = {
.period = WIFI_AP_DEFAULT_MAX_IDLE_PERIOD,
.protected_keep_alive = 1,
},
#endif
}, },
}; };
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) { if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {