Merge branch 'bugfix/lwip_core_locking_v5.0' into 'release/v5.0'

esp_netif/lwip: Fix core-locking config (v5.0)

See merge request espressif/esp-idf!22443
This commit is contained in:
Jiang Jiang Jian 2023-03-23 16:54:49 +08:00
commit e8205de110
26 changed files with 663 additions and 273 deletions

View File

@ -51,3 +51,4 @@ if(CONFIG_ESP_NETIF_L2_TAP OR CONFIG_ESP_NETIF_BRIDGE_EN)
endif()
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
target_compile_definitions(${COMPONENT_LIB} PRIVATE ESP_NETIF_COMPONENT_BUILD)

View File

@ -306,6 +306,34 @@ esp_err_t esp_netif_bridge_fdb_add(esp_netif_t *esp_netif_br, uint8_t *addr, uin
esp_err_t esp_netif_bridge_fdb_remove(esp_netif_t *esp_netif_br, uint8_t *addr);
#endif // CONFIG_ESP_NETIF_BRIDGE_EN
/**
* @brief Cause the TCP/IP stack to join a IPv6 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 IPv6 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);
/**
* @}
*/
@ -940,6 +968,27 @@ void esp_netif_netstack_buf_ref(void *netstack_buf);
*/
void esp_netif_netstack_buf_free(void *netstack_buf);
/**
* @}
*/
/** @addtogroup ESP_NETIF_TCPIP_EXEC
* @{
*/
/**
* @brief TCPIP thread safe callback used with esp_netif_tcpip_exec()
*/
typedef esp_err_t (*esp_netif_callback_fn)(void *ctx);
/**
* @brief Utility to execute the supplied callback in TCP/IP context
* @param fn Pointer to the callback
* @param ctx Parameter to the callback
* @return The error code (esp_err_t) returned by the callback
*/
esp_err_t esp_netif_tcpip_exec(esp_netif_callback_fn fn, void *ctx);
/**
* @}
*/

View File

@ -100,12 +100,8 @@ typedef enum esp_netif_action {
//
// Internal variables for this module
//
extern sys_thread_t g_lwip_task;
static const char *TAG = "esp_netif_lwip";
static bool tcpip_initialized = false;
#if LWIP_ESP_NETIF_DATA
static u8_t lwip_netif_client_id = 0xff;
#endif
@ -136,17 +132,28 @@ static void netif_callback_fn(struct netif* netif, netif_nsc_reason_t reason, co
#endif /* #if LWIP_IPV6 */
}
static void set_lwip_netif_callback(void)
#if LWIP_ESP_NETIF_DATA
static esp_err_t alloc_client_data_id(esp_netif_api_msg_t *msg)
{
if (netif_callback.callback_fn == NULL ) {
netif_add_ext_callback(&netif_callback, netif_callback_fn);
}
uint8_t *client_data_id = msg->data;
*client_data_id = netif_alloc_client_data_id();
return ESP_OK;
}
#endif // LWIP_ESP_NETIF_DATA
static esp_err_t set_lwip_netif_callback(struct esp_netif_api_msg_s *msg)
{
(void)msg;
netif_add_ext_callback(&netif_callback, netif_callback_fn);
return ESP_OK;
}
static void remove_lwip_netif_callback(void)
static esp_err_t remove_lwip_netif_callback(struct esp_netif_api_msg_s *msg)
{
(void)msg;
netif_remove_ext_callback(&netif_callback);
memset(&netif_callback, 0, sizeof(netif_callback));
return ESP_OK;
}
static void dns_clear_servers(bool keep_fallback)
@ -186,6 +193,7 @@ static void netif_unset_garp_flag(struct netif *netif)
#if !LWIP_TCPIP_CORE_LOCKING
static sys_sem_t api_sync_sem = NULL;
static sys_sem_t api_lock_sem = NULL;
#endif
/**
* @brief Api callback from tcpip thread used to call esp-netif
@ -202,33 +210,59 @@ static void esp_netif_api_cb(void *api_msg)
msg->ret = msg->api_fn(msg);
ESP_LOGD(TAG, "call api in lwip: ret=0x%x, give sem", msg->ret);
#if !LWIP_TCPIP_CORE_LOCKING
sys_sem_signal(&api_sync_sem);
}
#endif
}
/**
* @brief Initiates a tcpip remote call if called from another task
* or calls the function directly if executed from lwip task
*/
static inline esp_err_t esp_netif_lwip_ipc_call(esp_netif_api_fn fn, esp_netif_t *netif, void *data)
static inline esp_err_t esp_netif_lwip_ipc_call_msg(esp_netif_api_msg_t *msg)
{
if (!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) {
ESP_LOGD(TAG, "check: remote, if=%p fn=%p\n", msg->esp_netif, msg->api_fn);
#if LWIP_TCPIP_CORE_LOCKING
tcpip_send_msg_wait_sem((tcpip_callback_fn)esp_netif_api_cb, msg, NULL);
#else
sys_arch_sem_wait(&api_lock_sem, 0);
tcpip_send_msg_wait_sem((tcpip_callback_fn)esp_netif_api_cb, msg, &api_sync_sem);
sys_sem_signal(&api_lock_sem);
#endif /* LWIP_TCPIP_CORE_LOCKING */
return msg->ret;
}
ESP_LOGD(TAG, "check: local, if=%p fn=%p\n", msg->esp_netif, msg->api_fn);
return msg->api_fn(msg);
}
static inline esp_err_t esp_netif_lwip_ipc_call(esp_netif_api_fn fn, esp_netif_t* netif, void *data)
{
esp_netif_api_msg_t msg = {
.esp_netif = netif,
.data = data,
.api_fn = fn
};
#if !LWIP_TCPIP_CORE_LOCKING
if (tcpip_initialized && g_lwip_task != xTaskGetCurrentTaskHandle()) {
ESP_LOGD(TAG, "check: remote, if=%p fn=%p\n", netif, fn);
sys_arch_sem_wait(&api_lock_sem, 0);
tcpip_send_msg_wait_sem((tcpip_callback_fn)esp_netif_api_cb, &msg, &api_sync_sem);
sys_sem_signal(&api_lock_sem);
return msg.ret;
}
#endif /* !LWIP_TCPIP_CORE_LOCKING */
ESP_LOGD(TAG, "check: local, if=%p fn=%p\n", netif, fn);
return fn(&msg);
return esp_netif_lwip_ipc_call_msg(&msg);
}
static inline esp_err_t esp_netif_lwip_ipc_call_fn(esp_netif_api_fn fn, esp_netif_callback_fn user_fn, void *ctx)
{
esp_netif_api_msg_t msg = {
.user_fn = user_fn,
.data = ctx,
.api_fn = fn
};
return esp_netif_lwip_ipc_call_msg(&msg);
}
static inline esp_err_t esp_netif_lwip_ipc_no_args(esp_netif_api_fn fn)
{
esp_netif_api_msg_t msg = {
.api_fn = fn
};
return esp_netif_lwip_ipc_call_msg(&msg);
}
/**
@ -458,10 +492,15 @@ void* esp_netif_get_netif_impl(esp_netif_t *esp_netif)
return NULL;
}
static void tcpip_init_done(void *arg)
{
sys_sem_t *init_sem = arg;
sys_sem_signal(init_sem);
}
esp_err_t esp_netif_init(void)
{
if (tcpip_initialized == false) {
tcpip_initialized = true;
if (!sys_thread_tcpip(LWIP_CORE_IS_TCPIP_INITIALIZED)) {
#if CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT
uint8_t rand_buf[16];
/*
@ -474,13 +513,21 @@ esp_err_t esp_netif_init(void)
esp_fill_random(rand_buf, sizeof(rand_buf));
lwip_init_tcp_isn(esp_log_timestamp(), rand_buf);
#endif
tcpip_init(NULL, NULL);
ESP_LOGD(TAG, "LwIP stack has been initialized");
#if LWIP_ESP_NETIF_DATA
if (lwip_netif_client_id == 0xFF) {
lwip_netif_client_id = netif_alloc_client_data_id();
sys_sem_t init_sem;
if (sys_sem_new(&init_sem, 0) != ERR_OK) {
ESP_LOGE(TAG, "esp netif cannot create tcpip_init semaphore");
return ESP_FAIL;
}
#if LWIP_TCPIP_CORE_LOCKING
/* TCPIP thread is not initialized yet,
* pretend that the calling thread is holder
* to correctly set up the TCPIP task */
sys_thread_tcpip(LWIP_CORE_LOCK_MARK_HOLDER);
#endif
tcpip_init(tcpip_init_done, &init_sem);
sys_sem_wait(&init_sem);
sys_sem_free(&init_sem);
ESP_LOGD(TAG, "LwIP stack has been initialized");
}
#if !LWIP_TCPIP_CORE_LOCKING
@ -499,18 +546,22 @@ esp_err_t esp_netif_init(void)
}
#endif
#if LWIP_ESP_NETIF_DATA
if (lwip_netif_client_id == 0xFF) {
esp_netif_lwip_ipc_call(alloc_client_data_id, NULL, &lwip_netif_client_id);
}
#endif
ESP_LOGD(TAG, "esp-netif has been successfully initialized");
return ESP_OK;
}
esp_err_t esp_netif_deinit(void)
{
if (tcpip_initialized == true) {
if (sys_thread_tcpip(LWIP_CORE_IS_TCPIP_INITIALIZED)) {
/* deinit of LwIP not supported:
* do not deinit semaphores and states,
* so init could be called multiple times
*
tcpip_initialized = false;
sys_sem_free(&api_sync_sem);
sys_sem_free(&api_lock_sem);
*/
@ -612,6 +663,16 @@ static esp_err_t esp_netif_init_configuration(esp_netif_t *esp_netif, const esp_
return ESP_OK;
}
static esp_err_t tcpip_exec_api(esp_netif_api_msg_t *msg)
{
return msg->user_fn(msg->data);
}
esp_err_t esp_netif_tcpip_exec(esp_netif_callback_fn fn, void*ctx)
{
return esp_netif_lwip_ipc_call_fn(tcpip_exec_api, fn, ctx);
}
esp_netif_t *esp_netif_new(const esp_netif_config_t *esp_netif_config)
{
// mandatory configuration must be provided when creating esp_netif object
@ -657,7 +718,7 @@ esp_netif_t *esp_netif_new(const esp_netif_config_t *esp_netif_config)
// Optionally allocate netif client data for esp-netif ptr
// to allow for running esp_netif_new() before esp_netif_init()
if (lwip_netif_client_id == 0xFF) {
lwip_netif_client_id = netif_alloc_client_data_id();
esp_netif_lwip_ipc_call(alloc_client_data_id, NULL, &lwip_netif_client_id);
}
#endif
@ -696,7 +757,9 @@ esp_netif_t *esp_netif_new(const esp_netif_config_t *esp_netif_config)
}
lwip_set_esp_netif(lwip_netif, esp_netif);
set_lwip_netif_callback();
if (netif_callback.callback_fn == NULL ) {
esp_netif_lwip_ipc_no_args(set_lwip_netif_callback);
}
return esp_netif;
}
@ -783,18 +846,24 @@ static void esp_netif_destroy_related(esp_netif_t *esp_netif)
}
}
static esp_err_t esp_netif_lwip_remove_api(esp_netif_api_msg_t *msg)
{
esp_netif_lwip_remove(msg->esp_netif);
return ESP_OK;
}
void esp_netif_destroy(esp_netif_t *esp_netif)
{
if (esp_netif) {
esp_netif_remove_from_list(esp_netif);
if (esp_netif_get_nr_of_ifs() == 0) {
remove_lwip_netif_callback();
esp_netif_lwip_ipc_no_args(remove_lwip_netif_callback);
}
free(esp_netif->ip_info);
free(esp_netif->ip_info_old);
free(esp_netif->if_key);
free(esp_netif->if_desc);
esp_netif_lwip_remove(esp_netif);
esp_netif_lwip_ipc_call(esp_netif_lwip_remove_api, esp_netif, NULL);
esp_netif_destroy_related(esp_netif);
free(esp_netif->lwip_netif);
free(esp_netif->hostname);
@ -842,6 +911,15 @@ static esp_err_t esp_netif_reset_ip_info(esp_netif_t *esp_netif)
return ESP_OK;
}
esp_err_t esp_netif_set_mac_api(esp_netif_api_msg_t *msg)
{
uint8_t *mac = msg->data;
esp_netif_t* esp_netif = msg->esp_netif;
memcpy(esp_netif->mac, mac, NETIF_MAX_HWADDR_LEN);
memcpy(esp_netif->lwip_netif->hwaddr, mac, NETIF_MAX_HWADDR_LEN);
return ESP_OK;
}
esp_err_t esp_netif_set_mac(esp_netif_t *esp_netif, uint8_t mac[])
{
if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
@ -850,9 +928,7 @@ esp_err_t esp_netif_set_mac(esp_netif_t *esp_netif, uint8_t mac[])
if (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
return ESP_ERR_NOT_SUPPORTED;
}
memcpy(esp_netif->mac, mac, NETIF_MAX_HWADDR_LEN);
memcpy(esp_netif->lwip_netif->hwaddr, mac, NETIF_MAX_HWADDR_LEN);
return ESP_OK;
return esp_netif_lwip_ipc_call(esp_netif_set_mac_api, esp_netif, mac);
}
esp_err_t esp_netif_get_mac(esp_netif_t *esp_netif, uint8_t mac[])
@ -2018,70 +2094,75 @@ int32_t esp_netif_get_event_id(esp_netif_t *esp_netif, esp_netif_ip_event_type_t
}
}
struct dhcp_params {
esp_netif_dhcp_option_mode_t op;
esp_netif_dhcp_option_id_t id;
void *val;
uint32_t len;
};
#if ESP_DHCPS
esp_err_t esp_netif_dhcps_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_mode_t opt_op, esp_netif_dhcp_option_id_t opt_id, void *opt_val,
uint32_t opt_len)
esp_err_t esp_netif_dhcps_option_api(esp_netif_api_msg_t *msg)
{
if (esp_netif == NULL || esp_netif->dhcps == NULL) {
return ESP_ERR_ESP_NETIF_IF_NOT_READY;
}
void *opt_info = dhcps_option_info(esp_netif->dhcps, opt_id, opt_len);
esp_netif_t *esp_netif = msg->esp_netif;
struct dhcp_params *opt = msg->data;
void *opt_info = dhcps_option_info(esp_netif->dhcps, opt->id, opt->len);
esp_netif_dhcp_status_t dhcps_status = esp_netif->dhcps_status;
if (opt_info == NULL || opt_val == NULL) {
if (opt_info == NULL || opt->val == NULL) {
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
}
if (opt_op == ESP_NETIF_OP_GET) {
if (opt->op == ESP_NETIF_OP_GET) {
if (dhcps_status == ESP_NETIF_DHCP_STOPPED) {
return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED;
}
switch (opt_id) {
switch (opt->id) {
case IP_ADDRESS_LEASE_TIME: {
*(uint32_t *)opt_val = *(uint32_t *)opt_info;
*(uint32_t *)opt->val = *(uint32_t *)opt_info;
break;
}
case ESP_NETIF_SUBNET_MASK:
case REQUESTED_IP_ADDRESS: {
memcpy(opt_val, opt_info, opt_len);
memcpy(opt->val, opt_info, opt->len);
break;
}
case ROUTER_SOLICITATION_ADDRESS: {
if ((*(uint8_t *)opt_info) & OFFER_ROUTER) {
*(uint8_t *)opt_val = 1;
*(uint8_t *)opt->val = 1;
} else {
*(uint8_t *)opt_val = 0;
*(uint8_t *)opt->val = 0;
}
break;
}
case DOMAIN_NAME_SERVER: {
if ((*(uint8_t *)opt_info) & OFFER_DNS) {
*(uint8_t *)opt_val = 1;
*(uint8_t *)opt->val = 1;
} else {
*(uint8_t *)opt_val = 0;
*(uint8_t *)opt->val = 0;
}
break;
}
default:
break;
}
} else if (opt_op == ESP_NETIF_OP_SET) {
} else if (opt->op == ESP_NETIF_OP_SET) {
if (dhcps_status == ESP_NETIF_DHCP_STARTED) {
return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
}
switch (opt_id) {
switch (opt->id) {
case IP_ADDRESS_LEASE_TIME: {
if (*(uint32_t *)opt_val != 0) {
*(uint32_t *)opt_info = *(uint32_t *)opt_val;
if (*(uint32_t *)opt->val != 0) {
*(uint32_t *)opt_info = *(uint32_t *)opt->val;
} else {
*(uint32_t *)opt_info = DHCPS_LEASE_TIME_DEF;
}
break;
}
case ESP_NETIF_SUBNET_MASK: {
memcpy(opt_info, opt_val, opt_len);
memcpy(opt_info, opt->val, opt->len);
break;
}
case REQUESTED_IP_ADDRESS: {
@ -2089,7 +2170,7 @@ esp_err_t esp_netif_dhcps_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_m
uint32_t softap_ip = 0;
uint32_t start_ip = 0;
uint32_t end_ip = 0;
dhcps_lease_t *poll = opt_val;
dhcps_lease_t *poll = opt->val;
if (poll->enable) {
memset(&info, 0x00, sizeof(esp_netif_ip_info_t));
@ -2116,11 +2197,11 @@ esp_err_t esp_netif_dhcps_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_m
}
}
memcpy(opt_info, opt_val, opt_len);
memcpy(opt_info, opt->val, opt->len);
break;
}
case ROUTER_SOLICITATION_ADDRESS: {
if (*(uint8_t *)opt_val) {
if (*(uint8_t *)opt->val) {
*(uint8_t *)opt_info |= OFFER_ROUTER;
} else {
*(uint8_t *)opt_info &= ((~OFFER_ROUTER) & 0xFF);
@ -2128,7 +2209,7 @@ esp_err_t esp_netif_dhcps_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_m
break;
}
case DOMAIN_NAME_SERVER: {
if (*(uint8_t *)opt_val) {
if (*(uint8_t *)opt->val) {
*(uint8_t *)opt_info |= OFFER_DNS;
} else {
*(uint8_t *)opt_info &= ((~OFFER_DNS) & 0xFF);
@ -2139,63 +2220,82 @@ esp_err_t esp_netif_dhcps_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_m
default:
break;
}
dhcps_set_option_info(esp_netif->dhcps, opt_id, opt_info, opt_len);
dhcps_set_option_info(esp_netif->dhcps, opt->id, opt_info, opt->len);
} else {
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
}
return ESP_OK;
}
esp_err_t esp_netif_dhcps_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_mode_t opt_op, esp_netif_dhcp_option_id_t opt_id, void *opt_val,
uint32_t opt_len)
{
if (esp_netif == NULL || esp_netif->dhcps == NULL) {
return ESP_ERR_ESP_NETIF_IF_NOT_READY;
}
struct dhcp_params opts = { .op = opt_op, .id = opt_id, .len = opt_len, .val = opt_val };
return esp_netif_lwip_ipc_call(esp_netif_dhcps_option_api, esp_netif, &opts);
}
#endif
esp_err_t esp_netif_dhcpc_option_api(esp_netif_api_msg_t *msg)
{
esp_netif_t *esp_netif = msg->esp_netif;
struct dhcp_params *opt = msg->data;
struct dhcp *dhcp = netif_dhcp_data(esp_netif->lwip_netif);
if (dhcp == NULL || opt->val == NULL) {
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
}
if (opt->op == ESP_NETIF_OP_GET) {
if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STOPPED) {
return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED;
}
switch (opt->id) {
case ESP_NETIF_IP_REQUEST_RETRY_TIME:
if (opt->len == sizeof(dhcp->tries)) {
*(uint8_t *)opt->val = dhcp->tries;
}
break;
#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
case ESP_NETIF_VENDOR_SPECIFIC_INFO:
return dhcp_get_vendor_specific_information(opt->len, opt->val);
#endif
default:
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
}
} else if (opt->op == ESP_NETIF_OP_SET) {
if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STARTED) {
return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
}
switch (opt->id) {
case ESP_NETIF_IP_REQUEST_RETRY_TIME:
if (opt->len == sizeof(dhcp->tries)) {
dhcp->tries = *(uint8_t *)opt->val;
}
break;
#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
case ESP_NETIF_VENDOR_CLASS_IDENTIFIER:
return dhcp_set_vendor_class_identifier(opt->len, opt->val);
#endif
default:
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
}
} else {
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
}
return ESP_OK;
}
esp_err_t esp_netif_dhcpc_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_mode_t opt_op, esp_netif_dhcp_option_id_t opt_id, void *opt_val,
uint32_t opt_len)
{
if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
return ESP_ERR_ESP_NETIF_IF_NOT_READY;
}
struct dhcp *dhcp = netif_dhcp_data(esp_netif->lwip_netif);
if (dhcp == NULL || opt_val == NULL) {
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
}
if (opt_op == ESP_NETIF_OP_GET) {
if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STOPPED) {
return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED;
}
switch (opt_id) {
case ESP_NETIF_IP_REQUEST_RETRY_TIME:
if (opt_len == sizeof(dhcp->tries)) {
*(uint8_t *)opt_val = dhcp->tries;
}
break;
#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
case ESP_NETIF_VENDOR_SPECIFIC_INFO:
return dhcp_get_vendor_specific_information(opt_len, opt_val);
#endif
default:
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
}
} else if (opt_op == ESP_NETIF_OP_SET) {
if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STARTED) {
return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
}
switch (opt_id) {
case ESP_NETIF_IP_REQUEST_RETRY_TIME:
if (opt_len == sizeof(dhcp->tries)) {
dhcp->tries = *(uint8_t *)opt_val;
}
break;
#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
case ESP_NETIF_VENDOR_CLASS_IDENTIFIER:
return dhcp_set_vendor_class_identifier(opt_len, opt_val);
#endif
default:
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
}
} else {
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
}
return ESP_OK;
struct dhcp_params opts = { .op = opt_op, .id = opt_id, .len = opt_len, .val = opt_val };
return esp_netif_lwip_ipc_call(esp_netif_dhcpc_option_api, esp_netif, &opts);
}
int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif)
@ -2206,6 +2306,13 @@ int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif)
return netif_get_index(esp_netif->lwip_netif);
}
esp_err_t esp_netif_get_netif_impl_name_api(esp_netif_api_msg_t *msg)
{
struct netif* netif = msg->esp_netif->lwip_netif;
netif_index_to_name(netif_get_index(netif), msg->data);
return ESP_OK;
}
esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name)
{
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
@ -2213,8 +2320,7 @@ esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name)
if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
}
netif_index_to_name(netif_get_index(esp_netif->lwip_netif), name);
return ESP_OK;
return esp_netif_lwip_ipc_call(esp_netif_get_netif_impl_name_api, esp_netif, name);
}
#if MIB2_STATS

