Skip to content

Commit

Permalink
Merge branch 'feature/advanced_roaming_support' into 'master'
Browse files Browse the repository at this point in the history
Add advanced Wi-Fi roaming support through Wi-Fi app

Closes WIFI-6169, WIFI-4212, WIFIBUG-314, and IDFGH-10713

See merge request espressif/esp-idf!26126
  • Loading branch information
jack0c committed Apr 1, 2024
2 parents 4921c63 + 431a2a7 commit d885808
Show file tree
Hide file tree
Showing 40 changed files with 1,915 additions and 166 deletions.
1 change: 1 addition & 0 deletions Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -629,3 +629,4 @@ mainmenu "Espressif IoT Development Framework Configuration"
- CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH
- CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL
- CONFIG_ESP_WIFI_EAP_TLS1_3
- CONFIG_ESP_WIFI_ENABLE_ROAMING_APP
10 changes: 8 additions & 2 deletions components/esp_wifi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ if(CONFIG_ESP_WIFI_ENABLED OR CONFIG_ESP_HOST_WIFI_ENABLED)
endif()

if(CONFIG_ESP_WIFI_NAN_ENABLE)
list(APPEND srcs "wifi_apps/src/nan_app.c")
list(APPEND srcs "wifi_apps/nan_app/src/nan_app.c")
endif()
if(CONFIG_ESP_WIFI_ENABLE_ROAMING_APP)
list(APPEND srcs "wifi_apps/roaming_app/src/roaming_app.c")
endif()
set(local_include_dirs include/local)
else()
Expand All @@ -50,10 +53,13 @@ else()
endif()

idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "include" "wifi_apps/include" ${local_include_dirs}
INCLUDE_DIRS "include" "wifi_apps/include" "wifi_apps/nan_app/include" ${local_include_dirs}

REQUIRES esp_event esp_phy esp_netif
PRIV_REQUIRES driver esptool_py esp_pm esp_timer nvs_flash
wpa_supplicant hal lwip esp_coex ${extra_priv_requires}
PRIV_INCLUDE_DIRS ../wpa_supplicant/src/ ../wpa_supplicant/esp_supplicant/src/
wifi_apps/roaming_app/include
LDFRAGMENTS "${ldfragments}")

if(CONFIG_ESP_WIFI_ENABLED OR CONFIG_ESP_HOST_WIFI_ENABLED)
Expand Down
20 changes: 20 additions & 0 deletions components/esp_wifi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,26 @@ menu "Wi-Fi"
help
Select this option to enable WiFi Multiband operation certification support.

config ESP_WIFI_ENABLE_ROAMING_APP
bool "Advanced support for Wi-Fi Roaming (Experimental)"
depends on IDF_EXPERIMENTAL_FEATURES
default n
select ESP_WIFI_SCAN_CACHE
help
Enable Espressif's roaming app to allow for efficient Wi-Fi roaming.
This includes configurable periodic environment scans, maintaining a cache of the
best APs, handling low rssi events etc.

Risk Warning
Please note that this feature is still experimental and enabling this potentially can
lead to unpredictable scanning, connection and roaming attempts.
We are still working on tuning and optimising this feature to ensure reliable and stable use.

menu "Configure roaming App"
depends on ESP_WIFI_ENABLE_ROAMING_APP
rsource "wifi_apps/roaming_app/src/Kconfig.roaming"
endmenu

config ESP_WIFI_DPP_SUPPORT
bool "Enable DPP support"
default n
Expand Down
50 changes: 32 additions & 18 deletions components/esp_wifi/include/esp_wifi_types_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,21 @@ typedef struct {
cause station to disconnect from AP and are not recommended. */
} wifi_scan_time_t;

typedef struct {
uint16_t ghz_2_channels; /**< Represents 2.4 GHz channels */
uint32_t ghz_5_channels; /**< Represents 5 GHz channels */
} wifi_scan_channel_bitmap_t;

