.. | ||
include | ||
linux | ||
lwip | ||
CMakeLists.txt | ||
Kconfig.projbuild | ||
linux_connect.c | ||
make_tap_netif | ||
README.md |
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
- Add the path to this component to the
EXTRA_COMPONENT_DIRS
in your project makefile
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/common_components/tapif_io")
- Include lwip and linux side of the configuration
#include "esp_netif.h" // esp-netif
#include "tapio.h" // esp-netif's driver side
#include "lwip/tapif.h" // esp-netif's network stack side
- Configure the esp-netif a) setup the linux tap I/O config
esp_netif_driver_ifconfig_t driver_cfg = {
.handle = tapio_create(),
.transmit = tapio_output,
};
b) configure the lwip netif for the tap interface
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
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
};
- Initialize and attach the esp_netif to the I/O handle
esp_netif_t *tap_netif = esp_netif_new(&cfg);
esp_netif_attach(tap_netif, driver_cfg.handle);
Host side networking
-
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 -
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 iseth0
with IP range of192.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.
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:
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 betweentap0
and your default network interface (eth0
in the below example).
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.
- Configure and set the
esp-netif
up
- Same as in API usage, but update the base esp-netif config
3c)
to enable DHCP client
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
esp_netif_action_connected(tap_netif, 0, 0, 0);
- Wait for the IP address to be assigned. This could be implemented as a wait loop below, as the esp-event currently doesn't support IP events on Linux target.
esp_netif_ip_info_t ip_info = {};
while (ip_info.ip.addr == 0) {
ESP_LOGI("tap-init", "No IP assigned, waiting...");
usleep(1000000);
esp_netif_get_ip_info(tap_netif, &ip_info);
}
ESP_LOGI("tap-init", "Assigned IP address:"IPSTR ",", IP2STR(&ip_info.ip));
-
Configure forwarding/routing if needed based on the previous sections.
-
Configure the DHCP server on the host machine
Example for isc-dhcp-server
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;
}