View File

@ -21,7 +21,10 @@ typedef struct esp_netif_api_msg_s {
int type; /**< The first field MUST be int */
int ret;
esp_netif_api_fn api_fn;
esp_netif_t *esp_netif;
union {
esp_netif_t *esp_netif;
esp_netif_callback_fn user_fn;
};
void *data;
} esp_netif_api_msg_t;

View File

@ -1,16 +1,8 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE 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.
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _ESP_NETIF_PRIVATE_H_
#define _ESP_NETIF_PRIVATE_H_
@ -145,34 +137,6 @@ 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
*

View File

@ -19,12 +19,21 @@ menu "LWIP"
bool "Enable tcpip core locking"
default n
help
If Enable tcpip core locking,Creates a global mutex that is held
If Enable tcpip core locking,Creates a global mutex that is held
during TCPIP thread operations.Can be locked by client code to perform
lwIP operations without changing into TCPIP thread using callbacks.
See LOCK_TCPIP_CORE() and UNLOCK_TCPIP_CORE().
If disable tcpip core locking,TCP IP will perform tasks through context switching
If disable tcpip core locking,TCP IP will perform tasks through context switching
config LWIP_CHECK_THREAD_SAFETY
bool "Checks that lwip API runs in expected context"
default n
help
Enable to check that the project does not violate lwip thread safety.
If enabled, all lwip functions that require thread awareness run an assertion
to verify that the TCP/IP core functionality is either locked or accessed
from the correct thread.
config LWIP_DNS_SUPPORT_MDNS_QUERIES
bool "Enable mDNS queries in resolving host name"

