kopia lustrzana https://github.com/espressif/esp-idf
lwip/linux: Add lwip support for networking component under linux
linux/lwip: Wrap some IO posix functions * to workaourd the FreeRTOS EINTR issue (when building without lwip) * to correctly choose the sub-system based on fd (when building with lwip) -- passing control to either linux/system or to lwip This commit also addapts tapio-if to provide DHCP client by default and configurable settings for static IPpull/11344/head
rodzic
0bfffa0160
commit
b2af4d9689
|
@ -282,8 +282,8 @@ test_sockets_on_host:
|
||||||
- grep "Socket unable to connect" test.log
|
- grep "Socket unable to connect" test.log
|
||||||
# test the udp-client example with lwip sockets
|
# test the udp-client example with lwip sockets
|
||||||
- cd ${IDF_PATH}/examples/protocols/sockets/udp_client
|
- 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
|
- idf.py --preview set-target linux
|
||||||
|
- cat sdkconfig.ci.linux > sdkconfig
|
||||||
- idf.py build
|
- idf.py build
|
||||||
- timeout 5 ./build/udp_client.elf >test.log || true
|
- timeout 5 ./build/udp_client.elf >test.log || true
|
||||||
- grep "Message sent" test.log
|
- grep "Message sent" test.log
|
||||||
|
|
|
@ -32,8 +32,15 @@ if(NOT ${IDF_TARGET} STREQUAL "linux")
|
||||||
# due to cyclic dependencies present in IDF for lwip/esp_netif/mbedtls
|
# due to cyclic dependencies present in IDF for lwip/esp_netif/mbedtls
|
||||||
idf_component_get_property(lwip lwip COMPONENT_LIB)
|
idf_component_get_property(lwip lwip COMPONENT_LIB)
|
||||||
set_property(TARGET ${lwip} APPEND PROPERTY LINK_INTERFACE_MULTIPLICITY 5)
|
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()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if(CONFIG_ESP_TLS_USE_SECURE_ELEMENT)
|
if(CONFIG_ESP_TLS_USE_SECURE_ELEMENT)
|
||||||
idf_component_optional_requires(PRIVATE espressif__esp-cryptoauthlib esp-cryptoauthlib)
|
idf_component_optional_requires(PRIVATE espressif__esp-cryptoauthlib esp-cryptoauthlib)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -17,9 +17,10 @@
|
||||||
#include "esp_tls.h"
|
#include "esp_tls.h"
|
||||||
#include "esp_tls_private.h"
|
#include "esp_tls_private.h"
|
||||||
#include "esp_tls_error_capture_internal.h"
|
#include "esp_tls_error_capture_internal.h"
|
||||||
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_LINUX
|
#if CONFIG_IDF_TARGET_LINUX && !ESP_TLS_WITH_LWIP
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/tcp.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);
|
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";
|
static const char *TAG = "esp-tls";
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
if(NOT ${IDF_TARGET} STREQUAL "linux")
|
if(NOT ${IDF_TARGET} STREQUAL "linux")
|
||||||
set(req lwip esp_event)
|
set(req lwip esp_event)
|
||||||
else()
|
else()
|
||||||
set(req linux)
|
set(req linux esp_event)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS "esp_http_client.c"
|
idf_component_register(SRCS "esp_http_client.c"
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
set(priv_req mbedtls)
|
set(priv_req mbedtls)
|
||||||
set(priv_inc_dir "src/util")
|
set(priv_inc_dir "src/util")
|
||||||
set(requires http_parser)
|
set(requires http_parser esp_event)
|
||||||
if(NOT ${IDF_TARGET} STREQUAL "linux")
|
if(NOT ${IDF_TARGET} STREQUAL "linux")
|
||||||
list(APPEND priv_req lwip esp_timer)
|
list(APPEND priv_req lwip esp_timer)
|
||||||
list(APPEND priv_inc_dir "src/port/esp32")
|
list(APPEND priv_inc_dir "src/port/esp32")
|
||||||
list(APPEND requires esp_event)
|
|
||||||
else()
|
else()
|
||||||
list(APPEND priv_inc_dir "src/port/linux")
|
list(APPEND priv_inc_dir "src/port/linux")
|
||||||
list(APPEND priv_req pthread)
|
list(APPEND priv_req pthread)
|
||||||
list(APPEND requires linux)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS "src/httpd_main.c"
|
idf_component_register(SRCS "src/httpd_main.c"
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "esp_chip_info.h"
|
#include "esp_chip_info.h"
|
||||||
|
#include "esp_mac.h"
|
||||||
|
|
||||||
void esp_chip_info(esp_chip_info_t *out_info)
|
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->revision = 0;
|
||||||
out_info->cores = 1;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -60,6 +60,18 @@ if(${target} STREQUAL "linux")
|
||||||
if(NOT CONFIG_FREERTOS_SMP)
|
if(NOT CONFIG_FREERTOS_SMP)
|
||||||
list(APPEND srcs "${kernel_dir}/portable/${arch}/port_idf.c")
|
list(APPEND srcs "${kernel_dir}/portable/${arch}/port_idf.c")
|
||||||
endif()
|
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()
|
else()
|
||||||
list(APPEND srcs
|
list(APPEND srcs
|
||||||
"app_startup.c"
|
"app_startup.c"
|
||||||
|
@ -99,6 +111,9 @@ idf_component_register(SRCS "${srcs}"
|
||||||
if(${target} STREQUAL "linux")
|
if(${target} STREQUAL "linux")
|
||||||
target_compile_definitions(${COMPONENT_LIB} PUBLIC "projCOVERAGE_TEST=0")
|
target_compile_definitions(${COMPONENT_LIB} PUBLIC "projCOVERAGE_TEST=0")
|
||||||
target_link_libraries(${COMPONENT_LIB} PUBLIC pthread)
|
target_link_libraries(${COMPONENT_LIB} PUBLIC pthread)
|
||||||
|
if(BYPASS_EINTR_ISSUE)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=select")
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
idf_component_get_property(COMPONENT_DIR freertos COMPONENT_DIR)
|
idf_component_get_property(COMPONENT_DIR freertos COMPONENT_DIR)
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -3,6 +3,5 @@ if(NOT "${target}" STREQUAL "linux")
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS esp_event_stubs.c
|
idf_component_register(INCLUDE_DIRS include
|
||||||
INCLUDE_DIRS include ${IDF_PATH}/components/esp_event/include
|
|
||||||
REQUIRED_IDF_TARGETS linux)
|
REQUIRED_IDF_TARGETS linux)
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -9,7 +9,7 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_LINUX
|
#if CONFIG_IDF_TARGET_LINUX && !defined(__containerof)
|
||||||
#define __containerof(ptr, type, member) ({ \
|
#define __containerof(ptr, type, member) ({ \
|
||||||
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||||||
(type *)( (char *)__mptr - offsetof(type,member) );})
|
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||||
|
|
|
@ -13,6 +13,7 @@ set(include_dirs
|
||||||
port/freertos/include/
|
port/freertos/include/
|
||||||
port/${target}/include
|
port/${target}/include
|
||||||
port/${target}/include/arch
|
port/${target}/include/arch
|
||||||
|
port/${target}/include/sys
|
||||||
)
|
)
|
||||||
|
|
||||||
set(srcs
|
set(srcs
|
||||||
|
@ -142,6 +143,9 @@ if(NOT ${target} STREQUAL "linux")
|
||||||
else()
|
else()
|
||||||
list(APPEND srcs "port/${target}/no_vfs_syscalls.c")
|
list(APPEND srcs "port/${target}/no_vfs_syscalls.c")
|
||||||
endif()
|
endif()
|
||||||
|
else()
|
||||||
|
# This wraps some posix IO functions to conditionally pass control to lwip
|
||||||
|
list(APPEND srcs "port/${target}/vfs_lwip.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_LWIP_ICMP)
|
if(CONFIG_LWIP_ICMP)
|
||||||
|
@ -206,4 +210,13 @@ if(${target} STREQUAL "linux")
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
target_link_libraries(${COMPONENT_LIB} PRIVATE Threads::Threads)
|
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()
|
endif()
|
||||||
|
|
|
@ -4,9 +4,13 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
#ifdef LWIP_HDR_ESP_LWIPOPTS_H
|
#include "sdkconfig.h"
|
||||||
// ignore when included from lwipopts.h since lwip provides all necessary definitions
|
|
||||||
#else
|
#ifdef LWIP_HDR_LINUX_SYS_SOCKETS_H
|
||||||
// otherwise include system fcntl
|
// only if we prefer linux system sockets, include from system paths
|
||||||
#include_next <sys/fcntl.h>
|
#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
|
#endif
|
||||||
|
// ignore otherwise (typically included from lwipopts.h) since lwip provides all necessary definitions
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#ifndef LWIP_HDR_LINUX_SYS_SOCKETS_H
|
#pragma once
|
||||||
#define LWIP_HDR_LINUX_SYS_SOCKETS_H
|
#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 by default */
|
||||||
#include "lwip/sockets.h"
|
#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 */
|
#endif /* LWIP_HDR_LINUX_SYS_SOCKETS_H */
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -22,3 +22,13 @@ idf_component_register(SRCS "${srcs}"
|
||||||
INCLUDE_DIRS "include"
|
INCLUDE_DIRS "include"
|
||||||
PRIV_INCLUDE_DIRS "private_include"
|
PRIV_INCLUDE_DIRS "private_include"
|
||||||
REQUIRES ${req})
|
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()
|
||||||
|
|
|
@ -3,7 +3,7 @@ menu "Example Connection Configuration"
|
||||||
config EXAMPLE_CONNECT_LWIP_TAPIF
|
config EXAMPLE_CONNECT_LWIP_TAPIF
|
||||||
bool "connect using lwip to linux tap interface"
|
bool "connect using lwip to linux tap interface"
|
||||||
depends on IDF_TARGET_LINUX && ESP_NETIF_TCPIP_LWIP
|
depends on IDF_TARGET_LINUX && ESP_NETIF_TCPIP_LWIP
|
||||||
default n
|
default y
|
||||||
|
|
||||||
if EXAMPLE_CONNECT_LWIP_TAPIF
|
if EXAMPLE_CONNECT_LWIP_TAPIF
|
||||||
config EXAMPLE_CONNECT_IPV4
|
config EXAMPLE_CONNECT_IPV4
|
||||||
|
@ -18,24 +18,28 @@ menu "Example Connection Configuration"
|
||||||
help
|
help
|
||||||
Set to true to setup link local address and wait until it's valid
|
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
|
config EXAMPLE_CONNECT_TAPIF_IP_ADDR
|
||||||
string "Static IP address"
|
string "Static IP address"
|
||||||
default "192.168.5.100"
|
default "192.168.5.100"
|
||||||
depends on EXAMPLE_CONNECT_IPV4
|
depends on EXAMPLE_CONNECT_IPV4 && !EXAMPLE_CONNECT_WAIT_FOR_IP
|
||||||
help
|
help
|
||||||
Set static IP address.
|
Set static IP address.
|
||||||
|
|
||||||
config EXAMPLE_CONNECT_TAPIF_NETMASK
|
config EXAMPLE_CONNECT_TAPIF_NETMASK
|
||||||
string "Static netmask address"
|
string "Static netmask address"
|
||||||
default "255.255.255.0"
|
default "255.255.255.0"
|
||||||
depends on EXAMPLE_CONNECT_IPV4
|
depends on EXAMPLE_CONNECT_IPV4 && !EXAMPLE_CONNECT_WAIT_FOR_IP
|
||||||
help
|
help
|
||||||
Set static netmask address.
|
Set static netmask address.
|
||||||
|
|
||||||
config EXAMPLE_CONNECT_TAPIF_GW
|
config EXAMPLE_CONNECT_TAPIF_GW
|
||||||
string "Static gateway address"
|
string "Static gateway address"
|
||||||
default "192.168.5.1"
|
default "192.168.5.1"
|
||||||
depends on EXAMPLE_CONNECT_IPV4
|
depends on EXAMPLE_CONNECT_IPV4 && !EXAMPLE_CONNECT_WAIT_FOR_IP
|
||||||
help
|
help
|
||||||
Set static gateway address.
|
Set static gateway address.
|
||||||
|
|
||||||
|
|
|
@ -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)
|
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.
|
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**
|
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
|
* 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);
|
esp_netif_action_connected(tap_netif, 0, 0, 0);
|
||||||
```
|
```
|
||||||
* Wait for the IP address to be assigned.
|
* 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
|
```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 = {};
|
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));
|
ESP_LOGI("tap-init", "Assigned IP address:"IPSTR ",", IP2STR(&ip_info.ip));
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -4,26 +4,25 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "esp_netif.h"
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_log.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 <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <lwip/sys.h>
|
#include <lwip/sys.h>
|
||||||
#include "errno.h"
|
#include "errno.h"
|
||||||
|
|
||||||
#define LWIP_HDR_LINUX_SYS_SOCKETS_H
|
|
||||||
|
|
||||||
#include <linux/if.h>
|
#include <linux/if.h>
|
||||||
#include <linux/if_tun.h>
|
#include <linux/if_tun.h>
|
||||||
#include <esp_netif_net_stack.h>
|
|
||||||
|
|
||||||
#define DEVTAP "/dev/net/tun"
|
#define DEVTAP "/dev/net/tun"
|
||||||
#define DEVTAP_NAME "tap0"
|
#define DEVTAP_NAME "tap0"
|
||||||
|
|
|
@ -7,6 +7,26 @@
|
||||||
#include "esp_netif.h" // esp-netif
|
#include "esp_netif.h" // esp-netif
|
||||||
#include "tapio.h" // esp-netif's driver side
|
#include "tapio.h" // esp-netif's driver side
|
||||||
#include "lwip/tapif.h" // esp-netif's network stack 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)
|
esp_err_t example_connect(void)
|
||||||
{
|
{
|
||||||
|
@ -25,14 +45,20 @@ esp_err_t example_connect(void)
|
||||||
};
|
};
|
||||||
// configure inherent esp-netif parameters
|
// configure inherent esp-netif parameters
|
||||||
esp_netif_ip_info_t ip_info = {};
|
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.ip.addr = ipaddr_addr(CONFIG_EXAMPLE_CONNECT_TAPIF_IP_ADDR);
|
||||||
ip_info.netmask.addr = ipaddr_addr(CONFIG_EXAMPLE_CONNECT_TAPIF_NETMASK);
|
ip_info.netmask.addr = ipaddr_addr(CONFIG_EXAMPLE_CONNECT_TAPIF_NETMASK);
|
||||||
ip_info.gw.addr = ipaddr_addr(CONFIG_EXAMPLE_CONNECT_TAPIF_GW);
|
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 = {
|
esp_netif_inherent_config_t base_cfg = {
|
||||||
.if_key = "TAP",
|
.if_key = "TAP",
|
||||||
.flags = ESP_NETIF_FLAG_AUTOUP,
|
|
||||||
.ip_info = &ip_info,
|
.ip_info = &ip_info,
|
||||||
|
.flags = netif_flags,
|
||||||
|
.get_ip_event = TAP0_GOT_IP,
|
||||||
.route_prio = 100
|
.route_prio = 100
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -46,6 +72,15 @@ esp_err_t example_connect(void)
|
||||||
// create the interface and attach it to the tapio-handle
|
// create the interface and attach it to the tapio-handle
|
||||||
esp_netif_t *tap_netif = esp_netif_new(&cfg);
|
esp_netif_t *tap_netif = esp_netif_new(&cfg);
|
||||||
esp_netif_attach(tap_netif, driver_cfg.handle);
|
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
|
#endif // EXAMPLE_CONNECT_LWIP_TAPIF
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,7 @@ cmake_minimum_required(VERSION 3.16)
|
||||||
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
|
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
|
||||||
|
|
||||||
if(${IDF_TARGET} STREQUAL "linux")
|
if(${IDF_TARGET} STREQUAL "linux")
|
||||||
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/"
|
list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs)
|
||||||
"$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs")
|
|
||||||
set(COMPONENTS main)
|
set(COMPONENTS main)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# (If this was a component, we would set COMPONENT_EMBED_TXTFILES here.)
|
# (If this was a component, we would set COMPONENT_EMBED_TXTFILES here.)
|
||||||
set(requires "")
|
set(requires "")
|
||||||
if(${IDF_TARGET} STREQUAL "linux")
|
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()
|
endif()
|
||||||
idf_component_register(SRCS "esp_http_client_example.c"
|
idf_component_register(SRCS "esp_http_client_example.c"
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
|
|
|
@ -22,11 +22,9 @@
|
||||||
#include "esp_crt_bundle.h"
|
#include "esp_crt_bundle.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !CONFIG_IDF_TARGET_LINUX
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "esp_http_client.h"
|
#include "esp_http_client.h"
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,7 @@ cmake_minimum_required(VERSION 3.16)
|
||||||
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
|
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
|
||||||
|
|
||||||
if(${IDF_TARGET} STREQUAL "linux")
|
if(${IDF_TARGET} STREQUAL "linux")
|
||||||
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/"
|
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs")
|
||||||
"$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs")
|
|
||||||
set(COMPONENTS main)
|
set(COMPONENTS main)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_event.h"
|
|
||||||
|
|
||||||
extern void app_main(void);
|
|
||||||
|
|
||||||
esp_err_t esp_netif_init(void)
|
esp_err_t esp_netif_init(void)
|
||||||
{
|
{
|
||||||
|
@ -19,10 +16,3 @@ esp_err_t example_connect(void)
|
||||||
{
|
{
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
app_main();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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,4 +8,12 @@
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
esp_err_t esp_netif_init(void);
|
esp_err_t esp_netif_init(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -4,8 +4,7 @@ cmake_minimum_required(VERSION 3.16)
|
||||||
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
|
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
|
||||||
|
|
||||||
if("${IDF_TARGET}" STREQUAL "linux")
|
if("${IDF_TARGET}" STREQUAL "linux")
|
||||||
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/"
|
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs")
|
||||||
"$ENV{IDF_PATH}/examples/protocols/linux_stubs/esp_stubs")
|
|
||||||
set(COMPONENTS main)
|
set(COMPONENTS main)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
if(${IDF_TARGET} STREQUAL "linux")
|
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()
|
endif()
|
||||||
|
|
||||||
if("${CONFIG_EXAMPLE_IPV4}" STREQUAL y)
|
if("${CONFIG_EXAMPLE_IPV4}" STREQUAL y)
|
||||||
|
|
|
@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.16)
|
||||||
if("${IDF_TARGET}" STREQUAL "linux")
|
if("${IDF_TARGET}" STREQUAL "linux")
|
||||||
# This example uses an extra component with common functionality for lwip's port on linux target
|
# 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(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()
|
else()
|
||||||
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection on ESP target
|
# 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)
|
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
CONFIG_IDF_TARGET="linux"
|
||||||
|
CONFIG_EXAMPLE_IPV4_ADDR="127.0.0.1"
|
||||||
|
CONFIG_EXAMPLE_CONNECT_LWIP_TAPIF=n
|
Ładowanie…
Reference in New Issue