/** @brief Parameters for an SSID scan. */
typedef struct {
uint8_t *ssid; /**< SSID of AP */
uint8_t *bssid; /**< MAC address of AP */
uint8_t channel; /**< channel, scan the specific channel */
bool show_hidden; /**< enable to scan AP whose SSID is hidden */
wifi_scan_type_t scan_type; /**< scan type, active or passive */
wifi_scan_time_t scan_time; /**< scan time per channel */
uint8_t home_chan_dwell_time;/**< time spent at home channel between scanning consecutive channels.*/
uint8_t *ssid; /**< SSID of AP */
uint8_t *bssid; /**< MAC address of AP */
uint8_t channel; /**< channel, scan the specific channel */
bool show_hidden; /**< enable to scan AP whose SSID is hidden */
wifi_scan_type_t scan_type; /**< scan type, active or passive */
wifi_scan_time_t scan_time; /**< scan time per channel */
uint8_t home_chan_dwell_time; /**< time spent at home channel between scanning consecutive channels. */
wifi_scan_channel_bitmap_t channel_bitmap; /**< Channel bitmap for setting specific channels to be scanned. For 2.4ghz channels set ghz_2_channels from BIT(1) to BIT(14) from LSB to MSB order to indicate channels to be scanned. Currently scanning in 5ghz channels is not supported. Please note that the 'channel' parameter above needs to be set to 0 to allow scanning by bitmap. */
} wifi_scan_config_t;