View File

@ -1,27 +1,29 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE 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.
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
#include "esp_log.h"
#include "sntp.h"
#include "lwip/apps/sntp.h"
#include "esp_sntp.h"
#include "lwip/priv/tcpip_priv.h"
#include "esp_macros.h"
static const char *TAG = "sntp";
ESP_STATIC_ASSERT(SNTP_OPMODE_POLL == ESP_SNTP_OPMODE_POLL, "SNTP mode in lwip doesn't match the IDF enum. Please make sure lwIP version is correct");
ESP_STATIC_ASSERT(SNTP_OPMODE_LISTENONLY == ESP_SNTP_OPMODE_LISTENONLY, "SNTP mode in lwip doesn't match the IDF enum. Please make sure lwIP version is correct");
#define SNTP_ERROR(func, message) do { \
err_t err = func; \
LWIP_ERROR(message, err == ERR_OK, ); \
} while (0)
static volatile sntp_sync_mode_t sntp_sync_mode = SNTP_SYNC_MODE_IMMED;
static volatile sntp_sync_status_t sntp_sync_status = SNTP_SYNC_STATUS_RESET;
static sntp_sync_time_cb_t time_sync_notification_cb = NULL;
@ -108,11 +110,17 @@ uint32_t sntp_get_sync_interval(void)
return s_sync_interval;
}
static void sntp_do_restart(void *ctx)
{
(void)ctx;
sntp_stop();
sntp_init();
}
bool sntp_restart(void)
{
if (sntp_enabled()) {
sntp_stop();
sntp_init();
SNTP_ERROR(tcpip_callback(sntp_do_restart, NULL), "sntp_restart: tcpip_callback() failed");
return true;
}
return false;
@ -132,3 +140,106 @@ void sntp_get_system_time(uint32_t *sec, uint32_t *us)
*(us) = tv.tv_usec;
sntp_set_sync_status(SNTP_SYNC_STATUS_RESET);
}
static void do_setoperatingmode(void *ctx)
{
sntp_setoperatingmode((intptr_t)ctx);
}
void esp_sntp_setoperatingmode(esp_sntp_operatingmode_t operating_mode)
{
SNTP_ERROR(tcpip_callback(do_setoperatingmode, (void*)operating_mode),
"esp_sntp_setoperatingmode: tcpip_callback() failed");
}
static void do_init(void *ctx)
{
sntp_init();
}
void esp_sntp_init(void)
{
SNTP_ERROR(tcpip_callback(do_init, NULL), "esp_sntp_init: tcpip_callback() failed");
}
static void do_stop(void *ctx)
{
sntp_stop();
}
void esp_sntp_stop(void)
{
SNTP_ERROR(tcpip_callback(do_stop, NULL), "esp_sntp_stop: tcpip_callback() failed");
}
struct tcpip_setserver {
struct tcpip_api_call_data call;
u8_t idx;
const ip_addr_t *addr;
};
static err_t do_setserver(struct tcpip_api_call_data *msg)
{
struct tcpip_setserver *params = __containerof(msg, struct tcpip_setserver, call);
sntp_setserver(params->idx, params->addr);
return ERR_OK;
}
void esp_sntp_setserver(u8_t idx, const ip_addr_t *addr)
{
struct tcpip_setserver params = {
.idx = idx,
.addr = addr
};
SNTP_ERROR(tcpip_api_call(do_setserver, &params.call), "esp_sntp_setserver :tcpip_api_call() failed");
}
struct tcpip_setservername {
struct tcpip_api_call_data call;
u8_t idx;
const char *server;
};
static err_t do_setservername(struct tcpip_api_call_data *msg)
{
struct tcpip_setservername *params = __containerof(msg, struct tcpip_setservername, call);
sntp_setservername(params->idx, params->server);
return ERR_OK;
}
void esp_sntp_setservername(u8_t idx, const char *server)
{
struct tcpip_setservername params = {
.idx = idx,
.server = server
};
SNTP_ERROR(tcpip_api_call(do_setservername, &params.call), "esp_sntp_setservername :tcpip_api_call() failed");
}
const char *esp_sntp_getservername(u8_t idx)
{
return sntp_getservername(idx);
}
const ip_addr_t* esp_sntp_getserver(u8_t idx)
{
return sntp_getserver(idx);
}
#if LWIP_DHCP_GET_NTP_SRV
static void do_servermode_dhcp(void* ctx)
{
sntp_servermode_dhcp((intptr_t)ctx);
}
void esp_sntp_servermode_dhcp(bool enable)
{
SNTP_ERROR(tcpip_callback(do_servermode_dhcp, (void*)enable), "esp_sntp_servermode_dhcp: tcpip_callback() failed");
}
#endif /* LWIP_DHCP_GET_NTP_SRV */
bool esp_sntp_enabled(void)
{
return sntp_enabled();
}

