mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/ot-lwip-interface' into 'master'
openthread: add lwIP network interface See merge request espressif/esp-idf!13188
This commit is contained in:
commit
e470e7c4c3
@ -537,6 +537,12 @@ static const esp_err_msg_t esp_err_msg_table[] = {
|
||||
# endif
|
||||
# ifdef ESP_ERR_ESP_NETIF_DNS_NOT_CONFIGURED
|
||||
ERR_TBL_IT(ESP_ERR_ESP_NETIF_DNS_NOT_CONFIGURED), /* 20490 0x500a */
|
||||
# endif
|
||||
# ifdef ESP_ERR_ESP_NETIF_MLD6_FAILED
|
||||
ERR_TBL_IT(ESP_ERR_ESP_NETIF_MLD6_FAILED), /* 20490 0x500b */
|
||||
# endif
|
||||
# ifdef ESP_ERR_ESP_NETIF_IP6_ADDR_FAILED
|
||||
ERR_TBL_IT(ESP_ERR_ESP_NETIF_IP6_ADDR_FAILED), /* 20490 0x500a */
|
||||
# endif
|
||||
// components/esp_common/include/esp_err.h
|
||||
# ifdef ESP_ERR_FLASH_BASE
|
||||
@ -759,7 +765,7 @@ const char *esp_err_to_name(esp_err_t code)
|
||||
#ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(esp_err_msg_table)/sizeof(esp_err_msg_table[0]); ++i) {
|
||||
for (i = 0; i < sizeof(esp_err_msg_table) / sizeof(esp_err_msg_table[0]); ++i) {
|
||||
if (esp_err_msg_table[i].code == code) {
|
||||
return esp_err_msg_table[i].msg;
|
||||
}
|
||||
@ -774,7 +780,7 @@ const char *esp_err_to_name_r(esp_err_t code, char *buf, size_t buflen)
|
||||
#ifdef CONFIG_ESP_ERR_TO_NAME_LOOKUP
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(esp_err_msg_table)/sizeof(esp_err_msg_table[0]); ++i) {
|
||||
for (i = 0; i < sizeof(esp_err_msg_table) / sizeof(esp_err_msg_table[0]); ++i) {
|
||||
if (esp_err_msg_table[i].code == code) {
|
||||
strlcpy(buf, esp_err_msg_table[i].msg, buflen);
|
||||
return buf;
|
||||
|
@ -39,6 +39,8 @@ const esp_netif_inherent_config_t _g_esp_netif_inherent_ppp_config = ESP_NETIF_I
|
||||
|
||||
const esp_netif_inherent_config_t _g_esp_netif_inherent_slip_config = ESP_NETIF_INHERENT_DEFAULT_SLIP();
|
||||
|
||||
const esp_netif_inherent_config_t _g_esp_netif_inherent_openthread_config = ESP_NETIF_INHERENT_DEFAULT_OPENTHREAD();
|
||||
|
||||
const esp_netif_ip_info_t _g_esp_netif_soft_ap_ip = {
|
||||
.ip = { .addr = ESP_IP4TOADDR( 192, 168, 4, 1) },
|
||||
.gw = { .addr = ESP_IP4TOADDR( 192, 168, 4, 1) },
|
||||
|
@ -103,3 +103,31 @@ void esp_netif_action_got_ip(void *esp_netif, esp_event_base_t base, int32_t eve
|
||||
IP2STR(&event->ip_info.netmask),
|
||||
IP2STR(&event->ip_info.gw));
|
||||
}
|
||||
|
||||
void esp_netif_action_join_ip6_multicast_group(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data)
|
||||
{
|
||||
ESP_LOGD(TAG, "esp_netif action join_ip6_multicast group with netif%p from event_id=%d", esp_netif, event_id);
|
||||
const esp_ip6_addr_t *addr = (const esp_ip6_addr_t *)data;
|
||||
esp_netif_join_ip6_multicast_group(esp_netif, addr);
|
||||
}
|
||||
|
||||
void esp_netif_action_leave_ip6_multicast_group(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data)
|
||||
{
|
||||
ESP_LOGD(TAG, "esp_netif action leave_ip6_multicast_group with netif%p from event_id=%d", esp_netif, event_id);
|
||||
const esp_ip6_addr_t *addr = (const esp_ip6_addr_t *)data;
|
||||
esp_netif_leave_ip6_multicast_group(esp_netif, addr);
|
||||
}
|
||||
|
||||
void esp_netif_action_add_ip6_address(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data)
|
||||
{
|
||||
ESP_LOGD(TAG, "esp_netif action add_ip6_address with netif%p from event_id=%d", esp_netif, event_id);
|
||||
const ip_event_add_ip6_t *addr = (const ip_event_add_ip6_t *)data;
|
||||
esp_netif_add_ip6_address(esp_netif, addr);
|
||||
}
|
||||
|
||||
void esp_netif_action_remove_ip6_address(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data)
|
||||
{
|
||||
ESP_LOGD(TAG, "esp_netif action remove_ip6_address with netif%p from event_id=%d", esp_netif, event_id);
|
||||
const esp_ip6_addr_t *addr = (const esp_ip6_addr_t *)data;
|
||||
esp_netif_remove_ip6_address(esp_netif, addr);
|
||||
}
|
||||
|
@ -237,6 +237,54 @@ void esp_netif_action_disconnected(void *esp_netif, esp_event_base_t base, int32
|
||||
*/
|
||||
void esp_netif_action_got_ip(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data);
|
||||
|
||||
/**
|
||||
* @brief Default building block for network interface action upon IPv6 multicast group join
|
||||
*
|
||||
* @note This API can be directly used as event handler
|
||||
*
|
||||
* @param[in] esp_netif Handle to esp-netif instance
|
||||
* @param base
|
||||
* @param event_id
|
||||
* @param data
|
||||
*/
|
||||
void esp_netif_action_join_ip6_multicast_group(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data);
|
||||
|
||||
/**
|
||||
* @brief Default building block for network interface action upon IPv6 multicast group leave
|
||||
*
|
||||
* @note This API can be directly used as event handler
|
||||
*
|
||||
* @param[in] esp_netif Handle to esp-netif instance
|
||||
* @param base
|
||||
* @param event_id
|
||||
* @param data
|
||||
*/
|
||||
void esp_netif_action_leave_ip6_multicast_group(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data);
|
||||
|
||||
/**
|
||||
* @brief Default building block for network interface action upon IPv6 address added by the underlying stack
|
||||
*
|
||||
* @note This API can be directly used as event handler
|
||||
*
|
||||
* @param[in] esp_netif Handle to esp-netif instance
|
||||
* @param base
|
||||
* @param event_id
|
||||
* @param data
|
||||
*/
|
||||
void esp_netif_action_add_ip6_address(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data);
|
||||
|
||||
/**
|
||||
* @brief Default building block for network interface action upon IPv6 address removed by the underlying stack
|
||||
*
|
||||
* @note This API can be directly used as event handler
|
||||
*
|
||||
* @param[in] esp_netif Handle to esp-netif instance
|
||||
* @param base
|
||||
* @param event_id
|
||||
* @param data
|
||||
*/
|
||||
void esp_netif_action_remove_ip6_address(void *esp_netif, esp_event_base_t base, int32_t event_id, void *data);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@ -73,6 +73,18 @@ extern "C" {
|
||||
.route_prio = 20 \
|
||||
};
|
||||
|
||||
#define ESP_NETIF_INHERENT_DEFAULT_OPENTHREAD() \
|
||||
{ \
|
||||
.flags = 0, \
|
||||
ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(mac) \
|
||||
ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(ip_info) \
|
||||
.get_ip_event = 0, \
|
||||
.lost_ip_event = 0, \
|
||||
.if_key = "OT_DEF", \
|
||||
.if_desc = "openthread", \
|
||||
.route_prio = 15 \
|
||||
};
|
||||
|
||||
#define ESP_NETIF_INHERENT_DEFAULT_SLIP() \
|
||||
{ \
|
||||
.flags = ESP_NETIF_FLAG_IS_SLIP, \
|
||||
@ -85,6 +97,7 @@ extern "C" {
|
||||
.route_prio = 16 \
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Default configuration reference of ethernet interface
|
||||
*/
|
||||
@ -162,12 +175,12 @@ extern "C" {
|
||||
#define ESP_NETIF_BASE_DEFAULT_SLIP &_g_esp_netif_inherent_slip_config
|
||||
|
||||
|
||||
|
||||
#define ESP_NETIF_NETSTACK_DEFAULT_ETH _g_esp_netif_netstack_default_eth
|
||||
#define ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA _g_esp_netif_netstack_default_wifi_sta
|
||||
#define ESP_NETIF_NETSTACK_DEFAULT_WIFI_AP _g_esp_netif_netstack_default_wifi_ap
|
||||
#define ESP_NETIF_NETSTACK_DEFAULT_PPP _g_esp_netif_netstack_default_ppp
|
||||
#define ESP_NETIF_NETSTACK_DEFAULT_SLIP _g_esp_netif_netstack_default_slip
|
||||
#define ESP_NETIF_NETSTACK_DEFAULT_OPENTHREAD _g_esp_netif_netstack_default_openthread
|
||||
|
||||
//
|
||||
// Include default network stacks configs
|
||||
@ -194,6 +207,27 @@ extern const esp_netif_inherent_config_t _g_esp_netif_inherent_slip_config;
|
||||
|
||||
extern const esp_netif_ip_info_t _g_esp_netif_soft_ap_ip;
|
||||
|
||||
#if CONFIG_OPENTHREAD_ENABLED
|
||||
/**
|
||||
* @brief Default configuration reference of SLIP client
|
||||
*/
|
||||
#define ESP_NETIF_DEFAULT_OPENTHREAD() \
|
||||
{ \
|
||||
.base = ESP_NETIF_BASE_DEFAULT_OPENTHREAD, \
|
||||
.driver = NULL, \
|
||||
.stack = ESP_NETIF_NETSTACK_DEFAULT_OPENTHREAD, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Default base config (esp-netif inherent) of openthread interface
|
||||
*/
|
||||
#define ESP_NETIF_BASE_DEFAULT_OPENTHREAD &_g_esp_netif_inherent_openthread_config
|
||||
|
||||
extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_openthread;
|
||||
extern const esp_netif_inherent_config_t _g_esp_netif_inherent_openthread_config;
|
||||
|
||||
#endif // CONFIG_OPENTHREAD_ENABLED
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -33,6 +33,8 @@ extern "C" {
|
||||
#define ESP_ERR_ESP_NETIF_DRIVER_ATTACH_FAILED ESP_ERR_ESP_NETIF_BASE + 0x08
|
||||
#define ESP_ERR_ESP_NETIF_INIT_FAILED ESP_ERR_ESP_NETIF_BASE + 0x09
|
||||
#define ESP_ERR_ESP_NETIF_DNS_NOT_CONFIGURED ESP_ERR_ESP_NETIF_BASE + 0x0A
|
||||
#define ESP_ERR_ESP_NETIF_MLD6_FAILED ESP_ERR_ESP_NETIF_BASE + 0x0B
|
||||
#define ESP_ERR_ESP_NETIF_IP6_ADDR_FAILED ESP_ERR_ESP_NETIF_BASE + 0x0C
|
||||
|
||||
|
||||
/** @brief Type of esp_netif_object server */
|
||||
@ -125,6 +127,12 @@ typedef struct {
|
||||
int ip_index; /*!< IPv6 address index */
|
||||
} ip_event_got_ip6_t;
|
||||
|
||||
/** Event structure for ADD_IP6 event */
|
||||
typedef struct {
|
||||
esp_ip6_addr_t addr; /*!< The address to be added to the interface */
|
||||
bool preferred; /*!< The default preference of the address */
|
||||
} ip_event_add_ip6_t;
|
||||
|
||||
/** Event structure for IP_EVENT_AP_STAIPASSIGNED event */
|
||||
typedef struct {
|
||||
esp_ip4_addr_t ip; /*!< IP address which was assigned to the station */
|
||||
|
@ -455,4 +455,24 @@ int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif)
|
||||
return 0;
|
||||
}
|
||||
|
||||
esp_err_t esp_netif_join_ip6_multicast_group(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_err_t esp_netif_leave_ip6_multicast_group(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_err_t esp_netif_add_ip6_address(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr, uint8_t preference)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_err_t esp_netif_remove_ip6_address(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ESP_NETIF_LOOPBACK */
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <lwip/ip_addr.h>
|
||||
#include <lwip/sockets.h>
|
||||
|
||||
#include "esp_check.h"
|
||||
#include "esp_netif_lwip_internal.h"
|
||||
|
||||
#include "esp_netif.h"
|
||||
@ -27,6 +28,7 @@
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/ip6_addr.h"
|
||||
#include "lwip/mld6.h"
|
||||
#include "lwip/nd6.h"
|
||||
#include "lwip/priv/tcpip_priv.h"
|
||||
#include "lwip/netif.h"
|
||||
@ -1861,4 +1863,95 @@ esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_LWIP_IPV6
|
||||
|
||||
static esp_err_t esp_netif_join_ip6_multicast_group_api(esp_netif_api_msg_t *msg)
|
||||
{
|
||||
esp_ip6_addr_t *addr = (esp_ip6_addr_t *)msg->data;
|
||||
esp_err_t error = ESP_OK;
|
||||
ip6_addr_t ip6addr;
|
||||
|
||||
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
|
||||
memcpy(ip6addr.addr, addr->addr, sizeof(ip6addr.addr));
|
||||
#if LWIP_IPV6_SCOPES
|
||||
ip6addr.zone = 0;
|
||||
#endif
|
||||
if (mld6_joingroup_netif(msg->esp_netif->lwip_netif, &ip6addr) != ERR_OK) {
|
||||
error = ESP_ERR_ESP_NETIF_MLD6_FAILED;
|
||||
ESP_LOGE(TAG, "failed to join ip6 multicast group");
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
esp_err_t esp_netif_join_ip6_multicast_group(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr)
|
||||
_RUN_IN_LWIP_TASK(esp_netif_join_ip6_multicast_group_api, esp_netif, addr)
|
||||
|
||||
static esp_err_t esp_netif_leave_ip6_multicast_group_api(esp_netif_api_msg_t *msg)
|
||||
{
|
||||
esp_ip6_addr_t *addr = (esp_ip6_addr_t *)msg->data;
|
||||
ip6_addr_t ip6addr;
|
||||
|
||||
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
|
||||
memcpy(ip6addr.addr, addr->addr, sizeof(ip6addr.addr));
|
||||
#if LWIP_IPV6_SCOPES
|
||||
ip6addr.zone = 0;
|
||||
#endif
|
||||
ESP_RETURN_ON_FALSE(mld6_leavegroup_netif(msg->esp_netif->lwip_netif, &ip6addr) != ERR_OK,
|
||||
ESP_ERR_ESP_NETIF_MLD6_FAILED, TAG, "Failed to leave ip6 multicast group");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_netif_leave_ip6_multicast_group(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr)
|
||||
_RUN_IN_LWIP_TASK(esp_netif_leave_ip6_multicast_group_api, esp_netif, addr)
|
||||
|
||||
static esp_err_t esp_netif_add_ip6_address_api(esp_netif_api_msg_t *msg)
|
||||
{
|
||||
ip_event_add_ip6_t *addr = (ip_event_add_ip6_t *)msg->data;
|
||||
ip6_addr_t ip6addr;
|
||||
esp_err_t error = ESP_OK;
|
||||
int8_t index = -1;
|
||||
|
||||
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
|
||||
memcpy(ip6addr.addr, addr->addr.addr, sizeof(ip6addr.addr));
|
||||
#if LWIP_IPV6_SCOPES
|
||||
ip6addr.zone = 0;
|
||||
#endif
|
||||
err_t err = netif_add_ip6_address(msg->esp_netif->lwip_netif, &ip6addr, &index);
|
||||
ESP_RETURN_ON_FALSE(err == ERR_OK && index >= 0, ESP_ERR_ESP_NETIF_IP6_ADDR_FAILED, TAG,
|
||||
"Failed to add ip6 address");
|
||||
|
||||
netif_ip6_addr_set_state(msg->esp_netif->lwip_netif, index,
|
||||
addr->preferred ? IP6_ADDR_PREFERRED : IP6_ADDR_DEPRECATED);
|
||||
ip_event_got_ip6_t evt = {.esp_netif = msg->esp_netif, .if_index = -1, .ip_index = index};
|
||||
evt.ip6_info.ip = addr->addr;
|
||||
ESP_RETURN_ON_ERROR(esp_event_send_internal(IP_EVENT, IP_EVENT_GOT_IP6, &evt, sizeof(evt), 0), TAG,
|
||||
"Failed to post IP_EVENT_GOT_IP6");
|
||||
return error;
|
||||
}
|
||||
|
||||
esp_err_t esp_netif_add_ip6_address(esp_netif_t *esp_netif, const ip_event_add_ip6_t *addr)
|
||||
_RUN_IN_LWIP_TASK(esp_netif_add_ip6_address_api, esp_netif, addr)
|
||||
|
||||
static esp_err_t esp_netif_remove_ip6_address_api(esp_netif_api_msg_t *msg)
|
||||
{
|
||||
esp_ip6_addr_t *addr = (esp_ip6_addr_t *)msg->data;
|
||||
ip6_addr_t ip6addr;
|
||||
|
||||
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
|
||||
memcpy(ip6addr.addr, addr->addr, sizeof(ip6addr.addr));
|
||||
#if LWIP_IPV6_SCOPES
|
||||
ip6addr.zone = 0;
|
||||
#endif
|
||||
int8_t index = netif_get_ip6_addr_match(msg->esp_netif->lwip_netif, &ip6addr);
|
||||
if (index != -1) {
|
||||
netif_ip6_addr_set_state(msg->esp_netif->lwip_netif, index, IP6_ADDR_INVALID);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_netif_remove_ip6_address(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr)
|
||||
_RUN_IN_LWIP_TASK(esp_netif_remove_ip6_address_api, esp_netif, addr)
|
||||
|
||||
#endif // CONFIG_LWIP_IPV6
|
||||
|
||||
#endif /* CONFIG_ESP_NETIF_TCPIP_LWIP */
|
||||
|
@ -20,6 +20,9 @@
|
||||
|
||||
#include "netif/wlanif.h"
|
||||
#include "netif/ethernetif.h"
|
||||
#if CONFIG_OPENTHREAD_ENABLED
|
||||
#include "netif/openthreadif.h"
|
||||
#endif
|
||||
|
||||
//
|
||||
// Purpose of this object is to define default network stack configuration
|
||||
@ -56,10 +59,19 @@ static const struct esp_netif_netstack_config s_netif_config_ppp = {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_eth = &s_eth_netif_config;
|
||||
const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_sta = &s_wifi_netif_config_sta;
|
||||
const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_ap = &s_wifi_netif_config_ap;
|
||||
const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_ppp = &s_netif_config_ppp;
|
||||
|
||||
#if CONFIG_OPENTHREAD_ENABLED
|
||||
static const struct esp_netif_netstack_config s_netif_config_openthread = {
|
||||
.lwip = {
|
||||
.init_fn = openthread_netif_init,
|
||||
.input_fn = openthread_netif_input,
|
||||
}
|
||||
};
|
||||
const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_openthread = &s_netif_config_openthread;
|
||||
#endif // CONFIG_OPENTHREAD_ENABLED
|
||||
|
||||
#endif /*CONFIG_ESP_NETIF_TCPIP_LWIP*/
|
||||
|
@ -145,4 +145,60 @@ void esp_netif_list_unlock(void);
|
||||
*/
|
||||
bool esp_netif_is_netif_listed(esp_netif_t *esp_netif);
|
||||
|
||||
/**
|
||||
* @brief Cause the TCP/IP stack to join a multicast group
|
||||
*
|
||||
* @param[in] esp_netif Handle to esp-netif instance
|
||||
* @param[in] addr The multicast group to join
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_ERR_ESP_NETIF_INVALID_PARAMS
|
||||
* - ESP_ERR_ESP_NETIF_MLD6_FAILED
|
||||
* - ESP_ERR_NO_MEM
|
||||
*/
|
||||
esp_err_t esp_netif_join_ip6_multicast_group(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Cause the TCP/IP stack to leave a multicast group
|
||||
*
|
||||
* @param[in] esp_netif Handle to esp-netif instance
|
||||
* @param[in] addr The multicast group to leave
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_ERR_ESP_NETIF_INVALID_PARAMS
|
||||
* - ESP_ERR_ESP_NETIF_MLD6_FAILED
|
||||
* - ESP_ERR_NO_MEM
|
||||
*/
|
||||
esp_err_t esp_netif_leave_ip6_multicast_group(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Cause the TCP/IP stack to add an IPv6 address to the interface
|
||||
*
|
||||
* @param[in] esp_netif Handle to esp-netif instance
|
||||
* @param[in] addr The address to be added
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_ERR_ESP_NETIF_INVALID_PARAMS
|
||||
* - ESP_ERR_ESP_NETIF_IP6_ADDR_FAILED
|
||||
* - ESP_ERR_NO_MEM
|
||||
*/
|
||||
esp_err_t esp_netif_add_ip6_address(esp_netif_t *esp_netif, const ip_event_add_ip6_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Cause the TCP/IP stack to remove an IPv6 address from the interface
|
||||
*
|
||||
* @param[in] esp_netif Handle to esp-netif instance
|
||||
* @param[in] addr The address to be removed
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_ERR_ESP_NETIF_INVALID_PARAMS
|
||||
* - ESP_ERR_ESP_NETIF_IP6_ADDR_FAILED
|
||||
* - ESP_ERR_NO_MEM
|
||||
*/
|
||||
esp_err_t esp_netif_remove_ip6_address(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr);
|
||||
|
||||
#endif //_ESP_NETIF_PRIVATE_H_
|
||||
|
@ -137,11 +137,15 @@ else()
|
||||
list(APPEND srcs "port/esp32/no_vfs_syscalls.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_OPENTHREAD_ENABLED)
|
||||
list(APPEND srcs "port/esp32/netif/openthreadif.c")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "${include_dirs}"
|
||||
LDFRAGMENTS linker.lf
|
||||
REQUIRES vfs esp_wifi
|
||||
PRIV_REQUIRES esp_eth esp_netif tcpip_adapter nvs_flash)
|
||||
PRIV_REQUIRES esp_eth esp_netif tcpip_adapter nvs_flash openthread)
|
||||
|
||||
# lots of LWIP source files evaluate macros that check address of stack variables
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-address)
|
||||
|
@ -35,6 +35,9 @@ ifndef CONFIG_VFS_SUPPORT_IO
|
||||
else
|
||||
COMPONENT_OBJEXCLUDE += port/esp32/no_vfs_syscalls.o
|
||||
endif
|
||||
ifndef CONFIG_OPENTHREAD_ENABLED
|
||||
COMPONENT_OBJEXCLUDE += port/esp32/netif/openthreadif.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_LWIP_PPP_SUPPORT
|
||||
COMPONENT_SRCDIRS += lwip/src/netif/ppp lwip/src/netif/ppp/polarssl
|
||||
|
52
components/lwip/port/esp32/include/netif/openthreadif.h
Normal file
52
components/lwip/port/esp32/include/netif/openthreadif.h
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License
|
||||
|
||||
#ifndef _OPENTHREAD_LWIP_IF_H_
|
||||
#define _OPENTHREAD_LWIP_IF_H_
|
||||
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/ip6.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief This function initializes the OpenThread lwIP network interface.
|
||||
*
|
||||
* @param[in] netif The lwIP interface to initialize
|
||||
*
|
||||
* @return
|
||||
* - ERR_OK
|
||||
*
|
||||
*/
|
||||
err_t openthread_netif_init(struct netif *netif);
|
||||
|
||||
/**
|
||||
* @brief This function sends the buffer to the lwIP network interface
|
||||
*
|
||||
* @param[in] netif The lwIP interface to send to.
|
||||
* @param[in] buffer The packet to send.
|
||||
* @param[in] len The length of the buffer.
|
||||
* @param[in] eb Unused.
|
||||
*
|
||||
*/
|
||||
void openthread_netif_input(void *netif, void *buffer, size_t len, void *eb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _OPENTHREAD_LWIP_IF_H_ */
|
113
components/lwip/port/esp32/netif/openthreadif.c
Normal file
113
components/lwip/port/esp32/netif/openthreadif.c
Normal file
@ -0,0 +1,113 @@
|
||||
// Copyright 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_netif.h"
|
||||
#include "esp_netif_net_stack.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "netif/openthreadif.h"
|
||||
#include "openthread/ip6.h"
|
||||
#include "openthread/link.h"
|
||||
|
||||
#define OPENTHREAD_IP6_MTU 1280
|
||||
|
||||
static void openthread_free_rx_buf_l2(struct netif *netif, void *buf)
|
||||
{
|
||||
free(buf);
|
||||
}
|
||||
|
||||
static err_t openthread_output_ip6(struct netif *netif, struct pbuf *p, const struct ip6_addr *peer_addr)
|
||||
{
|
||||
struct pbuf *q = p;
|
||||
esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif);
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
if (!esp_netif) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("corresponding esp-netif is NULL: netif=%p pbuf=%p len=%d\n", netif, p, p->len));
|
||||
return ERR_IF;
|
||||
}
|
||||
|
||||
if (q->next == NULL) {
|
||||
ret = esp_netif_transmit(esp_netif, q->payload, q->len);
|
||||
} else {
|
||||
LWIP_DEBUGF(PBUF_DEBUG, ("low_level_output: pbuf is a list, application may has bug"));
|
||||
q = pbuf_alloc(PBUF_RAW_TX, p->tot_len, PBUF_RAM);
|
||||
if (q != NULL) {
|
||||
#if ESP_LWIP
|
||||
/* This pbuf RAM was not allocated on layer2, no extra free operation needed in pbuf_free */
|
||||
q->l2_owner = NULL;
|
||||
q->l2_buf = NULL;
|
||||
#endif
|
||||
pbuf_copy(q, p);
|
||||
} else {
|
||||
return ERR_MEM;
|
||||
}
|
||||
ret = esp_netif_transmit(esp_netif, q->payload, q->len);
|
||||
/* content in payload has been copied to OpenThread queue, it's safe to free pbuf now */
|
||||
pbuf_free(q);
|
||||
}
|
||||
/* Check error */
|
||||
if (unlikely(ret != ESP_OK)) {
|
||||
return ERR_ABRT;
|
||||
} else {
|
||||
return ERR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void openthread_netif_input(void *h, void *buffer, size_t len, void *eb)
|
||||
{
|
||||
struct netif *netif = h;
|
||||
struct pbuf *p;
|
||||
|
||||
if (unlikely(buffer == NULL || !netif_is_up(netif))) {
|
||||
if (buffer) {
|
||||
openthread_free_rx_buf_l2(netif, buffer);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* acquire new pbuf, type: PBUF_REF */
|
||||
p = pbuf_alloc(PBUF_RAW, len, PBUF_REF);
|
||||
if (p == NULL) {
|
||||
openthread_free_rx_buf_l2(netif, buffer);
|
||||
return;
|
||||
}
|
||||
p->payload = buffer;
|
||||
#if ESP_LWIP
|
||||
p->l2_owner = netif;
|
||||
p->l2_buf = buffer;
|
||||
#endif
|
||||
/* full packet send to tcpip_thread to process */
|
||||
if (unlikely(netif->input(p, netif) != ERR_OK)) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("openthread_netif_input: IP input error\n"));
|
||||
pbuf_free(p);
|
||||
}
|
||||
/* the pbuf will be free in upper layer, eg: tcpip_input */
|
||||
}
|
||||
|
||||
err_t openthread_netif_init(struct netif *netif)
|
||||
{
|
||||
netif->name[0] = 'o';
|
||||
netif->name[1] = 't';
|
||||
netif->hwaddr_len = sizeof(otExtAddress);
|
||||
memset(netif->hwaddr, 0, sizeof(netif->hwaddr));
|
||||
netif->mtu = OPENTHREAD_IP6_MTU;
|
||||
netif->flags = NETIF_FLAG_BROADCAST;
|
||||
netif->output = NULL;
|
||||
netif->output_ip6 = openthread_output_ip6;
|
||||
netif->l2_buffer_free_notify = openthread_free_rx_buf_l2;
|
||||
netif_set_link_up(netif);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
@ -65,4 +65,11 @@ menu "OpenThread"
|
||||
help
|
||||
The storage size should be at least 8192 bytes.
|
||||
|
||||
config OPENTHREAD_NETIF_QUEUE_SIZE
|
||||
int "The size of the packet queue for OpenThread lwIP network interface"
|
||||
depends on OPENTHREAD_ENABLED
|
||||
default 10
|
||||
help
|
||||
The size of the packet queue for OpenThread lwIP network interface.
|
||||
|
||||
endmenu
|
||||
|
64
components/openthread/include/esp_openthread_netif_glue.h
Normal file
64
components/openthread/include/esp_openthread_netif_glue.h
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_openthread_types.h"
|
||||
#include "openthread/instance.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief This function initializes the OpenThread network interface glue.
|
||||
*
|
||||
* @return
|
||||
* - glue pointer on success
|
||||
* - NULL on failure
|
||||
*
|
||||
*/
|
||||
void *esp_openthread_netif_glue_init(void);
|
||||
|
||||
/**
|
||||
* @brief This function deinitializes the OpenThread network interface glue.
|
||||
*
|
||||
*/
|
||||
void esp_openthread_netif_glue_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief This function updates the netif fds and timeouts to the main loop.
|
||||
*
|
||||
* @param[inout] mainloop The main loop context.
|
||||
*
|
||||
*/
|
||||
void esp_openthread_netif_glue_update(esp_openthread_mainloop_context_t *mainloop);
|
||||
|
||||
/**
|
||||
* @brief This function performs the netif process.
|
||||
*
|
||||
* @param[in] instance The OpenThread instance.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_FAIL on OpenThread failure
|
||||
* - ESP_ERR_NO_MEM on memory allocation failure
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_openthread_netif_glue_process(otInstance *instance, const esp_openthread_mainloop_context_t *mainloop);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -16,11 +16,33 @@
|
||||
|
||||
#include "hal/uart_types.h"
|
||||
#include "sys/select.h"
|
||||
#include "esp_event_base.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief OpenThread event declarations
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
OPENTHREAD_EVENT_START, /*!< OpenThread stack start */
|
||||
OPENTHREAD_EVENT_STOP, /*!< OpenThread stack stop */
|
||||
OPENTHREAD_EVENT_IF_UP, /*!< OpenThread network interface up */
|
||||
OPENTHREAD_EVENT_IF_DOWN, /*!< OpenThread network interface down */
|
||||
OPENTHREAD_EVENT_GOT_IP6, /*!< OpenThread stack added IPv6 address */
|
||||
OPENTHREAD_EVENT_LOST_IP6, /*!< OpenThread stack removed IPv6 address */
|
||||
OPENTHREAD_EVENT_MULTICAST_GROUP_JOIN, /*!< OpenThread stack joined IPv6 multicast group */
|
||||
OPENTHREAD_EVENT_MULTICAST_GROUP_LEAVE, /*!< OpenThread stack left IPv6 multicast group */
|
||||
} esp_openthread_event_t;
|
||||
|
||||
/**
|
||||
* @brief OpenThread event base declaration
|
||||
*
|
||||
*/
|
||||
ESP_EVENT_DECLARE_BASE(OPENTHREAD_EVENT);
|
||||
|
||||
/**
|
||||
* This structure represents a context for a select() based mainloop.
|
||||
*
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "esp_openthread_alarm.h"
|
||||
#include "esp_openthread_common_macro.h"
|
||||
#include "esp_openthread_lock.h"
|
||||
#include "esp_openthread_netif_glue.h"
|
||||
#include "esp_openthread_radio_uart.h"
|
||||
#include "esp_openthread_types.h"
|
||||
#include "esp_openthread_uart.h"
|
||||
@ -92,6 +93,7 @@ void esp_openthread_platform_update(esp_openthread_mainloop_context_t *mainloop)
|
||||
esp_openthread_uart_update(mainloop);
|
||||
}
|
||||
esp_openthread_radio_update(mainloop);
|
||||
esp_openthread_netif_glue_update(mainloop);
|
||||
}
|
||||
|
||||
esp_err_t esp_openthread_platform_process(otInstance *instance, const esp_openthread_mainloop_context_t *mainloop)
|
||||
@ -101,6 +103,5 @@ esp_err_t esp_openthread_platform_process(otInstance *instance, const esp_openth
|
||||
}
|
||||
esp_openthread_radio_process(instance, mainloop);
|
||||
esp_openthread_alarm_process(instance);
|
||||
|
||||
return ESP_OK;
|
||||
return esp_openthread_netif_glue_process(instance, mainloop);
|
||||
}
|
||||
|
@ -22,13 +22,13 @@ static SemaphoreHandle_t s_openthread_mutex = NULL;
|
||||
|
||||
bool esp_openthread_lock_acquire(TickType_t block_ticks)
|
||||
{
|
||||
BaseType_t ret = xSemaphoreTake(s_openthread_mutex, block_ticks);
|
||||
BaseType_t ret = xSemaphoreTakeRecursive(s_openthread_mutex, block_ticks);
|
||||
return (ret == pdTRUE);
|
||||
}
|
||||
|
||||
void esp_openthread_lock_release(void)
|
||||
{
|
||||
xSemaphoreGive(s_openthread_mutex);
|
||||
xSemaphoreGiveRecursive(s_openthread_mutex);
|
||||
}
|
||||
|
||||
esp_err_t esp_openthread_lock_init(void)
|
||||
@ -36,7 +36,7 @@ esp_err_t esp_openthread_lock_init(void)
|
||||
if (s_openthread_mutex != NULL) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
s_openthread_mutex = xSemaphoreCreateMutex();
|
||||
s_openthread_mutex = xSemaphoreCreateRecursiveMutex();
|
||||
if (s_openthread_mutex == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
351
components/openthread/port/esp_openthread_netif_glue.c
Normal file
351
components/openthread/port/esp_openthread_netif_glue.c
Normal file
@ -0,0 +1,351 @@
|
||||
// Copyright 2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License
|
||||
|
||||
#include "esp_openthread_netif_glue.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_check.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_openthread.h"
|
||||
#include "esp_openthread_common_macro.h"
|
||||
#include "esp_openthread_lock.h"
|
||||
#include "esp_vfs_eventfd.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/logging.hpp"
|
||||
#include "config/link_quality.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "openthread/error.h"
|
||||
#include "openthread/icmp6.h"
|
||||
#include "openthread/instance.h"
|
||||
#include "openthread/ip6.h"
|
||||
#include "openthread/link.h"
|
||||
#include "openthread/message.h"
|
||||
#include "openthread/thread.h"
|
||||
|
||||
typedef struct {
|
||||
esp_netif_driver_base_t base;
|
||||
int event_fd;
|
||||
} esp_openthread_netif_glue_t;
|
||||
|
||||
static esp_openthread_netif_glue_t s_openthread_netif_glue = {
|
||||
.event_fd = -1,
|
||||
};
|
||||
|
||||
ESP_EVENT_DEFINE_BASE(OPENTHREAD_EVENT);
|
||||
|
||||
static QueueHandle_t s_packet_queue;
|
||||
|
||||
#define NETIF_OUTPUT_SIGNAL 1
|
||||
|
||||
static esp_err_t notify_packets_pending(void)
|
||||
{
|
||||
uint64_t signal = NETIF_OUTPUT_SIGNAL;
|
||||
ssize_t ret = write(s_openthread_netif_glue.event_fd, &signal, sizeof(signal));
|
||||
if (ret != sizeof(signal)) {
|
||||
otLogWarnPlat("Thread netif failed to notify eventfd");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void process_thread_address(const otIp6AddressInfo *address_info, bool is_added, void *context)
|
||||
{
|
||||
bool is_multicast = address_info->mAddress->mFields.m8[0] == 0xff;
|
||||
esp_ip6_addr_t addr;
|
||||
|
||||
memcpy(addr.addr, address_info->mAddress->mFields.m8, sizeof(addr.addr));
|
||||
if (is_added) {
|
||||
if (is_multicast) {
|
||||
if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_MULTICAST_GROUP_JOIN, &addr, sizeof(addr), 0) !=
|
||||
ESP_OK) {
|
||||
otLogCritPlat("Failed to post OpenThread join multicast group event");
|
||||
}
|
||||
} else {
|
||||
ip_event_add_ip6_t add_addr;
|
||||
add_addr.addr = addr;
|
||||
add_addr.preferred = !address_info->mIsAnycast;
|
||||
if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_GOT_IP6, &add_addr, sizeof(add_addr), 0) != ESP_OK) {
|
||||
otLogCritPlat("Failed to post OpenThread got ip6 address event");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (is_multicast) {
|
||||
if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_MULTICAST_GROUP_LEAVE, &addr, sizeof(addr), 0) !=
|
||||
ESP_OK) {
|
||||
otLogCritPlat("Failed to post OpenThread leave multicast group event");
|
||||
}
|
||||
} else {
|
||||
if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_LOST_IP6, &addr, sizeof(addr), 0) != ESP_OK) {
|
||||
otLogCritPlat("Failed to post OpenThread lost ip6 address event");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void process_thread_receive(otMessage *message, void *context)
|
||||
{
|
||||
esp_err_t error;
|
||||
uint16_t length = otMessageGetLength(message);
|
||||
uint8_t *buffer = malloc(length);
|
||||
|
||||
VerifyOrExit(buffer != NULL, error = OT_ERROR_NO_BUFS);
|
||||
uint16_t read_length = otMessageRead(message, 0, buffer, length);
|
||||
assert(read_length == length);
|
||||
|
||||
error = esp_netif_receive(s_openthread_netif_glue.base.netif, buffer, length, NULL);
|
||||
buffer = NULL;
|
||||
|
||||
exit:
|
||||
if (error != ESP_OK) {
|
||||
otLogWarnPlat("process_thread_receive failed: %s", esp_err_to_name(error));
|
||||
}
|
||||
|
||||
otMessageFree(message);
|
||||
}
|
||||
|
||||
static esp_err_t process_thread_transmit(otInstance *instance)
|
||||
{
|
||||
otMessage *msg = NULL;
|
||||
esp_err_t error = ESP_OK;
|
||||
uint64_t event;
|
||||
|
||||
int ret = read(s_openthread_netif_glue.event_fd, &event, sizeof(event));
|
||||
assert(ret == sizeof(event));
|
||||
while (xQueueReceive(s_packet_queue, &msg, 0) == pdTRUE) {
|
||||
if (msg) {
|
||||
otError ot_error = otIp6Send(esp_openthread_get_instance(), msg);
|
||||
if (ot_error != OT_ERROR_NONE && ot_error != OT_ERROR_DROP) {
|
||||
otLogWarnPlat("ThreadNetif Failed to send OpenThread IP6 message: %s", otThreadErrorToString(ot_error));
|
||||
}
|
||||
if (ot_error == OT_ERROR_DROP) {
|
||||
// OpenThread will intentionally drop some multicast and ICMPv6 packets
|
||||
// which are not required for the Thread network.
|
||||
otLogDebgPlat("OpenThread stack filtered netif packet");
|
||||
}
|
||||
if (ot_error != OT_ERROR_NONE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uxQueueMessagesWaiting(s_packet_queue) > 0) {
|
||||
error = notify_packets_pending();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void process_thread_state(otChangedFlags changed_flags, void *context)
|
||||
{
|
||||
otInstance *instance = (otInstance *)context;
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
if (OT_CHANGED_THREAD_NETIF_STATE & changed_flags) {
|
||||
if (otLinkIsEnabled(instance)) {
|
||||
otLogInfoPlat("netif up");
|
||||
if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_IF_UP, NULL, 0, 0) != ESP_OK) {
|
||||
otLogCritPlat("Failed to post OpenThread if up event");
|
||||
}
|
||||
} else {
|
||||
otLogInfoPlat("netif down");
|
||||
if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_IF_DOWN, NULL, 0, 0) != ESP_OK) {
|
||||
otLogCritPlat("Failed to post OpenThread if down event");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (err != ESP_OK) {
|
||||
otLogCritPlat("Failed to configure netif state");
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t openthread_netif_transmit(void *handle, void *buffer, size_t len)
|
||||
{
|
||||
esp_err_t error = ESP_OK;
|
||||
otError ot_error = OT_ERROR_NONE;
|
||||
|
||||
esp_openthread_lock_acquire(portMAX_DELAY);
|
||||
otMessage *message = otIp6NewMessage(esp_openthread_get_instance(), NULL);
|
||||
if (message == NULL) {
|
||||
otLogCritPlat("Failed to allocate OpenThread message");
|
||||
ExitNow(error = ESP_ERR_NO_MEM);
|
||||
}
|
||||
|
||||
ot_error = otMessageAppend(message, buffer, len);
|
||||
if (ot_error != OT_ERROR_NONE) {
|
||||
otLogCritPlat("Failed to copy to OpenThread message: %s", otThreadErrorToString(ot_error));
|
||||
ExitNow(error = ESP_ERR_NO_MEM);
|
||||
}
|
||||
|
||||
if (xQueueSend(s_packet_queue, &message, 0) != pdTRUE) {
|
||||
otLogCritPlat("Failed to send to Thread netif: packet queue full");
|
||||
ExitNow(error = ESP_ERR_NO_MEM);
|
||||
}
|
||||
VerifyOrExit(notify_packets_pending() == ESP_OK, error = ESP_FAIL);
|
||||
|
||||
exit:
|
||||
if (ot_error != OT_ERROR_NONE && message != NULL) {
|
||||
otMessageFree(message);
|
||||
}
|
||||
esp_openthread_lock_release();
|
||||
return error;
|
||||
}
|
||||
|
||||
static esp_err_t register_openthread_event_handlers(esp_netif_t *esp_netif)
|
||||
{
|
||||
ESP_RETURN_ON_ERROR(
|
||||
esp_event_handler_register(OPENTHREAD_EVENT, OPENTHREAD_EVENT_START, esp_netif_action_start, esp_netif),
|
||||
OT_PLAT_LOG_TAG, "OpenThread start event register failed");
|
||||
ESP_RETURN_ON_ERROR(
|
||||
esp_event_handler_register(OPENTHREAD_EVENT, OPENTHREAD_EVENT_STOP, esp_netif_action_stop, esp_netif),
|
||||
OT_PLAT_LOG_TAG, "OpenThread stop event register failed");
|
||||
ESP_RETURN_ON_ERROR(
|
||||
esp_event_handler_register(OPENTHREAD_EVENT, OPENTHREAD_EVENT_IF_UP, esp_netif_action_connected, esp_netif),
|
||||
OT_PLAT_LOG_TAG, "OpenThread interface up event register failed");
|
||||
ESP_RETURN_ON_ERROR(esp_event_handler_register(OPENTHREAD_EVENT, OPENTHREAD_EVENT_IF_DOWN,
|
||||
esp_netif_action_disconnected, esp_netif),
|
||||
OT_PLAT_LOG_TAG, "OpenThread interface down event register failed");
|
||||
ESP_RETURN_ON_ERROR(esp_event_handler_register(OPENTHREAD_EVENT, OPENTHREAD_EVENT_GOT_IP6,
|
||||
esp_netif_action_add_ip6_address, esp_netif),
|
||||
OT_PLAT_LOG_TAG, "OpenThread interface got ip6 event register failed");
|
||||
ESP_RETURN_ON_ERROR(esp_event_handler_register(OPENTHREAD_EVENT, OPENTHREAD_EVENT_LOST_IP6,
|
||||
esp_netif_action_remove_ip6_address, esp_netif),
|
||||
OT_PLAT_LOG_TAG, "OpenThread interface remove ip6 event register failed");
|
||||
ESP_RETURN_ON_ERROR(esp_event_handler_register(OPENTHREAD_EVENT, OPENTHREAD_EVENT_MULTICAST_GROUP_JOIN,
|
||||
esp_netif_action_join_ip6_multicast_group, esp_netif),
|
||||
OT_PLAT_LOG_TAG, "OpenThread interface join ip6 multicast group event register failed");
|
||||
ESP_RETURN_ON_ERROR(esp_event_handler_register(OPENTHREAD_EVENT, OPENTHREAD_EVENT_MULTICAST_GROUP_LEAVE,
|
||||
esp_netif_action_leave_ip6_multicast_group, esp_netif),
|
||||
OT_PLAT_LOG_TAG, "OpenThread interface leave ip6 multicast group event register failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void unregister_openthread_event_handlers(void)
|
||||
{
|
||||
esp_event_handler_unregister(OPENTHREAD_EVENT, OPENTHREAD_EVENT_START, esp_netif_action_start);
|
||||
esp_event_handler_unregister(OPENTHREAD_EVENT, OPENTHREAD_EVENT_STOP, esp_netif_action_stop);
|
||||
esp_event_handler_unregister(OPENTHREAD_EVENT, OPENTHREAD_EVENT_IF_UP, esp_netif_action_connected);
|
||||
esp_event_handler_unregister(OPENTHREAD_EVENT, OPENTHREAD_EVENT_IF_DOWN, esp_netif_action_disconnected);
|
||||
esp_event_handler_unregister(OPENTHREAD_EVENT, OPENTHREAD_EVENT_GOT_IP6, esp_netif_action_add_ip6_address);
|
||||
esp_event_handler_unregister(OPENTHREAD_EVENT, OPENTHREAD_EVENT_LOST_IP6, esp_netif_action_remove_ip6_address);
|
||||
esp_event_handler_unregister(OPENTHREAD_EVENT, OPENTHREAD_EVENT_MULTICAST_GROUP_JOIN,
|
||||
esp_netif_action_join_ip6_multicast_group);
|
||||
esp_event_handler_unregister(OPENTHREAD_EVENT, OPENTHREAD_EVENT_MULTICAST_GROUP_LEAVE,
|
||||
esp_netif_action_leave_ip6_multicast_group);
|
||||
}
|
||||
|
||||
static esp_err_t openthread_netif_post_attach(esp_netif_t *esp_netif, void *args)
|
||||
{
|
||||
esp_netif_driver_base_t *base = (esp_netif_driver_base_t *)args;
|
||||
base->netif = esp_netif;
|
||||
|
||||
// set driver related config to esp-netif
|
||||
esp_netif_driver_ifconfig_t driver_ifconfig = {
|
||||
.handle = &s_openthread_netif_glue, .transmit = openthread_netif_transmit, .driver_free_rx_buffer = NULL
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &driver_ifconfig));
|
||||
|
||||
otLogInfoPlat("OpenThread attached to netif");
|
||||
esp_err_t error = register_openthread_event_handlers(esp_netif);
|
||||
if (error == ESP_OK) {
|
||||
error = esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_START, NULL, 0, 0);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void *esp_openthread_netif_glue_init(void)
|
||||
{
|
||||
otInstance *instance = esp_openthread_get_instance();
|
||||
otError ot_err;
|
||||
esp_err_t error = ESP_OK;
|
||||
|
||||
if (instance == NULL || s_packet_queue || s_openthread_netif_glue.event_fd >= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s_packet_queue = xQueueCreate(CONFIG_OPENTHREAD_NETIF_QUEUE_SIZE, sizeof(otMessage *));
|
||||
if (s_packet_queue == NULL) {
|
||||
otLogCritPlat("Failed to allocate Thread netif packet queue");
|
||||
ExitNow(error = ESP_ERR_NO_MEM);
|
||||
}
|
||||
|
||||
otIp6SetAddressCallback(instance, process_thread_address, instance);
|
||||
otIp6SetReceiveCallback(instance, process_thread_receive, instance);
|
||||
ot_err = otSetStateChangedCallback(instance, process_thread_state, instance);
|
||||
if (ot_err != OT_ERROR_NONE) {
|
||||
otLogCritPlat("Failed to register callback for OpenThread lwip interface: %s", otThreadErrorToString(ot_err));
|
||||
ExitNow(error = ESP_FAIL);
|
||||
}
|
||||
otIp6SetReceiveFilterEnabled(instance, true);
|
||||
otIcmp6SetEchoMode(instance, OT_ICMP6_ECHO_HANDLER_DISABLED);
|
||||
|
||||
s_openthread_netif_glue.event_fd = eventfd(0, 0);
|
||||
if (s_openthread_netif_glue.event_fd < 0) {
|
||||
otLogCritPlat("Failed to create event fd for Thread netif");
|
||||
ExitNow(error = ESP_FAIL);
|
||||
}
|
||||
s_openthread_netif_glue.base.post_attach = openthread_netif_post_attach;
|
||||
|
||||
exit:
|
||||
if (error != ESP_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &s_openthread_netif_glue.base;
|
||||
}
|
||||
|
||||
void esp_openthread_netif_glue_deinit(void)
|
||||
{
|
||||
otInstance *instance = esp_openthread_get_instance();
|
||||
otRemoveStateChangeCallback(instance, process_thread_state, instance);
|
||||
otIp6SetAddressCallback(instance, NULL, NULL);
|
||||
otIp6SetReceiveCallback(instance, NULL, NULL);
|
||||
if (s_packet_queue) {
|
||||
vQueueDelete(s_packet_queue);
|
||||
s_packet_queue = NULL;
|
||||
}
|
||||
if (s_openthread_netif_glue.event_fd >= 0) {
|
||||
close(s_openthread_netif_glue.event_fd);
|
||||
s_openthread_netif_glue.event_fd = -1;
|
||||
}
|
||||
if (esp_event_post(OPENTHREAD_EVENT, OPENTHREAD_EVENT_STOP, NULL, 0, 0) != ESP_OK) {
|
||||
otLogCritPlat("Failed to stop OpenThread netif");
|
||||
}
|
||||
unregister_openthread_event_handlers();
|
||||
}
|
||||
|
||||
void esp_openthread_netif_glue_update(esp_openthread_mainloop_context_t *mainloop)
|
||||
{
|
||||
if (s_openthread_netif_glue.event_fd >= 0) {
|
||||
FD_SET(s_openthread_netif_glue.event_fd, &mainloop->read_fds);
|
||||
if (s_openthread_netif_glue.event_fd > mainloop->max_fd) {
|
||||
mainloop->max_fd = s_openthread_netif_glue.event_fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_openthread_netif_glue_process(otInstance *instance, const esp_openthread_mainloop_context_t *context)
|
||||
{
|
||||
if (s_openthread_netif_glue.event_fd >= 0 && FD_ISSET(s_openthread_netif_glue.event_fd, &context->read_fds)) {
|
||||
return process_thread_transmit(instance);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
@ -16,12 +16,14 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_openthread.h"
|
||||
#include "esp_openthread_lock.h"
|
||||
#include "esp_openthread_netif_glue.h"
|
||||
#include "esp_openthread_types.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_vfs_eventfd.h"
|
||||
#include "driver/uart.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/portmacro.h"
|
||||
@ -79,10 +81,20 @@ static void ot_task_worker(void *aContext)
|
||||
},
|
||||
},
|
||||
};
|
||||
esp_vfs_eventfd_config_t eventfd_config = {
|
||||
.max_fds = 2,
|
||||
};
|
||||
|
||||
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD();
|
||||
esp_netif_t *netif = esp_netif_new(&cfg);
|
||||
assert(netif != NULL);
|
||||
|
||||
esp_openthread_mainloop_context_t mainloop;
|
||||
|
||||
ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config));
|
||||
ESP_ERROR_CHECK(esp_openthread_platform_init(&config));
|
||||
otInstance *instance = otInstanceInitSingle();
|
||||
ESP_ERROR_CHECK(esp_netif_attach(netif, esp_openthread_netif_glue_init()));
|
||||
assert(instance != NULL);
|
||||
|
||||
esp_openthread_lock_acquire(portMAX_DELAY);
|
||||
@ -120,12 +132,17 @@ static void ot_task_worker(void *aContext)
|
||||
}
|
||||
}
|
||||
|
||||
esp_netif_destroy(netif);
|
||||
esp_openthread_netif_glue_deinit();
|
||||
otInstanceFinalize(instance);
|
||||
esp_openthread_platform_deinit();
|
||||
esp_vfs_eventfd_unregister();
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
xTaskCreate(ot_task_worker, "ot_cli_main", 10240, xTaskGetCurrentTaskHandle(), 5, NULL);
|
||||
}
|
||||
|
@ -31,3 +31,9 @@ CONFIG_MBEDTLS_ECJPAKE_C=y
|
||||
#
|
||||
CONFIG_OPENTHREAD_ENABLED=y
|
||||
# end of OpenThread
|
||||
|
||||
#
|
||||
# lwIP
|
||||
#
|
||||
CONFIG_LWIP_IPV6_NUM_ADDRESSES=8
|
||||
# end of lwIP
|
||||
|
Loading…
Reference in New Issue
Block a user