typedef enum {
Expand Down Expand Up @@ -247,7 +253,7 @@ typedef enum {
typedef struct {
int8_t rssi; /**< The minimum rssi to accept in the fast scan mode */
wifi_auth_mode_t authmode; /**< The weakest authmode to accept in the fast scan mode
Note: Incase this value is not set and password is set as per WPA2 standards(password len >= 8), it will be defaulted to WPA2 and device won't connect to deprecated WEP/WPA networks. Please set authmode threshold as WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK to connect to WEP/WPA networks */
Note: In case this value is not set and password is set as per WPA2 standards(password len >= 8), it will be defaulted to WPA2 and device won't connect to deprecated WEP/WPA networks. Please set authmode threshold as WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK to connect to WEP/WPA networks */
}wifi_scan_threshold_t;

typedef enum {
Expand All @@ -269,8 +275,8 @@ typedef enum {

/** Configuration structure for Protected Management Frame */
typedef struct {
bool capable; /**< Deprecated variable. Device will always connect in PMF mode if other device also advertizes PMF capability. */
bool required; /**< Advertizes that Protected Management Frame is required. Device will not associate to non-PMF capable devices. */
bool capable; /**< Deprecated variable. Device will always connect in PMF mode if other device also advertises PMF capability. */
bool required; /**< Advertises that Protected Management Frame is required. Device will not associate to non-PMF capable devices. */
} wifi_pmf_config_t;

/** Configuration for SAE PWE derivation */
Expand Down Expand Up @@ -318,16 +324,16 @@ typedef struct {
wifi_scan_threshold_t threshold; /**< When scan_threshold is set, only APs which have an auth mode that is more secure than the selected auth mode and a signal stronger than the minimum RSSI will be used. */
wifi_pmf_config_t pmf_cfg; /**< Configuration for Protected Management Frame. Will be advertised in RSN Capabilities in RSN IE. */
uint32_t rm_enabled:1; /**< Whether Radio Measurements are enabled for the connection */
uint32_t btm_enabled:1; /**< Whether BSS Transition Management is enabled for the connection */
uint32_t mbo_enabled:1; /**< Whether MBO is enabled for the connection */
uint32_t btm_enabled:1; /**< Whether BSS Transition Management is enabled for the connection. Note that when btm is enabled, the application itself should not set specific bssid (i.e using bssid_set and bssid in this config)or channel to connect to. This defeats the purpose of a BTM supported network, and hence if btm is supported and a specific bssid or channel is set in this config, it will be cleared from the config at the first disconnection or connection so that the device can roam to other BSS. It is recommended not to set BSSID when BTM is enabled. */
uint32_t mbo_enabled:1; /**< Whether MBO is enabled for the connection. Note that when mbo is enabled, the application itself should not set specific bssid (i.e using bssid_set and bssid in this config)or channel to connect to. This defeats the purpose of a MBO supported network, and hence if btm is supported and a specific bssid or channel is set in this config, it will be cleared from the config at the first disconnection or connection so that the device can roam to other BSS. It is recommended not to set BSSID when MBO is enabled. Enabling mbo here, automatically enables btm and rm above.*/
uint32_t ft_enabled:1; /**< Whether FT is enabled for the connection */
uint32_t owe_enabled:1; /**< Whether OWE is enabled for the connection */
uint32_t transition_disable:1; /**< Whether to enable transition disable feature */
uint32_t reserved:26; /**< Reserved for future feature set */
wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */
wifi_sae_pk_mode_t sae_pk_mode; /**< Configuration for SAE-PK (Public Key) Authentication method */
uint8_t failure_retry_cnt; /**< Number of connection retries station will do before moving to next AP. scan_method should be set as WIFI_ALL_CHANNEL_SCAN to use this config.
Note: Enabling this may cause connection time to increase incase best AP doesn't behave properly. */
Note: Enabling this may cause connection time to increase in case best AP doesn't behave properly. */
uint32_t he_dcm_set:1; /**< Whether DCM max.constellation for transmission and reception is set. */
uint32_t he_dcm_max_constellation_tx:2; /**< Indicate the max.constellation for DCM in TB PPDU the STA supported. 0: not supported. 1: BPSK, 2: QPSK, 3: 16-QAM. The default value is 3. */
uint32_t he_dcm_max_constellation_rx:2; /**< Indicate the max.constellation for DCM in both Data field and HE-SIG-B field the STA supported. 0: not supported. 1: BPSK, 2: QPSK, 3: 16-QAM. The default value is 3. */
Expand Down Expand Up @@ -441,7 +447,7 @@ typedef struct {
typedef enum {
WIFI_PKT_MGMT, /**< Management frame, indicates 'buf' argument is wifi_promiscuous_pkt_t */
WIFI_PKT_CTRL, /**< Control frame, indicates 'buf' argument is wifi_promiscuous_pkt_t */
WIFI_PKT_DATA, /**< Data frame, indiciates 'buf' argument is wifi_promiscuous_pkt_t */
WIFI_PKT_DATA, /**< Data frame, indicates 'buf' argument is wifi_promiscuous_pkt_t */
WIFI_PKT_MISC, /**< Other type, such as MIMO etc. 'buf' argument is wifi_promiscuous_pkt_t but the payload is zero length. */
} wifi_promiscuous_pkt_type_t;

Expand Down Expand Up @@ -565,10 +571,10 @@ typedef struct {
#define ESP_WIFI_NDP_ROLE_INITIATOR 1
#define ESP_WIFI_NDP_ROLE_RESPONDER 2

#define ESP_WIFI_MAX_SVC_NAME_LEN 256
#define ESP_WIFI_MAX_FILTER_LEN 256
#define ESP_WIFI_MAX_SVC_INFO_LEN 64

#define ESP_WIFI_MAX_SVC_NAME_LEN 256
#define ESP_WIFI_MAX_FILTER_LEN 256
#define ESP_WIFI_MAX_SVC_INFO_LEN 64
#define ESP_WIFI_MAX_NEIGHBOR_REP_LEN 64
/**
* @brief NAN Services types
*
Expand Down Expand Up @@ -781,6 +787,8 @@ typedef enum {
WIFI_EVENT_NDP_TERMINATED, /**< NAN Datapath terminated indication */
WIFI_EVENT_HOME_CHANNEL_CHANGE, /**< WiFi home channel change,doesn't occur when scanning */

WIFI_EVENT_STA_NEIGHBOR_REP, /**< Received Neighbor Report response */

WIFI_EVENT_MAX, /**< Invalid WiFi event ID */
} wifi_event_t;

Expand Down Expand Up @@ -1009,6 +1017,12 @@ typedef struct {
uint8_t init_ndi[6]; /**< Initiator's NAN Data Interface MAC */
} wifi_event_ndp_terminated_t;

/** Argument structure for WIFI_EVENT_STA_NEIGHBOR_REP event */
typedef struct {
uint8_t report[ESP_WIFI_MAX_NEIGHBOR_REP_LEN]; /**< Neighbor Report received from the AP*/
uint16_t report_len; /**< Length of the report*/
} wifi_event_neighbor_report_t;

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion components/esp_wifi/lib
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ static void nan_app_action_ndp_confirm(void *arg, esp_event_base_t event_base, i
}

if (nan_find_ndl(evt->ndp_id, NULL) == NULL) {
/* As ndl isn't found, timeout has occured for NDP response and datapath request is rejected */
/* As ndl isn't found, timeout has occurred for NDP response and datapath request is rejected */
goto done;
}
if (evt->status == NDP_STATUS_REJECTED) {
Expand Down
131 changes: 131 additions & 0 deletions components/esp_wifi/wifi_apps/roaming_app/include/esp_roaming.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_err.h"
#include "esp_wifi_types.h"
#include "utils/common.h"
#include <sys/time.h>
#ifdef __cplusplus
extern "C" {
#endif

#define SUPPLICANT_CANDIDATE_LIST_EXPIRY 10

/* Global Roaming Configuration */
#define ROAMING_BACKOFF_TIME CONFIG_ESP_WIFI_ROAMING_BACKOFF_TIME

/* Low RSSI based roaming configuration */
#define LOW_RSSI_ROAMING_ENABLED CONFIG_ESP_WIFI_ROAMING_LOW_RSSI_ROAMING
#if LOW_RSSI_ROAMING_ENABLED
#define ROAMING_LOW_RSSI_THRESHOLD CONFIG_ESP_WIFI_ROAMING_LOW_RSSI_THRESHOLD
#define RSSI_THRESHOLD_REDUCTION_OFFSET CONFIG_ESP_WIFI_ROAMING_LOW_RSSI_OFFSET
#endif /*LOW_RSSI_ROAMING_ENABLED*/

/* Periodic Scan based Roaming configuration */
#define PERIODIC_SCAN_MONITORING CONFIG_ESP_WIFI_ROAMING_PERIODIC_SCAN_MONITOR
#if PERIODIC_SCAN_MONITORING
#define SCAN_MONITOR_INTERVAL CONFIG_ESP_WIFI_ROAMING_SCAN_MONITOR_INTERVAL
#define SCAN_MONITOR_RSSI_THRESHOLD CONFIG_ESP_WIFI_ROAMING_PERIODIC_SCAN_THRESHOLD
#define SCAN_ROAM_RSSI_DIFF CONFIG_ESP_WIFI_ROAMING_SCAN_ROAM_RSSI_DIFF
#endif /* PERIODIC_SCAN_MONITORING */

/* Scan configuration */
#define SCAN_TIME_MIN_DURATION CONFIG_ESP_WIFI_ROAMING_SCAN_MIN_SCAN_TIME
#define SCAN_TIME_MAX_DURATION CONFIG_ESP_WIFI_ROAMING_SCAN_MAX_SCAN_TIME
#define HOME_CHANNEL_DWELL_TIME CONFIG_ESP_WIFI_ROAMING_HOME_CHANNEL_DWELL_TIME
#define SCAN_PREFERRED_CHAN_LIST CONFIG_ESP_WIFI_ROAMING_SCAN_CHAN_LIST
#define DEFAULT_PREFERRED_SCAN_CHAN_LIST "None"
#define SCAN_RESULTS_USABILITY_WINDOW CONFIG_ESP_WIFI_ROAMING_SCAN_EXPIRY_WINDOW
#define MAX_CANDIDATE_COUNT CONFIG_ESP_WIFI_ROAMING_MAX_CANDIDATES

/* Legacy roaming configuration */
#define LEGACY_ROAM_ENABLED CONFIG_ESP_WIFI_ROAMING_LEGACY_ROAMING

#define BSS_TM_RETRY_COUNT CONFIG_ESP_WIFI_NETWORK_ASSISTED_ROAMING_RETRY_COUNT

/* Network Assisted Roaming */
#define NETWORK_ASSISTED_ROAMING_ENABLED CONFIG_ESP_WIFI_ROAMING_NETWORK_ASSISTED_ROAM

/* Periodic RRM configuration */
#define PERIODIC_RRM_MONITORING CONFIG_ESP_WIFI_ROAMING_PERIODIC_RRM_MONITORING
#if PERIODIC_RRM_MONITORING
#define RRM_MONITOR_TIME CONFIG_ESP_WIFI_ROAMING_RRM_MONITOR_TIME
#define RRM_MONITOR_RSSI_THRESHOLD CONFIG_ESP_WIFI_ROAMING_RRM_MONITOR_THRESHOLD
#endif /*PERIODIC_RRM_MONITORING*/

#define MAX_SCAN_CHAN_LIST_COUNT 14

#define MAX_NEIGHBOR_LEN 512

#define IS_PSK(authmode) \
(((authmode == WIFI_AUTH_WPA_PSK) || (authmode == WIFI_AUTH_WPA2_PSK) || \
(authmode == WIFI_AUTH_WPA_WPA2_PSK) || (authmode == WIFI_AUTH_WPA3_PSK) || \
(authmode == WIFI_AUTH_WPA2_WPA3_PSK) || (authmode == WIFI_AUTH_WAPI_PSK) ? 1 : 0))

#define OWE_COMPATIBLE(curr_auth, cand_auth) \
((((curr_auth == WIFI_AUTH_OPEN) || (curr_auth == WIFI_AUTH_OWE)) && ((cand_auth == WIFI_AUTH_OPEN) || (cand_auth == WIFI_AUTH_OWE)))? 1 : 0)

#define PSK_COMPATIBLE(curr_auth, cand_auth) \
((IS_PSK(curr_auth) && IS_PSK(cand_auth)) ? 1 : 0)

struct scanned_ap_info {
uint16_t current_count;
struct timeval time;
wifi_ap_record_t ap_records[MAX_CANDIDATE_COUNT];
};
struct cand_bss {
uint8_t channel;
uint8_t bssid[ETH_ALEN];
};

struct roaming_app {
wifi_scan_config_t scan_params;
bool scan_ongoing;
int8_t current_rssi_threshold;
char *btm_neighbor_list;
struct timeval last_roamed_time;
wifi_ap_record_t ap_info;
struct scanned_ap_info scanned_aps;
bool btm_support;
bool rrm_support;

#if LOW_RSSI_ROAMING_ENABLED
int8_t current_low_rssi_threshold;
#endif
#if LEGACY_ROAM_ENABLED && NETWORK_ASSISTED_ROAMING_ENABLED
uint8_t btm_attempt;
#endif
#if LEGACY_ROAM_ENABLED
bool force_roam_ongoing;
#endif
#if PERIODIC_RRM_MONITORING
bool periodic_rrm_active;
bool rrm_request_active;
#endif
#if PERIODIC_SCAN_MONITORING
bool periodic_scan_active;
#endif
};

void init_roaming_app(void);
void deinit_roaming_app(void);

#if PERIODIC_RRM_MONITORING
void roaming_app_periodic_rrm_internal_handler(void *data, void *ctx);
#endif /*PERIODIC_RRM_MONITORING*/

#if PERIODIC_SCAN_MONITORING
void roaming_app_periodic_scan_internal_handler(void *data, void *ctx);
#endif /*PERIODIC_SCAN_ROAM_MONITORING*/

void roaming_app_trigger_roam_internal_handler(void *data, void *ctx);
#ifdef __cplusplus
}
#endif
Loading

0 comments on commit d885808

Please sign in to comment.