View File

@ -10,7 +10,6 @@
#include "lwip/err.h"
#include "lwip/apps/sntp.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -38,6 +37,17 @@ extern "C" {
* to wait for the next sync cycle.
*/
/// Aliases for esp_sntp prefixed API (inherently thread safe)
#define esp_sntp_sync_time sntp_sync_time
#define esp_sntp_set_sync_mode sntp_set_sync_mode
#define esp_sntp_get_sync_mode sntp_get_sync_mode
#define esp_sntp_get_sync_status sntp_get_sync_status
#define esp_sntp_set_sync_status sntp_set_sync_status
#define esp_sntp_set_time_sync_notification_cb sntp_set_time_sync_notification_cb
#define esp_sntp_set_sync_interval sntp_set_sync_interval
#define esp_sntp_get_sync_interval sntp_get_sync_interval
#define esp_sntp_restart sntp_restart
/// SNTP time update mode
typedef enum {
SNTP_SYNC_MODE_IMMED, /*!< Update system time immediately when receiving a response from the SNTP server. */
@ -51,6 +61,12 @@ typedef enum {
SNTP_SYNC_STATUS_IN_PROGRESS, // Smooth time sync in progress.
} sntp_sync_status_t;
/// SNTP operating modes per lwip SNTP module
typedef enum {
ESP_SNTP_OPMODE_POLL,
ESP_SNTP_OPMODE_LISTENONLY,
} esp_sntp_operatingmode_t;
/**
* @brief SNTP callback function for notifying about time sync event
*
@ -143,6 +159,66 @@ uint32_t sntp_get_sync_interval(void);
*/
bool sntp_restart(void);
/**
* @brief Sets SNTP operating mode. The mode has to be set before init.
*
* @param operating_mode Desired operating mode
*/
void esp_sntp_setoperatingmode(esp_sntp_operatingmode_t operating_mode);
/**
* @brief Init and start SNTP service
*/
void esp_sntp_init(void);
/**
* @brief Stops SNTP service
*/
void esp_sntp_stop(void);
/**
* @brief Sets SNTP server address
*
* @param idx Index of the server
* @param addr IP address of the server
*/
void esp_sntp_setserver(u8_t idx, const ip_addr_t *addr);
/**
* @brief Sets SNTP hostname
* @param idx Index of the server
* @param server Name of the server
*/
void esp_sntp_setservername(u8_t idx, const char *server);
/**
* @brief Gets SNTP server name
* @param idx Index of the server
* @return Name of the server
*/
const char *esp_sntp_getservername(u8_t idx);
/**
* @brief Get SNTP server IP
* @param idx Index of the server
* @return IP address of the server
*/
const ip_addr_t* esp_sntp_getserver(u8_t idx);
/**
* @brief Checks if sntp is enabled
* @return true if sntp module is enabled
*/
bool esp_sntp_enabled(void);
#if LWIP_DHCP_GET_NTP_SRV
/**
* @brief Enable acquiring SNTP server from DHCP
* @param enable True for enabling SNTP from DHCP
*/
void esp_sntp_servermode_dhcp(bool enable);
#endif /* LWIP_DHCP_GET_NTP_SRV */
#ifdef __cplusplus
}
#endif

