Add Linux TAP
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
if(${target} STREQUAL "linux")
|
||||
idf_component_register(INCLUDE_DIRS include
|
||||
SRCS linux/tapio.c linux_connect.c lwip/tapif.c
|
||||
PRIV_REQUIRES esp_netif lwip)
|
||||
else()
|
||||
message(FATAL_ERROR "This component is currently only supported for linux target")
|
||||
endif()
|
||||
@@ -0,0 +1,63 @@
|
||||
menu "Example Connection Configuration"
|
||||
|
||||
config EXAMPLE_CONNECT_LWIP_TAPIF
|
||||
bool "connect using lwip to linux tap interface"
|
||||
depends on IDF_TARGET_LINUX && ESP_NETIF_TCPIP_LWIP
|
||||
default y
|
||||
|
||||
if EXAMPLE_CONNECT_LWIP_TAPIF
|
||||
config EXAMPLE_CONNECT_IPV4
|
||||
bool
|
||||
depends on LWIP_IPV4
|
||||
default y
|
||||
|
||||
config EXAMPLE_CONNECT_IPV6
|
||||
bool "Obtain IPv6 address"
|
||||
depends on LWIP_IPV6
|
||||
default y
|
||||
help
|
||||
Set to true to setup link local address and wait until it's valid
|
||||
|
||||
config EXAMPLE_CONNECT_WAIT_FOR_IP
|
||||
bool "run DHCP and wait for IP"
|
||||
default y
|
||||
|
||||
config EXAMPLE_CONNECT_TAPIF_IP_ADDR
|
||||
string "Static IP address"
|
||||
default "192.168.5.100"
|
||||
depends on EXAMPLE_CONNECT_IPV4 && !EXAMPLE_CONNECT_WAIT_FOR_IP
|
||||
help
|
||||
Set static IP address.
|
||||
|
||||
config EXAMPLE_CONNECT_TAPIF_NETMASK
|
||||
string "Static netmask address"
|
||||
default "255.255.255.0"
|
||||
depends on EXAMPLE_CONNECT_IPV4 && !EXAMPLE_CONNECT_WAIT_FOR_IP
|
||||
help
|
||||
Set static netmask address.
|
||||
|
||||
config EXAMPLE_CONNECT_TAPIF_GW
|
||||
string "Static gateway address"
|
||||
default "192.168.5.1"
|
||||
depends on EXAMPLE_CONNECT_IPV4 && !EXAMPLE_CONNECT_WAIT_FOR_IP
|
||||
help
|
||||
Set static gateway address.
|
||||
|
||||
config EXAMPLE_CONNECT_TAPIF_OUT_LOSS
|
||||
int "Percentage of packets to be dropped on transmission"
|
||||
default 0
|
||||
range 0 100
|
||||
help
|
||||
Set non-zero number simulate packet loss when sending data.
|
||||
Number represents probability between 0 and 100%
|
||||
|
||||
config EXAMPLE_CONNECT_TAPIF_IN_LOSS
|
||||
int "Percentage of packets to be dropped on reception"
|
||||
default 0
|
||||
range 0 100
|
||||
help
|
||||
Set non-zero number simulate packet loss when receiving data.
|
||||
Number represents probability between 0 and 100%
|
||||
endif
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,161 @@
|
||||
# tapif-io Component
|
||||
|
||||
This component implements a tap networking interface that provides connectivity to host network using `tuntap` interface in Linux.
|
||||
It could be used to route lwip traffic to host side network, typically when working with the **Linux target**.
|
||||
|
||||
## How to use this component
|
||||
|
||||
### Usage of the API
|
||||
|
||||
1) Add the path to this component to as a dependency to the `main` component of your project using the following idf_component.yml file:
|
||||
```yaml
|
||||
dependencies:
|
||||
tapif_io:
|
||||
path: ${IDF_PATH}/examples/common_components/tapif_io
|
||||
```
|
||||
2) Include lwip and linux side of the configuration
|
||||
```cpp
|
||||
#include "esp_netif.h" // esp-netif
|
||||
#include "tapio.h" // esp-netif's driver side
|
||||
#include "lwip/tapif.h" // esp-netif's network stack side
|
||||
```
|
||||
3) Configure the esp-netif
|
||||
a) setup the linux tap I/O config
|
||||
```cpp
|
||||
esp_netif_driver_ifconfig_t driver_cfg = {
|
||||
.handle = tapio_create(),
|
||||
.transmit = tapio_output,
|
||||
};
|
||||
```
|
||||
|
||||
b) configure the lwip netif for the tap interface
|
||||
```cpp
|
||||
struct esp_netif_netstack_config stack_cfg = {
|
||||
.lwip = {
|
||||
.init_fn = lwip_tapif_init,
|
||||
.input_fn = lwip_tapif_input,
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
c) configure the esp-netif basic parameters
|
||||
```cpp
|
||||
esp_netif_inherent_config_t base_cfg = {
|
||||
.if_key = "TAP", // unique name of the interface
|
||||
.flags = ESP_NETIF_FLAG_AUTOUP, // no dhcp client, starts when it's set up
|
||||
.ip_info = &ip_info, // add static IP info
|
||||
.route_prio = 100 // priority for setting default gateway
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
4) Initialize and attach the esp_netif to the I/O handle
|
||||
```cpp
|
||||
esp_netif_t *tap_netif = esp_netif_new(&cfg);
|
||||
esp_netif_attach(tap_netif, driver_cfg.handle);
|
||||
```
|
||||
|
||||
### Host side networking
|
||||
|
||||
1) Create a new tun/tap interface type named `tap0`
|
||||
a) You can run the script `./make_tap_netif`
|
||||
b) Update the IP address of the interface to correspond to the configured static IP in previous step
|
||||
|
||||
2) Start the application and send/receive the packets via `tap0` interface
|
||||
* it is possible to create server or client test application listening or connecting to this interface.
|
||||
* it is also possible to route these packets to external network (using routing rules or simply by ip forwarding if using the same subnet)
|
||||
|
||||
#### Common networking/routing examples
|
||||
|
||||
##### Isolated internal connection
|
||||
|
||||
Is useful to experiment with one interface with no intention to connect to internet or external facilities.
|
||||
Typically, when we want to create a server listening on the `tap0` interface and run a client in lwip, e.g. the default `tcp_client` socket example in IDF.
|
||||
* Create the tap interface using `./make_tap_netif` and set the IP address **not to overlap** with any other IPv4 network range (e.g. `ip addr add 192.168.5.1/24 dev tap0`)
|
||||
* Configure the `tapif_io` component to use static address from that range (e.g. `192.168.5.x`)
|
||||
* Configure the `tcp_client` example to connect to the tap interface IP address (e.g. `192.168.5.1`)
|
||||
* Execute a tcp server listening on the tap interface and the configured port (e.g. `nc -l 3333`)
|
||||
* Build and run the `tcp_client` example to send and receive data between the server created in the previous step.
|
||||
|
||||
##### Connecting to the external network using IP forwarding
|
||||
|
||||
This allows using full-featured network facilities of your host network, but a care must be taken to the selected IP addresses to avoid potential conflicts.
|
||||
* Set the IP address of the `tap0` interface from the range used by your host system's default gateway (e.g. `ip addr add 192.168.0.123/24 dev tap0`, assuming the default netif is `eth0` with IP range of `192.168.0.x` and this address doesn't overlap with any other IP address in this network)
|
||||
* Configure the `tapif_io` with another address from the same range, e.g.
|
||||
```text
|
||||
CONFIG_EXAMPLE_CONNECT_TAPIF_IP_ADDR="192.168.0.100"
|
||||
CONFIG_EXAMPLE_CONNECT_TAPIF_NETMASK="255.255.255.0"
|
||||
CONFIG_EXAMPLE_CONNECT_TAPIF_GW="192.168.0.1"
|
||||
```
|
||||
assuming that the default gateway of your host network is configured to `192.168.0.1`
|
||||
* Build and run the lwip example to interact with the host network, e.g, to send an HTTP request to a publicly available http server (if the server is reachable from your host network)
|
||||
|
||||
(Note, that the IP forwarding must be enabled in the host system:
|
||||
```bash
|
||||
echo 1 > /proc/sys/net/ipv4/ip_forward
|
||||
```
|
||||
)
|
||||
|
||||
##### Routing the internal interface to the host network with IP tables
|
||||
|
||||
Uses an isolated interface with routing and NAT-ing between interfaces
|
||||
* Configure the `tap0` interface address **not to overlap** with any other IPv4 network range.
|
||||
* Setup `MASQUERADE` target to route network traffic between `tap0` and your default network interface (`eth0` in the below example).
|
||||
```bash
|
||||
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||||
sudo iptables -A FORWARD -i eth0 -o tap0 -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||
sudo iptables -A FORWARD -i tap0 -o eth0 -j ACCEPT
|
||||
```
|
||||
|
||||
##### Using DHCP
|
||||
|
||||
It's also possible to configure the lwip interface to use DHCP client (common setup for most default network interfaces, such as Ethernet or WiFi station)
|
||||
and set up a DHCP server on the host machine to assign the IP address dynamically.
|
||||
|
||||
This component sets up a DHCP client if `CONFIG_EXAMPLE_CONNECT_WAIT_FOR_IP` is enabled and waits for assigning an IP address. See below the description of DHCP client workflow for tap interface:
|
||||
|
||||
1) **Configure and set the `esp-netif` up**
|
||||
|
||||
* Same as in [API usage](#Usage-of-the-API), but update the base esp-netif config `3c)` to enable DHCP client
|
||||
```cpp
|
||||
esp_netif_inherent_config_t base_cfg = {
|
||||
.if_key = "TAP",
|
||||
.flags = (esp_netif_flags_t)(ESP_NETIF_DHCP_CLIENT | ESP_NETIF_FLAG_EVENT_IP_MODIFIED | ESP_NETIF_FLAG_AUTOUP),
|
||||
.route_prio = 100
|
||||
};
|
||||
```
|
||||
* After starting the netif, tell the lwIP that we're connected
|
||||
```cpp
|
||||
esp_netif_action_connected(tap_netif, 0, 0, 0);
|
||||
```
|
||||
* Wait for the IP address to be assigned.
|
||||
This could be implemented using an event handler
|
||||
```cpp
|
||||
esp_netif_inherent_config_t base_cfg = {
|
||||
...
|
||||
.get_ip_event = TAP0_GOT_IP,
|
||||
...
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, TAP0_GOT_IP, event_handler, NULL));
|
||||
// wait for the IP event (e.g. using signalling semaphores from the handler)
|
||||
// ...
|
||||
esp_netif_ip_info_t ip_info = {};
|
||||
ESP_LOGI("tap-init", "Assigned IP address:"IPSTR ",", IP2STR(&ip_info.ip));
|
||||
```
|
||||
|
||||
2) **Configure forwarding/routing** if needed based on the previous sections.
|
||||
|
||||
3) **Configure the DHCP server on the host machine**
|
||||
|
||||
Example for `isc-dhcp-server`
|
||||
|
||||
```bash
|
||||
INTERFACES="tap0";
|
||||
authoritative;
|
||||
|
||||
subnet 192.168.5.0 netmask 255.255.255.0 {
|
||||
range 192.168.5.2 192.168.5.200;
|
||||
option routers 192.168.5.1;
|
||||
option domain-name-servers 8.8.8.8;
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
/* Common functions for protocol examples, to establish tap interface connection
|
||||
* For linux target
|
||||
|
||||
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.
|
||||
*/
|
||||
#pragma once
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Configure and connect, wait for IP
|
||||
*
|
||||
* @return ESP_OK on successful connection
|
||||
*/
|
||||
esp_err_t example_connect(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
#include "esp_err.h"
|
||||
#include "esp_netif.h"
|
||||
|
||||
/**
|
||||
* @brief Creates tapio layer as a driver interface to esp-netif
|
||||
*
|
||||
* @warning Implemented as singleton, can use only one tapio in the system!
|
||||
*
|
||||
* @return pointer to the tapio driver handle
|
||||
*/
|
||||
void *tapio_create(void);
|
||||
|
||||
/**
|
||||
* @brief esp-netif driver I/O output path
|
||||
*
|
||||
* @param h Driver's handle
|
||||
* @param buffer Data to output
|
||||
* @param len Data size
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t tapio_output(void *h, void *buffer, size_t len);
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_netif.h"
|
||||
|
||||
// Use linux system sockets to connect to tap interface
|
||||
#define LWIP_HDR_LINUX_SYS_SOCKETS_H
|
||||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <lwip/sys.h>
|
||||
#include "errno.h"
|
||||
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
|
||||
#define DEVTAP "/dev/net/tun"
|
||||
#define DEVTAP_NAME "tap0"
|
||||
|
||||
|
||||
typedef struct tap_io {
|
||||
esp_netif_driver_base_t base;
|
||||
int fd;
|
||||
} tap_io_t;
|
||||
|
||||
static const char *TAG = "tap-netif";
|
||||
|
||||
static void tapio_input_task(void *arg)
|
||||
{
|
||||
tap_io_t *io = arg;
|
||||
fd_set fdset;
|
||||
int ret;
|
||||
while (1) {
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(io->fd, &fdset);
|
||||
|
||||
/* Wait for a packet to arrive. */
|
||||
ret = select(io->fd + 1, &fdset, NULL, NULL, NULL);
|
||||
|
||||
if (ret == 1) {
|
||||
/* Handle incoming packet. */
|
||||
ssize_t readlen;
|
||||
char buf[1518]; /* max packet size including VLAN excluding CRC */
|
||||
|
||||
/* Obtain the size of the packet and put it into the "len"
|
||||
variable. */
|
||||
readlen = read(io->fd, buf, sizeof(buf));
|
||||
if (readlen < 0) {
|
||||
ESP_LOGE(TAG, "Failed to read from tap fd: returned %ld", readlen);
|
||||
exit(1);
|
||||
}
|
||||
#if CONFIG_EXAMPLE_CONNECT_TAPIF_IN_LOSS
|
||||
if (((double)rand()/(double)RAND_MAX) < ((double)CONFIG_EXAMPLE_CONNECT_TAPIF_IN_LOSS)/100.0) {
|
||||
ESP_LOGW(TAG, "Simulated packet drop on input");
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
esp_netif_receive(io->base.netif, buf, readlen, NULL);
|
||||
} else if (ret == -1) {
|
||||
if (errno == EINTR /* Interrupted system call (used by FreeRTOS simulated interrupts) */) {
|
||||
vTaskDelay(1); // yield to the FreeRTOS simulator
|
||||
} else {
|
||||
ESP_LOGE(TAG, "tapif_thread: select() error(%d), %s", errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t tapio_start(esp_netif_t *esp_netif, void *arg)
|
||||
{
|
||||
tap_io_t *io = arg;
|
||||
io->base.netif = esp_netif;
|
||||
esp_netif_action_start(esp_netif, 0, 0, 0);
|
||||
|
||||
sys_thread_new("tapio_rx", tapio_input_task, io, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void *tapio_create(void)
|
||||
{
|
||||
static tap_io_t tap_io = {};
|
||||
tap_io.base.post_attach = tapio_start;
|
||||
tap_io.fd = open(DEVTAP, O_RDWR);
|
||||
if (tap_io.fd == -1) {
|
||||
ESP_LOGE(TAG, "Cannot open tap device %s", DEVTAP);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ifreq ifr = {};
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
|
||||
strncpy(ifr.ifr_name, DEVTAP_NAME, sizeof(ifr.ifr_name));
|
||||
ifr.ifr_name[sizeof(ifr.ifr_name)-1] = 0; /* ensure \0 termination */
|
||||
ifr.ifr_flags = IFF_TAP|IFF_NO_PI;
|
||||
if (ioctl(tap_io.fd, TUNSETIFF, (void *) &ifr) < 0) {
|
||||
ESP_LOGE(TAG, "Cannot configure ioctl(TUNSETIFF) for \"%s\"", DEVTAP);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return &tap_io;
|
||||
}
|
||||
|
||||
esp_err_t tapio_output(void *h, void *buffer, size_t len)
|
||||
{
|
||||
tap_io_t *io = h;
|
||||
ssize_t written;
|
||||
|
||||
#if CONFIG_EXAMPLE_CONNECT_TAPIF_OUT_LOSS
|
||||
if (((double)rand()/(double)RAND_MAX) < ((double)CONFIG_EXAMPLE_CONNECT_TAPIF_OUT_LOSS)/100.0) {
|
||||
ESP_LOGW(TAG, "Simulated packet drop on output");
|
||||
return ESP_OK; /* ESP_OK because we simulate packet loss on cable */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* signal that packet should be sent(); */
|
||||
written = write(io->fd, buffer, len);
|
||||
if (written < len) {
|
||||
ESP_LOGE(TAG, "Failed to write from tap fd: returned %ld", written);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "esp_err.h"
|
||||
#include "esp_netif.h" // esp-netif
|
||||
#include "tapio.h" // esp-netif's driver side
|
||||
#include "lwip/tapif.h" // esp-netif's network stack side
|
||||
#include "esp_log.h"
|
||||
|
||||
#if CONFIG_EXAMPLE_CONNECT_WAIT_FOR_IP
|
||||
#include "esp_event.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
static const char *TAG = "linux_connect";
|
||||
|
||||
static EventGroupHandle_t s_events;
|
||||
|
||||
static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
|
||||
{
|
||||
xEventGroupSetBits(s_events, 1);
|
||||
}
|
||||
|
||||
#endif // CONFIG_EXAMPLE_CONNECT_WAIT_FOR_IP
|
||||
|
||||
#define TAP0_GOT_IP (0x1234)
|
||||
|
||||
esp_err_t example_connect(void)
|
||||
{
|
||||
#if CONFIG_EXAMPLE_CONNECT_LWIP_TAPIF
|
||||
// configure linux tapio
|
||||
esp_netif_driver_ifconfig_t driver_cfg = {
|
||||
.handle = tapio_create(),
|
||||
.transmit = tapio_output,
|
||||
};
|
||||
// configure lwip netif for the tapif
|
||||
struct esp_netif_netstack_config stack_cfg = {
|
||||
.lwip = {
|
||||
.init_fn = lwip_tapif_init,
|
||||
.input_fn = lwip_tapif_input,
|
||||
}
|
||||
};
|
||||
// configure inherent esp-netif parameters
|
||||
esp_netif_ip_info_t ip_info = {};
|
||||
esp_netif_flags_t netif_flags = (ESP_NETIF_FLAG_EVENT_IP_MODIFIED | ESP_NETIF_FLAG_AUTOUP);
|
||||
#if !CONFIG_EXAMPLE_CONNECT_WAIT_FOR_IP
|
||||
ip_info.ip.addr = ipaddr_addr(CONFIG_EXAMPLE_CONNECT_TAPIF_IP_ADDR);
|
||||
ip_info.netmask.addr = ipaddr_addr(CONFIG_EXAMPLE_CONNECT_TAPIF_NETMASK);
|
||||
ip_info.gw.addr = ipaddr_addr(CONFIG_EXAMPLE_CONNECT_TAPIF_GW);
|
||||
#else
|
||||
netif_flags |= ESP_NETIF_DHCP_CLIENT;
|
||||
#endif
|
||||
|
||||
esp_netif_inherent_config_t base_cfg = {
|
||||
.if_key = "TAP",
|
||||
.ip_info = &ip_info,
|
||||
.flags = netif_flags,
|
||||
.get_ip_event = TAP0_GOT_IP,
|
||||
.route_prio = 100
|
||||
};
|
||||
|
||||
// put all configs together
|
||||
esp_netif_config_t cfg = {
|
||||
.base = &base_cfg,
|
||||
.driver = &driver_cfg,
|
||||
.stack = &stack_cfg
|
||||
};
|
||||
|
||||
// create the interface and attach it to the tapio-handle
|
||||
esp_netif_t *tap_netif = esp_netif_new(&cfg);
|
||||
esp_netif_attach(tap_netif, driver_cfg.handle);
|
||||
#if CONFIG_EXAMPLE_CONNECT_WAIT_FOR_IP
|
||||
ESP_LOGI(TAG, "Waiting for IP addresses...");
|
||||
esp_netif_action_connected(tap_netif, 0, 0, 0);
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, TAP0_GOT_IP, event_handler, NULL));
|
||||
s_events = xEventGroupCreate();
|
||||
xEventGroupWaitBits(s_events, 1, pdFALSE, pdFALSE, portMAX_DELAY);
|
||||
esp_netif_get_ip_info(tap_netif, &ip_info);
|
||||
ESP_LOGI(TAG, "Assigned IP address:"IPSTR ",", IP2STR(&ip_info.ip));
|
||||
#endif // CONFIG_EXAMPLE_CONNECT_WAIT_FOR_IP
|
||||
#endif // EXAMPLE_CONNECT_LWIP_TAPIF
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2001-2003 Swedish Institute of Computer Science
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* SPDX-FileContributor: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/ethip6.h"
|
||||
#include "netif/etharp.h"
|
||||
|
||||
#include "esp_netif.h"
|
||||
#include "esp_netif_net_stack.h"
|
||||
|
||||
#define IFNAME0 't'
|
||||
#define IFNAME1 'p'
|
||||
|
||||
static err_t
|
||||
low_level_output(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
esp_netif_t *esp_netif = esp_netif_get_handle_from_netif_impl(netif);
|
||||
char buf[1518]; /* max packet size including VLAN excluding CRC */
|
||||
|
||||
if (p->tot_len > sizeof(buf)) {
|
||||
MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("tapif: packet too large"));
|
||||
return ERR_IF;
|
||||
}
|
||||
|
||||
/* initiate transfer(); */
|
||||
pbuf_copy_partial(p, buf, p->tot_len, 0);
|
||||
|
||||
int ret = esp_netif_transmit(esp_netif, buf, p->tot_len);
|
||||
/* Check error */
|
||||
if (likely(ret == ESP_OK)) {
|
||||
return ERR_OK;
|
||||
}
|
||||
if (ret == ESP_ERR_NO_MEM) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
return ERR_IF;
|
||||
}
|
||||
|
||||
static void
|
||||
low_level_init(struct netif *netif)
|
||||
{
|
||||
|
||||
/* Obtain MAC address from network interface. */
|
||||
netif->hwaddr[0] = 0x02;
|
||||
netif->hwaddr[1] = 0x12;
|
||||
netif->hwaddr[2] = 0x34;
|
||||
netif->hwaddr[3] = 0x56;
|
||||
netif->hwaddr[4] = 0x78;
|
||||
netif->hwaddr[5] = 0xab;
|
||||
netif->hwaddr_len = 6;
|
||||
|
||||
/* device capabilities */
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP;
|
||||
}
|
||||
|
||||
err_t lwip_tapif_init(struct netif *netif)
|
||||
{
|
||||
LWIP_ASSERT("Tried to initialize tapif with NULL netif", netif != NULL);
|
||||
netif->name[0] = IFNAME0;
|
||||
netif->name[1] = IFNAME1;
|
||||
#if LWIP_IPV4
|
||||
netif->output = etharp_output;
|
||||
#endif /* LWIP_IPV4 */
|
||||
#if LWIP_IPV6
|
||||
netif->output_ip6 = ethip6_output;
|
||||
#endif /* LWIP_IPV6 */
|
||||
netif->linkoutput = low_level_output;
|
||||
netif->mtu = 1500;
|
||||
|
||||
low_level_init(netif);
|
||||
netif_set_link_up(netif);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
esp_err_t lwip_tapif_input(void *h, void *buffer, size_t len, void *l2_buff)
|
||||
{
|
||||
struct netif *netif = h;
|
||||
struct pbuf *p;
|
||||
LWIP_ASSERT("running tapif input with NULL netif", netif != NULL);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
|
||||
if (p == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
memcpy(p->payload, buffer, len);
|
||||
|
||||
/* full packet send to tcpip_thread to process */
|
||||
if (unlikely(netif->input(p, netif) != ERR_OK)) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("tapif_input: IP input error\n"));
|
||||
pbuf_free(p);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2001-2003 Swedish Institute of Computer Science
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* SPDX-FileContributor: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
#pragma once
|
||||
#include "lwip/esp_netif_net_stack.h"
|
||||
|
||||
/**
|
||||
* @brief lwip netif init API
|
||||
* @param netif pointer to lwip's netif
|
||||
* @return ERR_OK on success
|
||||
*/
|
||||
err_t lwip_tapif_init(struct netif *netif);
|
||||
|
||||
/**
|
||||
* @brief Input data path
|
||||
* @param h pointer to network stack handle (stuct netif* in our case)
|
||||
* @param buffer Data
|
||||
* @param len Data size
|
||||
* @param l2_buff Data L2 buffer
|
||||
*/
|
||||
esp_err_t lwip_tapif_input(void *h, void *buffer, size_t len, void *l2_buff);
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
sudo ip tuntap add dev tap0 mode tap user `whoami`
|
||||
sudo ip link set tap0 up
|
||||
sudo ip addr add 192.168.5.1/24 dev tap0
|
||||
Reference in New Issue
Block a user