Просмотр исходного кода

Merge branch 'bugfix/linux_target_with_out_lwip' into 'master'

linux: Add lwip support to networking components under linux

See merge request espressif/esp-idf!23053
David Čermák 2 лет назад
Родитель
Сommit
292d16b440
31 измененных файлов с 275 добавлено и 86 удалено
  1. 1 1
      .gitlab/ci/host-test.yml
  2. 7 0
      components/esp-tls/CMakeLists.txt
  3. 3 2
      components/esp-tls/esp_tls.c
  4. 1 1
      components/esp_http_client/CMakeLists.txt
  5. 1 3
      components/esp_http_server/CMakeLists.txt
  6. 13 0
      components/esp_hw_support/port/linux/chip_info.c
  7. 15 0
      components/freertos/CMakeLists.txt
  8. 51 0
      components/freertos/esp_additions/arch/linux/FreeRTOSSimulator_wrappers.c
  9. 1 2
      components/linux/CMakeLists.txt
  10. 0 18
      components/linux/esp_event_stubs.c
  11. 1 1
      components/linux/include/esp_linux_helper.h
  12. 13 0
      components/lwip/CMakeLists.txt
  13. 9 5
      components/lwip/port/linux/include/sys/fcntl.h
  14. 5 5
      components/lwip/port/linux/include/sys/socket.h
  15. 65 0
      components/lwip/port/linux/vfs_lwip.c
  16. 10 0
      components/tcp_transport/CMakeLists.txt
  17. 8 4
      examples/common_components/protocol_examples_tapif_io/Kconfig.projbuild
  18. 11 6
      examples/common_components/protocol_examples_tapif_io/README.md
  19. 7 8
      examples/common_components/protocol_examples_tapif_io/linux/tapio.c
  20. 36 1
      examples/common_components/protocol_examples_tapif_io/linux_connect.c
  21. 1 2
      examples/protocols/esp_http_client/CMakeLists.txt
  22. 1 1
      examples/protocols/esp_http_client/main/CMakeLists.txt
  23. 0 2
      examples/protocols/esp_http_client/main/esp_http_client_example.c
  24. 1 2
      examples/protocols/http_server/simple/CMakeLists.txt
  25. 0 10
      examples/protocols/linux_stubs/esp_stubs/esp_stubs.c
  26. 0 8
      examples/protocols/linux_stubs/esp_stubs/include/esp_event.h
  27. 8 0
      examples/protocols/linux_stubs/esp_stubs/include/esp_netif.h
  28. 1 2
      examples/protocols/sockets/tcp_client/CMakeLists.txt
  29. 1 1
      examples/protocols/sockets/tcp_client/main/CMakeLists.txt
  30. 1 1
      examples/protocols/sockets/udp_client/CMakeLists.txt
  31. 3 0
      examples/protocols/sockets/udp_client/sdkconfig.ci.linux

+ 1 - 1
.gitlab/ci/host-test.yml

@@ -282,8 +282,8 @@ test_sockets_on_host:
     - grep "Socket unable to connect" test.log
     # test the udp-client example with lwip sockets
     - cd ${IDF_PATH}/examples/protocols/sockets/udp_client
-    - echo 'CONFIG_EXAMPLE_IPV4_ADDR="127.0.0.1"' >> sdkconfig.defaults
     - idf.py --preview set-target linux
+    - cat sdkconfig.ci.linux > sdkconfig
     - idf.py build
     - timeout 5 ./build/udp_client.elf >test.log || true
     - grep "Message sent" test.log

+ 7 - 0
components/esp-tls/CMakeLists.txt

@@ -32,8 +32,15 @@ if(NOT ${IDF_TARGET} STREQUAL "linux")
 # due to cyclic dependencies present in IDF for lwip/esp_netif/mbedtls
 idf_component_get_property(lwip lwip COMPONENT_LIB)
 set_property(TARGET ${lwip} APPEND PROPERTY LINK_INTERFACE_MULTIPLICITY 5)
+else()
+    # Check if LWIP in the build for linux target to adapt esp-tls compatibility layer
+    idf_build_get_property(build_components BUILD_COMPONENTS)
+    if("lwip" IN_LIST build_components)
+        target_compile_definitions(${COMPONENT_LIB} PRIVATE ESP_TLS_WITH_LWIP=1)
+    endif()
 endif()
 