View File

@ -1,27 +1,16 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE 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
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// 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 __SNTP_H__
#define __SNTP_H__
#pragma once
#warning "sntp.h in IDF's lwip port folder is deprecated. Please include esp_sntp.h"
/*
* This header is provided only for compatibility reasons for existing
* applications which directly include "sntp.h" from the IDF default paths.
* and will be removed in IDF v5.0.
* and will be removed in IDF v6.0.
* It is recommended to use "esp_sntp.h" from IDF's lwip port folder
*/
#include "esp_sntp.h"
#endif // __SNTP_H__

View File

@ -53,7 +53,6 @@ static sys_mutex_t g_lwip_protect_mutex = NULL;
static pthread_key_t sys_thread_sem_key;
static void sys_thread_sem_free(void* data);
sys_thread_t g_lwip_task;
#if !LWIP_COMPAT_MUTEX
@ -428,10 +427,8 @@ sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize
ret = xTaskCreatePinnedToCore(thread, name, stacksize, arg, prio, &rtos_task,
CONFIG_LWIP_TCPIP_TASK_AFFINITY);
g_lwip_task = rtos_task;
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_task_hdlxxx : %x, prio:%d,stack:%d\n",
(u32_t)g_lwip_task,TCPIP_THREAD_PRIO,TCPIP_THREAD_STACKSIZE));
LWIP_DEBUGF(TCPIP_DEBUG, ("new lwip task : %x, prio:%d,stack:%d\n",
(u32_t)rtos_task, prio, stacksize));
if (ret != pdTRUE) {
return NULL;
@ -577,3 +574,36 @@ sys_delay_ms(uint32_t ms)
{
vTaskDelay(ms / portTICK_PERIOD_MS);
}
bool
sys_thread_tcpip(sys_thread_core_lock_t type)
{
static sys_thread_t lwip_task = NULL;
#if LWIP_TCPIP_CORE_LOCKING
static sys_thread_t core_lock_holder = NULL;
#endif
switch (type) {
default:
return false;
case LWIP_CORE_IS_TCPIP_INITIALIZED:
return lwip_task != NULL;
case LWIP_CORE_MARK_TCPIP_TASK:
LWIP_ASSERT("LWIP_CORE_MARK_TCPIP_TASK: lwip_task == NULL", (lwip_task == NULL));
lwip_task = (sys_thread_t) xTaskGetCurrentTaskHandle();
return true;
#if LWIP_TCPIP_CORE_LOCKING
case LWIP_CORE_LOCK_QUERY_HOLDER:
return lwip_task ? core_lock_holder == (sys_thread_t) xTaskGetCurrentTaskHandle() : true;
case LWIP_CORE_LOCK_MARK_HOLDER:
core_lock_holder = (sys_thread_t) xTaskGetCurrentTaskHandle();
return true;
case LWIP_CORE_LOCK_UNMARK_HOLDER:
core_lock_holder = NULL;
return true;
#else
case LWIP_CORE_LOCK_QUERY_HOLDER:
return lwip_task == NULL || lwip_task == (sys_thread_t) xTaskGetCurrentTaskHandle();
#endif /* LWIP_TCPIP_CORE_LOCKING */
}
return true;
}

View File

@ -100,6 +100,17 @@ sys_sem_t* sys_thread_sem_init(void);
void sys_thread_sem_deinit(void);
sys_sem_t* sys_thread_sem_get(void);
typedef enum {
LWIP_CORE_LOCK_QUERY_HOLDER,
LWIP_CORE_LOCK_MARK_HOLDER,
LWIP_CORE_LOCK_UNMARK_HOLDER,
LWIP_CORE_MARK_TCPIP_TASK,
LWIP_CORE_IS_TCPIP_INITIALIZED,
} sys_thread_core_lock_t;
bool
sys_thread_tcpip(sys_thread_core_lock_t type);
#ifdef __cplusplus
}
#endif

View File

@ -12,6 +12,7 @@
#include "lwip/pbuf.h"
#include "netif/dhcp_state.h"
#ifdef ESP_IDF_LWIP_HOOK_FILENAME
#include ESP_IDF_LWIP_HOOK_FILENAME
#endif

View File

@ -26,6 +26,7 @@
#include "sdkconfig.h"
#include "sntp/sntp_get_set_time.h"
#include "sockets_ext.h"
#include "arch/sys_arch.h"
#ifdef __cplusplus
extern "C" {
@ -46,9 +47,20 @@ extern "C" {
*/
#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING
#define LWIP_TCPIP_CORE_LOCKING 1
#define LOCK_TCPIP_CORE() do { sys_mutex_lock(&lock_tcpip_core); sys_thread_tcpip(LWIP_CORE_LOCK_MARK_HOLDER); } while(0)
#define UNLOCK_TCPIP_CORE() do { sys_thread_tcpip(LWIP_CORE_LOCK_UNMARK_HOLDER); sys_mutex_unlock(&lock_tcpip_core); } while(0)
#ifdef CONFIG_LWIP_CHECK_THREAD_SAFETY
#define LWIP_ASSERT_CORE_LOCKED() do { LWIP_ASSERT("Required to lock TCPIP core functionality!", sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)); } while(0)
#endif /* CONFIG_LWIP_CHECK_THREAD_SAFETY */
#else
#define LWIP_TCPIP_CORE_LOCKING 0
#endif
#ifdef CONFIG_LWIP_CHECK_THREAD_SAFETY
#define LWIP_ASSERT_CORE_LOCKED() do { LWIP_ASSERT("Required to run in TCPIP context!", sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)); } while(0)
#endif /* CONFIG_LWIP_CHECK_THREAD_SAFETY */
#endif /* CONFIG_LWIP_TCPIP_CORE_LOCKING */
#define LWIP_MARK_TCPIP_THREAD() sys_thread_tcpip(LWIP_CORE_MARK_TCPIP_TASK)
/**
* SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
@ -846,11 +858,7 @@ static inline uint32_t timeout_from_offered(uint32_t lease, uint32_t min)
* The latter 2 can be invoked up by calling netconn_thread_init()/netconn_thread_cleanup().
* Ports may call these for threads created with sys_thread_new().
*/
#if LWIP_TCPIP_CORE_LOCKING
#define LWIP_NETCONN_SEM_PER_THREAD 0
#else
#define LWIP_NETCONN_SEM_PER_THREAD 1
#endif
/** LWIP_NETCONN_FULLDUPLEX==1: Enable code that allows reading from one thread,
* writing from a 2nd thread and closing from a 3rd thread at the same time.
@ -1199,11 +1207,17 @@ static inline uint32_t timeout_from_offered(uint32_t lease, uint32_t min)
#endif
#define LWIP_HOOK_FILENAME "lwip_default_hooks.h"
#define LWIP_HOOK_IP4_ROUTE_SRC ip4_route_src_hook
#if LWIP_NETCONN_FULLDUPLEX
#define LWIP_DONE_SOCK(sock) done_socket(sock)
#else
#define LWIP_DONE_SOCK(sock) ((void)1)
#endif /* LWIP_NETCONN_FULLDUPLEX */
#define LWIP_HOOK_SOCKETS_GETSOCKOPT(s, sock, level, optname, optval, optlen, err) \
lwip_getsockopt_impl_ext(sock, level, optname, optval, optlen, err)?(done_socket(sock), true): false
lwip_getsockopt_impl_ext(sock, level, optname, optval, optlen, err)?(LWIP_DONE_SOCK(sock), true): false
#define LWIP_HOOK_SOCKETS_SETSOCKOPT(s, sock, level, optname, optval, optlen, err) \
lwip_setsockopt_impl_ext(sock, level, optname, optval, optlen, err)?(done_socket(sock), true): false
lwip_setsockopt_impl_ext(sock, level, optname, optval, optlen, err)?(LWIP_DONE_SOCK(sock), true): false
/*
---------------------------------------

View File

@ -10,6 +10,7 @@
#include "lwip/inet.h"
#include "lwip/netdb.h"
#include "lwip/sockets.h"
#include "lwip/tcpip.h"
#include "ping/ping_sock.h"
#include "dhcpserver/dhcpserver.h"
#include "dhcpserver/dhcpserver_options.h"
@ -125,12 +126,18 @@ TEST_CASE("dhcp server init/deinit", "[lwip][leaks=0]")
dhcps_delete(dhcps);
}
TEST_CASE("dhcp server start/stop on localhost", "[lwip]")
{
test_case_uses_tcpip();
struct netif *netif;
dhcps_t *dhcps;
struct dhcps_api {
EventGroupHandle_t event;
ip4_addr_t netmask;
ip4_addr_t ip;
err_t ret_start;
err_t ret_stop;
};
static void dhcps_test_net_classes_api(void* ctx)
{
struct netif *netif;
struct dhcps_api *api = ctx;
NETIF_FOREACH(netif) {
if (netif->name[0] == 'l' && netif->name[1] == 'o') {
@ -139,40 +146,49 @@ TEST_CASE("dhcp server start/stop on localhost", "[lwip]")
}
TEST_ASSERT_NOT_NULL(netif);
//Class A
dhcps = dhcps_new();
IP4_ADDR(&netmask, 255,0,0,0);
dhcps_set_option_info(dhcps, SUBNET_MASK, (void*)&netmask, sizeof(netmask));
ip4_addr_t a_ip = { .addr = 0x7f0001 };
IP4_ADDR(&netmask, 255,0,0,0);
TEST_ASSERT(dhcps_start(dhcps, netif, a_ip) == ERR_OK);
TEST_ASSERT(dhcps_stop(dhcps, netif) == ERR_OK);
dhcps_delete(dhcps);
//Class B
dhcps = dhcps_new();
IP4_ADDR(&netmask, 255,255,0,0);
dhcps_set_option_info(dhcps, SUBNET_MASK, (void*)&netmask, sizeof(netmask));
ip4_addr_t b_ip = { .addr = 0x1000080 };
TEST_ASSERT(dhcps_start(dhcps, netif, b_ip) == ERR_OK);
TEST_ASSERT(dhcps_stop(dhcps, netif) == ERR_OK);
dhcps_delete(dhcps);
//Class C
dhcps = dhcps_new();
IP4_ADDR(&netmask, 255,255,255,0);
dhcps_set_option_info(dhcps, SUBNET_MASK, (void*)&netmask, sizeof(netmask));
ip4_addr_t c_ip = { .addr = 0x101A8C0 };
TEST_ASSERT(dhcps_start(dhcps, netif, c_ip) == ERR_OK);
TEST_ASSERT(dhcps_stop(dhcps, netif) == ERR_OK);
dhcps_delete(dhcps);
// Class A: IP: 127.0.0.1, with inaccurate Mask: 255.248.255.0
// expect dhcps_start() to fail
dhcps = dhcps_new();
IP4_ADDR(&netmask, 255,248,255,0);
dhcps_set_option_info(dhcps, SUBNET_MASK, (void*)&netmask, sizeof(netmask));
TEST_ASSERT(dhcps_start(dhcps, netif, a_ip) == ERR_ARG);
TEST_ASSERT(dhcps_stop(dhcps, netif) == ERR_OK);
dhcps_t *dhcps = dhcps_new();
dhcps_set_option_info(dhcps, SUBNET_MASK, (void*)&api->netmask, sizeof(api->netmask));
api->ret_start = dhcps_start(dhcps, netif, api->ip);
api->ret_stop = dhcps_stop(dhcps, netif);
dhcps_delete(dhcps);
xEventGroupSetBits(api->event, 1);
}
static void dhcps_test_net_classes(uint32_t ip, uint32_t mask, bool pass)
{
struct dhcps_api api = {
.ret_start = ERR_IF,
.ret_stop = ERR_IF,
.ip = {.addr = PP_HTONL(ip)},
.netmask = {.addr = PP_HTONL(mask)},
.event = xEventGroupCreate()
};
tcpip_callback(dhcps_test_net_classes_api, &api);
xEventGroupWaitBits(api.event, 1, true, true, pdMS_TO_TICKS(5000));
vEventGroupDelete(api.event);
err_t ret_start_expected = pass ? ERR_OK : ERR_ARG;
TEST_ASSERT(api.ret_start == ret_start_expected);
TEST_ASSERT(api.ret_stop == ERR_OK);
}
TEST_CASE("dhcp server start/stop on localhost", "[lwip]")
{
test_case_uses_tcpip();
// Class A: IP: 127.0.0.1, Mask: 255.0.0.0
dhcps_test_net_classes(0x7f000001, 0xFF000000, true);
// Class B: IP: 128.1.1.1, Mask: 255.255.0.0
dhcps_test_net_classes(0x80010101, 0xFFFF0000, true);
// Class C: IP: 192.168.1.1, Mask: 255.255.255.0
dhcps_test_net_classes(0xC0A80101, 0xFFFFFF00, true);
// Class A: IP: 127.0.0.1, with inaccurate Mask: 255.248.255.0
// expect dhcps_start() to fail
dhcps_test_net_classes(0x7f000001, 0xFFF8FF00, false);
}

View File

@ -1,2 +1,4 @@
CONFIG_LWIP_TCPIP_CORE_LOCKING=n
CONFIG_LWIP_CHECK_THREAD_SAFETY=n
CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=n
CONFIG_FREERTOS_SMP=n

View File

@ -14,6 +14,11 @@ ESP-IDF supports the following lwIP TCP/IP stack functions:
Adapted APIs
^^^^^^^^^^^^
.. warning::
When using any lwIP API (other than `BSD Sockets API`_), please make sure that it is thread safe. To check if a given API call is safe, enable :ref:`CONFIG_LWIP_CHECK_THREAD_SAFETY` and run the application. This way lwIP asserts the TCP/IP core functionality to be correctly accessed; the execution aborts if it is not locked properly or accessed from the correct task (`lwIP FreeRTOS Task`_).
The general recommendation is to use :doc:`/api-reference/network/esp_netif` component to interact with lwIP.
Some common lwIP "app" APIs are supported indirectly by ESP-IDF:
- DHCP Server & Client are supported indirectly via the :doc:`/api-reference/network/esp_netif` functionality

View File

@ -41,9 +41,9 @@ The RTC timer has the following clock sources:
- ``Internal {IDF_TARGET_RTC_CLK_FRE} RC oscillator`` (default): Features the lowest Deep-sleep current consumption and no dependence on any external components. However, the frequency stability of this clock source is affected by temperature fluctuations, so time may drift in both Deep-sleep and Light-sleep modes.
:not esp32c2: - ``External 32 kHz crystal``: Requires a 32 kHz crystal to be connected to the {IDF_TARGET_EXT_CRYSTAL_PIN} pins. This source provides a better frequency stability at the expense of a slightly higher (by 1 μA) Deep-sleep current consumption.
- ``External 32 kHz oscillator at {IDF_TARGET_EXT_OSC_PIN} pin``: Allows using 32 kHz clock generated by an external circuit. The external clock signal must be connected to the {IDF_TARGET_EXT_OSC_PIN} pin. The amplitude should be less than 1.2 V for sine wave signal and less than 1 V for square wave signal. Common mode voltage should be in the range of 0.1 < Vcm < 0.5xVamp, where Vamp stands for signal amplitude. In this case, the {IDF_TARGET_EXT_OSC_PIN} pin cannot be used as a GPIO pin.
- ``Internal {IDF_TARGET_INT_OSC_FRE} oscillator, divided by 256 ({IDF_TARGET_INT_OSC_FRE_DIVIDED})``: Provides better frequency stability than the ``Internal {IDF_TARGET_RTC_CLK_FRE} RC oscillator`` at the expense of a higher (by 5 μA) Deep-sleep current consumption. It also does not require external components.
The choice depends on your requirements for system time accuracy and power consumption in sleep modes. To modify the RTC clock source, set :ref:`CONFIG_RTC_CLK_SRC` in project configuration.
@ -122,9 +122,9 @@ To start synchronization via SNTP, just call the following three functions:
.. code-block:: c
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, "pool.ntp.org");
sntp_init();
esp_sntp_setoperatingmode(ESP_SNTP_OPMODE_POLL);
esp_sntp_setservername(0, "pool.ntp.org");
esp_sntp_init();
An application with this initialization code will periodically synchronize the time. The time synchronization period is determined by :ref:`CONFIG_LWIP_SNTP_UPDATE_DELAY` (the default value is one hour). To modify the variable, set :ref:`CONFIG_LWIP_SNTP_UPDATE_DELAY` in project configuration.

View File

@ -122,9 +122,9 @@ lwIP SNTP 库提供了 API 函数,用于设置某个事件的回调函数。
.. code-block:: c
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, "pool.ntp.org");
sntp_init();
esp_sntp_setoperatingmode(ESP_SNTP_OPMODE_POLL);
esp_sntp_setservername(0, "pool.ntp.org");
esp_sntp_init();
添加此初始化代码后,应用程序将定期同步时间。时间同步周期由 :ref:`CONFIG_LWIP_SNTP_UPDATE_DELAY` 设置(默认为一小时)。如需修改,请在项目配置中设置 :ref:`CONFIG_LWIP_SNTP_UPDATE_DELAY`

View File

@ -17,7 +17,7 @@
#include "freertos/task.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "lwip/apps/sntp.h"
#include "esp_sntp.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "protocol_examples_common.h"
@ -90,8 +90,8 @@ static void set_time(void)
settimeofday(&tv, &tz);
/* Start SNTP service */
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_init();
esp_sntp_setoperatingmode(ESP_SNTP_OPMODE_POLL);
esp_sntp_init();
}
static void http2_task(void *args)

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -33,12 +33,12 @@ static const char *TAG = "time_sync";
void initialize_sntp(void)
{
ESP_LOGI(TAG, "Initializing SNTP");
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, "pool.ntp.org");
esp_sntp_setoperatingmode(ESP_SNTP_OPMODE_POLL);
esp_sntp_setservername(0, "pool.ntp.org");
#ifdef CONFIG_SNTP_TIME_SYNC_METHOD_SMOOTH
sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH);
#endif
sntp_init();
esp_sntp_init();
}
static void obtain_time(void)
@ -47,8 +47,8 @@ static void obtain_time(void)
* NTP server address could be aquired via DHCP,
* see LWIP_DHCP_GET_NTP_SRV menuconfig option
*/
#ifdef LWIP_DHCP_GET_NTP_SRV
sntp_servermode_dhcp(1);
#if LWIP_DHCP_GET_NTP_SRV
esp_sntp_servermode_dhcp(1);
#endif
// wait for time to be set
@ -89,7 +89,7 @@ void fetch_and_store_time_in_nvs(void *args)
}
nvs_close(my_handle);
sntp_stop();
esp_sntp_stop();
exit:
if (err != ESP_OK) {

View File

@ -19,3 +19,4 @@ CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
CONFIG_EXAMPLE_CONNECT_IPV6=y
CONFIG_LWIP_CHECK_THREAD_SAFETY=y

View File

@ -9,3 +9,5 @@ CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
CONFIG_EXAMPLE_CONNECT_IPV6=y
CONFIG_LWIP_TCPIP_CORE_LOCKING=y
CONFIG_LWIP_CHECK_THREAD_SAFETY=y

View File

@ -8,3 +8,4 @@ CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
CONFIG_EXAMPLE_CONNECT_IPV6=y
CONFIG_LWIP_CHECK_THREAD_SAFETY=y

View File

@ -9,3 +9,5 @@ CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
CONFIG_EXAMPLE_CONNECT_IPV6=y
CONFIG_LWIP_TCPIP_CORE_LOCKING=y
CONFIG_LWIP_CHECK_THREAD_SAFETY=y

View File

@ -135,8 +135,8 @@ static void obtain_time(void)
* NOTE: This call should be made BEFORE esp aquires IP address from DHCP,
* otherwise NTP option would be rejected by default.
*/
#ifdef LWIP_DHCP_GET_NTP_SRV
sntp_servermode_dhcp(1); // accept NTP offers from DHCP server, if any
#if LWIP_DHCP_GET_NTP_SRV
esp_sntp_servermode_dhcp(1); // accept NTP offers from DHCP server, if any
#endif
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
@ -165,7 +165,7 @@ static void obtain_time(void)
static void initialize_sntp(void)
{
ESP_LOGI(TAG, "Initializing SNTP");
sntp_setoperatingmode(SNTP_OPMODE_POLL);
esp_sntp_setoperatingmode(ESP_SNTP_OPMODE_POLL);
/*
* If 'NTP over DHCP' is enabled, we set dynamic pool address
@ -173,37 +173,37 @@ static void initialize_sntp(void)
* provided via NTP over DHCP is not accessible
*/
#if LWIP_DHCP_GET_NTP_SRV && SNTP_MAX_SERVERS > 1
sntp_setservername(1, "pool.ntp.org");
esp_sntp_setservername(1, "pool.ntp.org");
#if LWIP_IPV6 && SNTP_MAX_SERVERS > 2 // statically assigned IPv6 address is also possible
ip_addr_t ip6;
if (ipaddr_aton("2a01:3f7::1", &ip6)) { // ipv6 ntp source "ntp.netnod.se"
sntp_setserver(2, &ip6);
esp_sntp_setserver(2, &ip6);
}
#endif /* LWIP_IPV6 */
#else /* LWIP_DHCP_GET_NTP_SRV && (SNTP_MAX_SERVERS > 1) */
// otherwise, use DNS address from a pool
sntp_setservername(0, CONFIG_SNTP_TIME_SERVER);
esp_sntp_setservername(0, CONFIG_SNTP_TIME_SERVER);
sntp_setservername(1, "pool.ntp.org"); // set the secondary NTP server (will be used only if SNTP_MAX_SERVERS > 1)
esp_sntp_setservername(1, "pool.ntp.org"); // set the secondary NTP server (will be used only if SNTP_MAX_SERVERS > 1)
#endif
sntp_set_time_sync_notification_cb(time_sync_notification_cb);
#ifdef CONFIG_SNTP_TIME_SYNC_METHOD_SMOOTH
sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH);
#endif
sntp_init();
esp_sntp_init();
ESP_LOGI(TAG, "List of configured NTP servers:");
for (uint8_t i = 0; i < SNTP_MAX_SERVERS; ++i){
if (sntp_getservername(i)){
ESP_LOGI(TAG, "server %d: %s", i, sntp_getservername(i));
if (esp_sntp_getservername(i)){
ESP_LOGI(TAG, "server %d: %s", i, esp_sntp_getservername(i));
} else {
// we have either IPv4 or IPv6 address, let's print it
char buff[INET6_ADDRSTRLEN];
ip_addr_t const *ip = sntp_getserver(i);
ip_addr_t const *ip = esp_sntp_getserver(i);
if (ipaddr_ntoa_r(ip, buff, INET6_ADDRSTRLEN) != NULL)
ESP_LOGI(TAG, "server %d: %s", i, buff);
}

View File

@ -459,7 +459,6 @@ components/esp_local_ctrl/src/esp_local_ctrl_handler.c
components/esp_local_ctrl/src/esp_local_ctrl_priv.h
components/esp_local_ctrl/src/esp_local_ctrl_transport_ble.c
components/esp_netif/include/esp_netif_ppp.h
components/esp_netif/private_include/esp_netif_private.h
components/esp_netif/test/test_esp_netif.c
components/esp_netif/test_apps/component_ut_test.py
components/esp_netif/test_apps/main/esp_netif_test.c
@ -796,11 +795,9 @@ components/log/esp_log_private.h
components/log/host_test/log_test/main/log_test.cpp
components/log/log_linux.c
components/lwip/apps/ping/ping.c
components/lwip/apps/sntp/sntp.c
components/lwip/include/apps/dhcpserver/dhcpserver_options.h
components/lwip/include/apps/esp_ping.h
components/lwip/include/apps/ping/ping.h
components/lwip/include/apps/sntp/sntp.h
components/lwip/port/esp32/debug/lwip_debug.c
components/lwip/port/esp32/freertos/sys_arch.c
components/lwip/port/esp32/hooks/tcp_isn_default.c