From b89d8a7ab27a45068d2bbffb62006c7b899de04b Mon Sep 17 00:00:00 2001 From: yuanjm Date: Tue, 17 Dec 2019 10:31:03 +0800 Subject: [PATCH] feat(lwip): update lwip component from idf --- components/coap/port/coap_io_socket.c | 2 + .../coap/port/include/coap_config_posix.h | 2 +- components/esp8266/source/startup.c | 2 + components/esp_common/include/esp_task.h | 2 +- components/freertos/Kconfig | 4 + components/lwip/CMakeLists.txt | 30 +- components/lwip/Kconfig | 26 +- .../lwip/apps/multi-threads/sockets_mt.c | 826 ++++++++++++++++++ components/lwip/apps/ping/ping_sock.c | 22 +- components/lwip/component.mk | 20 +- components/lwip/include/apps/ping/ping_sock.h | 7 +- components/lwip/linker.lf | 85 +- components/lwip/port/esp32/netif/wlanif.c | 245 ------ .../{esp32 => esp8266}/debug/lwip_debug.c | 8 +- .../{esp32 => esp8266}/freertos/sys_arch.c | 0 .../port/{esp32 => esp8266}/include/arch/cc.h | 0 .../{esp32 => esp8266}/include/arch/perf.h | 0 .../include/arch/sys_arch.h | 0 .../include/arch/vfs_lwip.h | 0 .../{esp32 => esp8266}/include/arpa/inet.h | 0 .../include/debug/lwip_debug.h | 0 .../{esp32 => esp8266}/include/lwipopts.h | 46 +- .../port/{esp32 => esp8266}/include/netdb.h | 0 .../include/netif/dhcp_state.h | 0 .../include/netif/ethernetif.h | 0 .../include/netif/nettestif.h | 0 .../{esp32 => esp8266}/include/netif/wlanif.h | 18 - .../{esp32 => esp8266}/include/netinet/in.h | 0 .../{esp32 => esp8266}/include/sys/socket.h | 0 .../{esp32 => esp8266}/netif/dhcp_state.c | 1 + .../{esp32 => esp8266}/netif/ethernetif.c | 0 .../port/{esp32 => esp8266}/netif/nettestif.c | 0 components/lwip/port/esp8266/netif/wlanif.c | 629 +++++++++++++ .../lwip/port/{esp32 => esp8266}/vfs_lwip.c | 22 +- components/newlib/newlib/include/limits.h | 2 +- components/newlib/newlib/port/time.c | 112 +++ components/pthread/Kconfig | 1 + .../tcpip_adapter/include/tcpip_adapter.h | 18 +- components/tcpip_adapter/tcpip_adapter_lwip.c | 30 +- components/vfs/Kconfig | 6 +- components/vfs/include/esp_vfs.h | 17 + components/vfs/vfs.c | 77 ++ .../main/openssl_client_example_main.c | 14 +- .../main/openssl_demo_example_main.c | 14 +- .../main/udp_multicast_example_main.c | 25 +- 45 files changed, 1863 insertions(+), 450 deletions(-) create mode 100644 components/lwip/apps/multi-threads/sockets_mt.c delete mode 100644 components/lwip/port/esp32/netif/wlanif.c rename components/lwip/port/{esp32 => esp8266}/debug/lwip_debug.c (97%) rename components/lwip/port/{esp32 => esp8266}/freertos/sys_arch.c (100%) rename components/lwip/port/{esp32 => esp8266}/include/arch/cc.h (100%) rename components/lwip/port/{esp32 => esp8266}/include/arch/perf.h (100%) rename components/lwip/port/{esp32 => esp8266}/include/arch/sys_arch.h (100%) rename components/lwip/port/{esp32 => esp8266}/include/arch/vfs_lwip.h (100%) rename components/lwip/port/{esp32 => esp8266}/include/arpa/inet.h (100%) rename components/lwip/port/{esp32 => esp8266}/include/debug/lwip_debug.h (100%) rename components/lwip/port/{esp32 => esp8266}/include/lwipopts.h (94%) rename components/lwip/port/{esp32 => esp8266}/include/netdb.h (100%) rename components/lwip/port/{esp32 => esp8266}/include/netif/dhcp_state.h (100%) rename components/lwip/port/{esp32 => esp8266}/include/netif/ethernetif.h (100%) rename components/lwip/port/{esp32 => esp8266}/include/netif/nettestif.h (100%) rename components/lwip/port/{esp32 => esp8266}/include/netif/wlanif.h (66%) rename components/lwip/port/{esp32 => esp8266}/include/netinet/in.h (100%) rename components/lwip/port/{esp32 => esp8266}/include/sys/socket.h (100%) rename components/lwip/port/{esp32 => esp8266}/netif/dhcp_state.c (98%) rename components/lwip/port/{esp32 => esp8266}/netif/ethernetif.c (100%) rename components/lwip/port/{esp32 => esp8266}/netif/nettestif.c (100%) create mode 100644 components/lwip/port/esp8266/netif/wlanif.c rename components/lwip/port/{esp32 => esp8266}/vfs_lwip.c (74%) diff --git a/components/coap/port/coap_io_socket.c b/components/coap/port/coap_io_socket.c index 4c3f85b4..45f7fc60 100644 --- a/components/coap/port/coap_io_socket.c +++ b/components/coap/port/coap_io_socket.c @@ -217,6 +217,7 @@ coap_free_endpoint(coap_endpoint_t *ep) { /* define struct in6_pktinfo and struct in_pktinfo if not available FIXME: check with configure */ +#if 0 //update lwip and have conflict. Later will update COAP. struct in6_pktinfo { struct in6_addr ipi6_addr; /* src/dst IPv6 address */ unsigned int ipi6_ifindex; /* send/recv interface index */ @@ -228,6 +229,7 @@ struct in_pktinfo { struct in_addr ipi_addr; }; #endif +#endif #if defined(WITH_POSIX) && !defined(SOL_IP) /* Solaris expects level IPPROTO_IP for ancillary data. */ diff --git a/components/coap/port/include/coap_config_posix.h b/components/coap/port/include/coap_config_posix.h index a925b8d2..11101b71 100644 --- a/components/coap/port/include/coap_config_posix.h +++ b/components/coap/port/include/coap_config_posix.h @@ -26,7 +26,7 @@ #define HAVE_MALLOC #define HAVE_ARPA_INET_H -#define IP_PKTINFO IP_MULTICAST_IF +//#define IP_PKTINFO IP_MULTICAST_IF #define IPV6_PKTINFO IPV6_V6ONLY #define PACKAGE_NAME "libcoap-posix" diff --git a/components/esp8266/source/startup.c b/components/esp8266/source/startup.c index 8a444e73..e346a74a 100644 --- a/components/esp8266/source/startup.c +++ b/components/esp8266/source/startup.c @@ -49,6 +49,8 @@ extern int wifi_nvs_init(void); extern esp_err_t esp_pthread_init(void); extern void phy_get_bb_evm(void); extern void uart_div_modify(uint8_t uart_no, uint16_t DivLatchValue); +/*Only for calling esp_wifi_set_ps can compile successfully */ +uint32_t LwipTimOutLim = 0; static inline int should_load(uint32_t load_addr) { diff --git a/components/esp_common/include/esp_task.h b/components/esp_common/include/esp_task.h index 2178ffa7..1b793791 100644 --- a/components/esp_common/include/esp_task.h +++ b/components/esp_common/include/esp_task.h @@ -40,7 +40,7 @@ #define ESP_TASKD_EVENT_PRIO (ESP_TASK_PRIO_MAX - 5) #define ESP_TASKD_EVENT_STACK (CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE + TASK_EXTRA_STACK_SIZE) #define ESP_TASK_TCPIP_PRIO (ESP_TASK_PRIO_MAX - 7) -#define ESP_TASK_TCPIP_STACK (CONFIG_LWIP_TCPIP_TASK_STACK_SIZE + TASK_EXTRA_STACK_SIZE) +#define ESP_TASK_TCPIP_STACK (CONFIG_LWIP_TCPIP_TASK_STACK_SIZE) #define ESP_TASK_MAIN_PRIO (ESP_TASK_PRIO_MIN + 1) #define ESP_TASK_MAIN_STACK (CONFIG_ESP_MAIN_TASK_STACK_SIZE + TASK_EXTRA_STACK_SIZE) diff --git a/components/freertos/Kconfig b/components/freertos/Kconfig index 10ec69ac..64f35a88 100644 --- a/components/freertos/Kconfig +++ b/components/freertos/Kconfig @@ -16,6 +16,10 @@ config FREERTOS_ENABLE_REENT The configuration will enable newlib. +config FREERTOS_NO_AFFINITY + hex + default 0x7FFFFFFF + config FREERTOS_HZ int "Tick rate (Hz)" range 1 1000 diff --git a/components/lwip/CMakeLists.txt b/components/lwip/CMakeLists.txt index 7d346127..0a07b3b4 100644 --- a/components/lwip/CMakeLists.txt +++ b/components/lwip/CMakeLists.txt @@ -1,13 +1,15 @@ +idf_build_get_property(target IDF_TARGET) set(include_dirs include/apps include/apps/sntp lwip/src/include - port/esp32/include - port/esp32/include/arch + port/${target}/include + port/${target}/include/arch ) set(srcs "apps/dhcpserver/dhcpserver.c" + "apps/multi-threads/sockets_mt.c" "apps/ping/esp_ping.c" "apps/ping/ping.c" "apps/ping/ping_sock.c" @@ -85,12 +87,16 @@ set(srcs "lwip/src/netif/ppp/upap.c" "lwip/src/netif/ppp/utils.c" "lwip/src/netif/ppp/vj.c" - "port/esp32/vfs_lwip.c" - "port/esp32/debug/lwip_debug.c" - "port/esp32/freertos/sys_arch.c" - "port/esp32/netif/dhcp_state.c" - "port/esp32/netif/nettestif.c" - "port/esp32/netif/wlanif.c") + "port/${target}/vfs_lwip.c" + "port/${target}/debug/lwip_debug.c" + "port/${target}/freertos/sys_arch.c" + "port/${target}/netif/dhcp_state.c" + "port/${target}/netif/wlanif.c") + +if(CONFIG_IDF_TARGET_ESP32) + list(APPEND srcs + "port/${target}/netif/nettestif.c") +endif() if(CONFIG_LWIP_PPP_SUPPORT) list(APPEND srcs @@ -130,11 +136,15 @@ if(CONFIG_ETH_ENABLED) list(APPEND srcs "port/esp32/netif/ethernetif.c") endif() +if(CONFIG_LWIP_SOCKET_MULTITHREAD) + set(COMPONENT_OBJEXCLUDE lwip/src/api/sockets.c) +endif() + idf_component_register(SRCS "${srcs}" INCLUDE_DIRS "${include_dirs}" LDFRAGMENTS linker.lf - REQUIRES vfs esp_wifi - PRIV_REQUIRES ${priv_requires} esp_eth tcpip_adapter nvs_flash) + REQUIRES vfs + PRIV_REQUIRES ${priv_requires} tcpip_adapter nvs_flash) # lots of LWIP source files evaluate macros that check address of stack variables target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-address) diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index e1c3b70d..fdc46b61 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -124,6 +124,24 @@ menu "LWIP" help Enabling this option allows LWIP statistics + config LWIP_SOCKET_MULTITHREAD + bool "LWIP socket supports multithread" + default y + help + Enable the option can enable LWIP socket multithread and all + function will be thread safe. + + config SET_SOLINGER_DEFAULT + bool "set socket SO_LINGER default" + default y + depends on LWIP_SOCKET_MULTITHREAD + help + The function is only used by socket multi-thread. + + Enable this option can set the target socket to enable the "SO_LINGER" and config timeout to be "0" when it is created. + It means that if close the socket, all send queue will be dropped, so heap memory can be collected immediately, + but some packets which are waiting to be sent will lost. + config LWIP_ETHARP_TRUST_IP_MAC bool "Enable LWIP ARP trust" default n @@ -484,7 +502,7 @@ menu "LWIP" config LWIP_TCPIP_TASK_STACK_SIZE int "TCP/IP Task Stack Size" - default 3072 + default 2048 # for high log levels, tcpip_adapter API calls can end up # a few calls deep and logging there can trigger a stack overflow range 2048 65536 if LOG_DEFAULT_LEVEL < 4 @@ -593,6 +611,12 @@ menu "LWIP" endmenu # LWIP RAW API + config LWIP_IPV6 + bool "Enable IPv6" + default n + help + Enable IPV6 + menu "SNTP" config LWIP_DHCP_MAX_NTP_SERVERS diff --git a/components/lwip/apps/multi-threads/sockets_mt.c b/components/lwip/apps/multi-threads/sockets_mt.c new file mode 100644 index 00000000..c02a6645 --- /dev/null +++ b/components/lwip/apps/multi-threads/sockets_mt.c @@ -0,0 +1,826 @@ +// Copyright 2018-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. + +#include "lwip/opt.h" + +#ifdef SOCKETS_MT + +#define SOCKETS_MT_DISABLE_SHUTDOWN + +#include "lwip/priv/api_msg.h" + +/* disable all LWIP socket API when compiling LWIP raw socket */ + +#undef lwip_accept +#undef lwip_bind +#undef lwip_shutdown +#undef lwip_getpeername +#undef lwip_getsockname +#undef lwip_setsockopt +#undef lwip_getsockopt +#undef lwip_close +#undef lwip_connect +#undef lwip_listen +#undef lwip_recv +#undef lwip_recvfrom +#undef lwip_send +#undef lwip_sendmsg +#undef lwip_sendto +#undef lwip_socket +#undef lwip_select +#undef lwip_ioctlsocket + +#define lwip_accept lwip_accept_esp +#define lwip_bind lwip_bind_esp +#define lwip_shutdown lwip_shutdown_esp +#define lwip_getpeername lwip_getpeername_esp +#define lwip_getsockname lwip_getsockname_esp +#define lwip_setsockopt lwip_setsockopt_esp +#define lwip_getsockopt lwip_getsockopt_esp +#define lwip_close lwip_closesocket_esp +#define lwip_connect lwip_connect_esp +#define lwip_listen lwip_listen_esp +#define lwip_recv lwip_recv_esp +#define lwip_recvfrom lwip_recvfrom_esp +#define lwip_send lwip_send_esp +#define lwip_sendmsg lwip_sendmsg_esp +#define lwip_sendto lwip_sendto_esp +#define lwip_socket lwip_socket_esp +#define lwip_select lwip_select_esp +#define lwip_ioctlsocket lwip_ioctl_esp + +#undef lwip_read +#undef lwip_write +#undef lwip_writev +#undef lwip_close +#undef closesocket +#undef lwip_fcntl +#undef lwip_ioctl + +#define lwip_read lwip_read_esp +#define lwip_write lwip_write_esp +#define lwip_writev lwip_writev_esp +#define lwip_close lwip_close_esp +#define lwip_fcntl lwip_fcntl_esp +#define lwip_ioctl lwip_ioctl_esp + +#include "../../lwip/src/api/sockets.c" + +/* disable macros to enable LWIP function */ + +#undef lwip_accept +#undef lwip_bind +#undef lwip_shutdown +#undef lwip_getpeername +#undef lwip_getsockname +#undef lwip_setsockopt +#undef lwip_getsockopt +#undef lwip_close +#undef lwip_connect +#undef lwip_listen +#undef lwip_recv +#undef lwip_recvfrom +#undef lwip_send +#undef lwip_sendmsg +#undef lwip_sendto +#undef lwip_socket +#undef lwip_select +#undef lwip_ioctlsocket + +#undef lwip_read +#undef lwip_write +#undef lwip_writev +#undef lwip_close +#undef closesocket +#undef lwip_fcntl +#undef lwip_ioctl + +/********************************************************************/ +#define LWIP_SYNC_MT_SLEEP_MS 10 + +#define SOCK_MT_DEBUG_LEVEL 255 + +typedef struct socket_conn_sync { + struct tcpip_api_call_data call; + struct netconn *conn; +} socket_conn_sync_t; + +typedef int (*lwip_io_mt_fn)(int, int ); + +/* Use about 2 bit */ +#define SOCK_MT_STATE_SOCK 0 +#define SOCK_MT_STATE_ACCEPT 1 +#define SOCK_MT_STATE_CONNECT 2 +#define SOCK_MT_STATE_SEND 3 +#define SOCK_MT_STATE_ILL 4 + +#define SOCK_MT_LOCK_SEND (1 << 0) +#define SOCK_MT_LOCK_RECV (1 << 1) +#define SOCK_MT_LOCK_IOCTL (1 << 2) + +#define SOCK_MT_LOCK_MIN SOCK_MT_LOCK_SEND +#define SOCK_MT_LOCK_MAX SOCK_MT_LOCK_IOCTL + +#define SOCK_MT_SELECT_RECV (1 << 0) +#define SOCK_MT_SELECT_SEND (1 << 1) + +typedef struct _sock_mt { + uint8_t opened : 1; + uint8_t state : 2; + uint8_t select : 2; + uint8_t lock : 3; +} sock_mt_t; + +#if (SOCK_MT_DEBUG_LEVEL < 16) +#define SOCK_MT_DEBUG(level, ...) \ + if (level >= SOCK_MT_DEBUG_LEVEL) \ + printf(__VA_ARGS__); +#else +#define SOCK_MT_DEBUG(level, ...) +#endif + +#define SOCK_MT_ENTER_CHECK(s, l, st) \ +{ \ + if (_sock_lock(s, l) != ERR_OK) \ + return -1; \ + if (st != SOCK_MT_STATE_ILL) \ + _sock_set_state(s, st); \ +} + +#define SOCK_MT_EXIT_CHECK(s, l, st) \ +{ \ + if (st != SOCK_MT_STATE_ILL) \ + _sock_set_state(s, SOCK_MT_STATE_SOCK); \ + if (_sock_unlock(s, l) != ERR_OK) \ + return -1; \ +} + +static volatile sock_mt_t DRAM_ATTR sockets_mt[NUM_SOCKETS]; + +static inline void _sock_mt_init(int s) +{ + memset((void *)&sockets_mt[s - LWIP_SOCKET_OFFSET], 0, sizeof(sock_mt_t)); +} + +static inline int _sock_is_opened(int s) +{ + return sockets_mt[s - LWIP_SOCKET_OFFSET].opened != 0; +} + +static inline void _sock_set_open(int s, int opened) +{ + SYS_ARCH_DECL_PROTECT(lev); + + SYS_ARCH_PROTECT(lev); + sockets_mt[s - LWIP_SOCKET_OFFSET].opened = opened; + SYS_ARCH_UNPROTECT(lev); +} + +static inline void _sock_set_state(int s, int state) +{ + SYS_ARCH_DECL_PROTECT(lev); + + SYS_ARCH_PROTECT(lev); + sockets_mt[s - LWIP_SOCKET_OFFSET].state = state; + SYS_ARCH_UNPROTECT(lev); +} + +static inline int _sock_get_state(int s) +{ + return sockets_mt[s - LWIP_SOCKET_OFFSET].state; +} + +static inline int _sock_get_select(int s, int select) +{ + return sockets_mt[s - LWIP_SOCKET_OFFSET].select & select; +} + +static int inline _sock_is_lock(int s, int l) +{ + return sockets_mt[s - LWIP_SOCKET_OFFSET].lock & l; +} + +static int inline _sock_next_lock(int lock) +{ + return lock << 1; +} + +static void inline _sock_set_select(int s, int select) +{ + SYS_ARCH_DECL_PROTECT(lev); + + SYS_ARCH_PROTECT(lev); + sockets_mt[s - LWIP_SOCKET_OFFSET].select |= select; + SYS_ARCH_UNPROTECT(lev); +} + +static void inline _sock_reset_select(int s, int select) +{ + SYS_ARCH_DECL_PROTECT(lev); + + SYS_ARCH_PROTECT(lev); + sockets_mt[s - LWIP_SOCKET_OFFSET].select &= ~select; + SYS_ARCH_UNPROTECT(lev); +} + +static int _sock_try_lock(int s, int l) +{ + int ret = ERR_OK; + SYS_ARCH_DECL_PROTECT(lev); + + if (!_sock_is_opened(s)) { + ret = ERR_CLSD; + goto exit; + } + + if (sockets_mt[s - LWIP_SOCKET_OFFSET].lock & l) { + ret = ERR_INPROGRESS; + goto exit; + } + + SYS_ARCH_PROTECT(lev); + sockets_mt[s - LWIP_SOCKET_OFFSET].lock |= l; + SYS_ARCH_UNPROTECT(lev); + +exit: + return ret; +} + +static int _sock_lock(int s, int l) +{ + int ret = ERR_OK; + if (tryget_socket_unconn_nouse(s) == NULL) + return -1; + + SOCK_MT_DEBUG(1, "s %d l %d enter ", s, l); + + while (1) { + ret = _sock_try_lock(s, l); + + if (ret != ERR_INPROGRESS) + break; + + vTaskDelay(1); + } + + SOCK_MT_DEBUG(1, "OK %d\n", ret); + + return ret; +} + +static int _sock_unlock(int s, int l) +{ + int ret = 0; + SYS_ARCH_DECL_PROTECT(lev); + + SOCK_MT_DEBUG(1, "s %d l %d exit ", s, l); + + SYS_ARCH_PROTECT(lev); + sockets_mt[s - LWIP_SOCKET_OFFSET].lock &= ~l; + SYS_ARCH_UNPROTECT(lev); + + if (!_sock_is_opened(s)) { + ret = ERR_CLSD; + goto exit; + } + +exit: + SOCK_MT_DEBUG(1, "OK %d\n", ret); + + return ret; +} + +static int lwip_enter_mt_select(int s, fd_set *read_set, fd_set *write_set) +{ + int i; + + if (s > NUM_SOCKETS + LWIP_SOCKET_OFFSET || s < LWIP_SOCKET_OFFSET) + return -1; + + for (i = 0; i < s; i++) { + if(FD_ISSET(i, read_set) || FD_ISSET(i, write_set)) + if (tryget_socket_unconn_nouse(i) == NULL) + goto failed1; + + if (FD_ISSET(i, read_set)) { + err_t err; + + _sock_set_select(i, SOCK_MT_SELECT_RECV); + err = _sock_lock(i, SOCK_MT_LOCK_RECV); + if (err != ERR_OK) { + goto failed2; + } + } + + if (FD_ISSET(i, write_set)) { + err_t err; + + _sock_set_select(i, SOCK_MT_SELECT_SEND); + err = _sock_lock(i, SOCK_MT_LOCK_SEND); + if (err != ERR_OK) { + goto failed3; + } + } + } + + return 0; + +failed3: + _sock_unlock(i, SOCK_MT_LOCK_SEND); + _sock_reset_select(i, SOCK_MT_SELECT_SEND); +failed2: + if (FD_ISSET(i, read_set)) { + _sock_unlock(i, SOCK_MT_LOCK_RECV); + _sock_reset_select(i, SOCK_MT_SELECT_RECV); + } +failed1: + for (i--; i >=0; i--) { + if (FD_ISSET(i, read_set) ) { + _sock_unlock(i, SOCK_MT_LOCK_RECV); + _sock_reset_select(i, SOCK_MT_SELECT_RECV); + } + + if (FD_ISSET(i, write_set)) { + _sock_unlock(i, SOCK_MT_LOCK_SEND); + _sock_reset_select(i, SOCK_MT_SELECT_SEND); + } + } + + return -1; +} + +static void lwip_exit_mt_select(int s, fd_set *read_set, fd_set *write_set) +{ + int i; + + for (i = 0; i < s; i++) { + if (FD_ISSET(i, read_set)) { + _sock_unlock(i, SOCK_MT_LOCK_RECV); + _sock_reset_select(i, SOCK_MT_SELECT_RECV); + } + + if (FD_ISSET(i, write_set)) { + _sock_unlock(i, SOCK_MT_LOCK_SEND); + _sock_reset_select(i, SOCK_MT_SELECT_SEND); + } + } +} + +static err_t lwip_do_sync_accept(struct tcpip_api_call_data *call) +{ + socket_conn_sync_t *sync = (socket_conn_sync_t *)call; + struct netconn *conn = sync->conn; + + SYS_ARCH_DECL_PROTECT(lev); + SYS_ARCH_PROTECT(lev); + if (sys_mbox_valid(&conn->acceptmbox)) + sys_mbox_trypost(&conn->acceptmbox, NULL); + conn->state = NETCONN_NONE; + SYS_ARCH_UNPROTECT(lev); + + return ERR_OK; +} + +static err_t lwip_do_sync_send(struct tcpip_api_call_data *call) +{ + socket_conn_sync_t *sync = (socket_conn_sync_t *)call; + struct netconn *conn = sync->conn; + + SYS_ARCH_DECL_PROTECT(lev); + SYS_ARCH_PROTECT(lev); + if (conn->current_msg) { + conn->current_msg->err = ERR_OK; + if (sys_sem_valid(conn->current_msg->op_completed_sem)) + sys_sem_signal(conn->current_msg->op_completed_sem); + conn->current_msg = NULL; + } + conn->state = NETCONN_NONE; + SYS_ARCH_UNPROTECT(lev); + + return ERR_OK; +} + +static err_t lwip_do_sync_recv_state(struct tcpip_api_call_data *call) +{ + socket_conn_sync_t *sync = (socket_conn_sync_t *)call; + struct netconn *conn = sync->conn; + + SYS_ARCH_DECL_PROTECT(lev); + SYS_ARCH_PROTECT(lev); + SOCK_MT_DEBUG(1, "sync recv %d\n", conn->socket); + if (sys_mbox_valid(&conn->recvmbox)) + sys_mbox_trypost(&conn->recvmbox, NULL); + conn->state = NETCONN_NONE; + SYS_ARCH_UNPROTECT(lev); + + return ERR_OK; +} + +static err_t lwip_do_sync_select_state(struct tcpip_api_call_data *call) +{ + socket_conn_sync_t *sync = (socket_conn_sync_t *)call; + struct netconn *conn = sync->conn; + + SYS_ARCH_DECL_PROTECT(lev); + SYS_ARCH_PROTECT(lev); + event_callback(conn, NETCONN_EVT_ERROR, 0); + conn->state = NETCONN_NONE; + SYS_ARCH_UNPROTECT(lev); + + return ERR_OK; +} + +static void lwip_sync_state_mt(int s) +{ + struct lwip_sock *sock = tryget_socket_unconn_nouse(s); + int state = _sock_get_state(s); + socket_conn_sync_t sync = { + .conn = sock->conn, + }; + + SOCK_MT_DEBUG(1, "sync state %d\n", state); + + switch (state) { + case SOCK_MT_STATE_ACCEPT : + tcpip_api_call(lwip_do_sync_accept, &sync.call); + break; + case SOCK_MT_STATE_CONNECT: + case SOCK_MT_STATE_SEND : + tcpip_api_call(lwip_do_sync_send, &sync.call); + break; + default : + break; + } +} + +static void lwip_sync_recv_mt(int s) +{ + struct lwip_sock *sock = tryget_socket_unconn_nouse(s); + socket_conn_sync_t sync = { + .conn = sock->conn, + }; + + tcpip_api_call(lwip_do_sync_recv_state, &sync.call); +} + +static void lwip_sync_select_mt(int s) +{ + struct lwip_sock *sock = tryget_socket_unconn_nouse(s); + socket_conn_sync_t sync = { + .conn = sock->conn, + }; + + tcpip_api_call(lwip_do_sync_select_state, &sync.call); +} + +static void lwip_sync_mt(int s, int how) +{ + int lock = SOCK_MT_LOCK_MIN; + + do { + if (_sock_is_lock(s, lock)) { + int need_wait = 0; + + if (!_sock_get_select(s, SOCK_MT_SELECT_RECV | SOCK_MT_SELECT_SEND)) { + switch (lock) { + case SOCK_MT_LOCK_SEND: + lwip_sync_state_mt(s); + need_wait = 1; + break; + case SOCK_MT_LOCK_RECV: + lwip_sync_recv_mt(s); + need_wait = 1; + break; + default : + break; + } + } else { + lwip_sync_select_mt(s); + need_wait = 1; + } + + if (need_wait) + sys_delay_ms(LWIP_SYNC_MT_SLEEP_MS); + } else + lock = _sock_next_lock(lock); + } while (lock < SOCK_MT_LOCK_MAX); +} + +#if SET_SOLINGER_DEFAULT +#if LWIP_SO_LINGER +static void lwip_socket_set_so_link(int s, int linger) +{ + struct lwip_sock *sock = tryget_socket_unconn_nouse(s); + + if (sock) { + /* + * linker: + * -1: nothing + * 0: free sent_buf immediately + */ + sock->conn->linger = linger; + } +} +#else +#error "LWIP_SO_LINGER must be enable" +#endif /* LWIP_SO_LINGER */ +#else /* SET_SOLINGER_DEFAULT */ +#define lwip_socket_set_so_link(_s, _linger) +#endif /* SET_SOLINGER_DEFAULT */ + +int lwip_socket(int domain, int type, int protocol) +{ + int s; + + s = lwip_socket_esp(domain, type, protocol); + if (s < 0) + return -1; + + lwip_socket_set_so_link(s, 0); + _sock_mt_init(s); + _sock_set_open(s, 1); + + return s; +} + +int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen) +{ + int ret; + + SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_ILL); + + ret = lwip_bind_esp(s, name, namelen); + + SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_ILL); + + return ret; +} + +int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + int ret; + + SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_CONNECT); + + ret = lwip_connect_esp(s, name, namelen); + + SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_CONNECT); + + return ret; +} + +int lwip_listen(int s, int backlog) +{ + int ret; + + SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_ILL); + + lwip_socket_set_so_link(s, -1); + + ret = lwip_listen_esp(s, backlog); + + SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_ILL); + + return ret; +} + +int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + int ret; + + SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_ACCEPT) + + lwip_socket_set_so_link(s, -1); + + ret = lwip_accept_esp(s, addr, addrlen); + + SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_ACCEPT); + + if (ret < 0) + return -1; + + lwip_socket_set_so_link(ret, 0); + _sock_mt_init(ret); + _sock_set_open(ret, 1); + + return ret; +} + +int lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen) +{ + int ret; + + SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); + + ret = lwip_getpeername_esp(s, name, namelen); + + SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); + + return ret; +} + +int lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen) +{ + int ret; + + SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); + + ret = lwip_getsockname_esp(s, name, namelen); + + SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); + + return ret; +} + +int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + int ret; + + SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); + + ret = lwip_setsockopt_esp(s, level, optname, optval, optlen); + + SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); + + return ret; +} + +int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + int ret; + + if (tryget_socket_unconn_nouse(s) == NULL) + return -1; + + if (optname == SO_ERROR) { + int retval = 0; + + if (!_sock_is_opened(s)) + retval = ENOTCONN; + + if (retval) { + *(int *)optval = retval; + return 0; + } + } + + SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); + + ret = lwip_getsockopt_esp(s, level, optname, optval, optlen); + + SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); + + return ret; +} + +int lwip_ioctl(int s, long cmd, void *argp) +{ + int ret; + + SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL) + + ret = lwip_ioctl_esp(s, cmd, argp); + + SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); + + return ret; +} + +int lwip_sendto(int s, const void *data, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + int ret; + + SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_SEND); + + ret = lwip_sendto_esp(s, data, size, flags, to, tolen); + + SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_SEND); + + return ret; +} + +int lwip_send(int s, const void *data, size_t size, int flags) +{ + int ret; + + SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_SEND); + + ret = lwip_send_esp(s, data, size, flags); + + SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_SEND, SOCK_MT_STATE_SEND); + + return ret; +} + +int lwip_recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + int ret; + + SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_RECV, SOCK_MT_STATE_ILL); + + ret = lwip_recvfrom_esp(s, mem, len, flags, from, fromlen); + + SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_RECV, SOCK_MT_STATE_ILL); + + return ret; +} + +int lwip_recv(int s, void *mem, size_t len, int flags) +{ + return lwip_recvfrom(s, mem, len, flags, NULL, NULL); +} + +int lwip_read(int s, void *mem, size_t len) +{ + return lwip_recvfrom(s, mem, len, 0, NULL, NULL); +} + +int lwip_write(int s, const void *data, size_t size) +{ + return lwip_send(s, data, size, 0); +} + +int lwip_fcntl(int s, int cmd, int val) +{ + int ret; + + SOCK_MT_ENTER_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); + + ret = lwip_fcntl_esp(s, cmd, val); + + SOCK_MT_EXIT_CHECK(s, SOCK_MT_LOCK_IOCTL, SOCK_MT_STATE_ILL); + + return ret; +} + +int lwip_shutdown(int s, int how) +{ + return 0; +} + +int lwip_close(int s) +{ + int ret; + SYS_ARCH_DECL_PROTECT(lev); + + if (tryget_socket_unconn_nouse(s) == NULL) + return -1; + + SYS_ARCH_PROTECT(lev); + if (_sock_is_opened(s)) { + _sock_set_open(s, 0); + SYS_ARCH_UNPROTECT(lev); + } else { + SYS_ARCH_UNPROTECT(lev); + return -1; + } + + + lwip_sync_mt(s, SHUT_RDWR); + + ret = lwip_close_esp(s); + + return ret; +} + +int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, + fd_set *exceptset, struct timeval *timeout) +{ + int ret; + fd_set read_set, write_set; + + if (readset) + MEMCPY(&read_set, readset, sizeof(fd_set)); + else + FD_ZERO(&read_set); + + if (writeset) + MEMCPY(&write_set, writeset, sizeof(fd_set)); + else + FD_ZERO(&write_set); + + ret = lwip_enter_mt_select(maxfdp1, &read_set, &write_set); + if (ret) + return ret; + + ret = lwip_select_esp(maxfdp1, readset, writeset, exceptset, timeout); + + lwip_exit_mt_select(maxfdp1, &read_set, &write_set); + + return ret; +} + +#endif diff --git a/components/lwip/apps/ping/ping_sock.c b/components/lwip/apps/ping/ping_sock.c index 3982d2f1..8450a11a 100644 --- a/components/lwip/apps/ping/ping_sock.c +++ b/components/lwip/apps/ping/ping_sock.c @@ -112,13 +112,15 @@ static int esp_ping_receive(esp_ping_t *ep) struct sockaddr_in *from4 = (struct sockaddr_in *)&from; inet_addr_to_ip4addr(ip_2_ip4(&ep->recv_addr), &from4->sin_addr); IP_SET_TYPE_VAL(ep->recv_addr, IPADDR_TYPE_V4); - } else { + } +#if LWIP_IPV6 + else { // IPv6 struct sockaddr_in6 *from6 = (struct sockaddr_in6 *)&from; inet6_addr_to_ip6addr(ip_2_ip6(&ep->recv_addr), &from6->sin6_addr); IP_SET_TYPE_VAL(ep->recv_addr, IPADDR_TYPE_V6); } - +#endif // Currently we only process IPv4 if (IP_IS_V4_VAL(ep->recv_addr)) { struct ip_hdr *iphdr = (struct ip_hdr *)buf; @@ -236,12 +238,18 @@ esp_err_t esp_ping_new_session(const esp_ping_config_t *config, const esp_ping_c d[i] = 'A' + i; } - /* create socket */ - if (IP_IS_V4(&config->target_addr) || ip6_addr_isipv4mappedipv6(ip_2_ip6(&config->target_addr))) { +#if LWIP_IPV4 && LWIP_IPV6 + if (IP_IS_V4(&config->target_addr) || ip6_addr_isipv4mappedipv6(ip_2_ip6(&config->target_addr))) { + ep->sock = socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP); + } else { + ep->sock = socket(AF_INET6, SOCK_RAW, IP6_NEXTH_ICMP6); + } +#else + if (IP_IS_V4(&config->target_addr)) { ep->sock = socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP); - } else { - ep->sock = socket(AF_INET6, SOCK_RAW, IP6_NEXTH_ICMP6); } +#endif + PING_CHECK(ep->sock > 0, "create socket failed: %d", err, ESP_FAIL, ep->sock); struct timeval timeout; @@ -259,11 +267,13 @@ esp_err_t esp_ping_new_session(const esp_ping_config_t *config, const esp_ping_c to4->sin_family = AF_INET; inet_addr_from_ip4addr(&to4->sin_addr, ip_2_ip4(&config->target_addr)); } +#if LWIP_IPV6 if (IP_IS_V6(&config->target_addr)) { struct sockaddr_in6 *to6 = (struct sockaddr_in6 *)&ep->target_addr; to6->sin6_family = AF_INET6; inet6_addr_from_ip6addr(&to6->sin6_addr, ip_2_ip6(&config->target_addr)); } +#endif /* return ping handle to user */ *hdl_out = (esp_ping_handle_t)ep; return ESP_OK; diff --git a/components/lwip/component.mk b/components/lwip/component.mk index 46076d7a..2490bf45 100644 --- a/components/lwip/component.mk +++ b/components/lwip/component.mk @@ -7,8 +7,8 @@ COMPONENT_ADD_INCLUDEDIRS := \ include/apps \ include/apps/sntp \ lwip/src/include \ - port/esp32/include \ - port/esp32/include/arch + port/esp8266/include \ + port/esp8266/include/arch COMPONENT_SRCDIRS := \ apps/dhcpserver \ @@ -21,15 +21,21 @@ COMPONENT_SRCDIRS := \ lwip/src/core/ipv4 \ lwip/src/core/ipv6 \ lwip/src/netif \ - port/esp32 \ - port/esp32/freertos \ - port/esp32/netif \ - port/esp32/debug + port/esp8266 \ + port/esp8266/freertos \ + port/esp8266/netif \ + port/esp8266/debug ifndef CONFIG_IDF_TARGET_ESP32 - COMPONENT_OBJEXCLUDE := port/esp32/netif/ethernetif.o + COMPONENT_OBJEXCLUDE := port/esp8266/netif/ethernetif.o endif +ifdef CONFIG_LWIP_SOCKET_MULTITHREAD + COMPONENT_SRCDIRS += apps/multi-threads + COMPONENT_OBJEXCLUDE += lwip/src/api/sockets.o +endif + + ifdef CONFIG_LWIP_PPP_SUPPORT COMPONENT_SRCDIRS += lwip/src/netif/ppp lwip/src/netif/ppp/polarssl endif diff --git a/components/lwip/include/apps/ping/ping_sock.h b/components/lwip/include/apps/ping/ping_sock.h index ef1189e8..0c448030 100644 --- a/components/lwip/include/apps/ping/ping_sock.h +++ b/components/lwip/include/apps/ping/ping_sock.h @@ -77,6 +77,11 @@ typedef struct { * @brief Default ping configuration * */ +#if LWIP_IPV4 && LWIP_IPV6 +#define PING_TARGET_ADDR ip_addr_any_type +#else +#define PING_TARGET_ADDR ip_addr_any +#endif #define ESP_PING_DEFAULT_CONFIG() \ { \ .count = 5, \ @@ -84,7 +89,7 @@ typedef struct { .timeout_ms = 1000, \ .data_size = 56, \ .tos = 0, \ - .target_addr = ip_addr_any_type, \ + .target_addr = PING_TARGET_ADDR, \ .task_stack_size = 2048, \ .task_prio = 2, \ } diff --git a/components/lwip/linker.lf b/components/lwip/linker.lf index ec48930e..0cb0c919 100644 --- a/components/lwip/linker.lf +++ b/components/lwip/linker.lf @@ -1,87 +1,4 @@ [mapping:lwip] archive: liblwip.a entries: - if LWIP_IRAM_OPTIMIZATION = y: - sockets:get_socket (noflash_text) - sockets:tryget_socket (noflash_text) - sockets:tryget_socket_unconn (noflash_text) - sockets:sock_inc_used (noflash_text) - sockets:tryget_socket_unconn_nouse (noflash_text) - sockets:tryget_socket_unconn_locked (noflash_text) - sockets:done_socket (noflash_text) - sockets:lwip_recvfrom (noflash_text) - sockets:lwip_recv_tcp (noflash_text) - sockets:lwip_recv_tcp_from (noflash_text) - sockets:lwip_recvfrom_udp_raw (noflash_text) - sockets:lwip_send (noflash_text) - sockets:lwip_sendto (noflash_text) - sockets:event_callback (noflash_text) - sockets:lwip_select (noflash_text) - sockets:select_check_waiters (noflash_text) - api_lib:netconn_apimsg (noflash_text) - api_lib:netconn_recv_data (noflash_text) - api_lib:netconn_tcp_recvd_msg (noflash_text) - api_lib:netconn_tcp_recvd (noflash_text) - api_lib:netconn_recv_data_tcp (noflash_text) - api_lib:netconn_recv_tcp_pbuf_flags (noflash_text) - api_lib:netconn_recv_udp_raw_netbuf_flags (noflash_text) - api_lib:netconn_recv (noflash_text) - api_lib:netconn_sendto (noflash_text) - api_lib:netconn_send (noflash_text) - api_lib:netconn_write_partly (noflash_text) - api_lib:netconn_write_vectors_partly (noflash_text) - api_msg:lwip_netconn_do_send (noflash_text) - api_msg:lwip_netconn_do_write (noflash_text) - netbuf:netbuf_alloc (noflash_text) - netbuf:netbuf_free (noflash_text) - tcpip:tcpip_thread (noflash_text) - tcpip:tcpip_thread_handle_msg (noflash_text) - tcpip:tcpip_inpkt (noflash_text) - tcpip:tcpip_input (noflash_text) - tcpip:tcpip_callback (noflash_text) - tcpip:tcpip_try_callback (noflash_text) - tcpip:tcpip_send_msg_wait_sem (noflash_text) - inet_chksum:inet_cksum_pseudo_base (noflash_text) - inet_chksum:inet_chksum_pseudo (noflash_text) - etharp:etharp_output_to_arp_index (noflash_text) - etharp:etharp_output (noflash_text) - ip4_addr:ip4_addr_isbroadcast_u32 (noflash_text) - ip4:ip4_route_src_hook (noflash_text) - ip4:ip4_route_src (noflash_text) - ip4:ip4_route (noflash_text) - ip4:ip4_input (noflash_text) - ip4:ip4_output_if (noflash_text) - ip4:ip4_output_if_opt (noflash_text) - ip4:ip4_output_if_src (noflash_text) - ip4:ip4_output_if_opt_src (noflash_text) - ip4:ip4_output (noflash_text) - pbuf:pbuf_alloc (noflash_text) - pbuf:pbuf_add_header_impl (noflash_text) - pbuf:pbuf_add_header (noflash_text) - pbuf:pbuf_remove_header (noflash_text) - pbuf:pbuf_header_impl (noflash_text) - pbuf:pbuf_header (noflash_text) - pbuf:pbuf_free (noflash_text) - timeouts:sys_timeouts_mbox_fetch (noflash_text) - udp:udp_input_local_match (noflash_text) - udp:udp_input (noflash_text) - udp:udp_send (noflash_text) - udp:udp_sendto (noflash_text) - udp:udp_sendto_if (noflash_text) - udp:udp_sendto_if_src (noflash_text) - ethernet:ethernet_input (noflash_text) - ethernet:ethernet_output (noflash_text) - sys_arch:sys_mutex_lock (noflash_text) - sys_arch:sys_mutex_unlock (noflash_text) - sys_arch:sys_sem_signal (noflash_text) - sys_arch:sys_arch_sem_wait (noflash_text) - sys_arch:sys_mbox_post (noflash_text) - sys_arch:sys_mbox_trypost (noflash_text) - sys_arch:sys_arch_mbox_fetch (noflash_text) - ethernetif:ethernet_low_level_output (noflash_text) - ethernetif:ethernetif_input (noflash_text) - wlanif:low_level_output (noflash_text) - wlanif:wlanif_input (noflash_text) - else: - - * (default) + * (iram_bss) diff --git a/components/lwip/port/esp32/netif/wlanif.c b/components/lwip/port/esp32/netif/wlanif.c deleted file mode 100644 index 11e1fc85..00000000 --- a/components/lwip/port/esp32/netif/wlanif.c +++ /dev/null @@ -1,245 +0,0 @@ -/** - * @file - * Ethernet Interface Skeleton - * - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/opt.h" - -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/ethip6.h" -#include "netif/etharp.h" -#include "netif/wlanif.h" - -#include -#include - -#include "tcpip_adapter.h" - - -/** - * In this function, the hardware should be initialized. - * Called from ethernetif_init(). - * - * @param netif the already initialized lwip network interface structure - * for this ethernetif - */ -static void -low_level_init(struct netif *netif) -{ - /* set MAC hardware address length */ - netif->hwaddr_len = ETHARP_HWADDR_LEN; - - /* set MAC hardware address */ - - /* maximum transfer unit */ - netif->mtu = 1500; - - /* device capabilities */ - /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; - -#if ESP_LWIP -#if LWIP_IGMP - netif->flags |= NETIF_FLAG_IGMP; -#endif -#endif - -#if !ESP_L2_TO_L3_COPY - netif->l2_buffer_free_notify = esp_wifi_internal_free_rx_buffer; -#endif -} - -/** - * This function should do the actual transmission of the packet. The packet is - * contained in the pbuf that is passed to the function. This pbuf - * might be chained. - * - * @param netif the lwip network interface structure for this ethernetif - * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) - * @return ERR_OK if the packet could be sent - * an err_t value if the packet couldn't be sent - * - * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to - * strange results. You might consider waiting for space in the DMA queue - * to become availale since the stack doesn't retry to send a packet - * dropped because of memory failure (except for the TCP timers). - */ -static err_t ESP_IRAM_ATTR -low_level_output(struct netif *netif, struct pbuf *p) -{ - wifi_interface_t wifi_if = tcpip_adapter_get_esp_if(netif); - struct pbuf *q = p; - err_t ret; - - if (wifi_if >= ESP_IF_MAX) { - return ERR_IF; - } - - if(q->next == NULL) { - ret = esp_wifi_internal_tx(wifi_if, 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) { - q->l2_owner = NULL; - pbuf_copy(q, p); - } else { - return ERR_MEM; - } - ret = esp_wifi_internal_tx(wifi_if, q->payload, q->len); - pbuf_free(q); - } - - return ret; -} - -/** - * This function should be called when a packet is ready to be read - * from the interface. It uses the function low_level_input() that - * should handle the actual reception of bytes from the network - * interface. Then the type of the received packet is determined and - * the appropriate input function is called. - * - * @param netif the lwip network interface structure for this ethernetif - */ -void ESP_IRAM_ATTR -wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb) -{ - struct pbuf *p; - - if(!buffer || !netif_is_up(netif)) { - if (eb) { - esp_wifi_internal_free_rx_buffer(eb); - } - return; - } - -#if (ESP_L2_TO_L3_COPY == 1) - p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM); - if (p == NULL) { - esp_wifi_internal_free_rx_buffer(eb); - return; - } - p->l2_owner = NULL; - memcpy(p->payload, buffer, len); - esp_wifi_internal_free_rx_buffer(eb); -#else - p = pbuf_alloc(PBUF_RAW, len, PBUF_REF); - if (p == NULL){ - esp_wifi_internal_free_rx_buffer(eb); - return; - } - p->payload = buffer; - p->l2_owner = netif; - p->l2_buf = eb; -#endif - - /* full packet send to tcpip_thread to process */ - if (netif->input(p, netif) != ERR_OK) { - LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); - pbuf_free(p); - } - -} - -/** - * Should be called at the beginning of the program to set up the - * network interface. It calls the function low_level_init() to do the - * actual setup of the hardware. - * - * This function should be passed as a parameter to netif_add(). - * - * @param netif the lwip network interface structure for this ethernetif - * @return ERR_OK if the loopif is initialized - * ERR_MEM if private data couldn't be allocated - * any other err_t on error - */ -err_t -wlanif_init(struct netif *netif) -{ - LWIP_ASSERT("netif != NULL", (netif != NULL)); - -#if LWIP_NETIF_HOSTNAME - /* Initialize interface hostname */ - -#if ESP_LWIP - netif->hostname = CONFIG_LWIP_LOCAL_HOSTNAME; -#else - netif->hostname = "lwip"; -#endif - -#endif /* LWIP_NETIF_HOSTNAME */ - - /* - * Initialize the snmp variables and counters inside the struct netif. - * The last argument should be replaced with your link speed, in units - * of bits per second. - */ - NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100); - - /* We directly use etharp_output() here to save a function call. - * You can instead declare your own function an call etharp_output() - * from it if you have to do some checks before sending (e.g. if link - * is available...) */ - netif->output = etharp_output; -#if LWIP_IPV6 - netif->output_ip6 = ethip6_output; -#endif /* LWIP_IPV6 */ - netif->linkoutput = low_level_output; - - /* initialize the hardware */ - low_level_init(netif); - - return ERR_OK; -} - -err_t wlanif_init_sta(struct netif *netif) { - netif->name[0] = 's'; - netif->name[1] = 't'; - return wlanif_init(netif); -} - -err_t wlanif_init_ap(struct netif *netif) { - netif->name[0] = 'a'; - netif->name[1] = 'p'; - return wlanif_init(netif); -} - - diff --git a/components/lwip/port/esp32/debug/lwip_debug.c b/components/lwip/port/esp8266/debug/lwip_debug.c similarity index 97% rename from components/lwip/port/esp32/debug/lwip_debug.c rename to components/lwip/port/esp8266/debug/lwip_debug.c index c6c71b5f..d354f402 100644 --- a/components/lwip/port/esp32/debug/lwip_debug.c +++ b/components/lwip/port/esp8266/debug/lwip_debug.c @@ -23,10 +23,14 @@ #include "lwip/memp.h" #include "esp_log.h" +#if LWIP_IPV4 && LWIP_IPV6 #define DBG_LWIP_IP_SHOW(info, ip) ESP_LWIP_LOGI("%s type=%d ip=%x", (info), (ip).type, (ip).u_addr.ip4.addr) +#else +#define DBG_LWIP_IP_SHOW(info, ip) ESP_LWIP_LOGI("%s ip=%x", (info), (ip).addr) +#endif #define DBG_LWIP_IP_PCB_SHOW(pcb) \ DBG_LWIP_IP_SHOW("local ip", (pcb)->local_ip);\ - DBG_LWIP_IP_SHOW("remote ip", (pcb)->local_ip);\ + DBG_LWIP_IP_SHOW("remote ip", (pcb)->remote_ip);\ ESP_LWIP_LOGI("so_options=%x, tos=%d ttl=%d", (pcb)->so_options, (pcb)->tos, (pcb)->ttl) #define DBG_LWIP_SEG_SHOW(seg) while(seg) { ESP_LWIP_LOGI("\tseg=%p next=%p pbuf=%p flags=%x", (seg), (seg)->next, (seg)->p, (seg)->flags); (seg)=(seg)->next;} @@ -186,11 +190,13 @@ void dbg_lwip_stats_show(void) LINK_STATS_DISPLAY(); MEM_STATS_DISPLAY(); SYS_STATS_DISPLAY(); +#if LWIP_IPV6 IP6_STATS_DISPLAY(); ICMP6_STATS_DISPLAY(); IP6_FRAG_STATS_DISPLAY(); MLD6_STATS_DISPLAY(); ND6_STATS_DISPLAY(); +#endif } #if (ESP_STATS_MEM == 1) diff --git a/components/lwip/port/esp32/freertos/sys_arch.c b/components/lwip/port/esp8266/freertos/sys_arch.c similarity index 100% rename from components/lwip/port/esp32/freertos/sys_arch.c rename to components/lwip/port/esp8266/freertos/sys_arch.c diff --git a/components/lwip/port/esp32/include/arch/cc.h b/components/lwip/port/esp8266/include/arch/cc.h similarity index 100% rename from components/lwip/port/esp32/include/arch/cc.h rename to components/lwip/port/esp8266/include/arch/cc.h diff --git a/components/lwip/port/esp32/include/arch/perf.h b/components/lwip/port/esp8266/include/arch/perf.h similarity index 100% rename from components/lwip/port/esp32/include/arch/perf.h rename to components/lwip/port/esp8266/include/arch/perf.h diff --git a/components/lwip/port/esp32/include/arch/sys_arch.h b/components/lwip/port/esp8266/include/arch/sys_arch.h similarity index 100% rename from components/lwip/port/esp32/include/arch/sys_arch.h rename to components/lwip/port/esp8266/include/arch/sys_arch.h diff --git a/components/lwip/port/esp32/include/arch/vfs_lwip.h b/components/lwip/port/esp8266/include/arch/vfs_lwip.h similarity index 100% rename from components/lwip/port/esp32/include/arch/vfs_lwip.h rename to components/lwip/port/esp8266/include/arch/vfs_lwip.h diff --git a/components/lwip/port/esp32/include/arpa/inet.h b/components/lwip/port/esp8266/include/arpa/inet.h similarity index 100% rename from components/lwip/port/esp32/include/arpa/inet.h rename to components/lwip/port/esp8266/include/arpa/inet.h diff --git a/components/lwip/port/esp32/include/debug/lwip_debug.h b/components/lwip/port/esp8266/include/debug/lwip_debug.h similarity index 100% rename from components/lwip/port/esp32/include/debug/lwip_debug.h rename to components/lwip/port/esp8266/include/debug/lwip_debug.h diff --git a/components/lwip/port/esp32/include/lwipopts.h b/components/lwip/port/esp8266/include/lwipopts.h similarity index 94% rename from components/lwip/port/esp32/include/lwipopts.h rename to components/lwip/port/esp8266/include/lwipopts.h index 89e1b327..1a73fd03 100644 --- a/components/lwip/port/esp32/include/lwipopts.h +++ b/components/lwip/port/esp8266/include/lwipopts.h @@ -41,10 +41,12 @@ #include #include #include "esp_task.h" +#include "esp_libc.h" #include "esp_system.h" #include "sdkconfig.h" #include "sntp.h" #include "netif/dhcp_state.h" +#include "driver/soc.h" /* Enable all Espressif-only options */ @@ -100,6 +102,16 @@ */ #define MEM_ALIGNMENT 4 +#define mem_clib_free(s) heap_caps_free(s) +#define mem_clib_malloc(s) heap_caps_malloc(s, MALLOC_CAP_8BIT) +#define mem_clib_calloc(n, s) heap_caps_calloc(n, s, MALLOC_CAP_8BIT) + +/** + * @brief System + */ +#define SYS_ARCH_DECL_PROTECT(_lev) esp_irqflag_t _lev +#define SYS_ARCH_PROTECT(_lev) _lev = soc_save_local_irq() +#define SYS_ARCH_UNPROTECT(_lev) soc_restore_local_irq(_lev) /* ------------------------------------------------ ---------- Internal Memory Pool Sizes ---------- @@ -386,6 +398,13 @@ ---------- Pbuf options ---------- ---------------------------------- */ +/** + * PBUF_LINK_ENCAPSULATION_HLEN: the number of bytes that should be allocated + * for an additional encapsulation header before ethernet headers (e.g. 802.11) + */ +#define PBUF_LINK_ENCAPSULATION_HLEN 36u + +#define LWIP_SUPPORT_CUSTOM_PBUF 1 /* ------------------------------------------------ @@ -548,6 +567,13 @@ */ #define LWIP_SO_RCVBUF CONFIG_LWIP_SO_RCVBUF +/** + * LWIP_SO_LINGER==1: Enable SO_LINGER processing. + */ +#define LWIP_SO_LINGER 1 + +#define SET_SOLINGER_DEFAULT CONFIG_SET_SOLINGER_DEFAULT + /** * SO_REUSE==1: Enable SO_REUSEADDR option. * This option is set via menuconfig. @@ -668,7 +694,7 @@ /** * LWIP_IPV6==1: Enable IPv6 */ -#define LWIP_IPV6 1 +#define LWIP_IPV6 CONFIG_LWIP_IPV6 /* --------------------------------------- @@ -766,7 +792,9 @@ #define LWIP_SOCKET_OFFSET (FD_SETSIZE - CONFIG_LWIP_MAX_SOCKETS) /* Enable all Espressif-only options */ - +#ifdef CONFIG_LWIP_SOCKET_MULTITHREAD +#define SOCKETS_MT +#endif #define ESP_LWIP 1 #define ESP_LWIP_ARP 1 #define ESP_PER_SOC_TCP_WND 0 @@ -774,7 +802,7 @@ #define ESP_THREAD_SAFE_DEBUG LWIP_DBG_OFF #define ESP_DHCP 1 #define ESP_DNS 1 -#define ESP_IPV6_AUTOCONFIG 1 +#define ESP_IPV6_AUTOCONFIG LWIP_IPV6 #define ESP_PERF 0 #define ESP_RANDOM_TCP_PORT 1 #define ESP_IP4_ATON 1 @@ -793,7 +821,7 @@ #define ESP_AUTO_IP 1 #define ESP_PBUF 1 #define ESP_PPP 1 -#define ESP_IPV6 1 +#define ESP_IPV6 LWIP_IPV6 #define ESP_SOCKET 1 #define ESP_LWIP_SELECT 1 @@ -820,6 +848,16 @@ #define LWIP_DEBUG LWIP_DBG_OFF #define TCP_DEBUG LWIP_DBG_OFF +#define ESP_TCP_TXRX_PBUF_DEBUG LWIP_DBG_OFF +#define LWIP_SEND_DATA_TO_WIFI 1 +#define LWIP_RESEND_DATA_TO_WIFI_WHEN_WIFI_SEND_FAILED 2 +#define LWIP_RECV_DATA_FROM_WIFI 3 +#define LWIP_RETRY_DATA_WHEN_RECV_ACK_TIMEOUT 4 +#define LWIP_FETCH_DATA_AT_TCPIP_THREAD 5 +#define WIFI_SEND_DATA_FAILED 6 + +void tcp_print_status(int status, void* p, uint32_t tmp1, uint32_t tmp2, uint32_t tmp3); + #define CHECKSUM_CHECK_UDP 0 #define CHECKSUM_CHECK_IP 0 diff --git a/components/lwip/port/esp32/include/netdb.h b/components/lwip/port/esp8266/include/netdb.h similarity index 100% rename from components/lwip/port/esp32/include/netdb.h rename to components/lwip/port/esp8266/include/netdb.h diff --git a/components/lwip/port/esp32/include/netif/dhcp_state.h b/components/lwip/port/esp8266/include/netif/dhcp_state.h similarity index 100% rename from components/lwip/port/esp32/include/netif/dhcp_state.h rename to components/lwip/port/esp8266/include/netif/dhcp_state.h diff --git a/components/lwip/port/esp32/include/netif/ethernetif.h b/components/lwip/port/esp8266/include/netif/ethernetif.h similarity index 100% rename from components/lwip/port/esp32/include/netif/ethernetif.h rename to components/lwip/port/esp8266/include/netif/ethernetif.h diff --git a/components/lwip/port/esp32/include/netif/nettestif.h b/components/lwip/port/esp8266/include/netif/nettestif.h similarity index 100% rename from components/lwip/port/esp32/include/netif/nettestif.h rename to components/lwip/port/esp8266/include/netif/nettestif.h diff --git a/components/lwip/port/esp32/include/netif/wlanif.h b/components/lwip/port/esp8266/include/netif/wlanif.h similarity index 66% rename from components/lwip/port/esp32/include/netif/wlanif.h rename to components/lwip/port/esp8266/include/netif/wlanif.h index 21fa91c3..f560c0e7 100644 --- a/components/lwip/port/esp32/include/netif/wlanif.h +++ b/components/lwip/port/esp8266/include/netif/wlanif.h @@ -16,24 +16,6 @@ #ifndef _WLAN_LWIP_IF_H_ #define _WLAN_LWIP_IF_H_ -#include "esp_wifi.h" - -#include "esp_private/wifi.h" - -#include "lwip/err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -err_t wlanif_init_ap(struct netif *netif); -err_t wlanif_init_sta(struct netif *netif); - -void wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb); - -wifi_interface_t wifi_get_interface(void *dev); - -void netif_reg_addr_change_cb(void* cb); #ifdef __cplusplus } diff --git a/components/lwip/port/esp32/include/netinet/in.h b/components/lwip/port/esp8266/include/netinet/in.h similarity index 100% rename from components/lwip/port/esp32/include/netinet/in.h rename to components/lwip/port/esp8266/include/netinet/in.h diff --git a/components/lwip/port/esp32/include/sys/socket.h b/components/lwip/port/esp8266/include/sys/socket.h similarity index 100% rename from components/lwip/port/esp32/include/sys/socket.h rename to components/lwip/port/esp8266/include/sys/socket.h diff --git a/components/lwip/port/esp32/netif/dhcp_state.c b/components/lwip/port/esp8266/netif/dhcp_state.c similarity index 98% rename from components/lwip/port/esp32/netif/dhcp_state.c rename to components/lwip/port/esp8266/netif/dhcp_state.c index 8e2e3d9f..6ae00d70 100644 --- a/components/lwip/port/esp32/netif/dhcp_state.c +++ b/components/lwip/port/esp8266/netif/dhcp_state.c @@ -31,6 +31,7 @@ static const char *interface_key[] = {"IF_STA", "IF_AP", "IF_ETH", "IF_TEST"}; _Static_assert(sizeof(interface_key) / sizeof(char*) == TCPIP_ADAPTER_IF_MAX, "Number interface keys differs from number of interfaces"); +typedef nvs_handle nvs_handle_t; bool dhcp_ip_addr_restore(void *netif) { nvs_handle_t nvs; diff --git a/components/lwip/port/esp32/netif/ethernetif.c b/components/lwip/port/esp8266/netif/ethernetif.c similarity index 100% rename from components/lwip/port/esp32/netif/ethernetif.c rename to components/lwip/port/esp8266/netif/ethernetif.c diff --git a/components/lwip/port/esp32/netif/nettestif.c b/components/lwip/port/esp8266/netif/nettestif.c similarity index 100% rename from components/lwip/port/esp32/netif/nettestif.c rename to components/lwip/port/esp8266/netif/nettestif.c diff --git a/components/lwip/port/esp8266/netif/wlanif.c b/components/lwip/port/esp8266/netif/wlanif.c new file mode 100644 index 00000000..a1067fda --- /dev/null +++ b/components/lwip/port/esp8266/netif/wlanif.c @@ -0,0 +1,629 @@ +/** + * @file + * Ethernet Interface Skeleton + * + */ + +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#include + +#include "lwip/pbuf.h" +#include "lwip/ethip6.h" +#include "netif/etharp.h" +#include "esp_libc.h" +#include "esp_wifi.h" +#include "esp_aio.h" +#include "tcpip_adapter.h" +#include "freertos/semphr.h" +#include "lwip/tcpip.h" +#include "stdlib.h" + +#include "esp8266/eagle_soc.h" + +int ieee80211_output_pbuf(esp_aio_t *aio); +int8_t wifi_get_netif(uint8_t fd); +void wifi_station_set_default_hostname(uint8_t* hwaddr); + +#define IFNAME0 'e' +#define IFNAME1 'n' + +#if ESP_TCP +typedef struct pbuf_send_list { + struct pbuf_send_list* next; + struct pbuf* p; + int aiofd; + int err_cnt; +} pbuf_send_list_t; + +static pbuf_send_list_t* pbuf_list_head = NULL; +static int pbuf_send_list_num = 0; +#endif +static int low_level_send_cb(esp_aio_t* aio); + +#if ESP_TCP_TXRX_PBUF_DEBUG +void tcp_print_status(int status, void* buf, uint32_t tmp1, uint32_t tmp2, uint32_t tmp3) +{ + struct pbuf* p = (struct pbuf*)buf; + if (p->tot_len < 50) { + return; + } + + uint32_t i; + + i = *((unsigned char*)p->payload + 12); + + if (i == 0x08) { /*ipv4*/ + i = *((unsigned char*)p->payload + 13); + + if (i == 0) { + i = *((unsigned char*)p->payload + 23); + + if (i == 0x06) { /*tcp*/ + i = *((unsigned char*)p->payload + 16); + i <<= 8; + i += *((unsigned char*)p->payload + 17); + + if (i >= 40) { /*tcp data*/ + uint32_t len, seq, ack, srcport, destport, flags; + wifi_tx_status_t *tx_result = (wifi_tx_status_t *)(&tmp1); + len = i; + i = *((unsigned char*)p->payload + 38); + i <<= 8; + i += *((unsigned char*)p->payload + 39); + i <<= 8; + i += *((unsigned char*)p->payload + 40); + i <<= 8; + i += *((unsigned char*)p->payload + 41); + seq = i; + i = *((unsigned char*)p->payload + 42); + i <<= 8; + i += *((unsigned char*)p->payload + 43); + i <<= 8; + i += *((unsigned char*)p->payload + 44); + i <<= 8; + i += *((unsigned char*)p->payload + 45); + ack = i; + i = *((unsigned char*)p->payload + 34); + i <<= 8; + i += *((unsigned char*)p->payload + 35); + srcport = i; + i = *((unsigned char*)p->payload + 36); + i <<= 8; + i += *((unsigned char*)p->payload + 37); + destport = i; + flags = *((unsigned char *)p->payload+47); + + switch (status) { + case LWIP_SEND_DATA_TO_WIFI: + LWIP_DEBUGF(ESP_TCP_TXRX_PBUF_DEBUG, ("@@ Tx - L:%u, S:%u, A:%u, SP:%u, DP:%u, F:%x\n", len, seq, ack, srcport, destport, flags)); + break; + + case LWIP_RESEND_DATA_TO_WIFI_WHEN_WIFI_SEND_FAILED: + LWIP_DEBUGF(ESP_TCP_TXRX_PBUF_DEBUG, ("@@ Cache Tx - L:%u, S:%u, A:%u, SP:%u, DP:%u, F:%x\n", len, seq, ack, srcport, destport, flags)); + break; + + case LWIP_RECV_DATA_FROM_WIFI: + LWIP_DEBUGF(ESP_TCP_TXRX_PBUF_DEBUG, ("@@ WiFi Rx - L:%u, S:%u, A:%u, SP:%u, DP:%u, F:%x\n", len, seq, ack, srcport, destport, flags)); + break; + + case LWIP_RETRY_DATA_WHEN_RECV_ACK_TIMEOUT: + LWIP_DEBUGF(ESP_TCP_TXRX_PBUF_DEBUG, ("@@ TCP RTY - rtime:%d, rto:%d, L:%u, S:%u, A:%u, SP:%u, DP:%u, F:%x\n", tmp1, tmp2, len, seq, ack, srcport, destport, flags)); + return; + + case LWIP_FETCH_DATA_AT_TCPIP_THREAD: + LWIP_DEBUGF(ESP_TCP_TXRX_PBUF_DEBUG, ("@@ eth Rx - L:%u, S:%u, A:%u, SP:%u, DP:%u, F:%x\n", len, seq, ack, srcport, destport, flags)); + break; + + case WIFI_SEND_DATA_FAILED: + LWIP_DEBUGF(ESP_TCP_TXRX_PBUF_DEBUG, ("@@ WiFi Tx Fail - result:%d, src:%d, lrc:%d, rate:%d, L:%u, S:%u, A:%u, SP:%u, DP:%u, F:%x\n",\ + tx_result->wifi_tx_result, tx_result->wifi_tx_src, tx_result->wifi_tx_lrc, tx_result->wifi_tx_rate, len, seq, ack, srcport, destport, flags)); + break; + + default: + LWIP_DEBUGF(ESP_TCP_TXRX_PBUF_DEBUG, ("@@ status:%d, L:%u, S:%u, A:%u, SP:%u, DP:%u, F:%x, tmp1:%d, tmp2:%d, tmp3:%d\n",\ + status, len, seq, ack, srcport, destport, flags, tmp1, tmp2, tmp3)); + break; + } + } + } + } + } +} +#endif + +#if ESP_TCP +static inline bool check_pbuf_to_insert(struct pbuf* p) +{ + uint8_t* buf = (uint8_t*)p->payload; + + /*Check if pbuf is tcp ip*/ + if (buf[12] == 0x08 && buf[13] == 0x00 && buf[23] == 0x06) { + return true; + } + + return false; +} + +static void insert_to_list(int fd, struct pbuf* p) +{ + pbuf_send_list_t* tmp_pbuf_list1; + pbuf_send_list_t* tmp_pbuf_list2; + + if (pbuf_send_list_num > (TCP_SND_QUEUELEN * MEMP_NUM_TCP_PCB + MEMP_NUM_TCP_PCB)) { + return; + } + + if (!check_pbuf_to_insert(p)) { + return; + } + + LWIP_DEBUGF(PBUF_CACHE_DEBUG, ("Insert %p,%d\n", p, pbuf_send_list_num)); + + if (pbuf_list_head == NULL) { + tmp_pbuf_list1 = (pbuf_send_list_t*)malloc(sizeof(pbuf_send_list_t)); + + if (!tmp_pbuf_list1) { + LWIP_DEBUGF(PBUF_CACHE_DEBUG, ("no memory malloc pbuf list error\n")); + return; + } + + pbuf_ref(p); + tmp_pbuf_list1->aiofd = fd; + tmp_pbuf_list1->p = p; + tmp_pbuf_list1->next = NULL; + tmp_pbuf_list1->err_cnt = 0; + pbuf_list_head = tmp_pbuf_list1; + pbuf_send_list_num++; + return; + } + + tmp_pbuf_list1 = pbuf_list_head; + tmp_pbuf_list2 = tmp_pbuf_list1; + + while (tmp_pbuf_list1 != NULL) { + if (tmp_pbuf_list1->p == p) { + tmp_pbuf_list1->err_cnt ++; + return; + } + + tmp_pbuf_list2 = tmp_pbuf_list1; + tmp_pbuf_list1 = tmp_pbuf_list2->next; + } + + tmp_pbuf_list1 = (pbuf_send_list_t*)malloc(sizeof(pbuf_send_list_t)); + + if (!tmp_pbuf_list1) { + LWIP_DEBUGF(PBUF_CACHE_DEBUG, ("no memory malloc pbuf list error\n")); + return; + } + + pbuf_ref(p); + tmp_pbuf_list1->aiofd = fd; + tmp_pbuf_list1->p = p; + tmp_pbuf_list1->next = NULL; + tmp_pbuf_list1->err_cnt = 0; + tmp_pbuf_list2->next = tmp_pbuf_list1; + pbuf_send_list_num++; +} + +void send_from_list() +{ + pbuf_send_list_t* tmp_pbuf_list1; + + while (pbuf_list_head != NULL) { + if (pbuf_list_head->p->ref == 1) { + tmp_pbuf_list1 = pbuf_list_head->next; + LWIP_DEBUGF(PBUF_CACHE_DEBUG, ("Delete %p,%d\n", pbuf_list_head->p, pbuf_send_list_num)); + pbuf_free(pbuf_list_head->p); + free(pbuf_list_head); + pbuf_send_list_num--; + pbuf_list_head = tmp_pbuf_list1; + } else { + esp_aio_t aio; + esp_err_t err; + aio.fd = (int)pbuf_list_head->aiofd; + aio.pbuf = pbuf_list_head->p->payload; + aio.len = pbuf_list_head->p->len; + aio.cb = low_level_send_cb; + aio.arg = pbuf_list_head->p; + aio.ret = 0; + + err = ieee80211_output_pbuf(aio); + +#if ESP_TCP_TXRX_PBUF_DEBUG + tcp_print_status(LWIP_RESEND_DATA_TO_WIFI_WHEN_WIFI_SEND_FAILED, (void*)pbuf_list_head->p, 0 ,0, 0); +#endif + tmp_pbuf_list1 = pbuf_list_head->next; + + if (err == ERR_MEM) { + pbuf_list_head->err_cnt++; + + if (pbuf_list_head->err_cnt >= 3) { + LWIP_DEBUGF(PBUF_CACHE_DEBUG, ("Delete %p,%d\n", pbuf_list_head->p, pbuf_send_list_num)); + pbuf_free(pbuf_list_head->p); + free(pbuf_list_head); + pbuf_send_list_num--; + pbuf_list_head = tmp_pbuf_list1; + } + + return; + } else if (err == ERR_OK) { + LWIP_DEBUGF(PBUF_CACHE_DEBUG, ("Delete %p,%d\n", pbuf_list_head->p, pbuf_send_list_num)); + free(pbuf_list_head); + pbuf_send_list_num--; + pbuf_list_head = tmp_pbuf_list1; + } else { + LWIP_DEBUGF(PBUF_CACHE_DEBUG, ("Delete %p,%d\n", pbuf_list_head->p, pbuf_send_list_num)); + pbuf_free(pbuf_list_head->p); + free(pbuf_list_head); + pbuf_send_list_num--; + pbuf_list_head = tmp_pbuf_list1; + } + } + } +} +#endif + +/** + * In this function, the hardware should be initialized. + * Called from ethernetif_init(). + * + * @param netif the already initialized lwip network interface structure + * for this ethernetif + */ +static void low_level_init(struct netif* netif) +{ + if (netif == NULL) { + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_init: netif is NULL\n")); + return; + } + + /* set MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* maximum transfer unit */ + netif->mtu = 1500; + + /* device capabilities */ + /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + +#if LWIP_IGMP + netif->flags |= NETIF_FLAG_IGMP; +#endif + /* Do whatever else is needed to initialize interface. */ +} + +/* + * @brief LWIP low-level AI/O sending callback function, it is to free pbuf + * + * @param aio AI/O control block pointer + * + * @return 0 meaning successs + */ +static int low_level_send_cb(esp_aio_t* aio) +{ + struct pbuf* pbuf = aio->arg; + +#if ESP_TCP_TXRX_PBUF_DEBUG + wifi_tx_status_t* status = (wifi_tx_status_t*) & (aio->ret); + if (TX_STATUS_SUCCESS != status->wifi_tx_result) { + uint8_t* buf = (uint8_t*)pbuf->payload; + + /*Check if pbuf is tcp ip*/ + if (buf[12] == 0x08 && buf[13] == 0x00 && buf[23] == 0x06) { + tcp_print_status(WIFI_SEND_DATA_FAILED, (void*)pbuf, aio->ret ,0, 0); + } + } +#endif + +#if ESP_TCP + wifi_tx_status_t* status = (wifi_tx_status_t*) & (aio->ret); + + if ((TX_STATUS_SUCCESS != status->wifi_tx_result) && check_pbuf_to_insert(pbuf)) { + uint8_t* buf = (uint8_t*)pbuf->payload; + struct eth_hdr ethhdr; + + if (*(buf - 17) & 0x01) { //From DS + memcpy(ðhdr.dest, buf - 2, ETH_HWADDR_LEN); + memcpy(ðhdr.src, buf - 2 - ETH_HWADDR_LEN, ETH_HWADDR_LEN); + } else if (*(buf - 17) & 0x02) { //To DS + memcpy(ðhdr.dest, buf - 2 - ETH_HWADDR_LEN - ETH_HWADDR_LEN, ETH_HWADDR_LEN); + memcpy(ðhdr.src, buf - 2, 6); + } else { + pbuf_free(pbuf); + return 0; + } + + memcpy(buf, ðhdr, (ETH_HWADDR_LEN + ETH_HWADDR_LEN)); + LWIP_DEBUGF(PBUF_CACHE_DEBUG, ("Send packet fail: result:%d, LRC:%d, SRC:%d, RATE:%d", + status->wifi_tx_result, status->wifi_tx_lrc, status->wifi_tx_src, status->wifi_tx_rate)); + insert_to_list(aio->fd, aio->arg); + } +#endif + + pbuf_free(pbuf); + + return 0; +} + +/* + * @brief transform custom pbuf to LWIP core pbuf, LWIP may use input custom pbuf + * to send ARP data directly + * + * @param pbuf LWIP pbuf pointer + * + * @return LWIP pbuf pointer which it not "PBUF_FLAG_IS_CUSTOM" attribute + */ +static inline struct pbuf* ethernetif_transform_pbuf(struct pbuf* pbuf) +{ + struct pbuf* p; + + if (!(pbuf->flags & PBUF_FLAG_IS_CUSTOM) && IS_DRAM(pbuf->payload)) { + /* + * Add ref to pbuf to avoid it to be freed by upper layer. + */ + pbuf_ref(pbuf); + return pbuf; + } + + p = pbuf_alloc(PBUF_RAW, pbuf->len, PBUF_RAM); + + if (!p) { + return NULL; + } + + if (IS_IRAM(p->payload)) { + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output: data in IRAM\n")); + pbuf_free(p); + return NULL; + } + + memcpy(p->payload, pbuf->payload, pbuf->len); + + /* + * The input pbuf(named "pbuf") should not be freed, becasue it will be + * freed by upper layer. + * + * The output pbuf(named "p") should not be freed either, becasue it will + * be freed at callback function "low_level_send_cb". + */ + + return p; +} + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the pbuf that is passed to the function. This pbuf + * might be chained. + * + * @param netif the lwip network interface structure for this ethernetif + * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return ERR_OK if the packet could be sent + * an int8_t value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become availale since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ + +static int8_t low_level_output(struct netif* netif, struct pbuf* p) +{ + esp_aio_t aio; + int8_t err = ERR_OK; + + if (netif == NULL) { + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output: netif is NULL\n")); + return ERR_ARG; + } + + if (!netif_is_up(netif)) { + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output: netif is not up\n")); + return ERR_RTE; + } + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + p = ethernetif_transform_pbuf(p); + + if (!p) { + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output: lack memory\n")); + return ERR_OK; + } + + aio.fd = (int)netif->state; + aio.pbuf = p->payload; + aio.len = p->len; + aio.cb = low_level_send_cb; + aio.arg = p; + aio.ret = 0; + +#if ESP_TCP_TXRX_PBUF_DEBUG + tcp_print_status(LWIP_SEND_DATA_TO_WIFI, (void*)p, 0 ,0, 0); +#endif + + /* + * we use "SOCK_RAW" to create socket, so all input/output datas include full ethernet + * header, meaning we should not pass target low-level address here. + */ + err = ieee80211_output_pbuf(&aio); + if (err != ERR_OK) { + if (err == ERR_MEM) { +#if ESP_TCP + insert_to_list(aio.fd, p); +#endif + err = ERR_OK; + } + + pbuf_free(p); + } + +// signal that packet should be sent(); + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + +#if LWIP_STATS + LINK_STATS_INC(link.xmit); +#endif + return err; +} + +/** + * This function should be called when a packet is ready to be read + * from the interface. It uses the function low_level_input() that + * should handle the actual reception of bytes from the network + * interface. Then the type of the received packet is determined and + * the appropriate input function is called. + * + * @param netif the lwip network interface structure for this ethernetif + */ +void ethernetif_input(struct netif* netif, struct pbuf* p) +{ + struct eth_hdr* ethhdr; + + if (p == NULL) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: pbuf is NULL\n")); + goto _exit; + } + + if (p->payload == NULL) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: payload is NULL\n")); + pbuf_free(p); + goto _exit; + } + + if (netif == NULL) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: netif is NULL\n")); + pbuf_free(p); + goto _exit; + } + + if (!(netif->flags & NETIF_FLAG_LINK_UP)) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: netif is not up\n")); + pbuf_free(p); + p = NULL; + goto _exit; + } + + /* points to packet payload, which starts with an Ethernet header */ + ethhdr = p->payload; + + switch (htons(ethhdr->type)) { + /* IP or ARP packet? */ + case ETHTYPE_IP: + case ETHTYPE_IPV6: + case ETHTYPE_ARP: +#if PPPOE_SUPPORT + + /* PPPoE packet? */ + case ETHTYPE_PPPOEDISC: + case ETHTYPE_PPPOE: +#endif /* PPPOE_SUPPORT */ + + /* full packet send to tcpip_thread to process */ + if (netif->input(p, netif) != ERR_OK) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); + pbuf_free(p); + p = NULL; + } + + break; + + default: + pbuf_free(p); + p = NULL; + break; + } + +_exit: + ; +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. It calls the function low_level_init() to do the + * actual setup of the hardware. + * + * This function should be passed as a parameter to netif_add(). + * + * @param netif the lwip network interface structure for this ethernetif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other int8_t on error + */ +int8_t ethernetif_init(struct netif* netif) +{ + if (netif == NULL) { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: netif is NULL\n")); + } + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + +#if ESP_LWIP + netif->hostname = CONFIG_LWIP_LOCAL_HOSTNAME; +#else + netif->hostname = "lwip"; +#endif + +#endif /* LWIP_NETIF_HOSTNAME */ + + /* + * Initialize the snmp variables and counters inside the struct netif. + * The last argument should be replaced with your link speed, in units + * of bits per second. + */ + + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + netif->output = etharp_output; +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; +#endif /* LWIP_IPV6 */ + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + return ERR_OK; +} diff --git a/components/lwip/port/esp32/vfs_lwip.c b/components/lwip/port/esp8266/vfs_lwip.c similarity index 74% rename from components/lwip/port/esp32/vfs_lwip.c rename to components/lwip/port/esp8266/vfs_lwip.c index 9ef74784..15da19f6 100644 --- a/components/lwip/port/esp32/vfs_lwip.c +++ b/components/lwip/port/esp8266/vfs_lwip.c @@ -21,35 +21,28 @@ #include "esp_vfs.h" #include "esp_vfs_dev.h" #include "esp_attr.h" +#include "esp8266/uart_struct.h" #include "lwip/sockets.h" #include "sdkconfig.h" #include "lwip/sys.h" _Static_assert(MAX_FDS >= CONFIG_LWIP_MAX_SOCKETS, "MAX_FDS < CONFIG_LWIP_MAX_SOCKETS"); -static void lwip_stop_socket_select(void *sem) +static void lwip_stop_socket_select() { - sys_sem_signal(sem); //socket_select will return + sys_sem_signal(sys_thread_sem_get()); //socket_select will return } -static void lwip_stop_socket_select_isr(void *sem, BaseType_t *woken) +static void lwip_stop_socket_select_isr(BaseType_t *woken) { - if (sys_sem_signal_isr(sem) && woken) { + if (sys_sem_signal_isr(sys_thread_sem_get()) && woken) { *woken = pdTRUE; } } -static void *lwip_get_socket_select_semaphore(void) +static int lwip_fcntl_r_wrapper(int fd, int cmd, va_list args) { - /* Calling this from the same process as select() will ensure that the semaphore won't be allocated from - * ISR (lwip_stop_socket_select_isr). - */ - return (void *) sys_thread_sem_get(); -} - -static int lwip_fcntl_r_wrapper(int fd, int cmd, int arg) -{ - return lwip_fcntl(fd, cmd, arg); + return lwip_fcntl(fd, cmd, va_arg(args, int)); } static int lwip_ioctl_r_wrapper(int fd, int cmd, va_list args) @@ -69,7 +62,6 @@ void esp_vfs_lwip_sockets_register(void) .fcntl = &lwip_fcntl_r_wrapper, .ioctl = &lwip_ioctl_r_wrapper, .socket_select = &lwip_select, - .get_socket_select_semaphore = &lwip_get_socket_select_semaphore, .stop_socket_select = &lwip_stop_socket_select, .stop_socket_select_isr = &lwip_stop_socket_select_isr, }; diff --git a/components/newlib/newlib/include/limits.h b/components/newlib/newlib/include/limits.h index 190f1f78..633b4459 100644 --- a/components/newlib/newlib/include/limits.h +++ b/components/newlib/newlib/include/limits.h @@ -142,5 +142,5 @@ #endif #ifndef PATH_MAX -#define PATH_MAX 4096 +#define PATH_MAX 1024 #endif diff --git a/components/newlib/newlib/port/time.c b/components/newlib/newlib/port/time.c index 68144925..95b2cc90 100644 --- a/components/newlib/newlib/port/time.c +++ b/components/newlib/newlib/port/time.c @@ -27,6 +27,7 @@ #include "task.h" #include "driver/soc.h" +#include "limits.h" #include "sdkconfig.h" #ifdef CONFIG_ESP8266_TIME_SYSCALL_USE_FRC1 @@ -35,6 +36,20 @@ static uint64_t s_boot_time; +#if defined(WITH_RTC) || defined(WITH_FRC) +// stores the start time of the slew +static uint64_t adjtime_start = 0; +// is how many microseconds total to slew +static int64_t adjtime_total_correction = 0; +#define ADJTIME_CORRECTION_FACTOR 6 +static uint64_t get_time_since_boot(void); +#endif +// Offset between FRC timer and the RTC. +// Initialized after reset or light sleep. +#if defined(WITH_RTC) && defined(WITH_FRC) +uint64_t s_microseconds_offset; +#endif + static inline void set_boot_time(uint64_t time_us) { esp_irqflag_t flag; @@ -56,6 +71,103 @@ static inline uint64_t get_boot_time() return result; } +// This function gradually changes boot_time to the correction value and immediately updates it. +static uint64_t adjust_boot_time(void) +{ + uint64_t boot_time = get_boot_time(); + if ((boot_time == 0) || (get_time_since_boot() < adjtime_start)) { + adjtime_start = 0; + } + if (adjtime_start > 0) { + uint64_t since_boot = get_time_since_boot(); + // If to call this function once per second, then (since_boot - adjtime_start) will be 1_000_000 (1 second), + // and the correction will be equal to (1_000_000us >> 6) = 15_625 us. + // The minimum possible correction step can be (64us >> 6) = 1us. + // Example: if the time error is 1 second, then it will be compensate for 1 sec / 0,015625 = 64 seconds. + int64_t correction = (since_boot >> ADJTIME_CORRECTION_FACTOR) - (adjtime_start >> ADJTIME_CORRECTION_FACTOR); + if (correction > 0) { + adjtime_start = since_boot; + if (adjtime_total_correction < 0) { + if ((adjtime_total_correction + correction) >= 0) { + boot_time = boot_time + adjtime_total_correction; + adjtime_start = 0; + } else { + adjtime_total_correction += correction; + boot_time -= correction; + } + } else { + if ((adjtime_total_correction - correction) <= 0) { + boot_time = boot_time + adjtime_total_correction; + adjtime_start = 0; + } else { + adjtime_total_correction -= correction; + boot_time += correction; + } + } + set_boot_time(boot_time); + } + } + return boot_time; +} + +#if defined( WITH_FRC ) || defined( WITH_RTC ) +static uint64_t get_time_since_boot(void) +{ + uint64_t microseconds = 0; +#ifdef WITH_FRC +#ifdef WITH_RTC + microseconds = s_microseconds_offset + esp_timer_get_time(); +#else + microseconds = esp_timer_get_time(); +#endif // WITH_RTC +#elif defined(WITH_RTC) + microseconds = get_rtc_time_us(); +#endif // WITH_FRC + return microseconds; +} +#endif // defined( WITH_FRC ) || defined( WITH_RTC + +int adjtime(const struct timeval *delta, struct timeval *outdelta) +{ +#if defined( WITH_FRC ) || defined( WITH_RTC ) + esp_irqflag_t flag; + if(delta != NULL){ + int64_t sec = delta->tv_sec; + int64_t usec = delta->tv_usec; + if(llabs(sec) > ((INT_MAX / 1000000L) - 1L)) { + return -1; + } + /* + * If adjusting the system clock by adjtime () is already done during the second call adjtime (), + * and the delta of the second call is not NULL, the earlier tuning is stopped, + * but the already completed part of the adjustment is not canceled. + */ + flag = soc_save_local_irq(); + // If correction is already in progress (adjtime_start != 0), then apply accumulated corrections. + adjust_boot_time(); + adjtime_start = get_time_since_boot(); + adjtime_total_correction = sec * 1000000L + usec; + soc_restore_local_irq(flag); + } + if(outdelta != NULL){ + flag = soc_save_local_irq(); + adjust_boot_time(); + if (adjtime_start != 0) { + outdelta->tv_sec = adjtime_total_correction / 1000000L; + outdelta->tv_usec = adjtime_total_correction % 1000000L; + } else { + outdelta->tv_sec = 0; + outdelta->tv_usec = 0; + } + soc_restore_local_irq(flag); + } + return 0; +#else + return -1; +#endif + +} + int _gettimeofday_r(struct _reent* r, struct timeval* tv, void* tz) { (void) tz; diff --git a/components/pthread/Kconfig b/components/pthread/Kconfig index 29f3eddb..415bfb43 100644 --- a/components/pthread/Kconfig +++ b/components/pthread/Kconfig @@ -2,6 +2,7 @@ menu "PThreads" config ENABLE_PTHREAD bool "Enable Pthread" + default y help Enable this option and then pthread is to be used. diff --git a/components/tcpip_adapter/include/tcpip_adapter.h b/components/tcpip_adapter/include/tcpip_adapter.h index 141ce09e..43cc6e36 100644 --- a/components/tcpip_adapter/include/tcpip_adapter.h +++ b/components/tcpip_adapter/include/tcpip_adapter.h @@ -127,11 +127,12 @@ typedef struct { #define ESP_ERR_TCPIP_ADAPTER_NO_MEM ESP_ERR_TCPIP_ADAPTER_BASE + 0x06 #define ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED ESP_ERR_TCPIP_ADAPTER_BASE + 0x07 -/* TODO: add Ethernet interface */ +/* @brief On-chip network interfaces */ typedef enum { - TCPIP_ADAPTER_IF_STA = 0, /**< TCP-IP adatpter station interface */ - TCPIP_ADAPTER_IF_AP, /**< TCP-IP adatpter soft-AP interface */ - TCPIP_ADAPTER_IF_ETH, /**< TCP-IP adatpter ethernet interface */ + TCPIP_ADAPTER_IF_STA = 0, /**< Wi-Fi STA (station) interface */ + TCPIP_ADAPTER_IF_AP, /**< Wi-Fi soft-AP interface */ + TCPIP_ADAPTER_IF_ETH, /**< Ethernet interface */ + TCPIP_ADAPTER_IF_TEST, /**< tcpip stack test interface */ TCPIP_ADAPTER_IF_MAX } tcpip_adapter_if_t; @@ -660,6 +661,15 @@ esp_err_t tcpip_adapter_set_default_wifi_handlers(); */ esp_err_t tcpip_adapter_clear_default_wifi_handlers(); +/** + * @brief Search nefit index through netif interface + * @param[in] tcpip_if Interface to search for netif index + * @return + * - netif_index on success + * - -1 if an invalid parameter is supplied + */ +int tcpip_adapter_get_netif_index(tcpip_adapter_if_t tcpip_if); + #ifdef __cplusplus } #endif diff --git a/components/tcpip_adapter/tcpip_adapter_lwip.c b/components/tcpip_adapter/tcpip_adapter_lwip.c index 55c2eb82..091e88dc 100644 --- a/components/tcpip_adapter/tcpip_adapter_lwip.c +++ b/components/tcpip_adapter/tcpip_adapter_lwip.c @@ -1223,28 +1223,6 @@ esp_err_t tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if, void ** netif) return ESP_OK; } -struct netif* ip4_route_src_hook(const ip4_addr_t* dest, const ip4_addr_t* src) -{ - extern struct netif *netif_list; - struct netif *netif = NULL; - - /* destination IP is broadcast IP? */ - if ((src != NULL) && !ip4_addr_isany(src)) { - /* iterate through netifs */ - for (netif = netif_list; netif != NULL; netif = netif->next) { - /* is the netif up, does it have a link and a valid address? */ - if (netif_is_up(netif) && netif_is_link_up(netif) && !ip4_addr_isany_val(*netif_ip4_addr(netif))) { - /* source IP matches? */ - if (ip4_addr_cmp(src, netif_ip4_addr(netif))) { - /* return netif on which to forward IP packet */ - return netif; - } - } - } - } - return netif; -} - bool tcpip_adapter_is_netif_up(tcpip_adapter_if_t tcpip_if) { if (esp_netif[tcpip_if] != NULL && netif_is_up(esp_netif[tcpip_if])) { @@ -1254,4 +1232,12 @@ bool tcpip_adapter_is_netif_up(tcpip_adapter_if_t tcpip_if) } } +int tcpip_adapter_get_netif_index(tcpip_adapter_if_t tcpip_if) +{ + if (tcpip_if >= TCPIP_ADAPTER_IF_MAX || esp_netif[tcpip_if] == NULL) { + return -1; + } + return netif_get_index(esp_netif[tcpip_if]); +} + #endif /* CONFIG_TCPIP_LWIP */ diff --git a/components/vfs/Kconfig b/components/vfs/Kconfig index 8894f7e1..1bb7b5d2 100644 --- a/components/vfs/Kconfig +++ b/components/vfs/Kconfig @@ -2,14 +2,14 @@ menu "Virtual file system" config USING_ESP_VFS bool "Using espressif VFS" - default n + default y help Enable this option, espressif VFS can be used. Users can use APIs like "open", "read", "write" and so on to operate I/O device which is registered. config SUPPRESS_SELECT_DEBUG_OUTPUT bool "Suppress select() related debug outputs" - default y + default n depends on USING_ESP_VFS help Select() related functions might produce an unconveniently lot of @@ -19,7 +19,7 @@ config SUPPRESS_SELECT_DEBUG_OUTPUT config SUPPORT_TERMIOS bool "Add support for termios.h" - default y + default n depends on USING_ESP_VFS help Disabling this option can save memory when the support for termios.h is not required. diff --git a/components/vfs/include/esp_vfs.h b/components/vfs/include/esp_vfs.h index d7467d22..b0883ab9 100644 --- a/components/vfs/include/esp_vfs.h +++ b/components/vfs/include/esp_vfs.h @@ -19,6 +19,7 @@ #include #include #include +#include #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "esp_err.h" @@ -27,6 +28,7 @@ #include #include #include +#include #include #include #include "sdkconfig.h" @@ -379,6 +381,21 @@ void esp_vfs_select_triggered(SemaphoreHandle_t *signal_sem); */ void esp_vfs_select_triggered_isr(SemaphoreHandle_t *signal_sem, BaseType_t *woken); +/** + * @brief Implements the VFS layer for synchronous I/O multiplexing by poll() + * + * The implementation is based on esp_vfs_select. The parameters and return values are compatible with POSIX poll(). + * + * @param fds Pointer to the array containing file descriptors and events poll() should consider. + * @param nfds Number of items in the array fds. + * @param timeout Poll() should wait at least timeout milliseconds. If the value is 0 then it should return + * immediately. If the value is -1 then it should wait (block) until the event occurs. + * + * @return A positive return value indicates the number of file descriptors that have been selected. The 0 + * return value indicates a timed-out poll. -1 is return on failure and errno is set accordingly. + * + */ +int esp_vfs_poll(struct pollfd *fds, int nfds, int timeout); #ifdef __cplusplus } // extern "C" #endif diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index e59795cc..b7a0a86c 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -1096,3 +1096,80 @@ int tcsendbreak(int fd, int duration) return ret; } #endif // CONFIG_SUPPORT_TERMIOS + +int esp_vfs_poll(struct pollfd *fds, int nfds, int timeout) +{ + struct timeval tv = { + // timeout is in milliseconds + .tv_sec = timeout / 1000, + .tv_usec = (timeout % 1000) * 1000, + }; + int max_fd = -1; + fd_set readfds; + fd_set writefds; + fd_set errorfds; + struct _reent* r = __getreent(); + int ret = 0; + + if (fds == NULL) { + __errno_r(r) = ENOENT; + return -1; + } + + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&errorfds); + + for (int i = 0; i < nfds; ++i) { + fds[i].revents = 0; + + if (fds[i].fd < 0) { + // revents should remain 0 and events ignored (according to the documentation of poll()). + continue; + } + + if (fds[i].fd >= MAX_FDS) { + fds[i].revents |= POLLNVAL; + ++ret; + continue; + } + + if (fds[i].events & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) { + FD_SET(fds[i].fd, &readfds); + FD_SET(fds[i].fd, &errorfds); + max_fd = MAX(max_fd, fds[i].fd); + } + + if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) { + FD_SET(fds[i].fd, &writefds); + FD_SET(fds[i].fd, &errorfds); + max_fd = MAX(max_fd, fds[i].fd); + } + } + + const int select_ret = esp_vfs_select(max_fd + 1, &readfds, &writefds, &errorfds, timeout < 0 ? NULL: &tv); + + if (select_ret > 0) { + ret += select_ret; + + for (int i = 0; i < nfds; ++i) { + if (FD_ISSET(fds[i].fd, &readfds)) { + fds[i].revents |= POLLIN; + } + + if (FD_ISSET(fds[i].fd, &writefds)) { + fds[i].revents |= POLLOUT; + } + + if (FD_ISSET(fds[i].fd, &errorfds)) { + fds[i].revents |= POLLERR; + } + } + } else { + ret = select_ret; + // keeping the errno from select() + } + + return ret; +} + diff --git a/examples/protocols/openssl_client/main/openssl_client_example_main.c b/examples/protocols/openssl_client/main/openssl_client_example_main.c index 564f3397..b88359ef 100644 --- a/examples/protocols/openssl_client/main/openssl_client_example_main.c +++ b/examples/protocols/openssl_client/main/openssl_client_example_main.c @@ -61,7 +61,7 @@ static void openssl_client_task(void* p) SSL_CTX* ctx; SSL* ssl; - int socket; + int sockfd; struct sockaddr_in sock_addr; struct hostent* entry = NULL; int recv_bytes = 0; @@ -108,9 +108,9 @@ static void openssl_client_task(void* p) SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); printf("create socket ......"); - socket = socket(AF_INET, SOCK_STREAM, 0); + sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (socket < 0) { + if (sockfd < 0) { printf("failed\n"); goto failed3; } @@ -122,7 +122,7 @@ static void openssl_client_task(void* p) sock_addr.sin_family = AF_INET; sock_addr.sin_addr.s_addr = 0; sock_addr.sin_port = htons(OPENSSL_CLIENT_LOCAL_TCP_PORT); - ret = bind(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); + ret = bind(sockfd, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); if (ret) { printf("failed\n"); @@ -136,7 +136,7 @@ static void openssl_client_task(void* p) sock_addr.sin_family = AF_INET; sock_addr.sin_addr.s_addr = ((struct in_addr*)(entry->h_addr))->s_addr; sock_addr.sin_port = htons(CONFIG_TARGET_PORT_NUMBER); - ret = connect(socket, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); + ret = connect(sockfd, (struct sockaddr*)&sock_addr, sizeof(sock_addr)); if (ret) { printf("failed\n"); @@ -155,7 +155,7 @@ static void openssl_client_task(void* p) printf("OK\n"); - SSL_set_fd(ssl, socket); + SSL_set_fd(ssl, sockfd); printf("SSL connected to %s port %d ......", CONFIG_TARGET_DOMAIN, CONFIG_TARGET_PORT_NUMBER); ret = SSL_connect(ssl); @@ -198,7 +198,7 @@ failed7: failed6: failed5: failed4: - close(socket); + close(sockfd); failed3: failed2: SSL_CTX_free(ctx); diff --git a/examples/protocols/openssl_demo/main/openssl_demo_example_main.c b/examples/protocols/openssl_demo/main/openssl_demo_example_main.c index 837b9e20..7638e0cd 100644 --- a/examples/protocols/openssl_demo/main/openssl_demo_example_main.c +++ b/examples/protocols/openssl_demo/main/openssl_demo_example_main.c @@ -46,7 +46,7 @@ static void openssl_task(void *p) SSL_CTX *ctx; SSL *ssl; - int socket; + int sockfd; struct sockaddr_in sock_addr; struct hostent *entry = NULL; @@ -80,9 +80,9 @@ static void openssl_task(void *p) SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); ESP_LOGI(TAG, "create socket ......"); - socket = socket(AF_INET, SOCK_STREAM, 0); + sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (socket < 0) { + if (sockfd < 0) { ESP_LOGI(TAG, "failed"); goto failed2; } @@ -94,7 +94,7 @@ static void openssl_task(void *p) sock_addr.sin_family = AF_INET; sock_addr.sin_addr.s_addr = 0; sock_addr.sin_port = htons(OPENSSL_DEMO_LOCAL_TCP_PORT); - ret = bind(socket, (struct sockaddr *)&sock_addr, sizeof(sock_addr)); + ret = bind(sockfd, (struct sockaddr *)&sock_addr, sizeof(sock_addr)); if (ret) { ESP_LOGI(TAG, "failed"); @@ -108,7 +108,7 @@ static void openssl_task(void *p) sock_addr.sin_family = AF_INET; sock_addr.sin_addr.s_addr = ((struct in_addr *)(entry->h_addr))->s_addr; sock_addr.sin_port = htons(OPENSSL_DEMO_TARGET_TCP_PORT); - ret = connect(socket, (struct sockaddr *)&sock_addr, sizeof(sock_addr)); + ret = connect(sockfd, (struct sockaddr *)&sock_addr, sizeof(sock_addr)); if (ret) { ESP_LOGI(TAG, "failed\n"); @@ -127,7 +127,7 @@ static void openssl_task(void *p) ESP_LOGI(TAG, "OK"); - SSL_set_fd(ssl, socket); + SSL_set_fd(ssl, sockfd); ESP_LOGI(TAG, "SSL connected to %s port %d ......", OPENSSL_DEMO_TARGET_NAME, OPENSSL_DEMO_TARGET_TCP_PORT); ret = SSL_connect(ssl); @@ -169,7 +169,7 @@ failed6: failed5: failed4: failed3: - close(socket); + close(sockfd); failed2: SSL_CTX_free(ctx); failed1: diff --git a/examples/protocols/sockets/udp_multicast/main/udp_multicast_example_main.c b/examples/protocols/sockets/udp_multicast/main/udp_multicast_example_main.c index fe5db370..77d9ea59 100644 --- a/examples/protocols/sockets/udp_multicast/main/udp_multicast_example_main.c +++ b/examples/protocols/sockets/udp_multicast/main/udp_multicast_example_main.c @@ -18,6 +18,7 @@ #include "protocol_examples_common.h" #include "nvs.h" #include "nvs_flash.h" +#include "tcpip_adapter.h" #include "lwip/err.h" #include "lwip/sockets.h" @@ -161,9 +162,10 @@ err: static int create_multicast_ipv6_socket() { struct sockaddr_in6 saddr = { 0 }; + int netif_index; struct in6_addr if_inaddr = { 0 }; struct ip6_addr if_ipaddr = { 0 }; - struct ip6_mreq v6imreq = { 0 }; + struct ipv6_mreq v6imreq = { 0 }; int sock = -1; int err = 0; @@ -201,9 +203,14 @@ static int create_multicast_ipv6_socket() } #endif + // search for netif index + netif_index = tcpip_adapter_get_netif_index(TCPIP_ADAPTER_IF_STA); + if(netif_index < 0) { + ESP_LOGE(V6TAG, "Failed to get netif index"); + goto err; + } // Assign the multicast source interface, via its IP - err = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &if_inaddr, - sizeof(struct in6_addr)); + err = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &netif_index,sizeof(uint8_t)); if (err < 0) { ESP_LOGE(V6TAG, "Failed to set IPV6_MULTICAST_IF. Error %d", errno); goto err; @@ -231,13 +238,6 @@ static int create_multicast_ipv6_socket() // this is also a listening socket, so add it to the multicast // group for listening... - - // Configure source interface -#if USE_DEFAULT_IF - v6imreq.imr_interface.s_addr = IPADDR_ANY; -#else - inet6_addr_from_ip6addr(&v6imreq.ipv6mr_interface, &if_ipaddr); -#endif #ifdef CONFIG_EXAMPLE_IPV6 // Configure multicast address to listen to err = inet6_aton(MULTICAST_IPV6_ADDR, &v6imreq.ipv6mr_multiaddr); @@ -251,9 +251,10 @@ static int create_multicast_ipv6_socket() if (!ip6_addr_ismulticast(&multi_addr)) { ESP_LOGW(V6TAG, "Configured IPV6 multicast address '%s' is not a valid multicast address. This will probably not work.", MULTICAST_IPV6_ADDR); } - + // Configure source interface + v6imreq.ipv6mr_interface = (unsigned int)netif_index; err = setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, - &v6imreq, sizeof(struct ip6_mreq)); + &v6imreq, sizeof(struct ipv6_mreq)); if (err < 0) { ESP_LOGE(V6TAG, "Failed to set IPV6_ADD_MEMBERSHIP. Error %d", errno); goto err;