-
Notifications
You must be signed in to change notification settings - Fork 7.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'examples/multiinterface_vlan_support' into 'master'
network examples: Multiple ethernet interfaces and VLAN support. Closes IDFGH-7826 See merge request espressif/esp-idf!19708
- Loading branch information
Showing
9 changed files
with
612 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# For more information about build system see | ||
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html | ||
# The following five 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.16) | ||
|
||
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/ethernet/basic/components/ethernet_init) | ||
include($ENV{IDF_PATH}/tools/cmake/project.cmake) | ||
|
||
project(vlan_support) | ||
|
||
|
||
# Enabling Vlan by injecting vlan hooks into lwip. | ||
idf_component_get_property(lwip lwip COMPONENT_LIB) | ||
target_compile_options(${lwip} PRIVATE "-I${PROJECT_DIR}/main") | ||
|
||
target_compile_definitions(${lwip} PRIVATE "-DESP_IDF_LWIP_HOOK_FILENAME=\"vlan_hooks.h\"" | ||
"-DETHARP_SUPPORT_VLAN=1" | ||
"-DLWIP_HOOK_VLAN_CHECK=lwip_vlan_check" | ||
"-DLWIP_HOOK_VLAN_SET=lwip_vlan_set") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 | | ||
| ----------------- | ----- | -------- | -------- | -------- | -------- | | ||
|
||
# Ethernet VLAN Support Example | ||
|
||
See the [README.md](../../ethernet/README.md) file in the upper level [examples](../../ethernet) directory for more information about examples. | ||
|
||
## Overview | ||
|
||
This example demonstrates the creation of one virtual network interface over Ethernet, an additional VLAN interface(disabled by default), and an interface without vlan tag. The work flow of the example could be as follows: | ||
|
||
1. Install Ethernet driver for standard interface and both the virtual network interface. | ||
2. Setup static IP address to both the virtual network interface. | ||
3. Send DHCP requests and wait for a DHCP lease on the standard interface | ||
4. If get IP address successfully, then you will be able to ping the standard interface of the device. | ||
5. The virtual interfaces can be pinged over the configured static IP address. | ||
|
||
Note: The code in vlan_support_main.c can be modified to add more vlan interfaces. The maximum number of interfaces that can be added is specified by the macro `MAX_ETH_NETIF_COUNT`. | ||
## How to use example | ||
|
||
### Hardware Required | ||
|
||
To run this example, it's recommended that you have an official ESP32 Ethernet development board - [ESP32-Ethernet-Kit](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/get-started-ethernet-kit.html). This example should also work for 3rd party ESP32 board as long as it's integrated with a supported Ethernet PHY chip. | ||
|
||
### Configure the project | ||
|
||
``` | ||
idf.py menuconfig | ||
``` | ||
See common configurations for Ethernet examples from [upper level](../../ethernet/README.md#common-configurations). | ||
|
||
The Virtual network interface is enabled by default. | ||
An additional virtual network interface can also be enabled. | ||
The VLAN tag, Static IP address, network mask and default gateway of these interfaces are also configurable. | ||
|
||
To configure the virtual network interfaces select: | ||
``` | ||
Example Configuration ---> | ||
``` | ||
|
||
### Build, Flash, and Run | ||
|
||
Build the project and flash it to the board, then run monitor tool to view serial output: | ||
|
||
``` | ||
idf.py -p PORT build flash monitor | ||
``` | ||
|
||
(Replace PORT with the name of the serial port to use.) | ||
|
||
(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. | ||
|
||
## Example Output | ||
|
||
``` | ||
I (0) cpu_start: Starting scheduler on APP CPU. | ||
I (423) system_api: Base MAC address is not set | ||
I (423) system_api: read default base MAC address from EFUSE | ||
I (443) esp_eth.netif.netif_glue: 24:d7:eb:bb:f2:1b | ||
I (443) esp_eth.netif.netif_glue: ethernet attached to netif | ||
I (443) esp_eth.netif.netif_glue: 24:d7:eb:bb:f2:1b | ||
I (443) esp_eth.netif.netif_glue: ethernet attached to netif | ||
I (453) esp_eth.netif.netif_glue: 24:d7:eb:bb:f2:1b | ||
I (463) esp_eth.netif.netif_glue: ethernet attached to netif | ||
I (3563) eth_vlan_example: Ethernet Started | ||
I (3563) eth_vlan_example: Ethernet Link Up | ||
I (3563) eth_vlan_example: Ethernet HW Addr 24:d7:eb:bb:f2:1b | ||
I (3563) eth_vlan_example: Ethernet interface(24:d7:eb:bb:f2:1b): ETH_VLAN20, Got IP Address | ||
I (3573) eth_vlan_example: ~~~~~~~~~~~ | ||
I (3573) eth_vlan_example: ETHIP:192.168.20.10 | ||
I (3583) eth_vlan_example: ETHMASK:192.168.20.1 | ||
I (3583) eth_vlan_example: ETHGW:255.255.255.0 | ||
I (3593) eth_vlan_example: ~~~~~~~~~~~ | ||
I (3593) esp_netif_handlers: eth ip: 192.168.20.10, mask: 192.168.20.1, gw: 255.255.255.0 | ||
I (3603) eth_vlan_example: Ethernet interface(24:d7:eb:bb:f2:1b): ETH_VLAN30, Got IP Address | ||
I (3613) eth_vlan_example: ~~~~~~~~~~~ | ||
I (3623) eth_vlan_example: ETHIP:192.168.30.10 | ||
I (3623) eth_vlan_example: ETHMASK:192.168.30.1 | ||
I (3633) eth_vlan_example: ETHGW:255.255.255.0 | ||
I (3633) eth_vlan_example: ~~~~~~~~~~~ | ||
I (3643) esp_netif_handlers: eth ip: 192.168.30.10, mask: 192.168.30.1, gw: 255.255.255.0 | ||
I (7943) eth_vlan_example: Ethernet interface(24:d7:eb:bb:f2:1b): ETH_DEF, Got IP Address | ||
I (7943) eth_vlan_example: ~~~~~~~~~~~ | ||
I (7943) eth_vlan_example: ETHIP:192.168.10.100 | ||
I (7943) eth_vlan_example: ETHMASK:255.255.255.0 | ||
I (7953) eth_vlan_example: ETHGW:192.168.10.1 | ||
I (7953) eth_vlan_example: ~~~~~~~~~~~ | ||
I (7963) esp_netif_handlers: eth ip: 192.168.10.100, mask: 255.255.255.0, gw: 192.168.10.1 | ||
``` | ||
|
||
Now you can ping your ESP32 in the terminal. | ||
You can ping the ESP32 VLAN interface from the VLAN interface of your system with default VLAN tag 20. | ||
|
||
## Troubleshooting | ||
### Setup VLAN on Linux | ||
``` | ||
vconfig add eth0 20 | ||
ip addr add 192.168.20.30/24 dev eth0.20 | ||
ip link set eth0.20 up | ||
``` | ||
Replace interface eth0 with your system ethernet interface. | ||
### Setup VLAN on Mac | ||
``` | ||
sudo ifconfig vlan20 create | ||
sudo ifconfig vlan20 vlan 20 vlandev en5 | ||
sudo ifconfig vlan20 inet 192.168.20.30 netmask 255.255.255.0 | ||
``` | ||
Replace interface en5 with your system ethernet interface. | ||
|
||
See common troubleshooting for Ethernet examples from [upper level](../../ethernet/README.md#common-troubleshooting). | ||
|
||
(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.) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
idf_component_register(SRCS "vlan_support_main.c" "eth_vlan_utils.c" | ||
INCLUDE_DIRS ".") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
menu "Example Configuration" | ||
|
||
comment "Virtual Ethernet Interface Configuration" | ||
|
||
config EXAMPLE_ETHERNET_VLAN_ID | ||
int "VLAN identifier" | ||
range 1 4094 | ||
default 20 | ||
help | ||
Set the VLAN Id to the virtual interface | ||
|
||
config EXAMPLE_VLAN_STATIC_IPV4_ADDR | ||
string "IPV4 Address" | ||
default "192.168.20.10" | ||
help | ||
The example will set this IPV4 address to this interface. | ||
|
||
config EXAMPLE_VLAN_STATIC_ADDR_MASK | ||
string "Subnet Mask" | ||
default "255.255.255.0" | ||
|
||
config EXAMPLE_VLAN_STATIC_ADDR_DEF_GW | ||
string "IPV4 Default Gateway" | ||
default "192.168.20.1" | ||
|
||
config EXAMPLE_EXTRA_VLAN_INTERFACE | ||
bool "Additional Vlan Interface" | ||
default n | ||
help | ||
Enables an additional VLAN interface | ||
|
||
if EXAMPLE_EXTRA_VLAN_INTERFACE | ||
config EXAMPLE_EXTRA_ETHERNET_VLAN_ID | ||
int "VLAN identifier" | ||
range 1 4094 | ||
default 30 | ||
depends on EXAMPLE_EXTRA_VLAN_INTERFACE | ||
help | ||
Set the VLAN Id to the additional virtual interface | ||
|
||
config EXAMPLE_EXTRA_VLAN_STATIC_IPV4_ADDR | ||
string "IPV4 Address" | ||
default "192.168.30.10" | ||
depends on EXAMPLE_EXTRA_VLAN_INTERFACE | ||
help | ||
The example will set this IPV4 address to this interface. | ||
|
||
config EXAMPLE_EXTRA_VLAN_STATIC_ADDR_MASK | ||
string "Subnet Mask" | ||
default "255.255.255.0" | ||
depends on EXAMPLE_EXTRA_VLAN_INTERFACE | ||
|
||
config EXAMPLE_EXTRA_VLAN_STATIC_ADDR_DEF_GW | ||
string "IPV4 Default Gateway" | ||
default "192.168.30.1" | ||
depends on EXAMPLE_EXTRA_VLAN_INTERFACE | ||
|
||
endif #EXAMPLE_EXTRA_VLAN_INTERFACE | ||
|
||
endmenu |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
#include "esp_netif.h" | ||
#include "esp_eth_netif_glue.h" | ||
#include "esp_netif_net_stack.h" | ||
#include "esp_event.h" | ||
#include "esp_log.h" | ||
#include "esp_check.h" | ||
#include "lwip/esp_netif_net_stack.h" | ||
#include "sdkconfig.h" | ||
#include "lwip/prot/ethernet.h" | ||
#include "lwip/prot/ieee.h" | ||
#include "eth_vlan_utils.h" | ||
#if CONFIG_ESP_NETIF_L2_TAP | ||
#include "esp_vfs_l2tap.h" | ||
#endif | ||
|
||
|
||
/** | ||
* @brief This function gets invoked when Ethernet receive a new packets. | ||
* | ||
* @note This function is to be registered as a callback function which get invoked when Ethernet receive a new packets. | ||
* | ||
* @param eth_handle handle of Ethernet driver | ||
* @param buffer buffer of the received packet | ||
* @param length length of the received packet | ||
* @param priv private pointer | ||
* | ||
* @return | ||
* - ESP_OK: input frame buffer to upper stack successfully | ||
* - ESP_FAIL: error occurred when inputting buffer to upper stack | ||
*/ | ||
esp_err_t eth_input_to_netif(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length, void *priv) | ||
{ | ||
struct netif *lwip_netif; | ||
u16_t netif_vlan_id; | ||
struct eth_hdr *ethhdr = (struct eth_hdr *)buffer; | ||
struct eth_vlan_hdr *vlan; | ||
esp_vlan_netifs *vlan_netifs = (esp_vlan_netifs *)priv; | ||
|
||
if (PP_HTONS(ETHTYPE_VLAN) != ethhdr->type) { | ||
// L2 tap after VLAN is not supported. | ||
#if CONFIG_ESP_NETIF_L2_TAP | ||
esp_err_t ret = ESP_OK; | ||
ret = esp_vfs_l2tap_eth_filter(eth_handle, buffer, (size_t *)&length); | ||
if (length == 0) { | ||
return ret; | ||
} | ||
#endif | ||
return esp_netif_receive(vlan_netifs->esp_netif[0], buffer, length, NULL); | ||
} else { | ||
for (int i = 1; i < vlan_netifs->netif_count; i++) { | ||
lwip_netif = esp_netif_get_netif_impl(vlan_netifs->esp_netif[i]); | ||
netif_vlan_id = *((uint16_t *)netif_get_client_data(lwip_netif, LWIP_NETIF_CLIENT_DATA_INDEX_MAX + 1)); | ||
|
||
vlan = (struct eth_vlan_hdr *)(((char *)ethhdr) + SIZEOF_ETH_HDR); | ||
|
||
if (VLAN_ID(vlan) == netif_vlan_id) { | ||
return esp_netif_receive(vlan_netifs->esp_netif[i], buffer, length, NULL); | ||
} | ||
} | ||
|
||
// If the vlan id of the incoming frame doesn't match with any of the interface send it to the default interface. | ||
return esp_netif_receive(vlan_netifs->esp_netif[0], buffer, length, NULL); | ||
} | ||
} | ||
|
||
|
||
/** | ||
* @brief This function creates configuration for esp-netif Ethernet | ||
* | ||
* @param vlan_id handle of Ethernet driver, used to name the interface key. | ||
* @param vlan_eth_cfg_o output parameter returning the esp-netif ethernet configuration. | ||
* | ||
* @return ESP_OK or ESP_FAIL | ||
*/ | ||
esp_err_t get_vlan_netif_config(uint16_t vlan_id, esp_netif_config_t *vlan_eth_cfg_o) | ||
{ | ||
// Create new default instance of VLAN esp-netif for Ethernet | ||
char *if_key; | ||
if (asprintf(&if_key, "ETH_VLAN%d", vlan_id) == -1) { | ||
return ESP_FAIL; | ||
} | ||
|
||
esp_netif_inherent_config_t *esp_eth_vlan_base_config = malloc(sizeof(esp_netif_inherent_config_t)); | ||
if (NULL == esp_eth_vlan_base_config) { | ||
return ESP_FAIL; | ||
} | ||
*esp_eth_vlan_base_config = (esp_netif_inherent_config_t)ESP_NETIF_INHERENT_DEFAULT_ETH(); | ||
esp_eth_vlan_base_config->if_key = if_key; | ||
|
||
vlan_eth_cfg_o->base = esp_eth_vlan_base_config; | ||
vlan_eth_cfg_o->driver = NULL; | ||
vlan_eth_cfg_o->stack = ESP_NETIF_NETSTACK_DEFAULT_ETH; | ||
|
||
return ESP_OK; | ||
} | ||
|
||
/** | ||
* @brief This function frees the memory allocated for configuration for esp-netif Ethernet | ||
* | ||
* @param vlan_eth_cfg configuration for esp-netif Ethernet | ||
*/ | ||
void free_vlan_config(esp_netif_config_t *vlan_eth_cfg) | ||
{ | ||
if ((NULL != vlan_eth_cfg) && (NULL != vlan_eth_cfg->base)) { | ||
free((void *)(vlan_eth_cfg->base->if_key)); | ||
free((void *)(vlan_eth_cfg->base)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Unlicense OR CC0-1.0 | ||
*/ | ||
|
||
|
||
// Maximum number of interface that can be added | ||
#define MAX_ETH_NETIF_COUNT (10) | ||
|
||
typedef struct { | ||
esp_netif_t *esp_netif[MAX_ETH_NETIF_COUNT]; | ||
uint8_t netif_count; | ||
} esp_vlan_netifs; | ||
|
||
|
||
/** | ||
* @brief This function gets invoked when Ethernet receive a new packets. | ||
* | ||
* @note This function is to be registered as a callback function which get invoked when Ethernet receive a new packets. | ||
* | ||
* @param eth_handle handle of Ethernet driver | ||
* @param buffer buffer of the received packet | ||
* @param length length of the received packet | ||
* @param priv private pointer | ||
* | ||
* @return | ||
* - ESP_OK: input frame buffer to upper stack successfully | ||
* - ESP_FAIL: error occurred when inputting buffer to upper stack | ||
*/ | ||
esp_err_t eth_input_to_netif(esp_eth_handle_t eth_handle, uint8_t *buffer, uint32_t length, void *priv); | ||
|
||
|
||
/** | ||
* @brief This function creates configuration for esp-netif Ethernet | ||
* | ||
* @param vlan_id handle of Ethernet driver, used to name the interface key. | ||
* @param vlan_eth_cfg_o output parameter returning the esp-netif ethernet configuration. | ||
* | ||
* @return ESP_OK or ESP_FAIL | ||
*/ | ||
esp_err_t get_vlan_netif_config(uint16_t vlan_id, esp_netif_config_t *vlan_eth_cfg_o); | ||
|
||
|
||
/** | ||
* @brief This function frees the memory allocated for configuration for esp-netif Ethernet | ||
* | ||
* @param vlan_eth_cfg configuration for esp-netif Ethernet | ||
*/ | ||
void free_vlan_config(esp_netif_config_t *vlan_eth_cfg); |
Oops, something went wrong.