From 266be00254c6e8dcbda75005092260161c03ee95 Mon Sep 17 00:00:00 2001 From: ryan Date: Thu, 21 May 2020 17:55:56 +1200 Subject: [PATCH 1/4] esp-netif: Added esp_netif slip support, slip_modem component and example Merges https://github.com/espressif/esp-idf/pull/4985 --- components/esp_netif/CMakeLists.txt | 2 + components/esp_netif/esp_netif_defaults.c | 2 + .../esp_netif/include/esp_netif_defaults.h | 35 +- components/esp_netif/include/esp_netif_slip.h | 123 +++++++ .../esp_netif/include/esp_netif_types.h | 7 +- components/esp_netif/lwip/esp_netif_lwip.c | 46 ++- .../esp_netif/lwip/esp_netif_lwip_defaults.c | 11 +- .../esp_netif/lwip/esp_netif_lwip_internal.h | 13 +- .../esp_netif/lwip/esp_netif_lwip_ppp.c | 4 +- .../esp_netif/lwip/esp_netif_lwip_slip.c | 245 ++++++++++++++ .../esp_netif/lwip/esp_netif_lwip_slip.h | 71 ++++ .../esp_netif/lwip/esp_netif_lwip_slip_sio.c | 163 ++++++++++ components/lwip/Kconfig | 22 ++ components/lwip/port/esp32/include/lwipopts.h | 21 ++ .../pppos_client/main/CMakeLists.txt | 3 +- .../slip/components/slip_modem/CMakeLists.txt | 8 + .../slip_modem/include/slip_modem.h | 55 ++++ .../slip_modem/library/slip_modem.c | 303 ++++++++++++++++++ .../protocols/slip/slip_udp/CMakeLists.txt | 12 + examples/protocols/slip/slip_udp/Makefile | 9 + examples/protocols/slip/slip_udp/README.md | 57 ++++ .../slip/slip_udp/main/CMakeLists.txt | 7 + .../slip/slip_udp/main/Kconfig.projbuild | 32 ++ .../protocols/slip/slip_udp/main/component.mk | 4 + .../slip/slip_udp/main/slip_client_main.c | 229 +++++++++++++ .../slip/slip_udp/sdkconfig.defaults | 3 + 26 files changed, 1471 insertions(+), 16 deletions(-) create mode 100644 components/esp_netif/include/esp_netif_slip.h create mode 100644 components/esp_netif/lwip/esp_netif_lwip_slip.c create mode 100644 components/esp_netif/lwip/esp_netif_lwip_slip.h create mode 100644 components/esp_netif/lwip/esp_netif_lwip_slip_sio.c create mode 100644 examples/protocols/slip/components/slip_modem/CMakeLists.txt create mode 100644 examples/protocols/slip/components/slip_modem/include/slip_modem.h create mode 100644 examples/protocols/slip/components/slip_modem/library/slip_modem.c create mode 100644 examples/protocols/slip/slip_udp/CMakeLists.txt create mode 100644 examples/protocols/slip/slip_udp/Makefile create mode 100644 examples/protocols/slip/slip_udp/README.md create mode 100644 examples/protocols/slip/slip_udp/main/CMakeLists.txt create mode 100644 examples/protocols/slip/slip_udp/main/Kconfig.projbuild create mode 100644 examples/protocols/slip/slip_udp/main/component.mk create mode 100644 examples/protocols/slip/slip_udp/main/slip_client_main.c create mode 100644 examples/protocols/slip/slip_udp/sdkconfig.defaults diff --git a/components/esp_netif/CMakeLists.txt b/components/esp_netif/CMakeLists.txt index b775ba3b17..5ee19e4991 100644 --- a/components/esp_netif/CMakeLists.txt +++ b/components/esp_netif/CMakeLists.txt @@ -3,6 +3,8 @@ idf_component_register(SRCS "esp_netif_handlers.c" "esp_netif_defaults.c" "lwip/esp_netif_lwip.c" "lwip/esp_netif_lwip_ppp.c" + "lwip/esp_netif_lwip_slip.c" + "lwip/esp_netif_lwip_slip_sio.c" "loopback/esp_netif_loopback.c" "lwip/esp_netif_lwip_defaults.c" "lwip/esp_netif_sta_list.c" diff --git a/components/esp_netif/esp_netif_defaults.c b/components/esp_netif/esp_netif_defaults.c index af71eaef6a..8757ac9a39 100644 --- a/components/esp_netif/esp_netif_defaults.c +++ b/components/esp_netif/esp_netif_defaults.c @@ -37,6 +37,8 @@ const esp_netif_inherent_config_t _g_esp_netif_inherent_eth_config = ESP_NETIF_I const esp_netif_inherent_config_t _g_esp_netif_inherent_ppp_config = ESP_NETIF_INHERENT_DEFAULT_PPP(); +const esp_netif_inherent_config_t _g_esp_netif_inherent_slip_config = ESP_NETIF_INHERENT_DEFAULT_SLIP(); + const esp_netif_ip_info_t _g_esp_netif_soft_ap_ip = { .ip = { .addr = ESP_IP4TOADDR( 192, 168, 4, 1) }, .gw = { .addr = ESP_IP4TOADDR( 192, 168, 4, 1) }, diff --git a/components/esp_netif/include/esp_netif_defaults.h b/components/esp_netif/include/esp_netif_defaults.h index 3c41d9c2b9..0b7541abb7 100644 --- a/components/esp_netif/include/esp_netif_defaults.h +++ b/components/esp_netif/include/esp_netif_defaults.h @@ -70,7 +70,19 @@ extern "C" { .lost_ip_event = IP_EVENT_PPP_LOST_IP, \ .if_key = "PPP_DEF", \ .if_desc = "ppp", \ - .route_prio = 128 \ + .route_prio = 20 \ +}; + +#define ESP_NETIF_INHERENT_DEFAULT_SLIP() \ + { \ + .flags = ESP_NETIF_FLAG_IS_SLIP, \ + ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(mac) \ + ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(ip_info) \ + .get_ip_event = 0, \ + .lost_ip_event = 0, \ + .if_key = "SLIP_DEF", \ + .if_desc = "slip", \ + .route_prio = 20 \ }; /** @@ -112,6 +124,18 @@ extern "C" { .driver = NULL, \ .stack = ESP_NETIF_NETSTACK_DEFAULT_PPP, \ } + +/** +* @brief Default configuration reference of SLIP client +*/ +#define ESP_NETIF_DEFAULT_SLIP() \ + { \ + .base = ESP_NETIF_BASE_DEFAULT_SLIP, \ + .driver = NULL, \ + .stack = ESP_NETIF_NETSTACK_DEFAULT_SLIP, \ + } + + /** * @brief Default base config (esp-netif inherent) of WIFI STA */ @@ -132,11 +156,18 @@ extern "C" { */ #define ESP_NETIF_BASE_DEFAULT_PPP &_g_esp_netif_inherent_ppp_config +/** + * @brief Default base config (esp-netif inherent) of slip interface + */ +#define ESP_NETIF_BASE_DEFAULT_SLIP &_g_esp_netif_inherent_slip_config + + #define ESP_NETIF_NETSTACK_DEFAULT_ETH _g_esp_netif_netstack_default_eth #define ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA _g_esp_netif_netstack_default_wifi_sta #define ESP_NETIF_NETSTACK_DEFAULT_WIFI_AP _g_esp_netif_netstack_default_wifi_ap #define ESP_NETIF_NETSTACK_DEFAULT_PPP _g_esp_netif_netstack_default_ppp +#define ESP_NETIF_NETSTACK_DEFAULT_SLIP _g_esp_netif_netstack_default_slip // // Include default network stacks configs @@ -148,6 +179,7 @@ extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_eth; extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_sta; extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_ap; extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_ppp; +extern const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_slip; // // Include default common configs inherent to esp-netif @@ -158,6 +190,7 @@ extern const esp_netif_inherent_config_t _g_esp_netif_inherent_sta_config; extern const esp_netif_inherent_config_t _g_esp_netif_inherent_ap_config; extern const esp_netif_inherent_config_t _g_esp_netif_inherent_eth_config; extern const esp_netif_inherent_config_t _g_esp_netif_inherent_ppp_config; +extern const esp_netif_inherent_config_t _g_esp_netif_inherent_slip_config; extern const esp_netif_ip_info_t _g_esp_netif_soft_ap_ip; diff --git a/components/esp_netif/include/esp_netif_slip.h b/components/esp_netif/include/esp_netif_slip.h new file mode 100644 index 0000000000..088cca1751 --- /dev/null +++ b/components/esp_netif/include/esp_netif_slip.h @@ -0,0 +1,123 @@ +// Copyright 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. +// + +#ifndef _ESP_NETIF_SLIP_H_ +#define _ESP_NETIF_SLIP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "driver/uart.h" + +/** @brief SLIP event base */ +ESP_EVENT_DECLARE_BASE(SLIP_EVENT); + +typedef enum esp_netif_slip_event { + SLIP_EVENT_START = 1, + SLIP_EVENT_STOP = 2, + +} esp_netif_slip_event_e; + +/** @brief Forward declaration of lwip_slip_ctx for external use */ +typedef struct lwip_slip_ctx lwip_slip_ctx_t; + +/** @brief Configuration structure for SLIP network interface + * + */ +typedef struct esp_netif_slip_config { + ip6_addr_t addr; /* Local IP6 address */ + + uart_port_t uart_dev; /* UART device for reading and writing SLIP information, this must be initialised externally */ + +} esp_netif_slip_config_t; + + +/** @brief Sets common parameters for the supplied esp-netif. + * + * @param[in] esp_netif handle to slip esp-netif instance + * @param[in] config Pointer to SLIP netif configuration structure + * + * @return ESP_OK on success, ESP_ERR_ESP_NETIF_INVALID_PARAMS if netif null or not SLIP + */ +esp_err_t esp_netif_slip_set_params(esp_netif_t *netif, const esp_netif_slip_config_t *config); + +/** + * @brief Data path API to input incoming packets to SLIP + * + * @param[in] esp_netif handle to slip esp-netif instance + * @param[in] buffer pointer to the incoming data + * @param[in] len length of the data + * + * @return + * - ESP_OK on success + */ +void esp_netif_lwip_slip_raw_input(esp_netif_t *netif, void *buffer, size_t len); + +/** + * @brief Data path API to write raw packet ous the SLIP interface + * + * @param[in] esp_netif handle to slip esp-netif instance + * @param[in] buffer pointer to the outgoing data + * @param[in] len length of the data + * + * @return + * - ESP_OK on success + */ +void esp_netif_lwip_slip_raw_output(esp_netif_t *netif, void *buffer, size_t len); + +/** + * @brief Fetch IP6 address attached to the SLIP interface + * + * @param[in] esp_netif handle to slip esp-netif instance + * @param[in] address index (unused) + * + * @return + * - pointer to the internal ip6 address object + */ +const ip6_addr_t *esp_slip_get_ip6(esp_netif_t *slip_netif); + +/** + * @brief Fetch lwip_slip_ctx_t for esp_netif_t object + * + * This is required to support the wiring of esp_netif objects outside + * of this component. + * + * @return + * - lwip slip context + */ +lwip_slip_ctx_t *esp_netif_lwip_slip_get_ctx(esp_netif_t *slip_netif); + +/** + * @brief Start the esp slip netif + * + * @param[in] esp_netif handle to slip esp-netif instance + * + * @return + * - ESP_OK on success + */ +esp_err_t esp_netif_start_slip(lwip_slip_ctx_t *slip_ctx); + +/** + * @brief Stop the esp slip netif + * + * @param[in] esp_netif handle to slip esp-netif instance + * + * @return + * - ESP_OK on success + */ +esp_err_t esp_netif_stop_slip(lwip_slip_ctx_t *slip_ctx); + +#endif diff --git a/components/esp_netif/include/esp_netif_types.h b/components/esp_netif/include/esp_netif_types.h index 0e3613932b..fb91a85f31 100644 --- a/components/esp_netif/include/esp_netif_types.h +++ b/components/esp_netif/include/esp_netif_types.h @@ -138,7 +138,8 @@ typedef enum esp_netif_flags { ESP_NETIF_FLAG_AUTOUP = 1 << 2, ESP_NETIF_FLAG_GARP = 1 << 3, ESP_NETIF_FLAG_EVENT_IP_MODIFIED = 1 << 4, - ESP_NETIF_FLAG_IS_PPP = 1 << 5 + ESP_NETIF_FLAG_IS_PPP = 1 << 5, + ESP_NETIF_FLAG_IS_SLIP = 1 << 6, } esp_netif_flags_t; typedef enum esp_netif_ip_event_type { @@ -163,7 +164,9 @@ typedef struct esp_netif_inherent_config { const char * if_key; /*!< string identifier of the interface */ const char * if_desc; /*!< textual description of the interface */ int route_prio; /*!< numeric priority of this interface to become a default - routing if (if other netifs are up) */ + routing if (if other netifs are up). + A higher value of route_prio indicates + a higher priority */ } esp_netif_inherent_config_t; typedef struct esp_netif_config esp_netif_config_t; diff --git a/components/esp_netif/lwip/esp_netif_lwip.c b/components/esp_netif/lwip/esp_netif_lwip.c index 8fd274dba6..4ddf0f7479 100644 --- a/components/esp_netif/lwip/esp_netif_lwip.c +++ b/components/esp_netif/lwip/esp_netif_lwip.c @@ -34,6 +34,7 @@ #endif #include "esp_netif_lwip_ppp.h" +#include "esp_netif_lwip_slip.h" #include "dhcpserver/dhcpserver.h" #include "dhcpserver/dhcpserver_options.h" @@ -149,6 +150,8 @@ static void esp_netif_set_default_netif(esp_netif_t *esp_netif) { if (esp_netif->is_ppp_netif) { esp_netif_ppp_set_default_netif(esp_netif->netif_handle); + } else if (esp_netif->is_slip_netif) { + esp_netif_slip_set_default_netif(esp_netif->netif_handle); } else { netif_set_default(esp_netif->netif_handle); } @@ -346,6 +349,17 @@ static esp_err_t esp_netif_init_configuration(esp_netif_t *esp_netif, const esp_ esp_netif->is_ppp_netif = true; // Make the netif handle (used for tcpip input function) the ppp_netif esp_netif->netif_handle = esp_netif->lwip_ppp_ctx; + + } else if (cfg->base->flags & ESP_NETIF_FLAG_IS_SLIP) { + esp_netif->lwip_slip_ctx = esp_netif_new_slip(esp_netif, esp_netif_stack_config); + if (esp_netif->lwip_slip_ctx == NULL) { + return ESP_ERR_ESP_NETIF_INIT_FAILED; + } + esp_netif->lwip_input_fn = esp_netif_stack_config->lwip_slip.input_fn; + esp_netif->is_slip_netif = true; + // Make the netif handle (used for tcpip input function) the slip_netif + esp_netif->netif_handle = esp_netif->lwip_slip_ctx; + } else { if (esp_netif_stack_config-> lwip.init_fn) { esp_netif->lwip_init_fn = esp_netif_stack_config->lwip.init_fn; @@ -488,6 +502,8 @@ void esp_netif_destroy(esp_netif_t *esp_netif) esp_netif_lwip_remove(esp_netif); if (esp_netif->is_ppp_netif) { esp_netif_destroy_ppp(esp_netif->netif_handle); + } else if (esp_netif->is_slip_netif) { + esp_netif_destroy_slip(esp_netif->netif_handle); } free(esp_netif->lwip_netif); free(esp_netif->hostname); @@ -539,7 +555,7 @@ esp_err_t esp_netif_set_mac(esp_netif_t *esp_netif, uint8_t mac[]) if (esp_netif == NULL || esp_netif->lwip_netif == NULL) { return ESP_ERR_ESP_NETIF_IF_NOT_READY; } - if (esp_netif->is_ppp_netif) { + if (esp_netif->is_ppp_netif || esp_netif->is_slip_netif) { return ESP_ERR_NOT_SUPPORTED; } memcpy(esp_netif->mac, mac, NETIF_MAX_HWADDR_LEN); @@ -552,7 +568,7 @@ esp_err_t esp_netif_get_mac(esp_netif_t *esp_netif, uint8_t mac[]) if (esp_netif == NULL || esp_netif->lwip_netif == NULL) { return ESP_ERR_ESP_NETIF_IF_NOT_READY; } - if (esp_netif->is_ppp_netif) { + if (esp_netif->is_ppp_netif || esp_netif->is_slip_netif) { return ESP_ERR_NOT_SUPPORTED; } if (esp_netif_is_netif_up(esp_netif)) { @@ -675,6 +691,13 @@ esp_err_t esp_netif_start(esp_netif_t *esp_netif) esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED); } return ret; + } else if (esp_netif->is_slip_netif) { + // No need to start SLIP interface in lwip thread + esp_err_t ret = esp_netif_start_slip(esp_netif->lwip_slip_ctx); + if (ret == ESP_OK) { + esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED); + } + return ret; } return esp_netif_lwip_ipc_call(esp_netif_start_api, esp_netif, NULL); } @@ -724,6 +747,13 @@ esp_err_t esp_netif_stop(esp_netif_t *esp_netif) esp_netif_update_default_netif(esp_netif, ESP_NETIF_STOPPED);; } return ret; + } else if (esp_netif->is_slip_netif) { + // No need to stop PPP interface in lwip thread + esp_err_t ret = esp_netif_stop_slip(esp_netif->lwip_slip_ctx); + if (ret == ESP_OK) { + esp_netif_update_default_netif(esp_netif, ESP_NETIF_STOPPED);; + } + return ret; } return esp_netif_lwip_ipc_call(esp_netif_stop_api, esp_netif, NULL); } @@ -957,7 +987,7 @@ esp_err_t esp_netif_dhcpc_start(esp_netif_t *esp_netif) _RUN_IN_LWIP_TASK_IF_SUP esp_err_t esp_netif_dhcps_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status) { - if (!esp_netif || (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) || esp_netif->is_ppp_netif) { + if (!esp_netif || (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) || esp_netif->is_ppp_netif || esp_netif->is_slip_netif) { return ESP_ERR_INVALID_ARG; } @@ -967,7 +997,7 @@ esp_err_t esp_netif_dhcps_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_stat esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status) { - if (!esp_netif || (esp_netif->flags & ESP_NETIF_DHCP_SERVER) || esp_netif->is_ppp_netif) { + if (!esp_netif || (esp_netif->flags & ESP_NETIF_DHCP_SERVER) || esp_netif->is_ppp_netif || esp_netif->is_slip_netif) { return ESP_ERR_INVALID_ARG; } @@ -1080,7 +1110,7 @@ esp_err_t esp_netif_get_hostname(esp_netif_t *esp_netif, const char **hostname) { ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); - if (!esp_netif || esp_netif->is_ppp_netif) { + if (!esp_netif || esp_netif->is_ppp_netif || esp_netif->is_slip_netif) { return ESP_ERR_INVALID_ARG; } @@ -1339,7 +1369,7 @@ static esp_err_t esp_netif_set_dns_info_api(esp_netif_api_msg_t *msg) esp_err_t esp_netif_set_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t type, esp_netif_dns_info_t *dns) { - if (esp_netif->is_ppp_netif) { + if (esp_netif->is_ppp_netif || esp_netif->is_slip_netif) { return ESP_ERR_NOT_SUPPORTED; } esp_netif_dns_param_t dns_param = { @@ -1379,7 +1409,7 @@ static esp_err_t esp_netif_get_dns_info_api(esp_netif_api_msg_t *msg) esp_err_t esp_netif_get_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t type, esp_netif_dns_info_t *dns) { - if (esp_netif->is_ppp_netif) { + if (esp_netif->is_ppp_netif || esp_netif->is_slip_netif) { const ip_addr_t *dns_ip = dns_getserver(type); if (dns_ip == IP_ADDR_ANY) { return ESP_ERR_ESP_NETIF_DNS_NOT_CONFIGURED; @@ -1464,7 +1494,7 @@ esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if { ESP_LOGV(TAG, "%s esp-netif:%p", __func__, esp_netif); - if (esp_netif == NULL || if_ip6 == NULL || esp_netif->is_ppp_netif) { + if (esp_netif == NULL || if_ip6 == NULL || esp_netif->is_ppp_netif || esp_netif->is_slip_netif) { return ESP_ERR_ESP_NETIF_INVALID_PARAMS; } struct netif *p_netif = esp_netif->lwip_netif; diff --git a/components/esp_netif/lwip/esp_netif_lwip_defaults.c b/components/esp_netif/lwip/esp_netif_lwip_defaults.c index 955285024b..aa3d579058 100644 --- a/components/esp_netif/lwip/esp_netif_lwip_defaults.c +++ b/components/esp_netif/lwip/esp_netif_lwip_defaults.c @@ -54,7 +54,16 @@ static const struct esp_netif_netstack_config s_netif_config_ppp = { } }; +static const struct esp_netif_netstack_config s_netif_config_slip = { + .lwip_slip = { + .slip_config = { + .uart_dev = UART_NUM_1, + } + } +}; + const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_eth = &s_eth_netif_config; const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_sta = &s_wifi_netif_config_sta; const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_ap = &s_wifi_netif_config_ap; -const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_ppp = &s_netif_config_ppp; \ No newline at end of file +const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_ppp = &s_netif_config_ppp; +const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_slip = &s_netif_config_slip; diff --git a/components/esp_netif/lwip/esp_netif_lwip_internal.h b/components/esp_netif/lwip/esp_netif_lwip_internal.h index 853b0629e8..a3df2f2c7f 100644 --- a/components/esp_netif/lwip/esp_netif_lwip_internal.h +++ b/components/esp_netif/lwip/esp_netif_lwip_internal.h @@ -16,6 +16,7 @@ #include "esp_netif.h" #include "esp_netif_ppp.h" +#include "esp_netif_slip.h" #include "lwip/netif.h" struct esp_netif_netstack_lwip_vanilla_config { @@ -28,11 +29,17 @@ struct esp_netif_netstack_lwip_ppp_config { esp_netif_ppp_config_t ppp_events; }; +struct esp_netif_netstack_lwip_slip_config { + void (*input_fn)(void *netif, void *buffer, size_t len, void *eb); + esp_netif_slip_config_t slip_config; +}; + // LWIP netif specific network stack configuration struct esp_netif_netstack_config { union { struct esp_netif_netstack_lwip_vanilla_config lwip; struct esp_netif_netstack_lwip_ppp_config lwip_ppp; + struct esp_netif_netstack_lwip_slip_config lwip_slip; }; }; @@ -58,8 +65,9 @@ typedef struct esp_netif_ip_lost_timer_s { bool timer_running; } esp_netif_ip_lost_timer_t; -// Forward declare the ppp context +// Forward declare the ppp and slip context typedef struct lwip_ppp_ctx lwip_ppp_ctx_t; +typedef struct lwip_slip_ctx lwip_slip_ctx_t; /** * @brief Main esp-netif container with interface related information @@ -73,10 +81,13 @@ struct esp_netif_obj { // lwip netif related struct netif *lwip_netif; lwip_ppp_ctx_t *lwip_ppp_ctx; + lwip_slip_ctx_t *lwip_slip_ctx; err_t (*lwip_init_fn)(struct netif*); void (*lwip_input_fn)(void *input_netif_handle, void *buffer, size_t len, void *eb); void * netif_handle; // netif impl context (either vanilla lwip-netif or ppp_pcb) + bool is_ppp_netif; + bool is_slip_netif; // io driver related void* driver_handle; diff --git a/components/esp_netif/lwip/esp_netif_lwip_ppp.c b/components/esp_netif/lwip/esp_netif_lwip_ppp.c index bea508da1d..2a82ca404e 100644 --- a/components/esp_netif/lwip/esp_netif_lwip_ppp.c +++ b/components/esp_netif/lwip/esp_netif_lwip_ppp.c @@ -252,9 +252,9 @@ esp_err_t esp_netif_ppp_set_auth(esp_netif_t *netif, esp_netif_auth_type_t autht return ESP_OK; } -void esp_netif_ppp_set_default_netif(lwip_ppp_ctx_t* ppp_ctx) +void esp_netif_slip_set_default_netif(lwip_ppp_ctx_t* slip_ctx) { - ppp_set_default(ppp_ctx->ppp); + netif_set_default(slip_ctx->netif) } lwip_ppp_ctx_t* esp_netif_new_ppp(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config) diff --git a/components/esp_netif/lwip/esp_netif_lwip_slip.c b/components/esp_netif/lwip/esp_netif_lwip_slip.c new file mode 100644 index 0000000000..69386869be --- /dev/null +++ b/components/esp_netif/lwip/esp_netif_lwip_slip.c @@ -0,0 +1,245 @@ +// Copyright 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/dns.h" +#include "esp_netif.h" +#include "esp_log.h" +#include "esp_netif_net_stack.h" +#include "esp_event.h" +#include "esp_netif_slip.h" + +#include "esp_netif_lwip_internal.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 "netif/slipif.h" + +#include + + +ESP_EVENT_DEFINE_BASE(SLIP_EVENT); + +static const char *TAG = "esp-netif_lwip-slip"; + +/** + * @brief LWIP SLIP context object + */ +typedef struct lwip_slip_ctx { + //! ESP netif object + esp_netif_t *esp_netif; + + //! SLIP interface IP6 address + ip6_addr_t addr; + + + //! UART device for underling SIO + uart_port_t uart_dev; + +} lwip_slip_ctx_t; + +/** + * @brief Create a new lwip slip interface + */ +lwip_slip_ctx_t *esp_netif_new_slip(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config) +{ + ESP_LOGD(TAG, "%s", __func__); + + // Fetch netif and create context + struct netif *netif_impl = esp_netif->lwip_netif; + + lwip_slip_ctx_t *slip_ctx = calloc(1, sizeof(lwip_slip_ctx_t)); + if (slip_ctx == NULL) { + ESP_LOGE(TAG, "%s: cannot allocate lwip_slip_ctx_t", __func__); + return NULL; + } + + ESP_LOGD(TAG, "%s: Initialising SLIP (esp_netif %p, lwip_netif %p, device: %d)", __func__, esp_netif, netif_impl, slip_ctx->uart_dev); + + // Load config + const esp_netif_slip_config_t *slip_config = &esp_netif_stack_config->lwip_slip.slip_config; + + // Attache network interface and uart device + slip_ctx->uart_dev = slip_config->uart_dev; + slip_ctx->esp_netif = esp_netif; + + ESP_LOGI(TAG, "%s: Created SLIP interface (netif %p, slip_ctx: %p)", __func__, esp_netif, slip_ctx); + + return slip_ctx; +} + +/** + * @brief Creates new SLIP related structure + */ +esp_err_t esp_netif_start_slip(lwip_slip_ctx_t *slip_ctx) +{ + ESP_LOGI(TAG, "%s: Starting SLIP connection (slip_ctx: %p, addr: %s)", __func__, slip_ctx, ip6addr_ntoa(&slip_ctx->addr)); + + struct netif *netif_impl = slip_ctx->esp_netif->lwip_netif; + + // Store serial port number in net interface for SIO open command + netif_impl->state = (void *)slip_ctx->uart_dev; + + // Attach interface + netif_add_noaddr(slip_ctx->esp_netif->lwip_netif, (void *)slip_ctx->uart_dev, &slipif_init, &ip_input); + + // Bind address + int8_t addr_index = 0; + + // Note that addr_set is used here as the address is statically configured + // rather than negotiated over the link + netif_ip6_addr_set(slip_ctx->esp_netif->lwip_netif, addr_index, &slip_ctx->addr); + netif_ip6_addr_set_state(slip_ctx->esp_netif->lwip_netif, addr_index, IP6_ADDR_VALID); + + // Setup interface + netif_set_link_up(slip_ctx->esp_netif->lwip_netif); + netif_set_up(slip_ctx->esp_netif->lwip_netif); + + return ESP_OK; +} + +/** + * @brief Stops the SLIP interface + */ +esp_err_t esp_netif_stop_slip(lwip_slip_ctx_t *slip_ctx) +{ + ESP_LOGI(TAG, "%s: Stopped SLIP connection: %p", __func__, slip_ctx); + + // Stop interface + netif_set_link_down(slip_ctx->esp_netif->lwip_netif); + + return ESP_OK; +} + + +/** + * @brief Sets paramaters for the supplied netif + */ +esp_err_t esp_netif_slip_set_params(esp_netif_t *netif, const esp_netif_slip_config_t *slip_config) +{ + + lwip_slip_ctx_t *slip_ctx = netif->lwip_slip_ctx; + + ESP_LOGD(TAG, "%s (slip_ctx: %p)", __func__, slip_ctx); + + if (netif_is_link_up(slip_ctx->esp_netif->lwip_netif)) { + ESP_LOGE(TAG, "Cannot set parameters while SLIP interface is running"); + return ESP_ERR_INVALID_STATE; + } + + memcpy(&slip_ctx->addr, &slip_config->addr, sizeof(ip6_addr_t)); + slip_ctx->uart_dev = slip_config->uart_dev; + + return ESP_OK; +} + +/** + * @brief Write incoming serial data to the SLIP interface + */ +void esp_netif_lwip_slip_input(void *ctx, void *buffer, size_t len, void *eb) +{ + lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *)ctx; + + ESP_LOGD(TAG, "%s", __func__); + ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_DEBUG); + + // Update slip netif with data + slipif_received_bytes(slip_ctx->esp_netif->lwip_netif, buffer, len); + + // Process incoming bytes + for (int i = 0; i < len; i++) { + slipif_process_rxqueue(slip_ctx->esp_netif->lwip_netif); + } +} + +/** + * @brief Write raw data out the SLIP interface + */ +void esp_netif_lwip_slip_output(lwip_slip_ctx_t *slip_ctx, void *buffer, size_t len) +{ + struct netif *lwip_netif = slip_ctx->esp_netif->lwip_netif; + + ESP_LOGD(TAG, "%s", __func__); + ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_DEBUG); + + struct pbuf p = { + .next = NULL, + .payload = buffer, + .tot_len = len, + .len = len, + }; + + // Call slip if output function to feed data out slip interface + lwip_netif->output_ip6(lwip_netif, &p, NULL); +} + +/** + * @brief Write raw data out the SLIP interface + */ +void esp_netif_lwip_slip_raw_output(esp_netif_t *slip_netif, void *buffer, size_t len) +{ + struct netif *lwip_netif = slip_netif->lwip_netif; + + ESP_LOGD(TAG, "%s", __func__); + + struct pbuf p = { + .next = NULL, + .payload = buffer, + .tot_len = len, + .len = len, + }; + + // Call slip if output function to feed data out slip interface + lwip_netif->output_ip6(lwip_netif, &p, NULL); +} + +/** + * @brief Fetch pointer to internal slip_lwip_context + * + * This is required to support the wiring of esp_netif objects outside + * of this component. + * + * @return + * - lwip slip context + */ +lwip_slip_ctx_t *esp_netif_lwip_slip_get_ctx(esp_netif_t *slip_netif) +{ + return slip_netif->lwip_slip_ctx; +} + +/** + * @brief Destroys the SLIP context object + */ +void esp_netif_destroy_slip(lwip_slip_ctx_t *slip_ctx) +{ + ESP_LOGD(TAG, "%s", __func__); + + // Free base object + free(slip_ctx); +} + +void esp_netif_slip_set_default_netif(lwip_slip_ctx_t *slip_ctx) +{ + netif_set_default(slip_ctx->esp_netif->lwip_netif); +} + +const ip6_addr_t *esp_slip_get_ip6(esp_netif_t *slip_netif) +{ + return &slip_netif->lwip_slip_ctx->addr; +} + diff --git a/components/esp_netif/lwip/esp_netif_lwip_slip.h b/components/esp_netif/lwip/esp_netif_lwip_slip.h new file mode 100644 index 0000000000..0c64ee8a5b --- /dev/null +++ b/components/esp_netif/lwip/esp_netif_lwip_slip.h @@ -0,0 +1,71 @@ +// Copyright 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. + +#ifndef _ESP_NETIF_LWIP_SLIP_H_ +#define _ESP_NETIF_LWIP_SLIP_H_ + +typedef struct lwip_slip_ctx lwip_slip_ctx_t; + +/** + * @brief Creates new SLIP related structure + * + * @param[in] esp_netif pointer esp-netif instance + * @param[in] stack_config TCP/IP stack configuration structure + * + * @return + * - pointer to slip-netif object on success + * - NULL otherwise + */ +lwip_slip_ctx_t *esp_netif_new_slip(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config); + +/** + * @brief Creates new SLIP related structure + * + * @param[in] slip pointer to internal slip context instance + * + * @return + * - ESP_OK on success + */ +esp_err_t esp_netif_start_slip(lwip_slip_ctx_t *slip); + + + +/** + * @brief Destroys the slip netif object + * + * @param[in] slip pointer to internal slip context instance + */ +void esp_netif_destroy_slip(lwip_slip_ctx_t *slip); + +/** + * @brief Stops the SLIP interface + * + * @param[in] slip pointer to internal slip context instance + * + * @return + * - ESP_OK on success + */ +esp_err_t esp_netif_stop_slip(lwip_slip_ctx_t *slip); + +/** + * @brief Sets default netif for routing priority config + * + * @note: This function must be called from lwip thread + * + */ +void esp_netif_slip_set_default_netif(lwip_slip_ctx_t *slip_ctx); + + + +#endif // _ESP_NETIF_LWIP_SLIP_H_ \ No newline at end of file diff --git a/components/esp_netif/lwip/esp_netif_lwip_slip_sio.c b/components/esp_netif/lwip/esp_netif_lwip_slip_sio.c new file mode 100644 index 0000000000..d68b5fe03d --- /dev/null +++ b/components/esp_netif/lwip/esp_netif_lwip_slip_sio.c @@ -0,0 +1,163 @@ +// Copyright 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 + +#include "esp_log.h" +#include "driver/uart.h" + +#include "lwip/opt.h" +#include "lwip/sio.h" + +static const char *TAG = "esp-netif_lwip-slip_sio"; + +/*** + * @brief slip IO (SIO) uart driver + */ +typedef struct lwip_slip_sio { + uart_port_t uart_dev; + bool blocking; +} lwip_slip_sio_t; + +/*** + * @brief Open a serial device for communication + */ +sio_fd_t sio_open(uint8_t devnum) +{ + ESP_LOGD(TAG, "Opening device: %d\r\n", devnum); + + // Create SIO object + lwip_slip_sio_t *slip_sio = malloc(sizeof(lwip_slip_sio_t)); + + // Store device num etc. + slip_sio->uart_dev = devnum; + slip_sio->blocking = false; + + // Return SIO handle + return slip_sio; +} + +/*** + * @brief Send a single character to the serial device (blocking) + */ +void sio_send(uint8_t c, sio_fd_t fd) +{ + lwip_slip_sio_t *slip_sio = ( lwip_slip_sio_t *) fd; + + ESP_LOGD(TAG, "%s", __func__); + ESP_LOG_BUFFER_HEX_LEVEL(TAG, &c, 1, ESP_LOG_DEBUG); + + int res = uart_write_bytes(slip_sio->uart_dev, (const char *)&c, 1); + if (res < 0) { + // Handle errors + ESP_LOGD(TAG, "%s: uart_write_bytes error %i", __func__, res); + } +} + +/*** + * @brief Write to the serial port (blocking) + */ +uint32_t sio_write(sio_fd_t fd, uint8_t *data, uint32_t len) +{ + lwip_slip_sio_t *slip_sio = ( lwip_slip_sio_t *) fd; + + ESP_LOGD(TAG, "%s", __func__); + ESP_LOG_BUFFER_HEX_LEVEL(TAG, data, len, ESP_LOG_DEBUG); + + int32_t res = uart_write_bytes(slip_sio->uart_dev, (char *)data, len); + if (res < 0) { + // Handle errors + ESP_LOGD(TAG, "%s: uart_write_bytes error %i", __func__, res); + return 0; + } + + return (uint32_t) res; +} + +/*** + * @brief Receive a single character from the serial device (blocking) + */ +uint8_t sio_recv(sio_fd_t fd) +{ + lwip_slip_sio_t *slip_sio = ( lwip_slip_sio_t *) fd; + uint8_t b; + + slip_sio->blocking = true; + + while (slip_sio->blocking == true) { + int res = uart_read_bytes(slip_sio->uart_dev, &b, 1, portTICK_RATE_MS * 1); + if (res < 0) { + // Handle errors + ESP_LOGD(TAG, "%s: uart_read_bytes error %i", __func__, res); + return 0; + } else if (res == 1) { + break; + } + } + + return b; +} + +/*** + * @brief Read from the serial port (blocking, abort with `sio_read_abort`) + */ +uint32_t sio_read(sio_fd_t fd, uint8_t *data, uint32_t len) +{ + lwip_slip_sio_t *slip_sio = ( lwip_slip_sio_t *) fd; + int res = 0; + + slip_sio->blocking = true; + + while (slip_sio->blocking == true) { + res = uart_read_bytes(slip_sio->uart_dev, data, len, portTICK_RATE_MS * 1); + if (res < 0) { + // Handle errors + ESP_LOGD(TAG, "%s: uart_read_bytes error %i", __func__, res); + return 0; + } else if (res > 0) { + break; + } + } + + return (uint32_t) res; +} + +/*** + * @brief Read from the serial port (non-blocking) + */ +uint32_t sio_tryread(sio_fd_t fd, uint8_t *data, uint32_t len) +{ + lwip_slip_sio_t *slip_sio = ( lwip_slip_sio_t *) fd; + + int res = uart_read_bytes(slip_sio->uart_dev, data, len, portTICK_RATE_MS * 1); + if (res < 0) { + ESP_LOGD(TAG, "%s: uart_read_bytes error %i", __func__, res); + return 0; + } + + return (uint32_t)res; +} + + +/*** + * @brief Abort a pending sio_read call + */ +void sio_read_abort(sio_fd_t fd) +{ + lwip_slip_sio_t *slip_sio = ( lwip_slip_sio_t *) fd; + + slip_sio->blocking = false; +} + diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index acda93d6bf..5a6c800be6 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -647,6 +647,28 @@ menu "LWIP" help Enable PPP debug log output + menuconfig LWIP_SLIP_SUPPORT + bool "Enable SLIP support (new/experimental)" + default n + help + Enable SLIP stack. Now only SLIP over serial is possible. + + SLIP over serial support is experimental and unsupported. + + config LWIP_SLIP_RX_FROM_ISR + bool "Enable LWIP SLIP interrupt mode" + depends on LWIP_SLIP_SUPPORT + default y + help + Enable interrupt functions in SLIP netif/slipif.h + + config LWIP_SLIP_DEBUG_ON + bool "Enable SLIP debug log output" + depends on LWIP_SLIP_SUPPORT + default n + help + Enable SLIP debug log output + menu "ICMP" config LWIP_MULTICAST_PING diff --git a/components/lwip/port/esp32/include/lwipopts.h b/components/lwip/port/esp32/include/lwipopts.h index a229a71195..cc7df91b97 100644 --- a/components/lwip/port/esp32/include/lwipopts.h +++ b/components/lwip/port/esp32/include/lwipopts.h @@ -474,6 +474,27 @@ ------------------------------------ */ +#ifdef CONFIG_LWIP_SLIP_SUPPORT + +/** + * Enable SLIP receive from ISR functions + */ +#define SLIP_RX_FROM_ISR CONFIG_LWIP_SLIP_RX_FROM_ISR + +/** + * PPP_DEBUG: Enable debugging for PPP. + */ +#define SLIP_DEBUG_ON CONFIG_LWIP_SLIP_DEBUG_ON + +#if SLIP_DEBUG_ON +#define SLIP_DEBUG LWIP_DBG_ON +#else +#define SLIP_DEBUG LWIP_DBG_OFF +#endif + + +#endif + /* ------------------------------------ ---------- Thread options ---------- diff --git a/examples/protocols/pppos_client/main/CMakeLists.txt b/examples/protocols/pppos_client/main/CMakeLists.txt index 048a7246cd..26f0eec72f 100644 --- a/examples/protocols/pppos_client/main/CMakeLists.txt +++ b/examples/protocols/pppos_client/main/CMakeLists.txt @@ -1,2 +1,3 @@ idf_component_register(SRCS "pppos_client_main.c" - INCLUDE_DIRS ".") \ No newline at end of file + INCLUDE_DIRS ".") + \ No newline at end of file diff --git a/examples/protocols/slip/components/slip_modem/CMakeLists.txt b/examples/protocols/slip/components/slip_modem/CMakeLists.txt new file mode 100644 index 0000000000..4a596ca727 --- /dev/null +++ b/examples/protocols/slip/components/slip_modem/CMakeLists.txt @@ -0,0 +1,8 @@ +# SLIP Modem Component + +idf_component_register( + SRCS "library/slip_modem.c" + INCLUDE_DIRS "include" + REQUIRES lwip esp_netif +) + diff --git a/examples/protocols/slip/components/slip_modem/include/slip_modem.h b/examples/protocols/slip/components/slip_modem/include/slip_modem.h new file mode 100644 index 0000000000..e0e04da4a6 --- /dev/null +++ b/examples/protocols/slip/components/slip_modem/include/slip_modem.h @@ -0,0 +1,55 @@ + +#pragma once + +#include +#include + +#include "esp_netif.h" +#include "esp_netif_slip.h" + +#include "driver/uart.h" + +// Forward declare modem object +typedef struct esp_slip_modem esp_slip_modem_t; + +// Filter callbacks for handling application specific slip messages +typedef bool slip_rx_filter_cb_t(void *ctx, uint8_t *data, uint32_t len); + + +/** @brief Configuration structure for SLIP modem interface + * + */ +typedef struct { + uart_port_t uart_dev; /* UART device for reading and writing SLIP information, this must be initialised externally */ + + int uart_tx_pin; /* UART TX pin number */ + int uart_rx_pin; /* UART TX pin number */ + + uint32_t uart_baud; /* UART baud rate */ + + uint32_t rx_buffer_len; /* Length of buffer for RX messages */ + + slip_rx_filter_cb_t *rx_filter; /* Filter for parsing out non-SLIP messages from incoming SLIP stream */ + void *rx_filter_ctx; /* Context to be passed to SLIP filter function */ + +} esp_slip_modem_config_t; + + +/** @brief Create a slip modem + * + * @param[in] slip configured esp netif + * @param[in] configuration for the slip modem + * + * @returns + * - slip modem driver glue object + */ +void *esp_slip_modem_create(esp_netif_t *slip_netif, esp_slip_modem_config_t *modem_config); + +/** @brief Destroy a slip modem + * + * @param[in] slip modem object for destruction + * + * @return + * - ESP_OK on success + */ +esp_err_t esp_slip_modem_destroy(esp_slip_modem_t *slip_modem); diff --git a/examples/protocols/slip/components/slip_modem/library/slip_modem.c b/examples/protocols/slip/components/slip_modem/library/slip_modem.c new file mode 100644 index 0000000000..d7b6b4fba4 --- /dev/null +++ b/examples/protocols/slip/components/slip_modem/library/slip_modem.c @@ -0,0 +1,303 @@ + + +#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"; + + +// UART container object +typedef struct { + // UART device number for SIO use + uart_port_t uart_dev; + + // UART baud rate for configuration + uint32_t uart_baud; + + // UART TX pin for configuration + int uart_tx_pin; + + // UART RX pin for configuration + int uart_rx_pin; + + // QueueHandle for uart driver + QueueHandle_t uart_queue; + + // TaskHandle for receive task + TaskHandle_t uart_rx_task; +} esp_slip_uart_t; + + +// Modem object, implements glue logic for slip_driver and esp_netif +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; + + // Buffer for incoming messages + uint8_t *buffer; + uint32_t buffer_len; + + // Filter callbacks for application-specific slip message handling + slip_rx_filter_cb_t *rx_filter; + void *rx_filter_ctx; + + // Running flag + bool running; +}; + + +// Forward function definitions +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)); + if (!slip_modem) { + ESP_LOGE(TAG, "create netif glue failed"); + return NULL; + } + + // Attach driver and post_attach callbacks + slip_modem->slip_driver = slip_ctx; + slip_modem->base.post_attach = esp_slip_modem_post_attach; + + // Attach config + slip_modem->buffer_len = modem_config->rx_buffer_len; + + slip_modem->rx_filter = modem_config->rx_filter; + slip_modem->rx_filter_ctx = modem_config->rx_filter_ctx; + + slip_modem->uart.uart_dev = modem_config->uart_dev; + slip_modem->uart.uart_baud = modem_config->uart_baud; + slip_modem->uart.uart_rx_pin = modem_config->uart_rx_pin; + slip_modem->uart.uart_tx_pin = modem_config->uart_tx_pin; + + // Return new modem, with a cast to the first item + return &slip_modem->base; +} + +// Internal handler called on driver start +static esp_err_t esp_slip_driver_start(esp_slip_modem_t *slip_modem) +{ + ESP_LOGD(TAG, "%s: Starting SLIP modem (modem %p)", __func__, slip_modem); + + // Allocate RX buffer if one does not exist + if (slip_modem->buffer == NULL) { + slip_modem->buffer = malloc(slip_modem->buffer_len); + } + if (slip_modem->buffer == NULL) { + ESP_LOGE(TAG, "error allocating rx buffer"); + return ESP_ERR_NO_MEM; + } + + // Then, initialise UART + + // Build configuration + uart_config_t uart_config = { + .baud_rate = slip_modem->uart.uart_baud, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + }; + + // Initialise uart + ESP_ERROR_CHECK(uart_param_config(slip_modem->uart.uart_dev, &uart_config)); + + // Set UART pins + ESP_ERROR_CHECK(uart_set_pin(slip_modem->uart.uart_dev, slip_modem->uart.uart_tx_pin, slip_modem->uart.uart_rx_pin, 0, 0)); + + // Install UART driver + ESP_ERROR_CHECK(uart_driver_install(slip_modem->uart.uart_dev, slip_modem->buffer_len, slip_modem->buffer_len, 10, &slip_modem->uart.uart_queue, 0)); + + // Start slip RX task + slip_modem->running = true; + 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); + + return ESP_OK; +} + + +esp_err_t esp_slip_modem_destroy(esp_slip_modem_t *slip_modem) +{ + // Stop slip driver + esp_netif_stop_slip(slip_modem->slip_driver); + + // Stop uart rx task + vTaskDelete(slip_modem->uart.uart_rx_task); + + // Delete driver + uart_driver_delete(slip_modem->uart.uart_dev); + + // Free slip interface + free(slip_modem); + + return ESP_OK; +} + +// Modem transmit for glue logic +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); + + lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *) slip_driver; + + esp_netif_lwip_slip_output(slip_ctx, buffer, len); + + 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) +{ + esp_slip_modem_t *slip_modem = (esp_slip_modem_t *) args; + + ESP_LOGD(TAG, "%s (netif: %p args: %p)", __func__, esp_netif, args); + + const esp_netif_driver_ifconfig_t driver_ifconfig = { + .driver_free_rx_buffer = NULL, + .transmit = esp_slip_modem_transmit, + .handle = slip_modem->slip_driver, + }; + + slip_modem->base.netif = esp_netif; + ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &driver_ifconfig)); + + esp_slip_driver_start(slip_modem); + + return ESP_OK; +} + +esp_err_t esp_slip_modem_set_default_handlers(esp_netif_t *esp_netif) +{ + esp_err_t ret; + + if (esp_netif == NULL) { + ESP_LOGE(TAG, "esp-netif handle can't be null"); + return ESP_ERR_INVALID_ARG; + } + + ret = esp_event_handler_register(SLIP_EVENT, SLIP_EVENT_START, esp_netif_action_start, esp_netif); + if (ret != ESP_OK) { + goto fail; + } + + ret = esp_event_handler_register(SLIP_EVENT, SLIP_EVENT_STOP, esp_netif_action_stop, esp_netif); + if (ret != ESP_OK) { + goto fail; + } + +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) +{ + if (!esp_netif) { + ESP_LOGE(TAG, "esp-netif handle can't be null"); + return ESP_ERR_INVALID_ARG; + } + esp_event_handler_unregister(SLIP_EVENT, SLIP_EVENT_START, esp_netif_action_start); + esp_event_handler_unregister(SLIP_EVENT, SLIP_EVENT_STOP, esp_netif_action_stop); + + return ESP_OK; +} + + + +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, "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); + + if (len > 0) { + + // Log slip RX data + ESP_LOGD(TAG, "rx %d bytes", len); + ESP_LOG_BUFFER_HEX_LEVEL(TAG, slip_modem->buffer, len, ESP_LOG_DEBUG); + + // Ensure null termination + slip_modem->buffer[len] = '\0'; + + // Filter if provided + if ((slip_modem->rx_filter != NULL) && slip_modem->rx_filter(slip_modem->rx_filter_ctx, slip_modem->buffer, len)) { + continue; + } + + // Pass received bytes in to slip interface + esp_netif_lwip_slip_input(slip_modem->slip_driver, slip_modem->buffer, len, NULL); + } + + // Yeild to allow other tasks to progress + vTaskDelay(1 * portTICK_PERIOD_MS); + } +} + diff --git a/examples/protocols/slip/slip_udp/CMakeLists.txt b/examples/protocols/slip/slip_udp/CMakeLists.txt new file mode 100644 index 0000000000..b9d68c60fe --- /dev/null +++ b/examples/protocols/slip/slip_udp/CMakeLists.txt @@ -0,0 +1,12 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# 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/Makefile b/examples/protocols/slip/slip_udp/Makefile new file mode 100644 index 0000000000..453c971b3c --- /dev/null +++ b/examples/protocols/slip/slip_udp/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := slip_client + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/protocols/slip/slip_udp/README.md b/examples/protocols/slip/slip_udp/README.md new file mode 100644 index 0000000000..334d2d4673 --- /dev/null +++ b/examples/protocols/slip/slip_udp/README.md @@ -0,0 +1,57 @@ +# SLIP device client + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +## 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). + +## How to use example + +### Hardware Required + +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. + +#### Pin Assignment + +**Note:** The following pin assignments are used by default which can be changed in menuconfig. + +| ESP32 | Gateway | +| ------ | -------------- | +| GPIO4 | RX | +| GPIO36 | TX | +| GND | GND | +| 3v3 | VCC | + +### Configure the project + +Open the project configuration menu (`idf.py menuconfig`). Then go into `Example Configuration` menu. + +- Choose the RX and TX pins + +For use in external projects `SLIP support` must be enabled under the `components/lwip` menu. + + +### Build and Flash + +Run `idf.py -p PORT flash monitor` to build and flash the project.. + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. + + + +## Troubleshooting + +1. Invalid slip packets + +Many slip devices use additional messages for things like ipv6 prefix configuration (or sending log messages over the SLIP serial port). This is supported in the driver through the use of an `rx_filter` function that is called on receipt of all packets and can be used to filter packets prior to passing them to the stack. + +2. No packets received + +The first layer to check is the serial port, you can enable debugging of the SLIP component by setting the global log level to `DEBUG`, or changing the slip component log levbel with `esp_log_level_set("esp-netif_lwip-slip", ESP_LOG_DEBUG);` + +(For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you as soon as possible.) diff --git a/examples/protocols/slip/slip_udp/main/CMakeLists.txt b/examples/protocols/slip/slip_udp/main/CMakeLists.txt new file mode 100644 index 0000000000..903e70d277 --- /dev/null +++ b/examples/protocols/slip/slip_udp/main/CMakeLists.txt @@ -0,0 +1,7 @@ +# Slip client example + +idf_component_register( + SRCS "slip_client_main.c" + INCLUDE_DIRS "." + REQUIRES esp_netif slip_modem +) diff --git a/examples/protocols/slip/slip_udp/main/Kconfig.projbuild b/examples/protocols/slip/slip_udp/main/Kconfig.projbuild new file mode 100644 index 0000000000..1709058d0f --- /dev/null +++ b/examples/protocols/slip/slip_udp/main/Kconfig.projbuild @@ -0,0 +1,32 @@ +menu "Example Configuration" + + menu "UART Configuration" + config EXAMPLE_UART_TX_PIN + int "TXD Pin Number" + default 4 + range 0 36 + help + Pin number of UART TX. + + config EXAMPLE_UART_RX_PIN + int "RXD Pin Number" + default 36 + range 0 36 + help + Pin number of UART RX. + + config EXAMPLE_UART_BAUD + int "UART baud rate" + default 115200 + 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 + +endmenu diff --git a/examples/protocols/slip/slip_udp/main/component.mk b/examples/protocols/slip/slip_udp/main/component.mk new file mode 100644 index 0000000000..a98f634eae --- /dev/null +++ b/examples/protocols/slip/slip_udp/main/component.mk @@ -0,0 +1,4 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/protocols/slip/slip_udp/main/slip_client_main.c b/examples/protocols/slip/slip_udp/main/slip_client_main.c new file mode 100644 index 0000000000..682e363eb8 --- /dev/null +++ b/examples/protocols/slip/slip_udp/main/slip_client_main.c @@ -0,0 +1,229 @@ +/* SLIP Client Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" + + +#include "esp_system.h" +#include "esp_log.h" +#include "esp_event.h" +#include "esp_netif.h" +#include "esp_netif_slip.h" + +#include "lwip/sockets.h" +#include "lwip/dns.h" +#include "lwip/netdb.h" + +#include "slip_modem.h" + +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; + + struct sockaddr_in6 source_addr; + socklen_t socklen = sizeof(source_addr); + + + ESP_LOGI(TAG, "Starting node manager UDP task"); + + while (1) { + // Receive data + int len = recvfrom(sock, rx_buff, sizeof(rx_buff) - 1, 0, (struct sockaddr *)&source_addr, &socklen); + if (len < 0) { + ESP_LOGE(TAG, "recvfrom failed: errno %d", errno); + break; + } + + // Parse out address to string + 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; + ESP_LOGI(TAG, "Received '%s' from '%s'", rx_buff, addr_str); + + // Send data back + int err = sendto(sock, rx_buff, len, 0, (struct sockaddr *)&source_addr, socklen); + if (err < 0) { + ESP_LOGE(TAG, "sendto failed: errno %d", errno); + break; + } + } + + vTaskDelete(NULL); +} + +esp_err_t udp_rx_tx_init() +{ + // Setup bind address + struct sockaddr_in6 dest_addr; + bzero(&dest_addr.sin6_addr.un, sizeof(dest_addr.sin6_addr.un)); + dest_addr.sin6_family = AF_INET6; + dest_addr.sin6_port = htons(CONFIG_EXAMPLE_UDP_PORT); + + // Create socket + int sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IPV6); + if (sock < 0) { + ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); + return -1; + } + + // Disable IPv4 and reuse address + int opt = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)); + + // 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; + } + 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); + + return ESP_OK; +} + +// Write a prefix to the contiki slip device +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); + + ESP_LOGI(TAG, "%s: prefix set (%08x:%08x)", __func__, + lwip_ntohl(addr->addr[0]), lwip_ntohl(addr->addr[1])); + + // Build slip set message + buff[0] = '!'; + buff[1] = 'P'; + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 4; j++) { + buff[2 + i * 4 + j] = addr->addr[i] >> (j * 8); + } + } + + // Write raw data out the slip interface + esp_netif_lwip_slip_raw_output(slip_netif, buff, 2 + 8); +} + +// slip_rx_filter filters incomming 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) +{ + + esp_netif_t *slip_netif = (esp_netif_t *)ctx; + + if (data[1] == '?') { + switch (data[2]) { + case 'P': + ESP_LOGI(TAG, "Prefix request"); + slip_set_prefix(slip_netif); + + return true; + + default: + ESP_LOGI(TAG, "Unhandled request '%c'", data[2]); + break; + } + + return true; + + } else if (data[1] == '!') { + switch (data[2]) { + default: + ESP_LOGI(TAG, "Unhandled command '%c'", data[2]); + break; + } + } + + return false; +} + +// Initialise the SLIP interface +esp_netif_t *slip_if_init() +{ + ESP_LOGI(TAG, "Initialising SLIP interface"); + + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_SLIP(); + esp_netif_t *slip_netif = esp_netif_new(&cfg); + + esp_netif_slip_config_t slip_config = { + .uart_dev = UART_NUM_2, + }; + + IP6_ADDR(&slip_config.addr, + lwip_htonl(0xfd000000), + lwip_htonl(0x00000000), + lwip_htonl(0x00000000), + lwip_htonl(0x000000001) + ); + + esp_netif_slip_set_params(slip_netif, &slip_config); + + ESP_LOGI(TAG, "Initialising SLIP modem"); + + esp_slip_modem_config_t modem_cfg = { + .uart_dev = UART_NUM_2, + + .uart_tx_pin = CONFIG_EXAMPLE_UART_TX_PIN, + .uart_rx_pin = CONFIG_EXAMPLE_UART_RX_PIN, + .uart_baud = CONFIG_EXAMPLE_UART_BAUD, + + .rx_buffer_len = 1024, + + .rx_filter = slip_rx_filter, + .rx_filter_ctx = slip_netif, + }; + + void *slip_modem = esp_slip_modem_create(slip_netif, &modem_cfg); + ESP_ERROR_CHECK(esp_netif_attach(slip_netif, slip_modem)); + + ESP_LOGI(TAG, "SLIP init complete"); + + return slip_netif; +} + +void app_main(void) +{ + // Setup networking + tcpip_adapter_init(); + + esp_log_level_set("*", ESP_LOG_DEBUG); + + // Create event loop + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + // Setup slip interface + slip_if_init(); + + // Setup UDP loopback service + udp_rx_tx_init(); + + // Run + while (1) { + vTaskDelay(portTICK_PERIOD_MS * 10); + } +} diff --git a/examples/protocols/slip/slip_udp/sdkconfig.defaults b/examples/protocols/slip/slip_udp/sdkconfig.defaults new file mode 100644 index 0000000000..9f3d373fa8 --- /dev/null +++ b/examples/protocols/slip/slip_udp/sdkconfig.defaults @@ -0,0 +1,3 @@ +# Override some defaults to enable SLIP +CONFIG_LWIP_SLIP_SUPPORT=y + From 13de11fb328c366470ac27938a4210e4276676bf Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 15 Jul 2020 15:35:16 +0200 Subject: [PATCH 2/4] lwip: Added debug config options to enable lwIP low level debugging --- components/lwip/Kconfig | 39 ++++++++++++++ components/lwip/port/esp32/include/lwipopts.h | 51 +++++++++++++++++-- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index 5a6c800be6..7378667002 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -723,4 +723,43 @@ menu "LWIP" Enable this option allows lwip to check assert. It is recommended to keep it open, do not close it. + menu "Debug" + + config LWIP_NETIF_DEBUG + bool "Enable netif debug messages" + default n + + config LWIP_PBUF_DEBUG + bool "Enable pbuf debug messages" + default n + + config LWIP_ETHARP_DEBUG + bool "Enable etharp debug messages" + default n + + config LWIP_API_LIB_DEBUG + bool "Enable api lib debug messages" + default n + + config LWIP_SOCKETS_DEBUG + bool "Enable socket debug messages" + default n + + config LWIP_IP_DEBUG + bool "Enable IP debug messages" + default n + + config LWIP_ICMP_DEBUG + bool "Enable ICMP debug messages" + default n + + config LWIP_IP6_DEBUG + bool "Enable IP6 debug messages" + default n + + config LWIP_ICMP6_DEBUG + bool "Enable ICMP6 debug messages" + default n + + endmenu #debug endmenu diff --git a/components/lwip/port/esp32/include/lwipopts.h b/components/lwip/port/esp32/include/lwipopts.h index cc7df91b97..ea35bb89ca 100644 --- a/components/lwip/port/esp32/include/lwipopts.h +++ b/components/lwip/port/esp32/include/lwipopts.h @@ -759,37 +759,82 @@ /** * ETHARP_DEBUG: Enable debugging in etharp.c. */ -#define ETHARP_DEBUG LWIP_DBG_OFF +#ifdef CONFIG_LWIP_ETHARP_DEBUG +#define ETHARP_DEBUG LWIP_DBG_ON +#else +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + /** * NETIF_DEBUG: Enable debugging in netif.c. */ +#ifdef CONFIG_LWIP_NETIF_DEBUG +#define NETIF_DEBUG LWIP_DBG_ON +#else #define NETIF_DEBUG LWIP_DBG_OFF +#endif /** * PBUF_DEBUG: Enable debugging in pbuf.c. */ -#define PBUF_DEBUG LWIP_DBG_OFF +#ifdef CONFIG_LWIP_PBUF_DEBUG +#define PBUF_DEBUG LWIP_DBG_ON +#else +#define PBUF_DEBUG LWIP_DBG_OFF +#endif /** * API_LIB_DEBUG: Enable debugging in api_lib.c. */ -#define API_LIB_DEBUG LWIP_DBG_OFF +#ifdef CONFIG_LWIP_API_LIB_DEBUG +#define API_LIB_DEBUG LWIP_DBG_ON +#else +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + /** * SOCKETS_DEBUG: Enable debugging in sockets.c. */ +#ifdef CONFIG_LWIP_SOCKETS_DEBUG +#define SOCKETS_DEBUG LWIP_DBG_ON +#else #define SOCKETS_DEBUG LWIP_DBG_OFF +#endif /** * ICMP_DEBUG: Enable debugging in icmp.c. */ +#ifdef CONFIG_LWIP_ICMP_DEBUG +#define ICMP_DEBUG LWIP_DBG_ON +#else #define ICMP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef CONFIG_LWIP_ICMP6_DEBUG +#define ICMP6_DEBUG LWIP_DBG_ON +#else +#define ICMP6_DEBUG LWIP_DBG_OFF +#endif /** * IP_DEBUG: Enable debugging for IP. */ +#ifdef CONFIG_LWIP_IP_DEBUG +#define IP_DEBUG LWIP_DBG_ON +#else #define IP_DEBUG LWIP_DBG_OFF +#endif + +/** + * IP_DEBUG: Enable debugging for IP. + */ +#ifdef CONFIG_LWIP_IP6_DEBUG +#define IP6_DEBUG LWIP_DBG_ON +#else +#define IP6_DEBUG LWIP_DBG_OFF +#endif /** * MEMP_DEBUG: Enable debugging in memp.c. From 1a41545c3eb7c3b9ed6e64cd3800743236e469cb Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 12 Jun 2020 16:43:34 +0200 Subject: [PATCH 3/4] esp-netif: SLIP interface refactor to isolate interface from drivers --- components/esp_netif/CMakeLists.txt | 1 - components/esp_netif/esp_netif_objects.c | 2 +- .../esp_netif/include/esp_netif_defaults.h | 14 +- components/esp_netif/include/esp_netif_slip.h | 59 +---- components/esp_netif/lwip/esp_netif_lwip.c | 88 +++--- .../esp_netif/lwip/esp_netif_lwip_defaults.c | 8 - .../esp_netif/lwip/esp_netif_lwip_internal.h | 33 ++- .../esp_netif/lwip/esp_netif_lwip_ppp.c | 73 +++-- .../esp_netif/lwip/esp_netif_lwip_ppp.h | 16 +- .../esp_netif/lwip/esp_netif_lwip_slip.c | 250 ++++++++++-------- .../esp_netif/lwip/esp_netif_lwip_slip.h | 35 +-- .../esp_netif/lwip/esp_netif_lwip_slip_sio.c | 163 ------------ components/lwip/Kconfig | 7 - components/lwip/port/esp32/include/lwipopts.h | 11 +- .../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 +++--- 22 files changed, 439 insertions(+), 560 deletions(-) delete mode 100644 components/esp_netif/lwip/esp_netif_lwip_slip_sio.c 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/components/esp_netif/CMakeLists.txt b/components/esp_netif/CMakeLists.txt index 5ee19e4991..3ba64cd465 100644 --- a/components/esp_netif/CMakeLists.txt +++ b/components/esp_netif/CMakeLists.txt @@ -4,7 +4,6 @@ idf_component_register(SRCS "esp_netif_handlers.c" "lwip/esp_netif_lwip.c" "lwip/esp_netif_lwip_ppp.c" "lwip/esp_netif_lwip_slip.c" - "lwip/esp_netif_lwip_slip_sio.c" "loopback/esp_netif_loopback.c" "lwip/esp_netif_lwip_defaults.c" "lwip/esp_netif_sta_list.c" diff --git a/components/esp_netif/esp_netif_objects.c b/components/esp_netif/esp_netif_objects.c index 23a2c6dde7..30c645ef56 100644 --- a/components/esp_netif/esp_netif_objects.c +++ b/components/esp_netif/esp_netif_objects.c @@ -186,4 +186,4 @@ esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key) } while (NULL != (esp_netif = esp_netif_next_unsafe(esp_netif))); esp_netif_list_unlock(); return NULL; -} \ No newline at end of file +} diff --git a/components/esp_netif/include/esp_netif_defaults.h b/components/esp_netif/include/esp_netif_defaults.h index 0b7541abb7..f61d7294b8 100644 --- a/components/esp_netif/include/esp_netif_defaults.h +++ b/components/esp_netif/include/esp_netif_defaults.h @@ -79,10 +79,10 @@ extern "C" { ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(mac) \ ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(ip_info) \ .get_ip_event = 0, \ - .lost_ip_event = 0, \ - .if_key = "SLIP_DEF", \ - .if_desc = "slip", \ - .route_prio = 20 \ + .lost_ip_event = 0, \ + .if_key = "SLP_DEF", \ + .if_desc = "slip", \ + .route_prio = 16 \ }; /** @@ -129,9 +129,9 @@ extern "C" { * @brief Default configuration reference of SLIP client */ #define ESP_NETIF_DEFAULT_SLIP() \ - { \ + { \ .base = ESP_NETIF_BASE_DEFAULT_SLIP, \ - .driver = NULL, \ + .driver = NULL, \ .stack = ESP_NETIF_NETSTACK_DEFAULT_SLIP, \ } @@ -167,7 +167,7 @@ extern "C" { #define ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA _g_esp_netif_netstack_default_wifi_sta #define ESP_NETIF_NETSTACK_DEFAULT_WIFI_AP _g_esp_netif_netstack_default_wifi_ap #define ESP_NETIF_NETSTACK_DEFAULT_PPP _g_esp_netif_netstack_default_ppp -#define ESP_NETIF_NETSTACK_DEFAULT_SLIP _g_esp_netif_netstack_default_slip +#define ESP_NETIF_NETSTACK_DEFAULT_SLIP _g_esp_netif_netstack_default_slip // // Include default network stacks configs diff --git a/components/esp_netif/include/esp_netif_slip.h b/components/esp_netif/include/esp_netif_slip.h index 088cca1751..bb0aa08303 100644 --- a/components/esp_netif/include/esp_netif_slip.h +++ b/components/esp_netif/include/esp_netif_slip.h @@ -16,12 +16,12 @@ #ifndef _ESP_NETIF_SLIP_H_ #define _ESP_NETIF_SLIP_H_ +#include "esp_netif.h" + #ifdef __cplusplus extern "C" { #endif -#include "driver/uart.h" - /** @brief SLIP event base */ ESP_EVENT_DECLARE_BASE(SLIP_EVENT); @@ -31,16 +31,11 @@ typedef enum esp_netif_slip_event { } esp_netif_slip_event_e; -/** @brief Forward declaration of lwip_slip_ctx for external use */ -typedef struct lwip_slip_ctx lwip_slip_ctx_t; - /** @brief Configuration structure for SLIP network interface * */ typedef struct esp_netif_slip_config { - ip6_addr_t addr; /* Local IP6 address */ - - uart_port_t uart_dev; /* UART device for reading and writing SLIP information, this must be initialised externally */ + esp_ip6_addr_t ip6_addr; /* Local IP6 address */ } esp_netif_slip_config_t; @@ -54,21 +49,20 @@ typedef struct esp_netif_slip_config { */ esp_err_t esp_netif_slip_set_params(esp_netif_t *netif, const esp_netif_slip_config_t *config); -/** - * @brief Data path API to input incoming packets to SLIP +/** @brief Sets IPV6 address for the supplied esp-netif. * - * @param[in] esp_netif handle to slip esp-netif instance - * @param[in] buffer pointer to the incoming data - * @param[in] len length of the data + * @param[in] netif handle to slip esp-netif instance + * @param[in] ipv6 IPv6 address of the SLIP interface * - * @return - * - ESP_OK on success + * @return ESP_OK on success, ESP_ERR_ESP_NETIF_INVALID_PARAMS if netif null or not SLIP */ -void esp_netif_lwip_slip_raw_input(esp_netif_t *netif, void *buffer, size_t len); +esp_err_t esp_netif_slip_set_ipv6(esp_netif_t *netif, const esp_ip6_addr_t *ipv6); /** * @brief Data path API to write raw packet ous the SLIP interface * + * This API is typically used when implementing user defined methods + * * @param[in] esp_netif handle to slip esp-netif instance * @param[in] buffer pointer to the outgoing data * @param[in] len length of the data @@ -87,37 +81,6 @@ void esp_netif_lwip_slip_raw_output(esp_netif_t *netif, void *buffer, size_t len * @return * - pointer to the internal ip6 address object */ -const ip6_addr_t *esp_slip_get_ip6(esp_netif_t *slip_netif); - -/** - * @brief Fetch lwip_slip_ctx_t for esp_netif_t object - * - * This is required to support the wiring of esp_netif objects outside - * of this component. - * - * @return - * - lwip slip context - */ -lwip_slip_ctx_t *esp_netif_lwip_slip_get_ctx(esp_netif_t *slip_netif); - -/** - * @brief Start the esp slip netif - * - * @param[in] esp_netif handle to slip esp-netif instance - * - * @return - * - ESP_OK on success - */ -esp_err_t esp_netif_start_slip(lwip_slip_ctx_t *slip_ctx); - -/** - * @brief Stop the esp slip netif - * - * @param[in] esp_netif handle to slip esp-netif instance - * - * @return - * - ESP_OK on success - */ -esp_err_t esp_netif_stop_slip(lwip_slip_ctx_t *slip_ctx); +const esp_ip6_addr_t *esp_slip_get_ip6(esp_netif_t *slip_netif); #endif diff --git a/components/esp_netif/lwip/esp_netif_lwip.c b/components/esp_netif/lwip/esp_netif_lwip.c index 4ddf0f7479..f7bbc202ce 100644 --- a/components/esp_netif/lwip/esp_netif_lwip.c +++ b/components/esp_netif/lwip/esp_netif_lwip.c @@ -52,9 +52,14 @@ */ #define _RUN_IN_LWIP_TASK(function, netif, param) { return esp_netif_lwip_ipc_call(function, netif, (void *)(param)); } +/** + * @brief macros to check netif related data to evaluate interface type + */ +#define _IS_NETIF_ANY_POINT2POINT_TYPE(netif) (netif->related_data && netif->related_data->is_point2point) + #define _RUN_IN_LWIP_TASK_IF_SUPPORTED(function, netif, param) \ { \ - if (netif->is_ppp_netif) { \ + if (_IS_NETIF_ANY_POINT2POINT_TYPE(netif)) { \ return ESP_ERR_NOT_SUPPORTED; \ } \ return esp_netif_lwip_ipc_call(function, netif, (void *)(param)); \ @@ -148,10 +153,8 @@ static esp_netif_t* esp_netif_is_active(esp_netif_t *arg) */ static void esp_netif_set_default_netif(esp_netif_t *esp_netif) { - if (esp_netif->is_ppp_netif) { + if (_IS_NETIF_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) { esp_netif_ppp_set_default_netif(esp_netif->netif_handle); - } else if (esp_netif->is_slip_netif) { - esp_netif_slip_set_default_netif(esp_netif->netif_handle); } else { netif_set_default(esp_netif->netif_handle); } @@ -256,7 +259,7 @@ esp_netif_t* esp_netif_get_handle_from_netif_impl(void *dev) void* esp_netif_get_netif_impl(esp_netif_t *esp_netif) { // get impl ptr only for vanilla lwip impl (ppp_pcb not supported) - if (esp_netif && !esp_netif->is_ppp_netif) { + if (esp_netif && !_IS_NETIF_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) { return esp_netif->lwip_netif; } return NULL; @@ -341,24 +344,27 @@ static esp_err_t esp_netif_init_configuration(esp_netif_t *esp_netif, const esp_ // Install network stack functions -- connects netif and L3 stack const esp_netif_netstack_config_t *esp_netif_stack_config = cfg->stack; if (cfg->base->flags & ESP_NETIF_FLAG_IS_PPP) { - esp_netif->lwip_ppp_ctx = esp_netif_new_ppp(esp_netif, esp_netif_stack_config); - if (esp_netif->lwip_ppp_ctx == NULL) { + esp_netif->related_data = esp_netif_new_ppp(esp_netif, esp_netif_stack_config); + if (esp_netif->related_data == NULL) { return ESP_ERR_ESP_NETIF_INIT_FAILED; } esp_netif->lwip_input_fn = esp_netif_stack_config->lwip_ppp.input_fn; - esp_netif->is_ppp_netif = true; // Make the netif handle (used for tcpip input function) the ppp_netif - esp_netif->netif_handle = esp_netif->lwip_ppp_ctx; + esp_netif->netif_handle = esp_netif->related_data; } else if (cfg->base->flags & ESP_NETIF_FLAG_IS_SLIP) { - esp_netif->lwip_slip_ctx = esp_netif_new_slip(esp_netif, esp_netif_stack_config); - if (esp_netif->lwip_slip_ctx == NULL) { + esp_netif->related_data = esp_netif_new_slip(esp_netif, esp_netif_stack_config); + if (esp_netif->related_data == NULL) { return ESP_ERR_ESP_NETIF_INIT_FAILED; } - esp_netif->lwip_input_fn = esp_netif_stack_config->lwip_slip.input_fn; - esp_netif->is_slip_netif = true; - // Make the netif handle (used for tcpip input function) the slip_netif - esp_netif->netif_handle = esp_netif->lwip_slip_ctx; + if (esp_netif_stack_config->lwip.init_fn) { + esp_netif->lwip_init_fn = esp_netif_stack_config->lwip.init_fn; + } + if (esp_netif_stack_config->lwip.input_fn) { + esp_netif->lwip_input_fn = esp_netif_stack_config->lwip.input_fn; + } + // Make the netif handle (used for tcpip input function) the esp_netif itself + esp_netif->netif_handle = esp_netif; } else { if (esp_netif_stack_config-> lwip.init_fn) { @@ -491,6 +497,15 @@ static esp_err_t esp_netif_lwip_add(esp_netif_t *esp_netif) return ESP_OK; } +static void esp_netif_destroy_related(esp_netif_t *esp_netif) +{ + if (_IS_NETIF_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) { + esp_netif_destroy_ppp(esp_netif->related_data); + } else if (_IS_NETIF_POINT2POINT_TYPE(esp_netif, SLIP_LWIP_NETIF)) { + esp_netif_destroy_slip(esp_netif->related_data); + } +} + void esp_netif_destroy(esp_netif_t *esp_netif) { if (esp_netif) { @@ -500,11 +515,7 @@ void esp_netif_destroy(esp_netif_t *esp_netif) free(esp_netif->if_key); free(esp_netif->if_desc); esp_netif_lwip_remove(esp_netif); - if (esp_netif->is_ppp_netif) { - esp_netif_destroy_ppp(esp_netif->netif_handle); - } else if (esp_netif->is_slip_netif) { - esp_netif_destroy_slip(esp_netif->netif_handle); - } + esp_netif_destroy_related(esp_netif); free(esp_netif->lwip_netif); free(esp_netif->hostname); if (s_last_default_esp_netif == esp_netif) { @@ -555,7 +566,7 @@ esp_err_t esp_netif_set_mac(esp_netif_t *esp_netif, uint8_t mac[]) if (esp_netif == NULL || esp_netif->lwip_netif == NULL) { return ESP_ERR_ESP_NETIF_IF_NOT_READY; } - if (esp_netif->is_ppp_netif || esp_netif->is_slip_netif) { + if (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) { return ESP_ERR_NOT_SUPPORTED; } memcpy(esp_netif->mac, mac, NETIF_MAX_HWADDR_LEN); @@ -568,7 +579,7 @@ esp_err_t esp_netif_get_mac(esp_netif_t *esp_netif, uint8_t mac[]) if (esp_netif == NULL || esp_netif->lwip_netif == NULL) { return ESP_ERR_ESP_NETIF_IF_NOT_READY; } - if (esp_netif->is_ppp_netif || esp_netif->is_slip_netif) { + if (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) { return ESP_ERR_NOT_SUPPORTED; } if (esp_netif_is_netif_up(esp_netif)) { @@ -684,16 +695,9 @@ static esp_err_t esp_netif_start_api(esp_netif_api_msg_t *msg) esp_err_t esp_netif_start(esp_netif_t *esp_netif) { - if (esp_netif->is_ppp_netif) { + if (_IS_NETIF_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) { // No need to start PPP interface in lwip thread - esp_err_t ret = esp_netif_start_ppp(esp_netif->lwip_ppp_ctx); - if (ret == ESP_OK) { - esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED); - } - return ret; - } else if (esp_netif->is_slip_netif) { - // No need to start SLIP interface in lwip thread - esp_err_t ret = esp_netif_start_slip(esp_netif->lwip_slip_ctx); + esp_err_t ret = esp_netif_start_ppp(esp_netif->related_data); if (ret == ESP_OK) { esp_netif_update_default_netif(esp_netif, ESP_NETIF_STARTED); } @@ -740,16 +744,16 @@ static esp_err_t esp_netif_stop_api(esp_netif_api_msg_t *msg) esp_err_t esp_netif_stop(esp_netif_t *esp_netif) { - if (esp_netif->is_ppp_netif) { + if (_IS_NETIF_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) { // No need to stop PPP interface in lwip thread - esp_err_t ret = esp_netif_stop_ppp(esp_netif->lwip_ppp_ctx); + esp_err_t ret = esp_netif_stop_ppp(esp_netif->related_data); if (ret == ESP_OK) { esp_netif_update_default_netif(esp_netif, ESP_NETIF_STOPPED);; } return ret; - } else if (esp_netif->is_slip_netif) { + } else if (_IS_NETIF_POINT2POINT_TYPE(esp_netif, SLIP_LWIP_NETIF)) { // No need to stop PPP interface in lwip thread - esp_err_t ret = esp_netif_stop_slip(esp_netif->lwip_slip_ctx); + esp_err_t ret = esp_netif_stop_slip(esp_netif); if (ret == ESP_OK) { esp_netif_update_default_netif(esp_netif, ESP_NETIF_STOPPED);; } @@ -987,7 +991,7 @@ esp_err_t esp_netif_dhcpc_start(esp_netif_t *esp_netif) _RUN_IN_LWIP_TASK_IF_SUP esp_err_t esp_netif_dhcps_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status) { - if (!esp_netif || (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) || esp_netif->is_ppp_netif || esp_netif->is_slip_netif) { + if (!esp_netif || (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) || _IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) { return ESP_ERR_INVALID_ARG; } @@ -997,7 +1001,7 @@ esp_err_t esp_netif_dhcps_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_stat esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status) { - if (!esp_netif || (esp_netif->flags & ESP_NETIF_DHCP_SERVER) || esp_netif->is_ppp_netif || esp_netif->is_slip_netif) { + if (!esp_netif || (esp_netif->flags & ESP_NETIF_DHCP_SERVER) || _IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) { return ESP_ERR_INVALID_ARG; } @@ -1110,7 +1114,7 @@ esp_err_t esp_netif_get_hostname(esp_netif_t *esp_netif, const char **hostname) { ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif); - if (!esp_netif || esp_netif->is_ppp_netif || esp_netif->is_slip_netif) { + if (!esp_netif || _IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) { return ESP_ERR_INVALID_ARG; } @@ -1192,7 +1196,7 @@ bool esp_netif_is_netif_up(esp_netif_t *esp_netif) ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif); if (esp_netif != NULL && esp_netif->lwip_netif != NULL) { - if (esp_netif->is_ppp_netif) { + if (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) { // ppp implementation uses netif_set_link_up/down to update link state return netif_is_link_up(esp_netif->lwip_netif); } @@ -1369,7 +1373,7 @@ static esp_err_t esp_netif_set_dns_info_api(esp_netif_api_msg_t *msg) esp_err_t esp_netif_set_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t type, esp_netif_dns_info_t *dns) { - if (esp_netif->is_ppp_netif || esp_netif->is_slip_netif) { + if (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) { return ESP_ERR_NOT_SUPPORTED; } esp_netif_dns_param_t dns_param = { @@ -1409,7 +1413,7 @@ static esp_err_t esp_netif_get_dns_info_api(esp_netif_api_msg_t *msg) esp_err_t esp_netif_get_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t type, esp_netif_dns_info_t *dns) { - if (esp_netif->is_ppp_netif || esp_netif->is_slip_netif) { + if (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) { const ip_addr_t *dns_ip = dns_getserver(type); if (dns_ip == IP_ADDR_ANY) { return ESP_ERR_ESP_NETIF_DNS_NOT_CONFIGURED; @@ -1494,7 +1498,7 @@ esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if { ESP_LOGV(TAG, "%s esp-netif:%p", __func__, esp_netif); - if (esp_netif == NULL || if_ip6 == NULL || esp_netif->is_ppp_netif || esp_netif->is_slip_netif) { + if (esp_netif == NULL || if_ip6 == NULL || _IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) { return ESP_ERR_ESP_NETIF_INVALID_PARAMS; } struct netif *p_netif = esp_netif->lwip_netif; diff --git a/components/esp_netif/lwip/esp_netif_lwip_defaults.c b/components/esp_netif/lwip/esp_netif_lwip_defaults.c index aa3d579058..b241b00363 100644 --- a/components/esp_netif/lwip/esp_netif_lwip_defaults.c +++ b/components/esp_netif/lwip/esp_netif_lwip_defaults.c @@ -54,16 +54,8 @@ static const struct esp_netif_netstack_config s_netif_config_ppp = { } }; -static const struct esp_netif_netstack_config s_netif_config_slip = { - .lwip_slip = { - .slip_config = { - .uart_dev = UART_NUM_1, - } - } -}; const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_eth = &s_eth_netif_config; const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_sta = &s_wifi_netif_config_sta; const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_wifi_ap = &s_wifi_netif_config_ap; const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_ppp = &s_netif_config_ppp; -const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_slip = &s_netif_config_slip; diff --git a/components/esp_netif/lwip/esp_netif_lwip_internal.h b/components/esp_netif/lwip/esp_netif_lwip_internal.h index a3df2f2c7f..f383674b2d 100644 --- a/components/esp_netif/lwip/esp_netif_lwip_internal.h +++ b/components/esp_netif/lwip/esp_netif_lwip_internal.h @@ -30,6 +30,7 @@ struct esp_netif_netstack_lwip_ppp_config { }; struct esp_netif_netstack_lwip_slip_config { + err_t (*init_fn)(struct netif*); void (*input_fn)(void *netif, void *buffer, size_t len, void *eb); esp_netif_slip_config_t slip_config; }; @@ -39,7 +40,6 @@ struct esp_netif_netstack_config { union { struct esp_netif_netstack_lwip_vanilla_config lwip; struct esp_netif_netstack_lwip_ppp_config lwip_ppp; - struct esp_netif_netstack_lwip_slip_config lwip_slip; }; }; @@ -65,9 +65,28 @@ typedef struct esp_netif_ip_lost_timer_s { bool timer_running; } esp_netif_ip_lost_timer_t; -// Forward declare the ppp and slip context -typedef struct lwip_ppp_ctx lwip_ppp_ctx_t; -typedef struct lwip_slip_ctx lwip_slip_ctx_t; +/** + * @brief Check the netif if of a specific P2P type + */ +#define _IS_NETIF_POINT2POINT_TYPE(netif, type) (netif->related_data && netif->related_data->is_point2point && netif->related_data->netif_type == type) + +/** + * @brief Additional netif types when related data are needed + */ +enum netif_types { + COMMON_LWIP_NETIF, + PPP_LWIP_NETIF, + SLIP_LWIP_NETIF +}; + +/** + * @brief Related data to esp-netif (additional data for some special types of netif + * (typically for point-point network types, such as PPP or SLIP) + */ +typedef struct netif_related_data { + bool is_point2point; + enum netif_types netif_type; +} netif_related_data_t; /** * @brief Main esp-netif container with interface related information @@ -80,14 +99,10 @@ struct esp_netif_obj { // lwip netif related struct netif *lwip_netif; - lwip_ppp_ctx_t *lwip_ppp_ctx; - lwip_slip_ctx_t *lwip_slip_ctx; err_t (*lwip_init_fn)(struct netif*); void (*lwip_input_fn)(void *input_netif_handle, void *buffer, size_t len, void *eb); void * netif_handle; // netif impl context (either vanilla lwip-netif or ppp_pcb) - - bool is_ppp_netif; - bool is_slip_netif; + netif_related_data_t *related_data; // holds additional data for specific netifs // io driver related void* driver_handle; diff --git a/components/esp_netif/lwip/esp_netif_lwip_ppp.c b/components/esp_netif/lwip/esp_netif_lwip_ppp.c index 2a82ca404e..7500888d8a 100644 --- a/components/esp_netif/lwip/esp_netif_lwip_ppp.c +++ b/components/esp_netif/lwip/esp_netif_lwip_ppp.c @@ -31,13 +31,16 @@ static const char *TAG = "esp-netif_lwip-ppp"; #if PPPOS_SUPPORT /** - * @brief internal lwip_ppp context struct, used to hold PPP netif related parameters + * @brief internal lwip_ppp context struct extends the netif related data + * used to hold PPP netif related parameters */ -struct lwip_ppp_ctx { +typedef struct lwip_peer2peer_ctx { + netif_related_data_t base; // Generic portion of netif-related data + // PPP specific fields follow bool ppp_phase_event_enabled; bool ppp_error_event_enabled; ppp_pcb *ppp; -}; +} lwip_peer2peer_ctx_t; /** * @brief lwip callback from PPP client used here to produce PPP error related events, @@ -53,7 +56,8 @@ static void on_ppp_status_changed(ppp_pcb *pcb, int err_code, void *ctx) .if_index = -1, }; esp_err_t err; - struct lwip_ppp_ctx *obj = netif->lwip_ppp_ctx; + struct lwip_peer2peer_ctx *obj = (struct lwip_peer2peer_ctx*)netif->related_data; + assert(obj->base.netif_type == PPP_LWIP_NETIF); esp_ip4_addr_t ns1; esp_ip4_addr_t ns2; switch (err_code) { @@ -208,7 +212,8 @@ static void on_ppp_notify_phase(ppp_pcb *pcb, u8_t phase, void *ctx) break; } esp_netif_t *netif = ctx; - struct lwip_ppp_ctx *obj = netif->lwip_ppp_ctx; + lwip_peer2peer_ctx_t *obj = (lwip_peer2peer_ctx_t *)netif->related_data; + assert(obj->base.netif_type == PPP_LWIP_NETIF); if (obj && obj->ppp_phase_event_enabled) { esp_err_t err = esp_event_post(NETIF_PPP_STATUS, NETIF_PP_PHASE_OFFSET + phase, netif, sizeof(netif), 0); if (err != ESP_OK) { @@ -239,12 +244,13 @@ static uint32_t pppos_low_level_output(ppp_pcb *pcb, uint8_t *data, uint32_t len esp_err_t esp_netif_ppp_set_auth(esp_netif_t *netif, esp_netif_auth_type_t authtype, const char *user, const char *passwd) { - if (netif == NULL || !netif->is_ppp_netif) { + if (_IS_NETIF_POINT2POINT_TYPE(netif, PPP_LWIP_NETIF)) { return ESP_ERR_ESP_NETIF_INVALID_PARAMS; } #if PPP_AUTH_SUPPORT - struct lwip_ppp_ctx *obj = netif->lwip_ppp_ctx; - pppapi_set_auth(obj->ppp, authtype, user, passwd); + lwip_peer2peer_ctx_t *ppp_ctx = (lwip_peer2peer_ctx_t *)netif->related_data; + assert(ppp_ctx->base.netif_type == PPP_LWIP_NETIF); + pppapi_set_auth(ppp_ctx->ppp, authtype, user, passwd); #else ESP_LOGE(TAG, "%s failed: No authorisation enabled in menuconfig", __func__); return ESP_ERR_ESP_NETIF_IF_NOT_READY; @@ -252,35 +258,47 @@ esp_err_t esp_netif_ppp_set_auth(esp_netif_t *netif, esp_netif_auth_type_t autht return ESP_OK; } -void esp_netif_slip_set_default_netif(lwip_ppp_ctx_t* slip_ctx) +void esp_netif_ppp_set_default_netif(netif_related_data_t *netif_related) { - netif_set_default(slip_ctx->netif) + lwip_peer2peer_ctx_t *ppp_ctx = (lwip_peer2peer_ctx_t *)netif_related; + assert(ppp_ctx->base.netif_type == PPP_LWIP_NETIF); + + ppp_set_default(ppp_ctx->ppp); } -lwip_ppp_ctx_t* esp_netif_new_ppp(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config) +netif_related_data_t * esp_netif_new_ppp(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config) { struct netif * netif_impl = esp_netif->lwip_netif; - struct lwip_ppp_ctx * ppp_obj = calloc(1, sizeof(struct lwip_ppp_ctx)); + struct lwip_peer2peer_ctx * ppp_obj = calloc(1, sizeof(struct lwip_peer2peer_ctx)); if (ppp_obj == NULL) { ESP_LOGE(TAG, "%s: cannot allocate lwip_ppp_ctx", __func__); return NULL; } + // Setup the generic esp-netif fields + ppp_obj->base.is_point2point = true; + ppp_obj->base.netif_type = PPP_LWIP_NETIF; ppp_obj->ppp = pppapi_pppos_create(netif_impl, pppos_low_level_output, on_ppp_status_changed, esp_netif); ESP_LOGD(TAG, "%s: PPP connection created: %p", __func__, ppp_obj->ppp); if (!ppp_obj->ppp) { ESP_LOGE(TAG, "%s: lwIP PPP connection cannot be created", __func__); } + + // Set the related data here, since the phase callback could be triggered before this function exits + esp_netif->related_data = (netif_related_data_t *)ppp_obj; #if PPP_NOTIFY_PHASE ppp_set_notify_phase_callback(ppp_obj->ppp, on_ppp_notify_phase); #endif ppp_set_usepeerdns(ppp_obj->ppp, 1); - return ppp_obj; + return (netif_related_data_t *)ppp_obj; } -esp_err_t esp_netif_start_ppp(lwip_ppp_ctx_t *ppp_ctx) +esp_err_t esp_netif_start_ppp(netif_related_data_t *netif_related) { + lwip_peer2peer_ctx_t *ppp_ctx = (lwip_peer2peer_ctx_t *)netif_related; + assert(ppp_ctx->base.netif_type == PPP_LWIP_NETIF); + ESP_LOGD(TAG, "%s: Starting PPP connection: %p", __func__, ppp_ctx->ppp); esp_err_t err = pppapi_connect(ppp_ctx->ppp, 0); if (err != ESP_OK) { @@ -292,15 +310,17 @@ esp_err_t esp_netif_start_ppp(lwip_ppp_ctx_t *ppp_ctx) void esp_netif_lwip_ppp_input(void *ppp_ctx, void *buffer, size_t len, void *eb) { - struct lwip_ppp_ctx * obj = ppp_ctx; + struct lwip_peer2peer_ctx * obj = ppp_ctx; err_t ret = pppos_input_tcpip(obj->ppp, buffer, len); if (ret != ERR_OK) { ESP_LOGE(TAG, "pppos_input_tcpip failed with %d", ret); } } -esp_err_t esp_netif_stop_ppp(lwip_ppp_ctx_t *ppp_ctx) +esp_err_t esp_netif_stop_ppp(netif_related_data_t *netif_related) { + lwip_peer2peer_ctx_t *ppp_ctx = (lwip_peer2peer_ctx_t *)netif_related; + assert(ppp_ctx->base.netif_type == PPP_LWIP_NETIF); ESP_LOGD(TAG, "%s: Stopped PPP connection: %p", __func__, ppp_ctx->ppp); err_t ret = pppapi_close(ppp_ctx->ppp, 0); if (ret != ERR_OK) { @@ -310,21 +330,26 @@ esp_err_t esp_netif_stop_ppp(lwip_ppp_ctx_t *ppp_ctx) return ESP_OK; } -void esp_netif_destroy_ppp(lwip_ppp_ctx_t *ppp_ctx) +void esp_netif_destroy_ppp(netif_related_data_t *netif_related) { + lwip_peer2peer_ctx_t *ppp_ctx = (lwip_peer2peer_ctx_t *)netif_related; + assert(ppp_ctx->base.netif_type == PPP_LWIP_NETIF); + pppapi_free(ppp_ctx->ppp); - free(ppp_ctx); + free(netif_related); } esp_err_t esp_netif_ppp_set_params(esp_netif_t *netif, const esp_netif_ppp_config_t *config) { - struct lwip_ppp_ctx *obj = netif->lwip_ppp_ctx; + struct lwip_peer2peer_ctx *obj = (struct lwip_peer2peer_ctx *)netif->related_data; obj->ppp_phase_event_enabled = config->ppp_phase_event_enabled; obj->ppp_error_event_enabled = config->ppp_error_event_enabled; return ESP_OK; } #else /* PPPOS_SUPPORT */ +typedef struct lwip_peer2peer_ctx lwip_peer2peer_ctx_t; + /** * @brief If PPP not enabled in menuconfig, log the error and return appropriate code indicating failure */ @@ -337,22 +362,22 @@ esp_err_t esp_netif_ppp_set_params(esp_netif_t *netif, const esp_netif_ppp_confi esp_err_t esp_netif_ppp_set_auth(esp_netif_t *netif, esp_netif_auth_type_t authtype, const char *user, const char *passwd) LOG_PPP_DISABLED_AND_DO(return ESP_ERR_NOT_SUPPORTED) -void esp_netif_ppp_set_default_netif(lwip_ppp_ctx_t* ppp_ctx) +void esp_netif_ppp_set_default_netif(lwip_peer2peer_ctx_t* ppp_ctx) LOG_PPP_DISABLED_AND_DO() -lwip_ppp_ctx_t* esp_netif_new_ppp(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config) +lwip_peer2peer_ctx_t* esp_netif_new_ppp(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config) LOG_PPP_DISABLED_AND_DO(return NULL) -esp_err_t esp_netif_start_ppp(lwip_ppp_ctx_t *ppp_ctx) +esp_err_t esp_netif_start_ppp(lwip_peer2peer_ctx_t *ppp_ctx) LOG_PPP_DISABLED_AND_DO(return ESP_ERR_NOT_SUPPORTED) void esp_netif_lwip_ppp_input(void *ppp_ctx, void *buffer, size_t len, void *eb) LOG_PPP_DISABLED_AND_DO() -esp_err_t esp_netif_stop_ppp(lwip_ppp_ctx_t *ppp_ctx) +esp_err_t esp_netif_stop_ppp(lwip_peer2peer_ctx_t *ppp_ctx) LOG_PPP_DISABLED_AND_DO(return ESP_ERR_NOT_SUPPORTED) -void esp_netif_destroy_ppp(lwip_ppp_ctx_t *ppp_ctx) +void esp_netif_destroy_ppp(lwip_peer2peer_ctx_t *ppp_ctx) LOG_PPP_DISABLED_AND_DO() esp_err_t esp_netif_ppp_set_params(esp_netif_t *netif, const esp_netif_ppp_config_t *config) diff --git a/components/esp_netif/lwip/esp_netif_lwip_ppp.h b/components/esp_netif/lwip/esp_netif_lwip_ppp.h index 8b306e3454..c9a2ef6aeb 100644 --- a/components/esp_netif/lwip/esp_netif_lwip_ppp.h +++ b/components/esp_netif/lwip/esp_netif_lwip_ppp.h @@ -25,17 +25,17 @@ * - pointer to ppp-netif object on success * - NULL otherwise */ -lwip_ppp_ctx_t* esp_netif_new_ppp(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config); +netif_related_data_t * esp_netif_new_ppp(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config); /** * @brief Creates new PPP related structure * - * @param[in] ppp pointer to internal ppp context instance + * @param[in] netif_related pointer to internal ppp context instance * * @return * - ESP_OK on success */ -esp_err_t esp_netif_start_ppp(lwip_ppp_ctx_t *ppp); +esp_err_t esp_netif_start_ppp(netif_related_data_t *netif_related); /** * @brief Data path API to input incoming packets to PPP @@ -53,19 +53,19 @@ void esp_netif_lwip_ppp_input(void *ppp, void *buffer, size_t len, void *eb); /** * @brief Destroys the ppp netif object * - * @param[in] ppp pointer to internal ppp context instance + * @param[in] netif_related pointer to internal ppp context instance */ -void esp_netif_destroy_ppp(lwip_ppp_ctx_t *ppp); +void esp_netif_destroy_ppp(netif_related_data_t *netif_related); /** * @brief Stops the PPP interface * - * @param[in] ppp pointer to internal ppp context instance + * @param[in] netif_related pointer to internal ppp context instance * * @return * - ESP_OK on success */ -esp_err_t esp_netif_stop_ppp(lwip_ppp_ctx_t *ppp); +esp_err_t esp_netif_stop_ppp(netif_related_data_t *netif_related); /** * @brief Sets default netif for routing priority config @@ -73,6 +73,6 @@ esp_err_t esp_netif_stop_ppp(lwip_ppp_ctx_t *ppp); * @note: This function must be called from lwip thread * */ -void esp_netif_ppp_set_default_netif(lwip_ppp_ctx_t* ppp_ctx); +void esp_netif_ppp_set_default_netif(netif_related_data_t *netif_related); #endif // _ESP_NETIF_LWIP_PPP_H_ \ No newline at end of file diff --git a/components/esp_netif/lwip/esp_netif_lwip_slip.c b/components/esp_netif/lwip/esp_netif_lwip_slip.c index 69386869be..80cbf1b91f 100644 --- a/components/esp_netif/lwip/esp_netif_lwip_slip.c +++ b/components/esp_netif/lwip/esp_netif_lwip_slip.c @@ -16,19 +16,14 @@ #include "lwip/dns.h" #include "esp_netif.h" #include "esp_log.h" -#include "esp_netif_net_stack.h" -#include "esp_event.h" #include "esp_netif_slip.h" - #include "esp_netif_lwip_internal.h" - +#include "esp_netif_net_stack.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 "netif/slipif.h" +#include "lwip/sio.h" #include @@ -38,25 +33,21 @@ ESP_EVENT_DEFINE_BASE(SLIP_EVENT); static const char *TAG = "esp-netif_lwip-slip"; /** - * @brief LWIP SLIP context object + * @brief LWIP SLIP context object extends esp-netif related data */ typedef struct lwip_slip_ctx { - //! ESP netif object - esp_netif_t *esp_netif; + //! Generic esp-netif related data + netif_related_data_t base; //! SLIP interface IP6 address - ip6_addr_t addr; - - - //! UART device for underling SIO - uart_port_t uart_dev; + esp_ip6_addr_t addr; } lwip_slip_ctx_t; /** * @brief Create a new lwip slip interface */ -lwip_slip_ctx_t *esp_netif_new_slip(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config) +netif_related_data_t * esp_netif_new_slip(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config) { ESP_LOGD(TAG, "%s", __func__); @@ -68,60 +59,29 @@ lwip_slip_ctx_t *esp_netif_new_slip(esp_netif_t *esp_netif, const esp_netif_nets ESP_LOGE(TAG, "%s: cannot allocate lwip_slip_ctx_t", __func__); return NULL; } + // Setup the generic esp-netif fields + slip_ctx->base.is_point2point = true; + slip_ctx->base.netif_type = SLIP_LWIP_NETIF; - ESP_LOGD(TAG, "%s: Initialising SLIP (esp_netif %p, lwip_netif %p, device: %d)", __func__, esp_netif, netif_impl, slip_ctx->uart_dev); - - // Load config - const esp_netif_slip_config_t *slip_config = &esp_netif_stack_config->lwip_slip.slip_config; - - // Attache network interface and uart device - slip_ctx->uart_dev = slip_config->uart_dev; - slip_ctx->esp_netif = esp_netif; + ESP_LOGD(TAG, "%s: Initialising SLIP (esp_netif %p, lwip_netif %p)", __func__, esp_netif, netif_impl); ESP_LOGI(TAG, "%s: Created SLIP interface (netif %p, slip_ctx: %p)", __func__, esp_netif, slip_ctx); - return slip_ctx; -} - -/** - * @brief Creates new SLIP related structure - */ -esp_err_t esp_netif_start_slip(lwip_slip_ctx_t *slip_ctx) -{ - ESP_LOGI(TAG, "%s: Starting SLIP connection (slip_ctx: %p, addr: %s)", __func__, slip_ctx, ip6addr_ntoa(&slip_ctx->addr)); - - struct netif *netif_impl = slip_ctx->esp_netif->lwip_netif; - - // Store serial port number in net interface for SIO open command - netif_impl->state = (void *)slip_ctx->uart_dev; - - // Attach interface - netif_add_noaddr(slip_ctx->esp_netif->lwip_netif, (void *)slip_ctx->uart_dev, &slipif_init, &ip_input); - - // Bind address - int8_t addr_index = 0; - - // Note that addr_set is used here as the address is statically configured - // rather than negotiated over the link - netif_ip6_addr_set(slip_ctx->esp_netif->lwip_netif, addr_index, &slip_ctx->addr); - netif_ip6_addr_set_state(slip_ctx->esp_netif->lwip_netif, addr_index, IP6_ADDR_VALID); - - // Setup interface - netif_set_link_up(slip_ctx->esp_netif->lwip_netif); - netif_set_up(slip_ctx->esp_netif->lwip_netif); - - return ESP_OK; + return (netif_related_data_t *)slip_ctx; } /** * @brief Stops the SLIP interface */ -esp_err_t esp_netif_stop_slip(lwip_slip_ctx_t *slip_ctx) +esp_err_t esp_netif_stop_slip(esp_netif_t *esp_netif) { + lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *)esp_netif; + assert(slip_ctx->base.netif_type == SLIP_LWIP_NETIF); + ESP_LOGI(TAG, "%s: Stopped SLIP connection: %p", __func__, slip_ctx); // Stop interface - netif_set_link_down(slip_ctx->esp_netif->lwip_netif); + netif_set_link_down(esp_netif->lwip_netif); return ESP_OK; } @@ -133,59 +93,64 @@ esp_err_t esp_netif_stop_slip(lwip_slip_ctx_t *slip_ctx) esp_err_t esp_netif_slip_set_params(esp_netif_t *netif, const esp_netif_slip_config_t *slip_config) { - lwip_slip_ctx_t *slip_ctx = netif->lwip_slip_ctx; + lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *)netif->related_data; + assert(slip_ctx->base.netif_type == SLIP_LWIP_NETIF); ESP_LOGD(TAG, "%s (slip_ctx: %p)", __func__, slip_ctx); - if (netif_is_link_up(slip_ctx->esp_netif->lwip_netif)) { + if (netif_is_link_up(netif->lwip_netif)) { ESP_LOGE(TAG, "Cannot set parameters while SLIP interface is running"); return ESP_ERR_INVALID_STATE; } - memcpy(&slip_ctx->addr, &slip_config->addr, sizeof(ip6_addr_t)); - slip_ctx->uart_dev = slip_config->uart_dev; + memcpy(&slip_ctx->addr, &slip_config->ip6_addr, sizeof(ip6_addr_t)); + return ESP_OK; } +esp_err_t esp_netif_slip_set_ipv6(esp_netif_t *netif, const esp_ip6_addr_t *ipv6) +{ + lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *)netif->related_data; + assert(slip_ctx->base.netif_type == SLIP_LWIP_NETIF); + + ESP_LOGV(TAG, "%s (slip_ctx: %p)", __func__, slip_ctx); + + if (netif_is_link_up(netif->lwip_netif)) { + ESP_LOGE(TAG, "Cannot set parameters while SLIP interface is running"); + return ESP_ERR_INVALID_STATE; + } + memcpy(&slip_ctx->addr, ipv6, sizeof(ip6_addr_t)); + int8_t addr_index = 0; + + netif_ip6_addr_set(netif->lwip_netif, addr_index, (ip6_addr_t *)&slip_ctx->addr); + netif_ip6_addr_set_state(netif->lwip_netif, addr_index, IP6_ADDR_VALID); + + return ESP_OK; +} + + /** * @brief Write incoming serial data to the SLIP interface */ -void esp_netif_lwip_slip_input(void *ctx, void *buffer, size_t len, void *eb) +void esp_netif_lwip_slip_input(void *h, void *buffer, unsigned int len, void *eb) { - lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *)ctx; +#if CONFIG_LWIP_SLIP_SUPPORT + esp_netif_t *netif = h; + lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *)netif->related_data; + assert(slip_ctx->base.netif_type == SLIP_LWIP_NETIF); ESP_LOGD(TAG, "%s", __func__); ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_DEBUG); // Update slip netif with data - slipif_received_bytes(slip_ctx->esp_netif->lwip_netif, buffer, len); + slipif_received_bytes(netif->lwip_netif, buffer, len); // Process incoming bytes for (int i = 0; i < len; i++) { - slipif_process_rxqueue(slip_ctx->esp_netif->lwip_netif); + slipif_process_rxqueue(netif->lwip_netif); } -} - -/** - * @brief Write raw data out the SLIP interface - */ -void esp_netif_lwip_slip_output(lwip_slip_ctx_t *slip_ctx, void *buffer, size_t len) -{ - struct netif *lwip_netif = slip_ctx->esp_netif->lwip_netif; - - ESP_LOGD(TAG, "%s", __func__); - ESP_LOG_BUFFER_HEXDUMP(TAG, buffer, len, ESP_LOG_DEBUG); - - struct pbuf p = { - .next = NULL, - .payload = buffer, - .tot_len = len, - .len = len, - }; - - // Call slip if output function to feed data out slip interface - lwip_netif->output_ip6(lwip_netif, &p, NULL); +#endif } /** @@ -208,38 +173,111 @@ void esp_netif_lwip_slip_raw_output(esp_netif_t *slip_netif, void *buffer, size_ lwip_netif->output_ip6(lwip_netif, &p, NULL); } -/** - * @brief Fetch pointer to internal slip_lwip_context - * - * This is required to support the wiring of esp_netif objects outside - * of this component. - * - * @return - * - lwip slip context - */ -lwip_slip_ctx_t *esp_netif_lwip_slip_get_ctx(esp_netif_t *slip_netif) -{ - return slip_netif->lwip_slip_ctx; -} - /** * @brief Destroys the SLIP context object */ -void esp_netif_destroy_slip(lwip_slip_ctx_t *slip_ctx) +void esp_netif_destroy_slip(netif_related_data_t *slip) { ESP_LOGD(TAG, "%s", __func__); // Free base object - free(slip_ctx); + free(slip); } -void esp_netif_slip_set_default_netif(lwip_slip_ctx_t *slip_ctx) +const esp_ip6_addr_t *esp_slip_get_ip6(esp_netif_t *slip_netif) { - netif_set_default(slip_ctx->esp_netif->lwip_netif); + lwip_slip_ctx_t *slip_ctx = (lwip_slip_ctx_t *)slip_netif->related_data; + assert(slip_ctx->base.netif_type == SLIP_LWIP_NETIF); + return &slip_ctx->addr; } -const ip6_addr_t *esp_slip_get_ip6(esp_netif_t *slip_netif) +/** @brief Get esp-netif object corresponding to registration index + */ +static esp_netif_t * get_netif_with_esp_index(int index) { - return &slip_netif->lwip_slip_ctx->addr; + esp_netif_t *netif = NULL; + int counter = 0; + while ((netif = esp_netif_next(netif)) != NULL) { + if (counter == index) { + return netif; + } + counter++; + } + return NULL; } +/** @brief Return list registration index of the supplied netif ptr + */ +static int get_esp_netif_index(esp_netif_t * esp_netif) +{ + esp_netif_t *netif = NULL; + int counter = 0; + while ((netif = esp_netif_next(netif)) != NULL) { + if (esp_netif == netif) { + return counter; + } + counter++; + } + return -1; +} + +err_t esp_slipif_init(struct netif *netif) +{ + esp_netif_t *esp_netif = netif->state; + int esp_index = get_esp_netif_index(esp_netif); + if (esp_index < 0) { + return ERR_IF; + } + + // Store netif index in net interface for SIO open command to abstract the dev + netif->state = (void *)esp_index; + + err_t err = slipif_init(netif); + netif_set_up(netif); + netif_set_link_up(netif); + return err; +} + +static const struct esp_netif_netstack_config s_netif_config_slip = { + .lwip = { + .init_fn = esp_slipif_init, + .input_fn = esp_netif_lwip_slip_input, + } +}; + +const esp_netif_netstack_config_t *_g_esp_netif_netstack_default_slip = &s_netif_config_slip; + + +/*** + * @brief Open a serial device for communication + */ +sio_fd_t sio_open(uint8_t devnum) +{ + ESP_LOGD(TAG, "Opening device: %d\r\n", devnum); + + esp_netif_t *esp_netif = get_netif_with_esp_index(devnum); + if (!esp_netif) { + ESP_LOGE(TAG, "didn't find esp-netif with index=%d\n", devnum); + return NULL; + } + + // Return SIO handle + return esp_netif; +} + +/*** + * @brief Send a single character to the serial device (blocking) + */ +void sio_send(uint8_t c, sio_fd_t fd) +{ + esp_netif_t *esp_netif = fd; + + ESP_LOGD(TAG, "%s", __func__); + ESP_LOG_BUFFER_HEX_LEVEL(TAG, &c, 1, ESP_LOG_DEBUG); + + esp_err_t ret = esp_netif_transmit(esp_netif, &c, 1); + if (ret != ESP_OK) { + // Handle errors + ESP_LOGD(TAG, "%s: uart_write_bytes error %i", __func__, ret); + } +} diff --git a/components/esp_netif/lwip/esp_netif_lwip_slip.h b/components/esp_netif/lwip/esp_netif_lwip_slip.h index 0c64ee8a5b..8d6c55ad04 100644 --- a/components/esp_netif/lwip/esp_netif_lwip_slip.h +++ b/components/esp_netif/lwip/esp_netif_lwip_slip.h @@ -15,8 +15,6 @@ #ifndef _ESP_NETIF_LWIP_SLIP_H_ #define _ESP_NETIF_LWIP_SLIP_H_ -typedef struct lwip_slip_ctx lwip_slip_ctx_t; - /** * @brief Creates new SLIP related structure * @@ -27,45 +25,24 @@ typedef struct lwip_slip_ctx lwip_slip_ctx_t; * - pointer to slip-netif object on success * - NULL otherwise */ -lwip_slip_ctx_t *esp_netif_new_slip(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config); - -/** - * @brief Creates new SLIP related structure - * - * @param[in] slip pointer to internal slip context instance - * - * @return - * - ESP_OK on success - */ -esp_err_t esp_netif_start_slip(lwip_slip_ctx_t *slip); - - +netif_related_data_t * esp_netif_new_slip(esp_netif_t *esp_netif, const esp_netif_netstack_config_t *esp_netif_stack_config); /** * @brief Destroys the slip netif object * * @param[in] slip pointer to internal slip context instance */ -void esp_netif_destroy_slip(lwip_slip_ctx_t *slip); +void esp_netif_destroy_slip(netif_related_data_t *slip); /** - * @brief Stops the SLIP interface + * @brief Stop the esp slip netif * - * @param[in] slip pointer to internal slip context instance + * @param[in] esp_netif handle to slip esp-netif instance * * @return * - ESP_OK on success */ -esp_err_t esp_netif_stop_slip(lwip_slip_ctx_t *slip); - -/** - * @brief Sets default netif for routing priority config - * - * @note: This function must be called from lwip thread - * - */ -void esp_netif_slip_set_default_netif(lwip_slip_ctx_t *slip_ctx); +esp_err_t esp_netif_stop_slip(esp_netif_t *esp_netif); - -#endif // _ESP_NETIF_LWIP_SLIP_H_ \ No newline at end of file +#endif // _ESP_NETIF_LWIP_SLIP_H_ diff --git a/components/esp_netif/lwip/esp_netif_lwip_slip_sio.c b/components/esp_netif/lwip/esp_netif_lwip_slip_sio.c deleted file mode 100644 index d68b5fe03d..0000000000 --- a/components/esp_netif/lwip/esp_netif_lwip_slip_sio.c +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 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 - -#include "esp_log.h" -#include "driver/uart.h" - -#include "lwip/opt.h" -#include "lwip/sio.h" - -static const char *TAG = "esp-netif_lwip-slip_sio"; - -/*** - * @brief slip IO (SIO) uart driver - */ -typedef struct lwip_slip_sio { - uart_port_t uart_dev; - bool blocking; -} lwip_slip_sio_t; - -/*** - * @brief Open a serial device for communication - */ -sio_fd_t sio_open(uint8_t devnum) -{ - ESP_LOGD(TAG, "Opening device: %d\r\n", devnum); - - // Create SIO object - lwip_slip_sio_t *slip_sio = malloc(sizeof(lwip_slip_sio_t)); - - // Store device num etc. - slip_sio->uart_dev = devnum; - slip_sio->blocking = false; - - // Return SIO handle - return slip_sio; -} - -/*** - * @brief Send a single character to the serial device (blocking) - */ -void sio_send(uint8_t c, sio_fd_t fd) -{ - lwip_slip_sio_t *slip_sio = ( lwip_slip_sio_t *) fd; - - ESP_LOGD(TAG, "%s", __func__); - ESP_LOG_BUFFER_HEX_LEVEL(TAG, &c, 1, ESP_LOG_DEBUG); - - int res = uart_write_bytes(slip_sio->uart_dev, (const char *)&c, 1); - if (res < 0) { - // Handle errors - ESP_LOGD(TAG, "%s: uart_write_bytes error %i", __func__, res); - } -} - -/*** - * @brief Write to the serial port (blocking) - */ -uint32_t sio_write(sio_fd_t fd, uint8_t *data, uint32_t len) -{ - lwip_slip_sio_t *slip_sio = ( lwip_slip_sio_t *) fd; - - ESP_LOGD(TAG, "%s", __func__); - ESP_LOG_BUFFER_HEX_LEVEL(TAG, data, len, ESP_LOG_DEBUG); - - int32_t res = uart_write_bytes(slip_sio->uart_dev, (char *)data, len); - if (res < 0) { - // Handle errors - ESP_LOGD(TAG, "%s: uart_write_bytes error %i", __func__, res); - return 0; - } - - return (uint32_t) res; -} - -/*** - * @brief Receive a single character from the serial device (blocking) - */ -uint8_t sio_recv(sio_fd_t fd) -{ - lwip_slip_sio_t *slip_sio = ( lwip_slip_sio_t *) fd; - uint8_t b; - - slip_sio->blocking = true; - - while (slip_sio->blocking == true) { - int res = uart_read_bytes(slip_sio->uart_dev, &b, 1, portTICK_RATE_MS * 1); - if (res < 0) { - // Handle errors - ESP_LOGD(TAG, "%s: uart_read_bytes error %i", __func__, res); - return 0; - } else if (res == 1) { - break; - } - } - - return b; -} - -/*** - * @brief Read from the serial port (blocking, abort with `sio_read_abort`) - */ -uint32_t sio_read(sio_fd_t fd, uint8_t *data, uint32_t len) -{ - lwip_slip_sio_t *slip_sio = ( lwip_slip_sio_t *) fd; - int res = 0; - - slip_sio->blocking = true; - - while (slip_sio->blocking == true) { - res = uart_read_bytes(slip_sio->uart_dev, data, len, portTICK_RATE_MS * 1); - if (res < 0) { - // Handle errors - ESP_LOGD(TAG, "%s: uart_read_bytes error %i", __func__, res); - return 0; - } else if (res > 0) { - break; - } - } - - return (uint32_t) res; -} - -/*** - * @brief Read from the serial port (non-blocking) - */ -uint32_t sio_tryread(sio_fd_t fd, uint8_t *data, uint32_t len) -{ - lwip_slip_sio_t *slip_sio = ( lwip_slip_sio_t *) fd; - - int res = uart_read_bytes(slip_sio->uart_dev, data, len, portTICK_RATE_MS * 1); - if (res < 0) { - ESP_LOGD(TAG, "%s: uart_read_bytes error %i", __func__, res); - return 0; - } - - return (uint32_t)res; -} - - -/*** - * @brief Abort a pending sio_read call - */ -void sio_read_abort(sio_fd_t fd) -{ - lwip_slip_sio_t *slip_sio = ( lwip_slip_sio_t *) fd; - - slip_sio->blocking = false; -} - diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index 7378667002..d04631b17d 100644 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -655,13 +655,6 @@ menu "LWIP" SLIP over serial support is experimental and unsupported. - config LWIP_SLIP_RX_FROM_ISR - bool "Enable LWIP SLIP interrupt mode" - depends on LWIP_SLIP_SUPPORT - default y - help - Enable interrupt functions in SLIP netif/slipif.h - config LWIP_SLIP_DEBUG_ON bool "Enable SLIP debug log output" depends on LWIP_SLIP_SUPPORT diff --git a/components/lwip/port/esp32/include/lwipopts.h b/components/lwip/port/esp32/include/lwipopts.h index ea35bb89ca..c974a456f4 100644 --- a/components/lwip/port/esp32/include/lwipopts.h +++ b/components/lwip/port/esp32/include/lwipopts.h @@ -477,9 +477,16 @@ #ifdef CONFIG_LWIP_SLIP_SUPPORT /** - * Enable SLIP receive from ISR functions + * Enable SLIP receive from ISR functions and disable Rx thread + * + * This is the only supported mode of lwIP SLIP interface, so that + * - incoming packets are queued into pbufs + * - no thread is created from lwIP + * meaning it is the application responsibility to read data + * from IO driver and feed them to the slip interface */ -#define SLIP_RX_FROM_ISR CONFIG_LWIP_SLIP_RX_FROM_ISR +#define SLIP_RX_FROM_ISR 1 +#define SLIP_USE_RX_THREAD 0 /** * PPP_DEBUG: Enable debugging for PPP. diff --git a/examples/protocols/slip/slip_udp/CMakeLists.txt b/examples/protocols/slip/slip_udp/CMakeLists.txt index b9d68c60fe..5d7fdd6ce6 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 334d2d4673..d7869ff978 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 4a596ca727..7739fdfbc2 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 0000000000..b9a426049f --- /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 e0e04da4a6..2cbd4be519 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 d7b6b4fba4..0583dc2380 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 1709058d0f..e23abfa081 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 682e363eb8..2fdab88007 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); - } } From bb9a7356acfce03515a4c0bb117d0ec5b9ea4c69 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 16 Jun 2020 15:22:40 +0200 Subject: [PATCH 4/4] esp-netif: removing SLIP related events as the slip-modem set state synchronously --- components/esp_netif/include/esp_netif_slip.h | 9 ----- .../esp_netif/lwip/esp_netif_lwip_slip.c | 2 -- .../slip_modem/library/slip_modem.c | 36 ------------------- 3 files changed, 47 deletions(-) diff --git a/components/esp_netif/include/esp_netif_slip.h b/components/esp_netif/include/esp_netif_slip.h index bb0aa08303..9cfafb97ed 100644 --- a/components/esp_netif/include/esp_netif_slip.h +++ b/components/esp_netif/include/esp_netif_slip.h @@ -22,15 +22,6 @@ extern "C" { #endif -/** @brief SLIP event base */ -ESP_EVENT_DECLARE_BASE(SLIP_EVENT); - -typedef enum esp_netif_slip_event { - SLIP_EVENT_START = 1, - SLIP_EVENT_STOP = 2, - -} esp_netif_slip_event_e; - /** @brief Configuration structure for SLIP network interface * */ diff --git a/components/esp_netif/lwip/esp_netif_lwip_slip.c b/components/esp_netif/lwip/esp_netif_lwip_slip.c index 80cbf1b91f..990fbc84b9 100644 --- a/components/esp_netif/lwip/esp_netif_lwip_slip.c +++ b/components/esp_netif/lwip/esp_netif_lwip_slip.c @@ -28,8 +28,6 @@ #include -ESP_EVENT_DEFINE_BASE(SLIP_EVENT); - static const char *TAG = "esp-netif_lwip-slip"; /** diff --git a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c index 0583dc2380..2982774d88 100644 --- a/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c +++ b/examples/protocols/slip/slip_udp/components/slip_modem/library/slip_modem.c @@ -200,42 +200,6 @@ 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 ret; - - if (esp_netif == NULL) { - ESP_LOGE(TAG, "esp-netif handle can't be null"); - return ESP_ERR_INVALID_ARG; - } - - ret = esp_event_handler_register(SLIP_EVENT, SLIP_EVENT_START, esp_netif_action_start, esp_netif); - if (ret != ESP_OK) { - goto fail; - } - - ret = esp_event_handler_register(SLIP_EVENT, SLIP_EVENT_STOP, esp_netif_action_stop, esp_netif); - if (ret != ESP_OK) { - goto fail; - } - -fail: - esp_eth_clear_default_handlers(esp_netif); - return ret; -} - -esp_err_t esp_slip_modem_clear_default_handlers(void *esp_netif) -{ - if (!esp_netif) { - ESP_LOGE(TAG, "esp-netif handle can't be null"); - return ESP_ERR_INVALID_ARG; - } - esp_event_handler_unregister(SLIP_EVENT, SLIP_EVENT_START, esp_netif_action_start); - esp_event_handler_unregister(SLIP_EVENT, SLIP_EVENT_STOP, esp_netif_action_stop); - - return ESP_OK; -} - - static void esp_slip_modem_uart_rx_task(void *arg) { esp_slip_modem_t *slip_modem = (esp_slip_modem_t *) arg;