From 3bf488eb860d8fee4fa43f27eb5ac284d1c4dc50 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 12 Jun 2020 16:43:34 +0200 Subject: [PATCH] esp-netif: SLIP interface refactor to isolate interface from drivers * Original commit: espressif/esp-idf@1a41545c3eb7c3b9ed6e64cd3800743236e469cb --- .../protocols/slip/slip_udp/CMakeLists.txt | 6 -- examples/protocols/slip/slip_udp/README.md | 32 ++++++- .../components/slip_modem/CMakeLists.txt | 2 +- .../components/slip_modem/component.mk | 3 + .../slip_modem/include/slip_modem.h | 13 +++ .../slip_modem/library/slip_modem.c | 87 ++++++------------- .../slip/slip_udp/main/Kconfig.projbuild | 18 ++-- .../slip/slip_udp/main/slip_client_main.c | 78 ++++++++++------- 8 files changed, 134 insertions(+), 105 deletions(-) rename examples/protocols/slip/{ => slip_udp}/components/slip_modem/CMakeLists.txt (79%) create mode 100644 examples/protocols/slip/slip_udp/components/slip_modem/component.mk rename examples/protocols/slip/{ => slip_udp}/components/slip_modem/include/slip_modem.h (71%) rename examples/protocols/slip/{ => slip_udp}/components/slip_modem/library/slip_modem.c (80%) diff --git a/examples/protocols/slip/slip_udp/CMakeLists.txt b/examples/protocols/slip/slip_udp/CMakeLists.txt index b9d68c60f..5d7fdd6ce 100644 --- a/examples/protocols/slip/slip_udp/CMakeLists.txt +++ b/examples/protocols/slip/slip_udp/CMakeLists.txt @@ -2,11 +2,5 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) -set(EXTRA_COMPONENT_DIRS - ../components/slip_modem/ -) - - include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(slip_client) - diff --git a/examples/protocols/slip/slip_udp/README.md b/examples/protocols/slip/slip_udp/README.md index 334d2d467..d7869ff97 100644 --- a/examples/protocols/slip/slip_udp/README.md +++ b/examples/protocols/slip/slip_udp/README.md @@ -4,7 +4,7 @@ ## Overview -This provides SLIP support for connection to Contiki gateway devices, allowing the ESP32 to be used to bridge between low-power networks and IP (Wifi / Ethernet). +This provides SLIP support for connection to Contiki gateway devices, allowing the ESP platform board to be used to bridge between low-power networks and IP (Wifi / Ethernet). ## How to use example @@ -12,7 +12,33 @@ This provides SLIP support for connection to Contiki gateway devices, allowing t To run this example, you need an ESP32 dev board (e.g. ESP32-WROVER Kit) or ESP32 core board (e.g. ESP32-DevKitC). For test purpose, you also need a SLIP capable gateway device, such as anything running [Contiki](https://github.com/contiki-os/contiki) gateway firmware. -You can also try other modules as long as they implement the SLIP protocol. +You can also try other modules as long as they implement the SLIP protocol (e.g. linux device with slip module loaded) + +#### Setup a test SLIP device + +It is possible to configure any device with linux and a serial interface +(e.g. raspberry PI or a PC with USB to serial bridge) to enable SLIP interface. + +To test this example with such device, please follow these steps: + +- Configure IPv4 mode in the example configuration menu + +- Setup SLIP interface +``` +slattach -v -L -s 115200 -p slip /dev/ttyAMA0 +``` +where the `/dev/ttyAMA0` is the device's serial port + +- Configure IP addresses +``` +ifconfig sl0 10.0.0.1 dstaddr 10.0.0.2 +``` +where the `10.0.0.2` is IPv4 address of the ESP platform board + +- Send and receive back UDP packets, as the example implements UDP echo server +``` +nc -u 10.0.0.2 5678 +``` #### Pin Assignment @@ -30,7 +56,7 @@ You can also try other modules as long as they implement the SLIP protocol. Open the project configuration menu (`idf.py menuconfig`). Then go into `Example Configuration` menu. - Choose the RX and TX pins - +- Choose port number and IP protocol for socket udp server For use in external projects `SLIP support` must be enabled under the `components/lwip` menu. diff --git a/examples/protocols/slip/components/slip_modem/CMakeLists.txt b/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt similarity index 79% rename from examples/protocols/slip/components/slip_modem/CMakeLists.txt rename to examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt index 4a596ca72..7739fdfbc 100644 --- a/examples/protocols/slip/components/slip_modem/CMakeLists.txt +++ b/examples/protocols/slip/slip_udp/components/slip_modem/CMakeLists.txt @@ -3,6 +3,6 @@ idf_component_register( SRCS "library/slip_modem.c" INCLUDE_DIRS "include" - REQUIRES lwip esp_netif + REQUIRES esp_netif ) diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/component.mk b/examples/protocols/slip/slip_udp/components/slip_modem/component.mk new file mode 100644 index 000000000..b9a426049 --- /dev/null +++ b/examples/protocols/slip/slip_udp/components/slip_modem/component.mk @@ -0,0 +1,3 @@ +COMPONENT_ADD_INCLUDEDIRS := include + +COMPONENT_SRCDIRS := library diff --git a/examples/protocols/slip/components/slip_modem/include/slip_modem.h b/examples/protocols/slip/slip_udp/components/slip_modem/include/slip_modem.h similarity index 71% rename from examples/protocols/slip/components/slip_modem/include/slip_modem.h rename to examples/protocols/slip/slip_udp/components/slip_modem/include/slip_modem.h index e0e04da4a..2cbd4be51 100644 --- a/examples/protocols/slip/components/slip_modem/include/slip_modem.h +++ b/examples/protocols/slip/slip_udp/components/slip_modem/include/slip_modem.h @@ -1,3 +1,16 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #pragma once diff --git a/examples/protocols/slip/components/slip_modem/library/slip_modem.c b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c similarity index 80% rename from examples/protocols/slip/components/slip_modem/library/slip_modem.c rename to examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c index d7b6b4fba..0583dc238 100644 --- a/examples/protocols/slip/components/slip_modem/library/slip_modem.c +++ b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c @@ -1,28 +1,27 @@ - +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// 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 "slip_modem.h" - #include "esp_netif.h" #include "esp_netif_slip.h" #include "esp_event.h" #include "esp_log.h" - -#include "lwip/opt.h" -#include "lwip/sio.h" -#include "lwip/ip.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/netif.h" - -#include "esp_netif_slip.h" - - #define SLIP_RX_TASK_PRIORITY 10 #define SLIP_RX_TASK_STACK_SIZE (4 * 1024) - static const char *TAG = "esp-slip_modem"; @@ -53,9 +52,6 @@ struct esp_slip_modem { // ESP base netif driver esp_netif_driver_base_t base; - // LWIP slip context - lwip_slip_ctx_t *slip_driver; - // Uart for use with slip esp_slip_uart_t uart; @@ -72,28 +68,15 @@ struct esp_slip_modem { }; -// Forward function definitions +// Forward function declaration static void esp_slip_modem_uart_rx_task(void *arg); static esp_err_t esp_slip_modem_post_attach(esp_netif_t *esp_netif, void *args); - -// TODO: netif internal functions required for driver operation -esp_err_t esp_netif_start_slip(lwip_slip_ctx_t *slip_ctx); -esp_err_t esp_netif_stop_slip(lwip_slip_ctx_t *slip_ctx); - -void esp_netif_lwip_slip_output(lwip_slip_ctx_t *slip_ctx, void *buffer, size_t len); -void esp_netif_lwip_slip_input(void *ctx, void *buffer, size_t len, void *eb); - - // Create a new slip netif void *esp_slip_modem_create(esp_netif_t *slip_netif, esp_slip_modem_config_t *modem_config) { ESP_LOGI(TAG, "%s: Creating slip modem (netif: %p)", __func__, slip_netif); - // Fetch lwip slip ctx object - // TODO: is the the best / a reasonable approach? - lwip_slip_ctx_t *slip_ctx = esp_netif_lwip_slip_get_ctx(slip_netif); - ESP_LOGD(TAG, "%s (netif: %p)", __func__, slip_netif); esp_slip_modem_t *slip_modem = calloc(1, sizeof(esp_slip_modem_t)); @@ -103,7 +86,6 @@ void *esp_slip_modem_create(esp_netif_t *slip_netif, esp_slip_modem_config_t *mo } // Attach driver and post_attach callbacks - slip_modem->slip_driver = slip_ctx; slip_modem->base.post_attach = esp_slip_modem_post_attach; // Attach config @@ -135,8 +117,6 @@ static esp_err_t esp_slip_driver_start(esp_slip_modem_t *slip_modem) return ESP_ERR_NO_MEM; } - // Then, initialise UART - // Build configuration uart_config_t uart_config = { .baud_rate = slip_modem->uart.uart_baud, @@ -160,7 +140,7 @@ static esp_err_t esp_slip_driver_start(esp_slip_modem_t *slip_modem) xTaskCreate(esp_slip_modem_uart_rx_task, "slip_modem_uart_rx_task", SLIP_RX_TASK_STACK_SIZE, slip_modem, SLIP_RX_TASK_PRIORITY, &slip_modem->uart.uart_rx_task); // Finally, initialise slip network interface - esp_netif_start_slip(slip_modem->slip_driver); + esp_netif_action_start(slip_modem->base.netif, 0, 0, 0); return ESP_OK; } @@ -169,7 +149,7 @@ static esp_err_t esp_slip_driver_start(esp_slip_modem_t *slip_modem) esp_err_t esp_slip_modem_destroy(esp_slip_modem_t *slip_modem) { // Stop slip driver - esp_netif_stop_slip(slip_modem->slip_driver); + esp_netif_action_stop(slip_modem->base.netif, 0, 0, 0); // Stop uart rx task vTaskDelete(slip_modem->uart.uart_rx_task); @@ -184,27 +164,21 @@ esp_err_t esp_slip_modem_destroy(esp_slip_modem_t *slip_modem) } // Modem transmit for glue logic -esp_err_t esp_slip_modem_transmit(void *slip_driver, void *buffer, size_t len) +static esp_err_t esp_slip_modem_transmit(void *slip_driver, void *buffer, size_t len) { ESP_LOGD(TAG, "%s", __func__); ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_DEBUG); + esp_slip_modem_t *slip_modem = (esp_slip_modem_t *) slip_driver; - lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *) slip_driver; - - esp_netif_lwip_slip_output(slip_ctx, buffer, len); - + int32_t res = uart_write_bytes(slip_modem->uart.uart_dev, (char *)buffer, len); + if (res < 0) { + // Handle errors + ESP_LOGE(TAG, "%s: uart_write_bytes error %i", __func__, res); + return ESP_FAIL; + } return ESP_OK; } -// Modem receive for glue logic -void esp_slip_modem_receive(esp_netif_t *esp_netif, void *buffer, size_t len) -{ - ESP_LOGD(TAG, "%s", __func__); - ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_DEBUG); - - esp_netif_receive(esp_netif, buffer, len, NULL); -} - // Post-attach handler for netif static esp_err_t esp_slip_modem_post_attach(esp_netif_t *esp_netif, void *args) { @@ -215,7 +189,7 @@ static esp_err_t esp_slip_modem_post_attach(esp_netif_t *esp_netif, void *args) const esp_netif_driver_ifconfig_t driver_ifconfig = { .driver_free_rx_buffer = NULL, .transmit = esp_slip_modem_transmit, - .handle = slip_modem->slip_driver, + .handle = slip_modem, }; slip_modem->base.netif = esp_netif; @@ -226,8 +200,7 @@ static esp_err_t esp_slip_modem_post_attach(esp_netif_t *esp_netif, void *args) return ESP_OK; } -esp_err_t esp_slip_modem_set_default_handlers(esp_netif_t *esp_netif) -{ +esp_err_t esp_slip_modem_set_default_handlers(esp_netif_t *esp_netif) { esp_err_t ret; if (esp_netif == NULL) { @@ -248,8 +221,6 @@ esp_err_t esp_slip_modem_set_default_handlers(esp_netif_t *esp_netif) fail: esp_eth_clear_default_handlers(esp_netif); return ret; - - return ESP_OK; } esp_err_t esp_slip_modem_clear_default_handlers(void *esp_netif) @@ -265,15 +236,13 @@ esp_err_t esp_slip_modem_clear_default_handlers(void *esp_netif) } - static void esp_slip_modem_uart_rx_task(void *arg) { esp_slip_modem_t *slip_modem = (esp_slip_modem_t *) arg; - ESP_LOGD(TAG, "Start SLIP modem RX task (slip_modem %p slip_ctx %p filter: %p)", slip_modem, slip_modem->slip_driver, slip_modem->rx_filter); + ESP_LOGD(TAG, "Start SLIP modem RX task (slip_modem %p filter: %p)", slip_modem, slip_modem->rx_filter); ESP_LOGD(TAG, "Uart: %d, buffer: %p (%d bytes)", slip_modem->uart.uart_dev, slip_modem->buffer, slip_modem->buffer_len); - while (slip_modem->running == true) { // Read data from the UART int len = uart_read_bytes(slip_modem->uart.uart_dev, slip_modem->buffer, slip_modem->buffer_len, 1 / portTICK_RATE_MS); @@ -293,7 +262,7 @@ static void esp_slip_modem_uart_rx_task(void *arg) } // Pass received bytes in to slip interface - esp_netif_lwip_slip_input(slip_modem->slip_driver, slip_modem->buffer, len, NULL); + esp_netif_receive(slip_modem->base.netif, slip_modem->buffer, len, NULL); } // Yeild to allow other tasks to progress diff --git a/examples/protocols/slip/slip_udp/main/Kconfig.projbuild b/examples/protocols/slip/slip_udp/main/Kconfig.projbuild index 1709058d0..e23abfa08 100644 --- a/examples/protocols/slip/slip_udp/main/Kconfig.projbuild +++ b/examples/protocols/slip/slip_udp/main/Kconfig.projbuild @@ -21,12 +21,18 @@ menu "Example Configuration" help Baud rate for UART communication - config EXAMPLE_UDP_PORT - int "Port for UDP echo server" - default 5678 - help - Port for UDP echo server in example - endmenu + config EXAMPLE_UDP_PORT + int "Port for UDP echo server" + default 5678 + help + Port for UDP echo server in example + + config EXAMPLE_IPV4 + bool "Test with IPv4 address" + default n + help + Test interface using IPv4 + endmenu diff --git a/examples/protocols/slip/slip_udp/main/slip_client_main.c b/examples/protocols/slip/slip_udp/main/slip_client_main.c index 682e363eb..2fdab8800 100644 --- a/examples/protocols/slip/slip_udp/main/slip_client_main.c +++ b/examples/protocols/slip/slip_udp/main/slip_client_main.c @@ -9,8 +9,6 @@ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/event_groups.h" - #include "esp_system.h" #include "esp_log.h" @@ -19,8 +17,6 @@ #include "esp_netif_slip.h" #include "lwip/sockets.h" -#include "lwip/dns.h" -#include "lwip/netdb.h" #include "slip_modem.h" @@ -29,14 +25,12 @@ static const char *TAG = "SLIP_EXAMPLE"; #define STACK_SIZE (10 * 1024) #define PRIORITY 10 -TaskHandle_t udp_rx_tx_handle; - static void udp_rx_tx_task(void *arg) { char addr_str[128]; uint8_t rx_buff[1024]; - int sock = *(int *)arg; + int sock = (int)arg; struct sockaddr_in6 source_addr; socklen_t socklen = sizeof(source_addr); @@ -53,7 +47,11 @@ static void udp_rx_tx_task(void *arg) } // Parse out address to string - inet6_ntoa_r(source_addr.sin6_addr, addr_str, sizeof(addr_str) - 1); + if (source_addr.sin6_family == PF_INET) { + inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); + } else if (source_addr.sin6_family == PF_INET6) { + inet6_ntoa_r(source_addr.sin6_addr, addr_str, sizeof(addr_str) - 1); + } // Force null termination of received data and print rx_buff[len] = 0; @@ -70,37 +68,51 @@ static void udp_rx_tx_task(void *arg) vTaskDelete(NULL); } -esp_err_t udp_rx_tx_init() +esp_err_t udp_rx_tx_init(void) { // Setup bind address struct sockaddr_in6 dest_addr; +#if CONFIG_EXAMPLE_IPV4 + sa_family_t family = AF_INET; + int ip_protocol = IPPROTO_IP; + struct sockaddr_in *dest_addr_ip4 = (struct sockaddr_in *)&dest_addr; + dest_addr_ip4->sin_addr.s_addr = htonl(INADDR_ANY); + dest_addr_ip4->sin_family = AF_INET; + dest_addr_ip4->sin_port = htons(CONFIG_EXAMPLE_UDP_PORT); + ip_protocol = IPPROTO_IP; +#else + sa_family_t family = AF_INET6; + int ip_protocol = IPPROTO_IPV6; bzero(&dest_addr.sin6_addr.un, sizeof(dest_addr.sin6_addr.un)); - dest_addr.sin6_family = AF_INET6; + dest_addr.sin6_family = family; dest_addr.sin6_port = htons(CONFIG_EXAMPLE_UDP_PORT); +#endif // Create socket - int sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IPV6); + int sock = socket(family, SOCK_DGRAM, ip_protocol); if (sock < 0) { ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); - return -1; + return ESP_FAIL; } // Disable IPv4 and reuse address int opt = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); +#if !CONFIG_EXAMPLE_IPV4 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)); +#endif // Bind socket int err = bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); if (err < 0) { ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno); - return -2; + return ESP_FAIL; } ESP_LOGI(TAG, "Socket bound, port %d", CONFIG_EXAMPLE_UDP_PORT); // Start UDP rx thread - xTaskCreate(udp_rx_tx_task, "udp_rx_tx", STACK_SIZE, &sock, PRIORITY, &udp_rx_tx_handle); + xTaskCreate(udp_rx_tx_task, "udp_rx_tx", STACK_SIZE, (void *)sock, PRIORITY, NULL); return ESP_OK; } @@ -111,7 +123,7 @@ static void slip_set_prefix(esp_netif_t *slip_netif) uint8_t buff[10] = {0}; // Fetch the slip interface IP - const ip6_addr_t *addr = esp_slip_get_ip6(slip_netif); + const esp_ip6_addr_t *addr = esp_slip_get_ip6(slip_netif); ESP_LOGI(TAG, "%s: prefix set (%08x:%08x)", __func__, lwip_ntohl(addr->addr[0]), lwip_ntohl(addr->addr[1])); @@ -129,7 +141,7 @@ static void slip_set_prefix(esp_netif_t *slip_netif) esp_netif_lwip_slip_raw_output(slip_netif, buff, 2 + 8); } -// slip_rx_filter filters incomming commands from the slip interface +// slip_rx_filter filters incoming commands from the slip interface // this implementation is designed for use with contiki slip devices bool slip_rx_filter(void *ctx, uint8_t *data, uint32_t len) { @@ -162,23 +174,34 @@ bool slip_rx_filter(void *ctx, uint8_t *data, uint32_t len) return false; } +#if CONFIG_EXAMPLE_IPV4 +static const esp_netif_ip_info_t s_slip_ip4 = { + .ip = { .addr = ESP_IP4TOADDR( 10, 0, 0, 2) }, +}; +#endif + // Initialise the SLIP interface -esp_netif_t *slip_if_init() +esp_netif_t *slip_if_init(void) { ESP_LOGI(TAG, "Initialising SLIP interface"); - esp_netif_config_t cfg = ESP_NETIF_DEFAULT_SLIP(); + esp_netif_inherent_config_t base_cfg = ESP_NETIF_INHERENT_DEFAULT_SLIP() +#if CONFIG_EXAMPLE_IPV4 + base_cfg.ip_info = &s_slip_ip4; +#endif + esp_netif_config_t cfg = { .base = &base_cfg, + .driver = NULL, + .stack = ESP_NETIF_NETSTACK_DEFAULT_SLIP }; + esp_netif_t *slip_netif = esp_netif_new(&cfg); - esp_netif_slip_config_t slip_config = { - .uart_dev = UART_NUM_2, - }; + esp_netif_slip_config_t slip_config; - IP6_ADDR(&slip_config.addr, + IP6_ADDR(&slip_config.ip6_addr, lwip_htonl(0xfd000000), lwip_htonl(0x00000000), lwip_htonl(0x00000000), - lwip_htonl(0x000000001) + lwip_htonl(0x00000001) ); esp_netif_slip_set_params(slip_netif, &slip_config); @@ -186,7 +209,7 @@ esp_netif_t *slip_if_init() ESP_LOGI(TAG, "Initialising SLIP modem"); esp_slip_modem_config_t modem_cfg = { - .uart_dev = UART_NUM_2, + .uart_dev = UART_NUM_1, .uart_tx_pin = CONFIG_EXAMPLE_UART_TX_PIN, .uart_rx_pin = CONFIG_EXAMPLE_UART_RX_PIN, @@ -209,7 +232,7 @@ esp_netif_t *slip_if_init() void app_main(void) { // Setup networking - tcpip_adapter_init(); + esp_netif_init(); esp_log_level_set("*", ESP_LOG_DEBUG); @@ -221,9 +244,4 @@ void app_main(void) // Setup UDP loopback service udp_rx_tx_init(); - - // Run - while (1) { - vTaskDelay(portTICK_PERIOD_MS * 10); - } }