+
 if(CONFIG_ESP_TLS_USE_SECURE_ELEMENT)
     idf_component_optional_requires(PRIVATE espressif__esp-cryptoauthlib esp-cryptoauthlib)
 endif()

+ 3 - 2
components/esp-tls/esp_tls.c

@@ -17,9 +17,10 @@
 #include "esp_tls.h"
 #include "esp_tls_private.h"
 #include "esp_tls_error_capture_internal.h"
+#include <fcntl.h>
 #include <errno.h>
 
-#if CONFIG_IDF_TARGET_LINUX
+#if CONFIG_IDF_TARGET_LINUX && !ESP_TLS_WITH_LWIP
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
@@ -36,7 +37,7 @@ static inline char *ip6addr_ntoa(const ip6_addr_t *addr)
   return (char *)inet_ntop(AF_INET6, addr->s6_addr, str, 40);
 }
 
-#endif
+#endif  // CONFIG_IDF_TARGET_LINUX && !ESP_TLS_WITH_LWIP
 
 static const char *TAG = "esp-tls";
 

+ 1 - 1
components/esp_http_client/CMakeLists.txt

@@ -1,7 +1,7 @@
 if(NOT ${IDF_TARGET} STREQUAL "linux")
     set(req lwip esp_event)
 else()
-    set(req linux)
+    set(req linux esp_event)
 endif()
 
 idf_component_register(SRCS "esp_http_client.c"

+ 1 - 3
components/esp_http_server/CMakeLists.txt

@@ -1,14 +1,12 @@
 set(priv_req mbedtls)
 set(priv_inc_dir "src/util")
-set(requires http_parser)
+set(requires http_parser esp_event)
 if(NOT ${IDF_TARGET} STREQUAL "linux")
     list(APPEND priv_req lwip esp_timer)
     list(APPEND priv_inc_dir "src/port/esp32")
-    list(APPEND requires esp_event)
 else()
     list(APPEND priv_inc_dir "src/port/linux")
     list(APPEND priv_req pthread)
-    list(APPEND requires linux)
 endif()
 
 idf_component_register(SRCS "src/httpd_main.c"

+ 13 - 0
components/esp_hw_support/port/linux/chip_info.c

@@ -6,6 +6,7 @@
 
 #include <string.h>
 #include "esp_chip_info.h"
+#include "esp_mac.h"
 
 void esp_chip_info(esp_chip_info_t *out_info)
 {
@@ -18,3 +19,15 @@ void esp_chip_info(esp_chip_info_t *out_info)
     out_info->revision = 0;
     out_info->cores = 1;
 }
+
+esp_err_t esp_read_mac(uint8_t *mac, esp_mac_type_t type)
+{
+    // Provide Locally Administered (OUI range) MAC address on POSIX/Linux
+    mac[0] = 0x02;
+    mac[1] = 0x12;
+    mac[2] = 0x34;
+    mac[3] = 0x56;
+    mac[4] = 0x78;
+    mac[5] = 0xab;
+    return ESP_OK;
+}

+ 15 - 0
components/freertos/CMakeLists.txt

@@ -60,6 +60,18 @@ if(${target} STREQUAL "linux")
     if(NOT CONFIG_FREERTOS_SMP)
         list(APPEND srcs "${kernel_dir}/portable/${arch}/port_idf.c")
     endif()
+
+    # Check if we need to address the FreeRTOS EINTR coexistence with linux system calls
+    # if we're building without lwIP, we need to use linux system select which will receive
+    # EINTR event on every FreeRTOS interrupt, we workaround this problem by wrapping select()
+    # to bypass and silence the EINTR events
+    set(BYPASS_EINTR_ISSUE 0)
+    idf_build_get_property(build_components BUILD_COMPONENTS)
+    if(NOT "lwip" IN_LIST build_components)
+        set(BYPASS_EINTR_ISSUE 1)
+        list(APPEND srcs esp_additions/arch/linux/FreeRTOSSimulator_wrappers.c)
+    endif()
+
 else()
     list(APPEND srcs
         "app_startup.c"
@@ -99,6 +111,9 @@ idf_component_register(SRCS "${srcs}"
 if(${target} STREQUAL "linux")
     target_compile_definitions(${COMPONENT_LIB} PUBLIC "projCOVERAGE_TEST=0")
     target_link_libraries(${COMPONENT_LIB} PUBLIC pthread)
+    if(BYPASS_EINTR_ISSUE)
+        target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=select")
+    endif()
 else()
     idf_component_get_property(COMPONENT_DIR freertos COMPONENT_DIR)
 

+ 51 - 0
components/freertos/esp_additions/arch/linux/FreeRTOSSimulator_wrappers.c

@@ -0,0 +1,51 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <pthread.h>
+#include "esp_err.h"
+#include "errno.h"
+
+/** This module addresses the FreeRTOS simulator's coexistence with linux system calls from user apps.
+ *  It's only included when building without lwIP, so we need to use linux system's select() which would receive
+ *  EINTR event on every FreeRTOS interrupt; we workaround this problem by wrapping select()
+ *  to bypass and silence these events.
+ */
+extern int __real_select (int fd, fd_set * rfds, fd_set * wfds, fd_set *efds, struct timeval *tval);
+
+static inline int64_t get_us(void)
+{
+    struct timespec spec;
+    clock_gettime(CLOCK_REALTIME, &spec);
+    return spec.tv_nsec / 1000 + spec.tv_sec * 1000000;
+}
+
+int __wrap_select (int fd, fd_set * rfds, fd_set * wfds, fd_set *efds, struct timeval *tval)
+{
+    int ret;
+    struct timeval *tv = tval;
+    int64_t start = 0;
+    int64_t timeout_us = 0;
+    if (tv != NULL) {
+        start = get_us();
+        timeout_us = tval->tv_sec * 1000000 + tval->tv_usec;
+        struct timeval timeval_local = { .tv_sec = tval->tv_sec, .tv_usec = tval->tv_usec };
+        tv = &timeval_local;  // this (tv != NULL) indicates that we should handle timeouts
+    }
+    while ((ret = __real_select(fd, rfds, wfds, efds, tv)) < 0 && errno == EINTR) {
+        if (tv != NULL) {
+            int64_t now = get_us();
+            timeout_us -= now - start;
+            if (timeout_us < 0) {
+                errno = 0;
+                ret = 0;
+                break;
+            }
+            start = now;
+            tv->tv_usec = timeout_us % 1000000;
+            tv->tv_sec = timeout_us / 1000000;
+        }
+    }
+    return ret;
+}

+ 1 - 2
components/linux/CMakeLists.txt

@@ -3,6 +3,5 @@ if(NOT "${target}" STREQUAL "linux")
     return()
 endif()
 
-idf_component_register(SRCS esp_event_stubs.c
-                       INCLUDE_DIRS include ${IDF_PATH}/components/esp_event/include
+idf_component_register(INCLUDE_DIRS include
                        REQUIRED_IDF_TARGETS linux)

+ 0 - 18
components/linux/esp_event_stubs.c

@@ -1,18 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-#include "esp_err.h"
-#include "esp_event.h"
-
-esp_err_t esp_event_loop_create_default(void)
-{
-    return ESP_OK;
-}
-
-esp_err_t esp_event_post(esp_event_base_t event_base, int32_t event_id,
-        const void* event_data, size_t event_data_size, TickType_t ticks_to_wait)
-{
-    return ESP_OK;
-}

+ 1 - 1
components/linux/include/esp_linux_helper.h

@@ -9,7 +9,7 @@
 extern "C" {
 #endif
 
-#if CONFIG_IDF_TARGET_LINUX
+#if CONFIG_IDF_TARGET_LINUX && !defined(__containerof)
 #define __containerof(ptr, type, member) ({         \
     const typeof( ((type *)0)->member ) *__mptr = (ptr); \
     (type *)( (char *)__mptr - offsetof(type,member) );})

+ 13 - 0
components/lwip/CMakeLists.txt

@@ -13,6 +13,7 @@ set(include_dirs
     port/freertos/include/
     port/${target}/include
     port/${target}/include/arch
+    port/${target}/include/sys
     )
 
 set(srcs
@@ -142,6 +143,9 @@ if(NOT ${target} STREQUAL "linux")
     else()
         list(APPEND srcs "port/${target}/no_vfs_syscalls.c")
     endif()
+else()
+    # This wraps some posix IO functions to conditionally pass control to lwip
+    list(APPEND srcs "port/${target}/vfs_lwip.c")
 endif()
 
 if(CONFIG_LWIP_ICMP)
@@ -206,4 +210,13 @@ if(${target} STREQUAL "linux")
     set(THREADS_PREFER_PTHREAD_FLAG ON)
     find_package(Threads REQUIRED)
     target_link_libraries(${COMPONENT_LIB} PRIVATE Threads::Threads)
+    set(WRAP_FUNCTIONS      select
+                            read
+                            fcntl
+                            write
+                            close)
+    foreach(wrap ${WRAP_FUNCTIONS})
+                target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=${wrap}")
+                target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __wrap_${wrap}")
+    endforeach()
 endif()

+ 9 - 5
components/lwip/port/linux/include/sys/fcntl.h

@@ -4,9 +4,13 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 #pragma once
-#ifdef LWIP_HDR_ESP_LWIPOPTS_H
-// ignore when included from lwipopts.h since lwip provides all necessary definitions
-#else
-// otherwise include system fcntl
-#include_next <sys/fcntl.h>
+#include "sdkconfig.h"
+
+#ifdef LWIP_HDR_LINUX_SYS_SOCKETS_H
+// only if we prefer linux system sockets, include from system paths
+#include_next <fcntl.h>
+#elif CONFIG_IDF_TARGET_LINUX
+// need to declare, as on linux we bypass IDF vfs and wrap posix io functions
+extern int fcntl(int s, int cmd, ...);
 #endif
+// ignore otherwise (typically included from lwipopts.h) since lwip provides all necessary definitions

+ 5 - 5
components/lwip/port/linux/include/sys/socket.h

@@ -3,11 +3,11 @@
  *
  * SPDX-License-Identifier: Apache-2.0
  */
-#ifndef LWIP_HDR_LINUX_SYS_SOCKETS_H
-#define LWIP_HDR_LINUX_SYS_SOCKETS_H
+#pragma once
+#ifdef LWIP_HDR_LINUX_SYS_SOCKETS_H
+/* only if we prefer linux system sockets, include from system paths */
+#include_next <sys/socket.h>
+#else
 /* Include lwip sockets by default */
 #include "lwip/sockets.h"
-#else
-/* Otherwise use system sockets if LWIP_HDR_LINUX_SYS_SOCKETS_H already defined */
-#include_next <sys/socket.h>
 #endif /* LWIP_HDR_LINUX_SYS_SOCKETS_H */

+ 65 - 0
components/lwip/port/linux/vfs_lwip.c

@@ -0,0 +1,65 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <sys/socket.h>
+#include <stdarg.h>
+
+extern int __real_fcntl(int s, int cmd, ...);
+extern int __real_close(int s);
+extern ssize_t __real_write (int fd, const void *buf, size_t n);
+extern ssize_t __real_read (int fd, void *buf, size_t n);
+extern int __real_select (int fd, fd_set * rfds, fd_set * wfds, fd_set *efds, struct timeval *tval);
+
+ssize_t __wrap_write (int fd, const void *buf, size_t n)
+{
+#ifdef CONFIG_LWIP_MAX_SOCKETS
+    if (fd >= LWIP_SOCKET_OFFSET)
+        return lwip_write(fd, buf, n);
+#endif
+    return __real_write(fd, buf, n);
+}
+
+ssize_t __wrap_read (int fd, void *buf, size_t n)
+{
+#ifdef CONFIG_LWIP_MAX_SOCKETS
+    if (fd >= LWIP_SOCKET_OFFSET)
+        return lwip_read(fd, buf, n);
+#endif
+    return __real_read(fd, buf, n);
+}
+
+int __wrap_select (int fd, fd_set * rds, fd_set * wfds, fd_set *efds, struct timeval *tval)
+{
+#ifdef CONFIG_LWIP_MAX_SOCKETS
+    if (fd >= LWIP_SOCKET_OFFSET)
+        return lwip_select(fd, rds, wfds, efds, tval);
+#endif
+    return __real_select(fd, rds, wfds, efds, tval);
+}
+
+int __wrap_fcntl(int fd, int cmd, ...)
+{
+    va_list args;
+#ifdef CONFIG_LWIP_MAX_SOCKETS
+    if (fd >= LWIP_SOCKET_OFFSET) {
+        va_start(args, cmd);
+        int arg = va_arg(args, int);
+        va_end(args);
+        return lwip_fcntl(fd, cmd, arg);
+    }
+#endif
+
+    return __real_fcntl(fd, cmd, args);
+}
+
+int __wrap_close(int fd)
+{
+#ifdef CONFIG_LWIP_MAX_SOCKETS
+    if (fd >= LWIP_SOCKET_OFFSET)
+        return lwip_close(fd);
+#endif
+    return __real_close(fd);
+}

+ 10 - 0
components/tcp_transport/CMakeLists.txt

@@ -22,3 +22,13 @@ idf_component_register(SRCS "${srcs}"
                     INCLUDE_DIRS "include"
                     PRIV_INCLUDE_DIRS "private_include"
                     REQUIRES ${req})
+
+if(${IDF_TARGET} STREQUAL "linux")
+    # Check if LWIP in the build for linux target to add esp_timer to the dependencies
+    # since socks_proxy transport needs it and lwip & linux build could use it
+    idf_build_get_property(build_components BUILD_COMPONENTS)
+    if("lwip" IN_LIST build_components)
+        idf_component_get_property(esp_timer esp_timer COMPONENT_LIB)
+        target_link_libraries(${COMPONENT_LIB} PUBLIC ${esp_timer})
+    endif()
+endif()

+ 8 - 4
examples/common_components/protocol_examples_tapif_io/Kconfig.projbuild

@@ -3,7 +3,7 @@ menu "Example Connection Configuration"
     config EXAMPLE_CONNECT_LWIP_TAPIF
         bool "connect using lwip to linux tap interface"
         depends on IDF_TARGET_LINUX && ESP_NETIF_TCPIP_LWIP
-        default n
+        default y
 
     if EXAMPLE_CONNECT_LWIP_TAPIF
         config EXAMPLE_CONNECT_IPV4
@@ -18,24 +18,28 @@ menu "Example Connection Configuration"
             help
                 Set to true to setup link local address and wait until it's valid
 
+        config EXAMPLE_CONNECT_WAIT_FOR_IP
+            bool "run DHCP and wait for IP"
+            default y
+
         config EXAMPLE_CONNECT_TAPIF_IP_ADDR
             string "Static IP address"
             default "192.168.5.100"
-            depends on EXAMPLE_CONNECT_IPV4
+            depends on EXAMPLE_CONNECT_IPV4 && !EXAMPLE_CONNECT_WAIT_FOR_IP
             help
                 Set static IP address.
 
         config EXAMPLE_CONNECT_TAPIF_NETMASK
             string "Static netmask address"
             default "255.255.255.0"
-            depends on EXAMPLE_CONNECT_IPV4
+            depends on EXAMPLE_CONNECT_IPV4 && !EXAMPLE_CONNECT_WAIT_FOR_IP
             help
                 Set static netmask address.
 
         config EXAMPLE_CONNECT_TAPIF_GW
             string "Static gateway address"
             default "192.168.5.1"
-            depends on EXAMPLE_CONNECT_IPV4
+            depends on EXAMPLE_CONNECT_IPV4 && !EXAMPLE_CONNECT_WAIT_FOR_IP
             help
                 Set static gateway address.
 

+ 11 - 6
examples/common_components/protocol_examples_tapif_io/README.md

@@ -110,6 +110,8 @@ sudo iptables -A FORWARD -i tap0 -o eth0 -j ACCEPT
 It's also possible to configure the lwip interface to use DHCP client (common setup for most default network interfaces, such as Ethernet or WiFi station)
 and set up a DHCP server on the host machine to assign the IP address dynamically.
 
+This component sets up a DHCP client if `CONFIG_EXAMPLE_CONNECT_WAIT_FOR_IP` is enabled and waits for assigning an IP address. See below the description of DHCP client workflow for tap interface:
+
 1) **Configure and set the `esp-netif` up**
 
 * Same as in [API usage](#Usage-of-the-API), but update the base esp-netif config `3c)` to enable DHCP client
@@ -125,14 +127,17 @@ and set up a DHCP server on the host machine to assign the IP address dynamicall
     esp_netif_action_connected(tap_netif, 0, 0, 0);
 ```
 * Wait for the IP address to be assigned.
-This could be implemented as a wait loop below, as the esp-event currently doesn't support IP events on Linux target.
+This could be implemented using an event handler
 ```cpp
+    esp_netif_inherent_config_t base_cfg = {
+        ...
+       .get_ip_event = TAP0_GOT_IP,
+       ...
+    };
+    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, TAP0_GOT_IP, event_handler, NULL));
+    // wait for the IP event (e.g. using signalling semaphores from the handler)
+    // ...
     esp_netif_ip_info_t ip_info = {};
-    while (ip_info.ip.addr == 0) {
-        ESP_LOGI("tap-init", "No IP assigned, waiting...");
-        usleep(1000000);
-        esp_netif_get_ip_info(tap_netif, &ip_info);
-    }
     ESP_LOGI("tap-init", "Assigned IP address:"IPSTR ",", IP2STR(&ip_info.ip));
 ```
 

+ 7 - 8
examples/common_components/protocol_examples_tapif_io/linux/tapio.c

@@ -4,26 +4,25 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 #include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
 #include "esp_err.h"
 #include "esp_log.h"
-#include <stdlib.h>
 #include "esp_netif.h"
+
+// Use linux system sockets to connect to tap interface
+#define LWIP_HDR_LINUX_SYS_SOCKETS_H
+#include <sys/socket.h>
 #include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
+
 #include <sys/ioctl.h>
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <lwip/sys.h>
 #include "errno.h"
 
-#define LWIP_HDR_LINUX_SYS_SOCKETS_H
-
 #include <linux/if.h>
 #include <linux/if_tun.h>
-#include <esp_netif_net_stack.h>
 
 #define DEVTAP "/dev/net/tun"
 #define DEVTAP_NAME "tap0"

+ 36 - 1
examples/common_components/protocol_examples_tapif_io/linux_connect.c

@@ -7,6 +7,26 @@
 #include "esp_netif.h"      // esp-netif
 #include "tapio.h"          // esp-netif's driver side
 #include "lwip/tapif.h"     // esp-netif's network stack side
+#include "esp_log.h"
+
+#if CONFIG_EXAMPLE_CONNECT_WAIT_FOR_IP
+#include "esp_event.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/event_groups.h"
+
+static const char *TAG = "linux_connect";
+
+static EventGroupHandle_t s_events;
+
+static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
+{
+    xEventGroupSetBits(s_events, 1);
+}
+
+#endif // CONFIG_EXAMPLE_CONNECT_WAIT_FOR_IP
+
+#define TAP0_GOT_IP (0x1234)
 
 esp_err_t example_connect(void)
 {
@@ -25,14 +45,20 @@ esp_err_t example_connect(void)
     };
     // configure inherent esp-netif parameters
     esp_netif_ip_info_t ip_info = {};
+    esp_netif_flags_t netif_flags = (ESP_NETIF_FLAG_EVENT_IP_MODIFIED | ESP_NETIF_FLAG_AUTOUP);
+#if !CONFIG_EXAMPLE_CONNECT_WAIT_FOR_IP
     ip_info.ip.addr = ipaddr_addr(CONFIG_EXAMPLE_CONNECT_TAPIF_IP_ADDR);
     ip_info.netmask.addr = ipaddr_addr(CONFIG_EXAMPLE_CONNECT_TAPIF_NETMASK);
     ip_info.gw.addr = ipaddr_addr(CONFIG_EXAMPLE_CONNECT_TAPIF_GW);
+#else
+    netif_flags |= ESP_NETIF_DHCP_CLIENT;
+#endif
 
     esp_netif_inherent_config_t base_cfg = {
             .if_key = "TAP",
-            .flags = ESP_NETIF_FLAG_AUTOUP,
             .ip_info = &ip_info,
+            .flags = netif_flags,
+            .get_ip_event = TAP0_GOT_IP,
             .route_prio = 100
     };
 
@@ -46,6 +72,15 @@ esp_err_t example_connect(void)
     // create the interface and attach it to the tapio-handle
     esp_netif_t *tap_netif = esp_netif_new(&cfg);
     esp_netif_attach(tap_netif, driver_cfg.handle);
+#if CONFIG_EXAMPLE_CONNECT_WAIT_FOR_IP
+    ESP_LOGI(TAG, "Waiting for IP addresses...");
+    esp_netif_action_connected(tap_netif, 0, 0, 0);
+    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, TAP0_GOT_IP, event_handler, NULL));
+    s_events = xEventGroupCreate();
+    xEventGroupWaitBits(s_events, 1, pdFALSE, pdFALSE, portMAX_DELAY);
+    esp_netif_get_ip_info(tap_netif, &ip_info);
+    ESP_LOGI(TAG, "Assigned IP address:"IPSTR ",", IP2STR(&ip_info.ip));
+#endif // CONFIG_EXAMPLE_CONNECT_WAIT_FOR_IP
 #endif // EXAMPLE_CONNECT_LWIP_TAPIF
     return ESP_OK;
 }

+ 1 - 2
examples/protocols/esp_http_client/CMakeLists.txt

@@ -5,8 +5,7 @@ cmake_minimum_required(VERSION 3.16)
 set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
 
 if(${IDF_TARGET} STREQUAL "linux")
-    list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/"
-                    "$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs")
+    list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs)
     set(COMPONENTS main)
 endif()
 

+ 1 - 1
examples/protocols/esp_http_client/main/CMakeLists.txt

@@ -3,7 +3,7 @@
 # (If this was a component, we would set COMPONENT_EMBED_TXTFILES here.)
 set(requires "")
 if(${IDF_TARGET} STREQUAL "linux")
-    list(APPEND requires esp_stubs esp-tls esp_http_client protocol_examples_common nvs_flash)
+    list(APPEND requires esp_stubs esp_event esp-tls esp_http_client protocol_examples_common nvs_flash)
 endif()
 idf_component_register(SRCS "esp_http_client_example.c"
                     INCLUDE_DIRS "."

+ 0 - 2
examples/protocols/esp_http_client/main/esp_http_client_example.c

@@ -22,11 +22,9 @@
 #include "esp_crt_bundle.h"
 #endif
 
-#if !CONFIG_IDF_TARGET_LINUX
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "esp_system.h"
-#endif
 
 #include "esp_http_client.h"
 

+ 1 - 2
examples/protocols/http_server/simple/CMakeLists.txt

@@ -5,8 +5,7 @@ cmake_minimum_required(VERSION 3.16)
 set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
 
 if(${IDF_TARGET} STREQUAL "linux")
-    list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/"
-                    "$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs")
+    list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs")
     set(COMPONENTS main)
 endif()
 

+ 0 - 10
examples/protocols/linux_stubs/esp_stubs/esp_stubs.c

@@ -6,9 +6,6 @@
 #include <stdlib.h>
 #include "esp_err.h"
 #include "esp_log.h"
-#include "esp_event.h"
-
-extern void app_main(void);
 
 esp_err_t esp_netif_init(void)
 {
@@ -19,10 +16,3 @@ esp_err_t example_connect(void)
 {
     return ESP_OK;
 }
-
-int main(void)
-{
-    app_main();
-
-    return 0;
-}

+ 0 - 8
examples/protocols/linux_stubs/esp_stubs/include/esp_event.h

@@ -1,8 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Unlicense OR CC0-1.0
- */
-#include "esp_err.h"
-
-esp_err_t esp_event_loop_create_default(void);

+ 8 - 0
examples/protocols/linux_stubs/esp_stubs/include/esp_netif.h

@@ -8,4 +8,12 @@
 #include <ifaddrs.h>
 #include "esp_err.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 esp_err_t esp_netif_init(void);
+
+#ifdef __cplusplus
+}
+#endif

+ 1 - 2
examples/protocols/sockets/tcp_client/CMakeLists.txt

@@ -4,8 +4,7 @@ cmake_minimum_required(VERSION 3.16)
 set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
 
 if("${IDF_TARGET}" STREQUAL "linux")
-    list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/"
-                    "$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs")
+    list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs")
     set(COMPONENTS main)
 endif()
 

+ 1 - 1
examples/protocols/sockets/tcp_client/main/CMakeLists.txt

@@ -1,5 +1,5 @@
 if(${IDF_TARGET} STREQUAL "linux")
-    set(requires esp_stubs protocol_examples_common nvs_flash)
+    set(requires esp_event esp_stubs protocol_examples_common nvs_flash)
 endif()
 
 if("${CONFIG_EXAMPLE_IPV4}" STREQUAL y)

+ 1 - 1
examples/protocols/sockets/udp_client/CMakeLists.txt

@@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.16)
 if("${IDF_TARGET}" STREQUAL "linux")
     # This example uses an extra component with common functionality for lwip's port on linux target
     set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_tapif_io)
-    set(COMPONENTS main esp_netif protocol_examples_tapif_io startup esp_hw_support esp_system nvs_flash)
+    set(COMPONENTS main esp_netif lwip protocol_examples_tapif_io startup esp_hw_support esp_system nvs_flash)
 else()
     # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection on ESP target
     set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)

+ 3 - 0
examples/protocols/sockets/udp_client/sdkconfig.ci.linux

@@ -0,0 +1,3 @@
+CONFIG_IDF_TARGET="linux"
+CONFIG_EXAMPLE_IPV4_ADDR="127.0.0.1"
+CONFIG_EXAMPLE_CONNECT_LWIP_TAPIF=n