samples: net: echo-server: Add tunneling interface support
Add support for IP tunneling with overlay-tunnel.conf file. Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
68835f1006
commit
64b7a11ccc
7 changed files with 210 additions and 0 deletions
|
@ -21,6 +21,7 @@ target_sources( app PRIVATE src/echo-server.c)
|
|||
target_sources_ifdef(CONFIG_NET_UDP app PRIVATE src/udp.c)
|
||||
target_sources_ifdef(CONFIG_NET_TCP app PRIVATE src/tcp.c)
|
||||
target_sources_ifdef(CONFIG_NET_VLAN app PRIVATE src/vlan.c)
|
||||
target_sources_ifdef(CONFIG_NET_L2_IPIP app PRIVATE src/tunnel.c)
|
||||
|
||||
include(${ZEPHYR_BASE}/samples/net/common/common.cmake)
|
||||
|
||||
|
|
|
@ -60,6 +60,18 @@ config NET_SAMPLE_IFACE3_VLAN_TAG
|
|||
Set VLAN (virtual LAN) tag (id) that is used in the sample
|
||||
application.
|
||||
|
||||
config NET_SAMPLE_TUNNEL_PEER_ADDR
|
||||
string "Remote IP address of the tunnel interface"
|
||||
depends on NET_L2_IPIP
|
||||
help
|
||||
Use overlay-tunnel.conf to setup the tunnel support.
|
||||
|
||||
config NET_SAMPLE_TUNNEL_MY_ADDR
|
||||
string "My address for tunnel interface"
|
||||
depends on NET_L2_IPIP
|
||||
help
|
||||
The value depends on your network setup.
|
||||
|
||||
config NET_SAMPLE_PSK_HEADER_FILE
|
||||
string "Header file containing PSK"
|
||||
default "dummy_psk.h"
|
||||
|
|
|
@ -54,6 +54,9 @@ echo-server directory:
|
|||
- :file:`overlay-tls.conf`
|
||||
This overlay config enables support for TLS.
|
||||
|
||||
- :file:`overlay-tunnel.conf`
|
||||
This overlay config enables support for IP tunneling.
|
||||
|
||||
Build echo-server sample application like this:
|
||||
|
||||
.. zephyr-app-commands::
|
||||
|
|
16
samples/net/sockets/echo_server/overlay-tunnel.conf
Normal file
16
samples/net/sockets/echo_server/overlay-tunnel.conf
Normal file
|
@ -0,0 +1,16 @@
|
|||
CONFIG_NET_L2_VIRTUAL=y
|
||||
CONFIG_NET_L2_VIRTUAL_MGMT=y
|
||||
CONFIG_NET_L2_IPIP=y
|
||||
|
||||
CONFIG_NET_IF_MAX_IPV6_COUNT=4
|
||||
CONFIG_NET_IF_MAX_IPV4_COUNT=4
|
||||
|
||||
# First tunneling interface will have these settings
|
||||
CONFIG_NET_SAMPLE_TUNNEL_PEER_ADDR="192.0.2.2"
|
||||
#CONFIG_NET_SAMPLE_TUNNEL_PEER_ADDR="2001:db8::2"
|
||||
|
||||
# Use this for IPv6 over IPv4
|
||||
CONFIG_NET_SAMPLE_TUNNEL_MY_ADDR="2001:db8:200::1"
|
||||
|
||||
# Use this for IPv4 over IPv4
|
||||
#CONFIG_NET_SAMPLE_TUNNEL_MY_ADDR="198.51.100.1"
|
|
@ -81,3 +81,19 @@ static inline int init_vlan(void)
|
|||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_NET_VLAN */
|
||||
|
||||
#if defined(CONFIG_NET_L2_IPIP)
|
||||
int init_tunnel(void);
|
||||
bool is_tunnel(struct net_if *iface);
|
||||
#else
|
||||
static inline int init_tunnel(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool is_tunnel(struct net_if *iface)
|
||||
{
|
||||
ARG_UNUSED(iface);
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_NET_L2_IPIP */
|
||||
|
|
|
@ -93,6 +93,11 @@ static void event_handler(struct net_mgmt_event_callback *cb,
|
|||
want_to_quit = false;
|
||||
}
|
||||
|
||||
if (is_tunnel(iface)) {
|
||||
/* Tunneling is handled separately, so ignore it here */
|
||||
return;
|
||||
}
|
||||
|
||||
if (mgmt_event == NET_EVENT_L4_CONNECTED) {
|
||||
LOG_INF("Network connected");
|
||||
|
||||
|
@ -192,6 +197,7 @@ static void init_app(void)
|
|||
}
|
||||
|
||||
init_vlan();
|
||||
init_tunnel();
|
||||
}
|
||||
|
||||
static int cmd_sample_quit(const struct shell *shell,
|
||||
|
|
156
samples/net/sockets/echo_server/src/tunnel.c
Normal file
156
samples/net/sockets/echo_server/src/tunnel.c
Normal file
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(net_echo_server_sample, LOG_LEVEL_DBG);
|
||||
|
||||
#include <zephyr.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/virtual_mgmt.h>
|
||||
|
||||
/* User data for the interface callback */
|
||||
struct ud {
|
||||
struct net_if *tunnel;
|
||||
struct net_if *peer;
|
||||
};
|
||||
|
||||
bool is_tunnel(struct net_if *iface)
|
||||
{
|
||||
if (net_if_l2(iface) == &NET_L2_GET_NAME(VIRTUAL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void iface_cb(struct net_if *iface, void *user_data)
|
||||
{
|
||||
struct ud *ud = user_data;
|
||||
|
||||
if (!ud->tunnel && is_tunnel(iface)) {
|
||||
ud->tunnel = iface;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int setup_iface(struct net_if *iface, const char *ipaddr)
|
||||
{
|
||||
struct net_if_addr *ifaddr;
|
||||
struct sockaddr addr;
|
||||
|
||||
if (!net_ipaddr_parse(ipaddr, strlen(ipaddr), &addr)) {
|
||||
LOG_ERR("Tunnel peer address \"%s\" invalid.", ipaddr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6) && addr.sa_family == AF_INET6) {
|
||||
ifaddr = net_if_ipv6_addr_add(iface,
|
||||
&net_sin6(&addr)->sin6_addr,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
if (!ifaddr) {
|
||||
LOG_ERR("Cannot add %s to interface %d",
|
||||
ipaddr, net_if_get_by_iface(iface));
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4) && addr.sa_family == AF_INET) {
|
||||
ifaddr = net_if_ipv4_addr_add(iface,
|
||||
&net_sin(&addr)->sin_addr,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
if (!ifaddr) {
|
||||
LOG_ERR("Cannot add %s to interface %d",
|
||||
ipaddr, net_if_get_by_iface(iface));
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int init_tunnel(void)
|
||||
{
|
||||
struct virtual_interface_req_params params = { 0 };
|
||||
struct sockaddr peer = { 0 };
|
||||
struct ud ud;
|
||||
int ret;
|
||||
int mtu;
|
||||
|
||||
memset(&ud, 0, sizeof(ud));
|
||||
|
||||
if (!net_ipaddr_parse(CONFIG_NET_SAMPLE_TUNNEL_PEER_ADDR,
|
||||
strlen(CONFIG_NET_SAMPLE_TUNNEL_PEER_ADDR),
|
||||
&peer)) {
|
||||
LOG_ERR("Tunnel peer address \"%s\" invalid.",
|
||||
CONFIG_NET_SAMPLE_TUNNEL_PEER_ADDR);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6) && peer.sa_family == AF_INET6) {
|
||||
struct net_if *iface;
|
||||
|
||||
iface = net_if_ipv6_select_src_iface(
|
||||
&net_sin6(&peer)->sin6_addr);
|
||||
ud.peer = iface;
|
||||
params.family = AF_INET6;
|
||||
net_ipaddr_copy(¶ms.peer6addr,
|
||||
&net_sin6(&peer)->sin6_addr);
|
||||
mtu = NET_ETH_MTU - sizeof(struct net_ipv6_hdr);
|
||||
|
||||
} else if (IS_ENABLED(CONFIG_NET_IPV4) && peer.sa_family == AF_INET) {
|
||||
struct net_if *iface;
|
||||
|
||||
iface = net_if_ipv4_select_src_iface(
|
||||
&net_sin(&peer)->sin_addr);
|
||||
ud.peer = iface;
|
||||
params.family = AF_INET;
|
||||
net_ipaddr_copy(¶ms.peer4addr,
|
||||
&net_sin(&peer)->sin_addr);
|
||||
mtu = NET_ETH_MTU - sizeof(struct net_ipv4_hdr);
|
||||
|
||||
} else {
|
||||
LOG_ERR("Invalid address family %d", peer.sa_family);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ud.peer == NULL) {
|
||||
LOG_ERR("Peer address %s unreachable",
|
||||
CONFIG_NET_SAMPLE_TUNNEL_PEER_ADDR);
|
||||
return -ENETUNREACH;
|
||||
}
|
||||
|
||||
net_if_foreach(iface_cb, &ud);
|
||||
|
||||
ret = net_mgmt(NET_REQUEST_VIRTUAL_INTERFACE_SET_PEER_ADDRESS,
|
||||
ud.tunnel, ¶ms, sizeof(params));
|
||||
if (ret < 0 && ret != -ENOTSUP) {
|
||||
LOG_ERR("Cannot set peer address %s to "
|
||||
"interface %d (%d)",
|
||||
CONFIG_NET_SAMPLE_TUNNEL_PEER_ADDR,
|
||||
net_if_get_by_iface(ud.tunnel),
|
||||
ret);
|
||||
}
|
||||
|
||||
params.mtu = mtu;
|
||||
|
||||
ret = net_mgmt(NET_REQUEST_VIRTUAL_INTERFACE_SET_MTU,
|
||||
ud.tunnel, ¶ms, sizeof(params));
|
||||
if (ret < 0 && ret != -ENOTSUP) {
|
||||
LOG_ERR("Cannot set interface %d MTU to %d (%d)",
|
||||
net_if_get_by_iface(ud.tunnel), params.mtu, ret);
|
||||
}
|
||||
|
||||
ret = setup_iface(ud.tunnel,
|
||||
CONFIG_NET_SAMPLE_TUNNEL_MY_ADDR);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Cannot set IP address %s to tunnel interface",
|
||||
CONFIG_NET_SAMPLE_TUNNEL_MY_ADDR);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue