Merge branch 'fix/nan_improvements' into 'master'

Multiple NAN improvements in Service Discovery

Closes WIFI-5625

See merge request espressif/esp-idf!46455
This commit is contained in:
Jiang Jiang Jian
2026-05-13 19:51:55 +08:00
9 changed files with 276 additions and 66 deletions
+33 -11
View File
@@ -39,15 +39,34 @@ typedef struct {
void *storage; /**< storage for FreeRTOS queue */ void *storage; /**< storage for FreeRTOS queue */
} wifi_static_queue_t; } wifi_static_queue_t;
/* NAN Peer info parsed from SDF */
struct nan_cb_peer_info {
uint8_t peer_mac[6]; /**< Peer NMI / interface MAC */
uint8_t peer_svc_id; /**< Peer's service instance ID */
uint16_t sdea; /**< SDEA control field bits */
uint32_t device_caps; /**< NAN device capabilities */
uint8_t ssi_ver; /**< SSI version (service_match) */
uint8_t *ssi; /**< Service-specific information */
uint16_t ssi_len; /**< SSI length in bytes */
nan_vendor_ie_t *vendor_ie; /**< Vendor-specific IE, if any */
};
/* NDP Peer info parsed from NAF */
struct ndp_cb_peer_info {
uint8_t ndp_id;
uint8_t peer_nmi[6];
uint8_t peer_ndi[6];
uint8_t *ssi;
uint16_t ssi_len;
};
struct nan_sync_callbacks { struct nan_sync_callbacks {
void (* service_match)(uint8_t sub_id, uint8_t pub_id, uint8_t pub_mac[6], uint16_t capab, void (* service_match)(uint8_t sub_id, struct nan_cb_peer_info *peer_info);
uint8_t ssi_ver, uint8_t *ssi, uint16_t ssi_len); void (* replied)(uint8_t pub_id, struct nan_cb_peer_info *peer_info);
void (* replied)(uint8_t pub_id, uint8_t sub_id, uint8_t pub_mac[6], uint8_t *ssi, uint16_t ssi_len); void (* receive)(uint8_t svc_id, struct nan_cb_peer_info *peer_info);
void (* receive)(uint8_t svc_id, uint8_t peer_svc_id, uint8_t peer_mac[6], uint8_t *ssi, uint16_t ssi_len); void (* ndp_indication)(uint8_t pub_id, struct ndp_cb_peer_info *peer_info, uint32_t device_caps);
void (* ndp_indication)(uint8_t pub_id, uint8_t ndp_id, uint8_t peer_nmi[6], uint8_t peer_ndi[6], void (* ndp_confirm)(uint8_t status, struct ndp_cb_peer_info *peer_info,
uint8_t *ssi, uint16_t ssi_len); uint8_t own_ndi[6], uint8_t ipv6_identifier[8]);
void (* ndp_confirm)(uint8_t status, uint8_t ndp_id, uint8_t peer_nmi[6], uint8_t peer_ndi[6],
uint8_t own_ndi[6], uint8_t *ssi, uint16_t ssi_len);
void (* ndp_terminated)(uint8_t reason, uint8_t ndp_id, uint8_t init_ndi[6]); void (* ndp_terminated)(uint8_t reason, uint8_t ndp_id, uint8_t init_ndi[6]);
void (* action_txdone)(uint32_t context, bool tx_status); void (* action_txdone)(uint32_t context, bool tx_status);
}; };
@@ -741,13 +760,15 @@ esp_err_t esp_nan_internal_send_followup(const wifi_nan_followup_params_t *fup_p
* *
* @attention This API should be called after WIFI_EVENT_NAN_SVC_MATCH event is received. * @attention This API should be called after WIFI_EVENT_NAN_SVC_MATCH event is received.
* *
* @param req NAN Datapath Request parameters. * @param[in] req NAN Datapath Request parameters.
* @param[out] ndp_id Pointer to the NDP ID in the NAN Datapath Request.
* @param[in] ipv6_identifier IPV6 Address Identifier to be sent in the NDPE attribute.
* *
* @return * @return
* - ESP_OK: succeed * - ESP_OK: succeed
* - others: failed * - others: failed
*/ */
esp_err_t esp_nan_internal_datapath_req(wifi_nan_datapath_req_t *req, uint8_t *ndp_id); esp_err_t esp_nan_internal_datapath_req(wifi_nan_datapath_req_t *req, uint8_t *ndp_id, uint8_t ipv6_identifier[8]);
/** /**
* @brief Send Datapath Response to accept or reject the received request * @brief Send Datapath Response to accept or reject the received request
@@ -755,12 +776,13 @@ esp_err_t esp_nan_internal_datapath_req(wifi_nan_datapath_req_t *req, uint8_t *n
* @attention This API should be called on the Publisher after receiving WIFI_EVENT_NDP_INDICATION event. * @attention This API should be called on the Publisher after receiving WIFI_EVENT_NDP_INDICATION event.
* *
* @param resp NAN Datapath Response parameters. * @param resp NAN Datapath Response parameters.
* @param ipv6_identifier IPV6 Address Identifier to be sent in the NDPE attribute.
* *
* @return * @return
* - ESP_OK: succeed * - ESP_OK: succeed
* - others: failed * - others: failed
*/ */
esp_err_t esp_nan_internal_datapath_resp(wifi_nan_datapath_resp_t *resp); esp_err_t esp_nan_internal_datapath_resp(wifi_nan_datapath_resp_t *resp, uint8_t ipv6_identifier[8]);
/** /**
* @brief End NAN Datapath that is active * @brief End NAN Datapath that is active
@@ -592,10 +592,11 @@ typedef struct {
* @brief NAN Discovery start configuration * @brief NAN Discovery start configuration
*/ */
typedef struct { typedef struct {
uint8_t op_channel; /**< NAN Discovery operating channel */ uint8_t op_channel; /**< NAN Discovery operating channel */
uint8_t master_pref; /**< Device's preference value to serve as NAN Master */ uint8_t master_pref; /**< Device's preference value to serve as NAN Master */
uint8_t scan_time; /**< Scan time in seconds while searching for a NAN cluster */ uint8_t scan_time; /**< Scan time in seconds while searching for a NAN cluster */
uint16_t warm_up_sec; /**< Warm up time before assuming NAN Anchor Master role */ uint16_t warm_up_sec; /**< Warm up time before assuming NAN Anchor Master role */
bool disable_random_mac;/**< Disable the MAC Randomisation in NAN */
} wifi_nan_sync_config_t; } wifi_nan_sync_config_t;
/** /**
@@ -916,6 +917,17 @@ typedef struct {
uint8_t m_max; /**< Indicates maximum value of dwell period M used in the USD (Mmax)*/ uint8_t m_max; /**< Indicates maximum value of dwell period M used in the USD (Mmax)*/
} wifi_nan_usd_config_t; } wifi_nan_usd_config_t;
#define NAN_VENDOR_IE_MAX_BODY_LEN 255
/**
* @brief NAN Vendor Specific Attribute format
*/
typedef struct {
uint8_t vendor_oui[3]; /**< Vendor identifier (OUI) */
uint16_t body_len; /**< Length of body payload (max NAN_VENDOR_IE_MAX_BODY_LEN bytes) */
uint8_t *body; /**< Vendor specific body payload */
} nan_vendor_ie_t;
/** /**
* @brief NAN Publish service configuration parameters * @brief NAN Publish service configuration parameters
* *
@@ -936,6 +948,7 @@ typedef struct {
unsigned int ttl; /**< Run publish function for a given time interval in seconds. If ttl=0 and usd_discovery_flag is enabled, unsigned int ttl; /**< Run publish function for a given time interval in seconds. If ttl=0 and usd_discovery_flag is enabled,
only one Publish message is transmitted */ only one Publish message is transmitted */
wifi_nan_usd_config_t usd_publish_config; /**< USD configuration parameters. Relevant only when 'usd_discovery_flag' is set. */ wifi_nan_usd_config_t usd_publish_config; /**< USD configuration parameters. Relevant only when 'usd_discovery_flag' is set. */
nan_vendor_ie_t *vendor_ie; /**< Vendor specific IE to be added in publish frames */
} wifi_nan_publish_cfg_t; } wifi_nan_publish_cfg_t;
/** /**
@@ -957,6 +970,7 @@ typedef struct {
unsigned int ttl; /**< Run subscribe function for a given time interval in seconds. If ttl=0 and usd_discovery_flag is enabled, unsigned int ttl; /**< Run subscribe function for a given time interval in seconds. If ttl=0 and usd_discovery_flag is enabled,
the subscriber listens until the first service match is reported. */ the subscriber listens until the first service match is reported. */
wifi_nan_usd_config_t usd_subscribe_config; /**< USD configuration parameters. Relevant only when 'usd_discovery_flag' is set. */ wifi_nan_usd_config_t usd_subscribe_config; /**< USD configuration parameters. Relevant only when 'usd_discovery_flag' is set. */
nan_vendor_ie_t *vendor_ie; /**< Vendor specific IE to be added in subscribe frames */
} wifi_nan_subscribe_cfg_t; } wifi_nan_subscribe_cfg_t;
/** /**
@@ -969,6 +983,7 @@ typedef struct {
uint8_t peer_mac[6]; /**< Peer's MAC address */ uint8_t peer_mac[6]; /**< Peer's MAC address */
uint16_t ssi_len; /**< Length of service specific info, maximum allowed length - ESP_WIFI_MAX_FUP_SSI_LEN */ uint16_t ssi_len; /**< Length of service specific info, maximum allowed length - ESP_WIFI_MAX_FUP_SSI_LEN */
uint8_t *ssi; /**< Service Specific Info of type wifi_nan_wfa_ssi_t for WFA defined protocols, otherwise proprietary and defined by Applications */ uint8_t *ssi; /**< Service Specific Info of type wifi_nan_wfa_ssi_t for WFA defined protocols, otherwise proprietary and defined by Applications */
nan_vendor_ie_t *vendor_ie; /**< Vendor specific IE to be added in followup frames */
} wifi_nan_followup_params_t; } wifi_nan_followup_params_t;
/** /**
@@ -989,6 +1004,8 @@ typedef struct {
bool accept; /**< True - Accept incoming NDP, False - Reject it */ bool accept; /**< True - Accept incoming NDP, False - Reject it */
uint8_t ndp_id; /**< NAN Datapath Identifier */ uint8_t ndp_id; /**< NAN Datapath Identifier */
uint8_t peer_mac[6]; /**< Peer's MAC address */ uint8_t peer_mac[6]; /**< Peer's MAC address */
uint16_t ssi_len; /**< Length of service specific info, maximum allowed length - ESP_WIFI_MAX_SVC_SSI_LEN */
uint8_t *ssi; /**< Service Specific Info of type wifi_nan_wfa_ssi_t for WFA defined protocols, otherwise proprietary and defined by Applications */
} wifi_nan_datapath_resp_t; } wifi_nan_datapath_resp_t;
/** /**
@@ -1393,7 +1410,8 @@ typedef struct {
uint8_t datapath_reqd: 1; /**< NAN Datapath required for the service */ uint8_t datapath_reqd: 1; /**< NAN Datapath required for the service */
uint8_t fsd_reqd: 1; /**< Further Service Discovery(FSD) required */ uint8_t fsd_reqd: 1; /**< Further Service Discovery(FSD) required */
uint8_t fsd_gas: 1; /**< 0 - Follow-up used for FSD, 1 - GAS used for FSD */ uint8_t fsd_gas: 1; /**< 0 - Follow-up used for FSD, 1 - GAS used for FSD */
uint8_t reserved: 5; /**< Reserved */ uint8_t ndpe_support: 1; /**< NDPE supported by peer */
uint8_t reserved: 4; /**< Reserved */
uint32_t reserved_1; /**< Reserved */ uint32_t reserved_1; /**< Reserved */
uint32_t reserved_2; /**< Reserved */ uint32_t reserved_2; /**< Reserved */
uint8_t ssi_version; /**< Indicates version of SSI in Publish instance, 0 if not available */ uint8_t ssi_version; /**< Indicates version of SSI in Publish instance, 0 if not available */
@@ -1450,8 +1468,7 @@ typedef struct {
uint8_t peer_nmi[6]; /**< Peer's NAN Management Interface MAC */ uint8_t peer_nmi[6]; /**< Peer's NAN Management Interface MAC */
uint8_t peer_ndi[6]; /**< Peer's NAN Data Interface MAC */ uint8_t peer_ndi[6]; /**< Peer's NAN Data Interface MAC */
uint8_t own_ndi[6]; /**< Own NAN Data Interface MAC */ uint8_t own_ndi[6]; /**< Own NAN Data Interface MAC */
uint32_t reserved_1; /**< Reserved */ uint8_t ipv6_identifier[8]; /**< Peer's IPV6 Address Identifier */
uint32_t reserved_2; /**< Reserved */
uint16_t ssi_len; /**< Length of Service Specific Info */ uint16_t ssi_len; /**< Length of Service Specific Info */
uint8_t ssi[]; /**< Service specific info from NDP/NDPE Attribute */ uint8_t ssi[]; /**< Service specific info from NDP/NDPE Attribute */
} wifi_event_ndp_confirm_t; } wifi_event_ndp_confirm_t;
@@ -592,10 +592,11 @@ typedef struct {
* @brief NAN Discovery start configuration * @brief NAN Discovery start configuration
*/ */
typedef struct { typedef struct {
uint8_t op_channel; /**< NAN Discovery operating channel */ uint8_t op_channel; /**< NAN Discovery operating channel */
uint8_t master_pref; /**< Device's preference value to serve as NAN Master */ uint8_t master_pref; /**< Device's preference value to serve as NAN Master */
uint8_t scan_time; /**< Scan time in seconds while searching for a NAN cluster */ uint8_t scan_time; /**< Scan time in seconds while searching for a NAN cluster */
uint16_t warm_up_sec; /**< Warm up time before assuming NAN Anchor Master role */ uint16_t warm_up_sec; /**< Warm up time before assuming NAN Anchor Master role */
bool disable_random_mac;/**< Disable the MAC Randomisation in NAN */
} wifi_nan_sync_config_t; } wifi_nan_sync_config_t;
/** /**
@@ -916,6 +917,17 @@ typedef struct {
uint8_t m_max; /**< Indicates maximum value of dwell period M used in the USD (Mmax)*/ uint8_t m_max; /**< Indicates maximum value of dwell period M used in the USD (Mmax)*/
} wifi_nan_usd_config_t; } wifi_nan_usd_config_t;
#define NAN_VENDOR_IE_MAX_BODY_LEN 255
/**
* @brief NAN Vendor Specific Attribute format
*/
typedef struct {
uint8_t vendor_oui[3]; /**< Vendor identifier (OUI) */
uint16_t body_len; /**< Length of body payload (max NAN_VENDOR_IE_MAX_BODY_LEN bytes) */
uint8_t *body; /**< Vendor specific body payload */
} nan_vendor_ie_t;
/** /**
* @brief NAN Publish service configuration parameters * @brief NAN Publish service configuration parameters
* *
@@ -936,6 +948,7 @@ typedef struct {
unsigned int ttl; /**< Run publish function for a given time interval in seconds. If ttl=0 and usd_discovery_flag is enabled, unsigned int ttl; /**< Run publish function for a given time interval in seconds. If ttl=0 and usd_discovery_flag is enabled,
only one Publish message is transmitted */ only one Publish message is transmitted */
wifi_nan_usd_config_t usd_publish_config; /**< USD configuration parameters. Relevant only when 'usd_discovery_flag' is set. */ wifi_nan_usd_config_t usd_publish_config; /**< USD configuration parameters. Relevant only when 'usd_discovery_flag' is set. */
nan_vendor_ie_t *vendor_ie; /**< Vendor specific IE to be added in publish frames */
} wifi_nan_publish_cfg_t; } wifi_nan_publish_cfg_t;
/** /**
@@ -957,6 +970,7 @@ typedef struct {
unsigned int ttl; /**< Run subscribe function for a given time interval in seconds. If ttl=0 and usd_discovery_flag is enabled, unsigned int ttl; /**< Run subscribe function for a given time interval in seconds. If ttl=0 and usd_discovery_flag is enabled,
the subscriber listens until the first service match is reported. */ the subscriber listens until the first service match is reported. */
wifi_nan_usd_config_t usd_subscribe_config; /**< USD configuration parameters. Relevant only when 'usd_discovery_flag' is set. */ wifi_nan_usd_config_t usd_subscribe_config; /**< USD configuration parameters. Relevant only when 'usd_discovery_flag' is set. */
nan_vendor_ie_t *vendor_ie; /**< Vendor specific IE to be added in subscribe frames */
} wifi_nan_subscribe_cfg_t; } wifi_nan_subscribe_cfg_t;
/** /**
@@ -969,6 +983,7 @@ typedef struct {
uint8_t peer_mac[6]; /**< Peer's MAC address */ uint8_t peer_mac[6]; /**< Peer's MAC address */
uint16_t ssi_len; /**< Length of service specific info, maximum allowed length - ESP_WIFI_MAX_FUP_SSI_LEN */ uint16_t ssi_len; /**< Length of service specific info, maximum allowed length - ESP_WIFI_MAX_FUP_SSI_LEN */
uint8_t *ssi; /**< Service Specific Info of type wifi_nan_wfa_ssi_t for WFA defined protocols, otherwise proprietary and defined by Applications */ uint8_t *ssi; /**< Service Specific Info of type wifi_nan_wfa_ssi_t for WFA defined protocols, otherwise proprietary and defined by Applications */
nan_vendor_ie_t *vendor_ie; /**< Vendor specific IE to be added in followup frames */
} wifi_nan_followup_params_t; } wifi_nan_followup_params_t;
/** /**
@@ -989,6 +1004,8 @@ typedef struct {
bool accept; /**< True - Accept incoming NDP, False - Reject it */ bool accept; /**< True - Accept incoming NDP, False - Reject it */
uint8_t ndp_id; /**< NAN Datapath Identifier */ uint8_t ndp_id; /**< NAN Datapath Identifier */
uint8_t peer_mac[6]; /**< Peer's MAC address */ uint8_t peer_mac[6]; /**< Peer's MAC address */
uint16_t ssi_len; /**< Length of service specific info, maximum allowed length - ESP_WIFI_MAX_SVC_SSI_LEN */
uint8_t *ssi; /**< Service Specific Info of type wifi_nan_wfa_ssi_t for WFA defined protocols, otherwise proprietary and defined by Applications */
} wifi_nan_datapath_resp_t; } wifi_nan_datapath_resp_t;
/** /**
@@ -1393,7 +1410,8 @@ typedef struct {
uint8_t datapath_reqd: 1; /**< NAN Datapath required for the service */ uint8_t datapath_reqd: 1; /**< NAN Datapath required for the service */
uint8_t fsd_reqd: 1; /**< Further Service Discovery(FSD) required */ uint8_t fsd_reqd: 1; /**< Further Service Discovery(FSD) required */
uint8_t fsd_gas: 1; /**< 0 - Follow-up used for FSD, 1 - GAS used for FSD */ uint8_t fsd_gas: 1; /**< 0 - Follow-up used for FSD, 1 - GAS used for FSD */
uint8_t reserved: 5; /**< Reserved */ uint8_t ndpe_support: 1; /**< NDPE supported by peer */
uint8_t reserved: 4; /**< Reserved */
uint32_t reserved_1; /**< Reserved */ uint32_t reserved_1; /**< Reserved */
uint32_t reserved_2; /**< Reserved */ uint32_t reserved_2; /**< Reserved */
uint8_t ssi_version; /**< Indicates version of SSI in Publish instance, 0 if not available */ uint8_t ssi_version; /**< Indicates version of SSI in Publish instance, 0 if not available */
@@ -1450,8 +1468,7 @@ typedef struct {
uint8_t peer_nmi[6]; /**< Peer's NAN Management Interface MAC */ uint8_t peer_nmi[6]; /**< Peer's NAN Management Interface MAC */
uint8_t peer_ndi[6]; /**< Peer's NAN Data Interface MAC */ uint8_t peer_ndi[6]; /**< Peer's NAN Data Interface MAC */
uint8_t own_ndi[6]; /**< Own NAN Data Interface MAC */ uint8_t own_ndi[6]; /**< Own NAN Data Interface MAC */
uint32_t reserved_1; /**< Reserved */ uint8_t ipv6_identifier[8]; /**< Peer's IPV6 Address Identifier */
uint32_t reserved_2; /**< Reserved */
uint16_t ssi_len; /**< Length of Service Specific Info */ uint16_t ssi_len; /**< Length of Service Specific Info */
uint8_t ssi[]; /**< Service specific info from NDP/NDPE Attribute */ uint8_t ssi[]; /**< Service specific info from NDP/NDPE Attribute */
} wifi_event_ndp_confirm_t; } wifi_event_ndp_confirm_t;
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -21,6 +21,7 @@ extern "C" {
.master_pref = 2, \ .master_pref = 2, \
.scan_time = 3, \ .scan_time = 3, \
.warm_up_sec = 5, \ .warm_up_sec = 5, \
.disable_random_mac = false, \
}; };
#define NDP_STATUS_ACCEPTED 1 #define NDP_STATUS_ACCEPTED 1
@@ -29,6 +30,20 @@ extern "C" {
#define NAN_MAX_PEERS_RECORD 15 #define NAN_MAX_PEERS_RECORD 15
#define ESP_NAN_PUBLISH 2 #define ESP_NAN_PUBLISH 2
#define ESP_NAN_SUBSCRIBE 1 #define ESP_NAN_SUBSCRIBE 1
#define NAN_IPV6_ADDR_ID_LEN 8
#define IS_ZERO_NAN_ADDR_ID(a) (!((a)[0] | (a)[1] | (a)[2] | (a)[3] | \
(a)[4] | (a)[5] | (a)[6] | (a)[7]))
#define ESP_NAN_SET_IPV6_LINKLOCAL_FROM_IDENTIFIER(_target_addr, _identifier) \
do { \
(_target_addr).type = IPADDR_TYPE_V6; \
(_target_addr).u_addr.ip6.addr[0] = htonl(0xFE800000); \
(_target_addr).u_addr.ip6.addr[1] = 0; \
memcpy(&(_target_addr).u_addr.ip6.addr[2], \
(_identifier), \
NAN_IPV6_ADDR_ID_LEN); \
} while (0)
/** Parameters of a peer service record */ /** Parameters of a peer service record */
struct nan_peer_record { struct nan_peer_record {
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -33,6 +33,9 @@
#define NDP_TERMINATED BIT6 #define NDP_TERMINATED BIT6
#define NDP_REJECTED BIT7 #define NDP_REJECTED BIT7
/* NAN Caps */
#define NAN_CAPS_NDPE_ATTR BIT3
/* Macros */ /* Macros */
#define MACADDR_LEN 6 #define MACADDR_LEN 6
#define MACADDR_EQUAL(a1, a2) (memcmp(a1, a2, MACADDR_LEN)) #define MACADDR_EQUAL(a1, a2) (memcmp(a1, a2, MACADDR_LEN))
@@ -73,6 +76,7 @@ struct peer_svc_info {
uint8_t own_svc_id; /**< Identifier for own service */ uint8_t own_svc_id; /**< Identifier for own service */
uint8_t type; /**< Service type (Publish/Subscribe) */ uint8_t type; /**< Service type (Publish/Subscribe) */
uint8_t peer_nmi[MACADDR_LEN]; /**< Peer's NAN Management Interface address */ uint8_t peer_nmi[MACADDR_LEN]; /**< Peer's NAN Management Interface address */
uint32_t device_caps;
}; };
struct own_svc_info { struct own_svc_info {
@@ -90,6 +94,7 @@ struct ndl_info {
uint8_t peer_nmi[MACADDR_LEN]; /**< Peer's NAN Management Interface address */ uint8_t peer_nmi[MACADDR_LEN]; /**< Peer's NAN Management Interface address */
uint8_t publisher_id; /**< Publisher's service identifier */ uint8_t publisher_id; /**< Publisher's service identifier */
uint8_t own_role; /**< Own role (Publisher/Subscriber) */ uint8_t own_role; /**< Own role (Publisher/Subscriber) */
uint32_t device_caps; /**< Peer's Device Capabilities from NDP Indication/Confirm */
}; };
typedef struct { typedef struct {
@@ -208,7 +213,7 @@ static struct peer_svc_info *nan_find_peer_svc(uint8_t own_svc_id, uint8_t peer_
return p_peer_svc; return p_peer_svc;
} }
static bool nan_record_peer_svc(uint8_t own_svc_id, uint8_t peer_svc_id, uint8_t peer_nmi[]) static bool nan_record_peer_svc(uint8_t own_svc_id, uint8_t peer_svc_id, uint8_t peer_nmi[], uint32_t device_caps)
{ {
struct own_svc_info *p_own_svc; struct own_svc_info *p_own_svc;
struct peer_svc_info *p_peer_svc; struct peer_svc_info *p_peer_svc;
@@ -227,7 +232,7 @@ static bool nan_record_peer_svc(uint8_t own_svc_id, uint8_t peer_svc_id, uint8_t
p_peer_svc->own_svc_id = own_svc_id; p_peer_svc->own_svc_id = own_svc_id;
p_peer_svc->type = (p_own_svc->type == ESP_NAN_SUBSCRIBE) ? ESP_NAN_PUBLISH : ESP_NAN_SUBSCRIBE; p_peer_svc->type = (p_own_svc->type == ESP_NAN_SUBSCRIBE) ? ESP_NAN_PUBLISH : ESP_NAN_SUBSCRIBE;
MACADDR_COPY(p_peer_svc->peer_nmi, peer_nmi); MACADDR_COPY(p_peer_svc->peer_nmi, peer_nmi);
p_peer_svc->device_caps = device_caps;
if (p_own_svc->num_peer_records < NAN_MAX_PEERS_RECORD) { if (p_own_svc->num_peer_records < NAN_MAX_PEERS_RECORD) {
SLIST_INSERT_HEAD(&(p_own_svc->peer_list), p_peer_svc, next); SLIST_INSERT_HEAD(&(p_own_svc->peer_list), p_peer_svc, next);
p_own_svc->num_peer_records++; p_own_svc->num_peer_records++;
@@ -337,7 +342,7 @@ static bool ndl_limit_reached(void)
return true; return true;
} }
static void nan_record_new_ndl(uint8_t ndp_id, uint8_t publish_id, uint8_t peer_nmi[], uint8_t own_role) static void nan_record_new_ndl(uint8_t ndp_id, uint8_t publish_id, uint8_t peer_nmi[], uint8_t own_role, uint32_t device_caps)
{ {
struct ndl_info *ndl = NULL; struct ndl_info *ndl = NULL;
@@ -351,6 +356,7 @@ static void nan_record_new_ndl(uint8_t ndp_id, uint8_t publish_id, uint8_t peer_
return; return;
} }
ndl->ndp_id = ndp_id; ndl->ndp_id = ndp_id;
ndl->device_caps = device_caps;
if (peer_nmi) { if (peer_nmi) {
MACADDR_COPY(ndl->peer_nmi, peer_nmi); MACADDR_COPY(ndl->peer_nmi, peer_nmi);
} }
@@ -449,21 +455,36 @@ static void nan_app_post_event(int32_t event_id, void* event_data, size_t event_
g_wifi_osi_funcs._event_post(WIFI_EVENT, event_id, event_data, event_data_size, OSI_FUNCS_TIME_BLOCKING); g_wifi_osi_funcs._event_post(WIFI_EVENT, event_id, event_data, event_data_size, OSI_FUNCS_TIME_BLOCKING);
} }
void nan_app_service_match_cb(uint8_t sub_id, uint8_t pub_id, uint8_t pub_mac[6], uint16_t capab, void nan_app_service_match_cb(uint8_t sub_id, struct nan_cb_peer_info *peer_info)
uint8_t ssi_ver, uint8_t *ssi, uint16_t ssi_len)
{ {
NAN_DATA_LOCK(); if (!peer_info) {
struct peer_svc_info *peer_info = nan_find_peer_svc(sub_id, 0, pub_mac); return;
}
uint8_t pub_id = peer_info->peer_svc_id;
uint8_t *pub_mac = peer_info->peer_mac;
uint16_t capab = peer_info->sdea;
uint8_t ssi_ver = peer_info->ssi_ver;
uint8_t *ssi = peer_info->ssi;
uint16_t ssi_len = peer_info->ssi_len;
uint32_t device_caps = peer_info->device_caps;
if (peer_info && peer_info->svc_id != pub_id) { NAN_DATA_LOCK();
struct peer_svc_info *p_peer_svc = nan_find_peer_svc(sub_id, 0, pub_mac);
if (p_peer_svc) {
struct ndl_info *ndl = nan_find_ndl(0, pub_mac); struct ndl_info *ndl = nan_find_ndl(0, pub_mac);
peer_info->svc_id = pub_id; p_peer_svc->device_caps = device_caps;
if (ndl) { if (p_peer_svc->svc_id != pub_id) {
p_peer_svc->svc_id = pub_id;
if (ndl) {
ndl->publisher_id = pub_id;
}
} else if (ndl) {
ndl->publisher_id = pub_id; ndl->publisher_id = pub_id;
} }
} else { } else {
nan_record_peer_svc(sub_id, pub_id, pub_mac); nan_record_peer_svc(sub_id, pub_id, pub_mac, device_caps);
} }
NAN_DATA_UNLOCK(); NAN_DATA_UNLOCK();
@@ -481,6 +502,7 @@ void nan_app_service_match_cb(uint8_t sub_id, uint8_t pub_id, uint8_t pub_mac[6]
evt->fsd_reqd = (capab & NAN_SDEA_CTRL_FSD_REQD) ? 1 : 0; evt->fsd_reqd = (capab & NAN_SDEA_CTRL_FSD_REQD) ? 1 : 0;
evt->fsd_gas = (capab & NAN_SDEA_CTRL_FSD_GAS) ? 1 : 0; evt->fsd_gas = (capab & NAN_SDEA_CTRL_FSD_GAS) ? 1 : 0;
evt->datapath_reqd = (capab & NAN_SDEA_CTRL_DATAPATH_REQD) ? 1 : 0; evt->datapath_reqd = (capab & NAN_SDEA_CTRL_DATAPATH_REQD) ? 1 : 0;
evt->ndpe_support = (device_caps & NAN_CAPS_NDPE_ATTR) ? 1 : 0;
evt->ssi_version = ssi_ver; evt->ssi_version = ssi_ver;
if (ssi && ssi_len) { if (ssi && ssi_len) {
if (ssi_ver) { if (ssi_ver) {
@@ -498,11 +520,23 @@ void nan_app_service_match_cb(uint8_t sub_id, uint8_t pub_id, uint8_t pub_mac[6]
os_free(evt); os_free(evt);
} }
void nan_app_replied_cb(uint8_t pub_id, uint8_t sub_id, uint8_t sub_nmi[6], uint8_t *ssi, uint16_t ssi_len) void nan_app_replied_cb(uint8_t pub_id, struct nan_cb_peer_info *peer_info)
{ {
if (!peer_info) {
return;
}
uint8_t sub_id = peer_info->peer_svc_id;
uint8_t *sub_nmi = peer_info->peer_mac;
uint8_t *ssi = peer_info->ssi;
uint16_t ssi_len = peer_info->ssi_len;
uint32_t device_caps = peer_info->device_caps;
NAN_DATA_LOCK(); NAN_DATA_LOCK();
if (!nan_find_peer_svc(pub_id, sub_id, sub_nmi)) { struct peer_svc_info *p_peer_svc = nan_find_peer_svc(pub_id, sub_id, sub_nmi);
nan_record_peer_svc(pub_id, sub_id, sub_nmi); if (p_peer_svc) {
p_peer_svc->device_caps = device_caps;
} else {
nan_record_peer_svc(pub_id, sub_id, sub_nmi, device_caps);
} }
NAN_DATA_UNLOCK(); NAN_DATA_UNLOCK();
@@ -524,15 +558,27 @@ void nan_app_replied_cb(uint8_t pub_id, uint8_t sub_id, uint8_t sub_nmi[6], uint
ESP_LOG_BUFFER_HEXDUMP(TAG, ssi, ssi_len, ESP_LOG_DEBUG); ESP_LOG_BUFFER_HEXDUMP(TAG, ssi, ssi_len, ESP_LOG_DEBUG);
} }
nan_app_post_event(WIFI_EVENT_NAN_REPLIED, evt, sizeof(wifi_event_nan_replied_t)); nan_app_post_event(WIFI_EVENT_NAN_REPLIED, evt, evt_data_len);
os_free(evt); os_free(evt);
} }
void nan_app_receive_cb(uint8_t svc_id, uint8_t peer_svc_id, uint8_t peer_mac[6], uint8_t *ssi, uint16_t ssi_len) void nan_app_receive_cb(uint8_t svc_id, struct nan_cb_peer_info *peer_info)
{ {
if (!peer_info) {
return;
}
uint8_t peer_svc_id = peer_info->peer_svc_id;
uint8_t *peer_mac = peer_info->peer_mac;
uint8_t *ssi = peer_info->ssi;
uint16_t ssi_len = peer_info->ssi_len;
uint32_t device_caps = peer_info->device_caps;
NAN_DATA_LOCK(); NAN_DATA_LOCK();
if (!nan_find_peer_svc(svc_id, peer_svc_id, peer_mac)) { struct peer_svc_info *p_peer_svc = nan_find_peer_svc(svc_id, peer_svc_id, peer_mac);
nan_record_peer_svc(svc_id, peer_svc_id, peer_mac); if (p_peer_svc) {
p_peer_svc->device_caps = device_caps;
} else {
nan_record_peer_svc(svc_id, peer_svc_id, peer_mac, device_caps);
} }
NAN_DATA_UNLOCK(); NAN_DATA_UNLOCK();
@@ -557,9 +603,18 @@ void nan_app_receive_cb(uint8_t svc_id, uint8_t peer_svc_id, uint8_t peer_mac[6]
os_free(evt); os_free(evt);
} }
void nan_app_ndp_indication_cb(uint8_t pub_id, uint8_t ndp_id, uint8_t peer_nmi[6], uint8_t peer_ndi[6], void nan_app_ndp_indication_cb(uint8_t pub_id, struct ndp_cb_peer_info *peer_info, uint32_t device_caps)
uint8_t *ssi, uint16_t ssi_len)
{ {
if (!peer_info) {
return;
}
uint8_t ndp_id = peer_info->ndp_id;
uint8_t *peer_nmi = peer_info->peer_nmi;
uint8_t *peer_ndi = peer_info->peer_ndi;
uint8_t *ssi = peer_info->ssi;
uint16_t ssi_len = peer_info->ssi_len;
bool ndp_resp_needed = false;
NAN_DATA_LOCK(); NAN_DATA_LOCK();
struct own_svc_info *p_own_svc = nan_find_own_svc(pub_id); struct own_svc_info *p_own_svc = nan_find_own_svc(pub_id);
@@ -568,25 +623,46 @@ void nan_app_ndp_indication_cb(uint8_t pub_id, uint8_t ndp_id, uint8_t peer_nmi[
NAN_DATA_UNLOCK(); NAN_DATA_UNLOCK();
return; return;
} }
ndp_resp_needed = p_own_svc->ndp_resp_needed;
if (ndl_limit_reached()) { if (ndl_limit_reached()) {
ESP_LOGE(TAG, "NDP limit reached"); ESP_LOGE(TAG, "NDP limit reached");
NAN_DATA_UNLOCK(); NAN_DATA_UNLOCK();
return; return;
} }
nan_record_new_ndl(ndp_id, pub_id, peer_nmi, ESP_WIFI_NDP_ROLE_RESPONDER); if (!nan_find_peer_svc(pub_id, 0, peer_nmi)) {
nan_record_peer_svc(pub_id, 0, peer_nmi, device_caps);
}
if (p_own_svc->ndp_resp_needed) { if (p_own_svc->ndp_resp_needed) {
nan_record_new_ndl(ndp_id, pub_id, peer_nmi, ESP_WIFI_NDP_ROLE_RESPONDER, device_caps);
ESP_LOGI(TAG, "NDP Req from "MACSTR" [NDP Id: %d], Accept OR Deny using NDP command", ESP_LOGI(TAG, "NDP Req from "MACSTR" [NDP Id: %d], Accept OR Deny using NDP command",
MAC2STR(peer_nmi), ndp_id); MAC2STR(peer_nmi), ndp_id);
s_nan_ctx.event |= NDP_INDICATION; s_nan_ctx.event |= NDP_INDICATION;
} else { } else {
uint8_t own_bssid[6];
ip_addr_t own_ipv6 = {0};
wifi_nan_datapath_resp_t ndp_resp = {0}; wifi_nan_datapath_resp_t ndp_resp = {0};
ndp_resp.accept = true; ndp_resp.accept = true;
ndp_resp.ndp_id = ndp_id; ndp_resp.ndp_id = ndp_id;
MACADDR_COPY(ndp_resp.peer_mac, peer_nmi); MACADDR_COPY(ndp_resp.peer_mac, peer_nmi);
esp_nan_internal_datapath_resp(&ndp_resp); if (device_caps & NAN_CAPS_NDPE_ATTR) {
esp_err_t err = esp_wifi_get_mac(WIFI_IF_NAN, own_bssid);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Cannot get own BSSID!");
ndp_resp.accept = false;
} else {
esp_wifi_nan_get_ipv6_linklocal_from_mac(&own_ipv6.u_addr.ip6, own_bssid);
}
}
if (ndp_resp.accept) {
nan_record_new_ndl(ndp_id, pub_id, peer_nmi, ESP_WIFI_NDP_ROLE_RESPONDER, device_caps);
}
esp_nan_internal_datapath_resp(&ndp_resp, (uint8_t *)&own_ipv6.u_addr.ip6.addr[2] );
} }
NAN_DATA_UNLOCK(); NAN_DATA_UNLOCK();
@@ -594,6 +670,21 @@ void nan_app_ndp_indication_cb(uint8_t pub_id, uint8_t ndp_id, uint8_t peer_nmi[
wifi_event_ndp_indication_t *evt = (wifi_event_ndp_indication_t *)os_zalloc(evt_data_len); wifi_event_ndp_indication_t *evt = (wifi_event_ndp_indication_t *)os_zalloc(evt_data_len);
if (!evt) { if (!evt) {
ESP_LOGE(TAG, "Failed to allocate for event"); ESP_LOGE(TAG, "Failed to allocate for event");
if (ndp_resp_needed) {
uint8_t ipv6_identifier[8] = {0};
wifi_nan_datapath_resp_t ndp_resp = {0};
ndp_resp.accept = false;
ndp_resp.ndp_id = ndp_id;
MACADDR_COPY(ndp_resp.peer_mac, peer_nmi);
NAN_DATA_LOCK();
nan_reset_ndl(ndp_id, false);
s_nan_ctx.event &= ~NDP_INDICATION;
NAN_DATA_UNLOCK();
esp_nan_internal_datapath_resp(&ndp_resp, ipv6_identifier);
}
return; return;
} }
@@ -611,9 +702,17 @@ void nan_app_ndp_indication_cb(uint8_t pub_id, uint8_t ndp_id, uint8_t peer_nmi[
os_free(evt); os_free(evt);
} }
void nan_app_ndp_confirm_cb(uint8_t status, uint8_t ndp_id, uint8_t peer_nmi[6], uint8_t peer_ndi[6], void nan_app_ndp_confirm_cb(uint8_t status, struct ndp_cb_peer_info *peer_info,
uint8_t own_ndi[6], uint8_t *ssi, uint16_t ssi_len) uint8_t own_ndi[6], uint8_t ipv6_identifier[8])
{ {
if (!peer_info) {
return;
}
uint8_t ndp_id = peer_info->ndp_id;
uint8_t *peer_nmi = peer_info->peer_nmi;
uint8_t *peer_ndi = peer_info->peer_ndi;
uint8_t *ssi = peer_info->ssi;
uint16_t ssi_len = peer_info->ssi_len;
NAN_DATA_LOCK(); NAN_DATA_LOCK();
struct ndl_info *ndl = nan_find_ndl(ndp_id, peer_nmi); struct ndl_info *ndl = nan_find_ndl(ndp_id, peer_nmi);
if (!ndl) { if (!ndl) {
@@ -643,6 +742,7 @@ void nan_app_ndp_confirm_cb(uint8_t status, uint8_t ndp_id, uint8_t peer_nmi[6],
goto done; goto done;
} }
size_t evt_data_len = sizeof(wifi_event_ndp_confirm_t) + ssi_len; size_t evt_data_len = sizeof(wifi_event_ndp_confirm_t) + ssi_len;
wifi_event_ndp_confirm_t *evt = (wifi_event_ndp_confirm_t *)os_zalloc(evt_data_len); wifi_event_ndp_confirm_t *evt = (wifi_event_ndp_confirm_t *)os_zalloc(evt_data_len);
if (!evt) { if (!evt) {
@@ -660,6 +760,15 @@ void nan_app_ndp_confirm_cb(uint8_t status, uint8_t ndp_id, uint8_t peer_nmi[6],
MACADDR_COPY(evt->peer_nmi, peer_nmi); MACADDR_COPY(evt->peer_nmi, peer_nmi);
MACADDR_COPY(evt->peer_ndi, peer_ndi); MACADDR_COPY(evt->peer_ndi, peer_ndi);
MACADDR_COPY(evt->own_ndi, own_ndi); MACADDR_COPY(evt->own_ndi, own_ndi);
if (IS_ZERO_NAN_ADDR_ID(ipv6_identifier)) {
ip6_addr_t linklocal;
esp_wifi_nan_get_ipv6_linklocal_from_mac(&linklocal, peer_ndi);
memcpy(evt->ipv6_identifier, &linklocal.addr[2], NAN_IPV6_ADDR_ID_LEN);
} else {
memcpy(evt->ipv6_identifier, ipv6_identifier, NAN_IPV6_ADDR_ID_LEN);
}
if (ssi && ssi_len) { if (ssi && ssi_len) {
memcpy(evt->ssi, ssi, ssi_len); memcpy(evt->ssi, ssi, ssi_len);
evt->ssi_len = ssi_len; evt->ssi_len = ssi_len;
@@ -670,11 +779,14 @@ void nan_app_ndp_confirm_cb(uint8_t status, uint8_t ndp_id, uint8_t peer_nmi[6],
esp_netif_create_ip6_linklocal(s_nan_ctx.nan_netif); esp_netif_create_ip6_linklocal(s_nan_ctx.nan_netif);
NAN_DATA_UNLOCK(); NAN_DATA_UNLOCK();
ip_addr_t target_addr = {0}; ip6_addr_t peer_ip6 = {0};
esp_wifi_nan_get_ipv6_linklocal_from_mac(&target_addr.u_addr.ip6, peer_ndi); peer_ip6.addr[0] = PP_HTONL(0xfe800000);
target_addr.type = IPADDR_TYPE_V6; peer_ip6.addr[1] = 0;
memcpy(&peer_ip6.addr[2], evt->ipv6_identifier, 8);
ESP_LOGI(TAG, "NDP confirmed with Peer "MACSTR" [NDP ID - %d, Peer IPv6 - %s]", ESP_LOGI(TAG, "NDP confirmed with Peer "MACSTR" [NDP ID - %d, Peer IPv6 - %s]",
MAC2STR(peer_nmi), ndp_id, inet6_ntoa(*ip_2_ip6(&target_addr))); MAC2STR(peer_nmi), ndp_id, inet6_ntoa(peer_ip6));
os_event_group_set_bits(nan_event_group, NDP_ACCEPTED); os_event_group_set_bits(nan_event_group, NDP_ACCEPTED);
nan_app_post_event(WIFI_EVENT_NDP_CONFIRM, evt, evt_data_len); nan_app_post_event(WIFI_EVENT_NDP_CONFIRM, evt, evt_data_len);
@@ -1187,7 +1299,8 @@ done:
uint8_t esp_wifi_nan_datapath_req(wifi_nan_datapath_req_t *req) uint8_t esp_wifi_nan_datapath_req(wifi_nan_datapath_req_t *req)
{ {
uint8_t ndp_id = 0; uint8_t ndp_id = 0;
uint8_t own_bssid[6];
ip_addr_t own_ipv6 = {0};
NAN_DATA_LOCK(); NAN_DATA_LOCK();
struct peer_svc_info *p_peer_svc = nan_find_peer_svc(0, req->pub_id, req->peer_mac); struct peer_svc_info *p_peer_svc = nan_find_peer_svc(0, req->pub_id, req->peer_mac);
@@ -1195,6 +1308,17 @@ uint8_t esp_wifi_nan_datapath_req(wifi_nan_datapath_req_t *req)
ESP_LOGE(TAG, "Cannot send NDP Req, peer not found!"); ESP_LOGE(TAG, "Cannot send NDP Req, peer not found!");
goto fail; goto fail;
} }
if (p_peer_svc->device_caps & NAN_CAPS_NDPE_ATTR) {
esp_err_t err = esp_wifi_get_mac(WIFI_IF_NAN, own_bssid);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Cannot get own BSSID!");
goto fail;
}
esp_wifi_nan_get_ipv6_linklocal_from_mac(&own_ipv6.u_addr.ip6, own_bssid);
}
if (req->pub_id == 0) if (req->pub_id == 0)
req->pub_id = p_peer_svc->svc_id; req->pub_id = p_peer_svc->svc_id;
@@ -1212,12 +1336,12 @@ uint8_t esp_wifi_nan_datapath_req(wifi_nan_datapath_req_t *req)
} }
os_event_group_clear_bits(nan_event_group, NDP_ACCEPTED | NDP_REJECTED); os_event_group_clear_bits(nan_event_group, NDP_ACCEPTED | NDP_REJECTED);
if (esp_nan_internal_datapath_req(req, &ndp_id) != ESP_OK) { if (esp_nan_internal_datapath_req(req, &ndp_id,(uint8_t *)&own_ipv6.u_addr.ip6.addr[2]) != ESP_OK) {
ESP_LOGE(TAG, "Failed to initiate NDP req"); ESP_LOGE(TAG, "Failed to initiate NDP req");
goto fail; goto fail;
} }
nan_record_new_ndl(ndp_id, req->pub_id, req->peer_mac, ESP_WIFI_NDP_ROLE_INITIATOR); nan_record_new_ndl(ndp_id, req->pub_id, req->peer_mac, ESP_WIFI_NDP_ROLE_INITIATOR, p_peer_svc->device_caps);
NAN_DATA_UNLOCK(); NAN_DATA_UNLOCK();
ESP_LOGD(TAG, "Requested NDP with "MACSTR" [NDP ID - %d]", MAC2STR(req->peer_mac), ndp_id); ESP_LOGD(TAG, "Requested NDP with "MACSTR" [NDP ID - %d]", MAC2STR(req->peer_mac), ndp_id);
@@ -1243,6 +1367,8 @@ esp_err_t esp_wifi_nan_datapath_resp(wifi_nan_datapath_resp_t *resp)
{ {
NAN_DATA_LOCK(); NAN_DATA_LOCK();
struct ndl_info *ndl = nan_find_ndl(resp->ndp_id, NULL); struct ndl_info *ndl = nan_find_ndl(resp->ndp_id, NULL);
uint8_t own_bssid[6];
ip_addr_t own_ipv6 = {0};
if (!ndl) { if (!ndl) {
ESP_LOGE(TAG, "No NDL with ndp id %d", resp->ndp_id); ESP_LOGE(TAG, "No NDL with ndp id %d", resp->ndp_id);
@@ -1257,7 +1383,16 @@ esp_err_t esp_wifi_nan_datapath_resp(wifi_nan_datapath_resp_t *resp)
MACADDR_COPY(resp->peer_mac, ndl->peer_nmi); MACADDR_COPY(resp->peer_mac, ndl->peer_nmi);
} }
if (esp_nan_internal_datapath_resp(resp) == ESP_OK) { if (ndl->device_caps & NAN_CAPS_NDPE_ATTR) {
esp_err_t err = esp_wifi_get_mac(WIFI_IF_NAN, own_bssid);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Cannot get own BSSID!");
goto fail;
}
esp_wifi_nan_get_ipv6_linklocal_from_mac(&own_ipv6.u_addr.ip6, own_bssid);
}
if (esp_nan_internal_datapath_resp(resp, (uint8_t *)&own_ipv6.u_addr.ip6.addr[2]) == ESP_OK) {
s_nan_ctx.event &= ~NDP_INDICATION; s_nan_ctx.event &= ~NDP_INDICATION;
NAN_DATA_UNLOCK(); NAN_DATA_UNLOCK();
return ESP_OK; return ESP_OK;
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -70,6 +70,7 @@ static void nan_ndp_indication_event_handler(void *arg, esp_event_base_t event_b
esp_wifi_nan_datapath_resp(&ndp_resp); esp_wifi_nan_datapath_resp(&ndp_resp);
} }
void wifi_nan_publish(void) void wifi_nan_publish(void)
{ {
nan_event_group = xEventGroupCreate(); nan_event_group = xEventGroupCreate();
@@ -106,6 +107,7 @@ void wifi_nan_publish(void)
/* 0 - All incoming NDP requests will be internally accepted, /* 0 - All incoming NDP requests will be internally accepted,
1 - All incoming NDP requests raise NDP_INDICATION event and require esp_wifi_nan_datapath_resp to accept or reject. */ 1 - All incoming NDP requests raise NDP_INDICATION event and require esp_wifi_nan_datapath_resp to accept or reject. */
.ndp_resp_needed = 1, .ndp_resp_needed = 1,
.datapath_reqd = 1,
}; };
pub_id = esp_wifi_nan_publish_service(&publish_cfg); pub_id = esp_wifi_nan_publish_service(&publish_cfg);
@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Unlicense OR CC0-1.0 * SPDX-License-Identifier: Unlicense OR CC0-1.0
*/ */
@@ -45,6 +45,8 @@ const int NDP_FAILED = BIT2;
static wifi_event_nan_svc_match_t g_svc_match_evt; static wifi_event_nan_svc_match_t g_svc_match_evt;
static uint8_t s_ipv6_identifier[8] = {0};
static void nan_receive_event_handler(void *arg, esp_event_base_t event_base, static void nan_receive_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data) int32_t event_id, void *event_data)
{ {
@@ -111,6 +113,7 @@ static void nan_ndp_confirmed_event_handler(void *arg, esp_event_base_t event_ba
xEventGroupSetBits(nan_event_group, NDP_FAILED); xEventGroupSetBits(nan_event_group, NDP_FAILED);
} else { } else {
memcpy(g_peer_ndi, evt->peer_ndi, sizeof(g_peer_ndi)); memcpy(g_peer_ndi, evt->peer_ndi, sizeof(g_peer_ndi));
memcpy(s_ipv6_identifier, evt->ipv6_identifier, sizeof(evt->ipv6_identifier));
xEventGroupSetBits(nan_event_group, NDP_CONFIRMED); xEventGroupSetBits(nan_event_group, NDP_CONFIRMED);
} }
} }
@@ -121,8 +124,7 @@ static void ping_nan_peer(esp_netif_t *netif)
config.task_stack_size = 4096; config.task_stack_size = 4096;
ip_addr_t target_addr = {0}; ip_addr_t target_addr = {0};
esp_wifi_nan_get_ipv6_linklocal_from_mac(&target_addr.u_addr.ip6, g_peer_ndi); ESP_NAN_SET_IPV6_LINKLOCAL_FROM_IDENTIFIER(target_addr, s_ipv6_identifier);
target_addr.type = IPADDR_TYPE_V6;
config.target_addr = target_addr; config.target_addr = target_addr;
config.interface = esp_netif_get_netif_impl_index(netif); config.interface = esp_netif_get_netif_impl_index(netif);
@@ -183,6 +185,7 @@ void wifi_nan_subscribe(void)
esp_wifi_nan_sync_start(&nan_cfg); esp_wifi_nan_sync_start(&nan_cfg);
/* Subscribe a service */ /* Subscribe a service */
memset(s_ipv6_identifier, 0, sizeof(s_ipv6_identifier));
uint8_t sub_id; uint8_t sub_id;
wifi_nan_subscribe_cfg_t subscribe_cfg = { wifi_nan_subscribe_cfg_t subscribe_cfg = {
.service_name = EXAMPLE_NAN_SERV_NAME, .service_name = EXAMPLE_NAN_SERV_NAME,
@@ -216,7 +219,6 @@ void wifi_nan_subscribe(void)
return; return;
} }
memcpy((char *)fup.ssi, EXAMPLE_NAN_SVC_MSG, fup.ssi_len); memcpy((char *)fup.ssi, EXAMPLE_NAN_SVC_MSG, fup.ssi_len);
if (esp_wifi_nan_send_message(&fup) == ESP_OK) if (esp_wifi_nan_send_message(&fup) == ESP_OK)
ESP_LOGI(TAG, "Sending message '%s' to Publisher "MACSTR" ...", ESP_LOGI(TAG, "Sending message '%s' to Publisher "MACSTR" ...",
EXAMPLE_NAN_SVC_MSG, MAC2STR(g_svc_match_evt.pub_if_mac)); EXAMPLE_NAN_SVC_MSG, MAC2STR(g_svc_match_evt.pub_if_mac));