networkd and sd-netlink: add support for Generic netlink And FooOverUDP to IPIP tunnel

This work add support to generic netlink to sd-netlink.
See https://lwn.net/Articles/208755/

networkd: add support FooOverUDP support to IPIP tunnel netdev
https://lwn.net/Articles/614348/

Example conf:

/lib/systemd/network/1-fou-tunnel.netdev
```
[NetDev]
Name=fou-tun
Kind=fou

[FooOverUDP]
Port=5555
Protocol=4

```

/lib/systemd/network/ipip-tunnel.netdev
```
[NetDev]
Name=ipip-tun
Kind=ipip

[Tunnel]
Independent=true
Local=10.65.208.212
Remote=10.65.208.211
FooOverUDP=true
FOUDestinationPort=5555
```

$ ip -d link show ipip-tun
```
5: ipip-tun@NONE: <POINTOPOINT,NOARP> mtu 1472 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ipip 10.65.208.212 peer 10.65.208.211 promiscuity 0
    ipip remote 10.65.208.211 local 10.65.208.212 ttl inherit pmtudisc encap fou encap-sport auto encap-dport 5555 noencap-csum noencap-csum6 noencap-remcsum numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
```
This commit is contained in:
Susant Sahani
2018-08-23 11:30:37 +02:00
committed by Zbigniew Jędrzejewski-Szmek
parent c07fe6d0df
commit 53cb501a13
14 changed files with 386 additions and 2 deletions
+128
View File
@@ -0,0 +1,128 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <arpa/inet.h>
#include <net/if.h>
#include <linux/ip.h>
#include "conf-parser.h"
#include "missing.h"
#include "netdev/fou-tunnel.h"
#include "networkd-link.h"
#include "networkd-manager.h"
#include "parse-util.h"
#include "sd-netlink.h"
#include "string-table.h"
#include "string-util.h"
#include "util.h"
static const char* const fou_encap_type_table[_NETDEV_FOO_OVER_UDP_ENCAP_MAX] = {
[NETDEV_FOO_OVER_UDP_ENCAP_DIRECT] = "FooOverUDP",
[NETDEV_FOO_OVER_UDP_ENCAP_GUE] = "GenericUDPEncapsulation",
};
DEFINE_STRING_TABLE_LOOKUP(fou_encap_type, FooOverUDPEncapType);
DEFINE_CONFIG_PARSE_ENUM(config_parse_fou_encap_type, fou_encap_type, FooOverUDPEncapType, "Failed to parse Foo Over UDP Encap type");
static int netdev_fill_fou_tunnel_message(NetDev *netdev, sd_netlink_message **ret) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
FouTunnel *t;
int r;
assert(netdev);
t = FOU(netdev);
assert(t);
r = sd_genl_message_new(netdev->manager->genl, SD_GENL_FOU, FOU_CMD_ADD, &m);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Failed to allocate generic netlink message: %m");
r = sd_netlink_message_append_u16(m, FOU_ATTR_PORT, htobe16(t->port));
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_PORT attribute: %m");
r = sd_netlink_message_append_u8(m, FOU_ATTR_TYPE, FOU_ENCAP_GUE);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_TYPE attribute: %m");
r = sd_netlink_message_append_u8(m, FOU_ATTR_AF, AF_INET);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_AF attribute: %m");
r = sd_netlink_message_append_u8(m, FOU_ATTR_IPPROTO, t->fou_protocol);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_IPPROTO attribute: %m");
*ret = m;
m = NULL;
return 0;
}
static int netdev_fou_tunnel_create(NetDev *netdev) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
uint32_t serial;
FouTunnel *t;
int r;
assert(netdev);
t = FOU(netdev);
assert(t);
r = netdev_fill_fou_tunnel_message(netdev, &m);
if (r < 0)
return r;
r = sd_netlink_send(netdev->manager->genl, m, &serial);
if (r < 0 && r != -EADDRINUSE)
return log_netdev_error_errno(netdev, r, "Failed to add FooOverUDP tunnel: %m");
return 0;
}
static int netdev_fou_tunnel_verify(NetDev *netdev, const char *filename) {
FouTunnel *t;
assert(netdev);
assert(filename);
t = FOU(netdev);
assert(t);
if (t->fou_encap_type == NETDEV_FOO_OVER_UDP_ENCAP_DIRECT && t->fou_protocol <= 0) {
log_netdev_error(netdev, "FooOverUDP missing protocol configured in %s. Ignoring", filename);
return -EINVAL;
}
if (t->fou_encap_type == NETDEV_FOO_OVER_UDP_ENCAP_GUE && t->fou_protocol > 0) {
log_netdev_error(netdev, "FooOverUDP GUE can't be set with protocol configured in %s. Ignoring", filename);
return -EINVAL;
}
return 0;
}
static void fou_tunnel_init(NetDev *netdev) {
FouTunnel *t;
assert(netdev);
t = FOU(netdev);
assert(t);
t->fou_encap_type = NETDEV_FOO_OVER_UDP_ENCAP_DIRECT;
}
const NetDevVTable foutnl_vtable = {
.object_size = sizeof(FouTunnel),
.init = fou_tunnel_init,
.sections = "Match\0NetDev\0FooOverUDP\0",
.create = netdev_fou_tunnel_create,
.create_type = NETDEV_CREATE_INDEPENDENT,
.config_verify = netdev_fou_tunnel_verify,
};
+39
View File
@@ -0,0 +1,39 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#if HAVE_FOU_CMD_GET
#include <linux/fou.h>
#endif
#include "in-addr-util.h"
#include "netdev/netdev.h"
typedef enum FooOverUDPEncapType {
NETDEV_FOO_OVER_UDP_ENCAP_UNSPEC = FOU_ENCAP_UNSPEC,
NETDEV_FOO_OVER_UDP_ENCAP_DIRECT = FOU_ENCAP_DIRECT,
NETDEV_FOO_OVER_UDP_ENCAP_GUE = FOU_ENCAP_GUE,
_NETDEV_FOO_OVER_UDP_ENCAP_MAX,
_NETDEV_FOO_OVER_UDP_ENCAP_INVALID = -1,
} FooOverUDPEncapType;
typedef struct FouTunnel {
NetDev meta;
uint8_t fou_protocol;
uint16_t port;
FooOverUDPEncapType fou_encap_type;
} FouTunnel;
DEFINE_NETDEV_CAST(FOU, FouTunnel);
extern const NetDevVTable foutnl_vtable;
const char *fou_encap_type_to_string(FooOverUDPEncapType d) _const_;
FooOverUDPEncapType fou_encap_type_from_string(const char *d) _pure_;
int config_parse_fou_encap_type(const char *unit, const char *filename,
unsigned line, const char *section,
unsigned section_line, const char *lvalue,
int ltype, const char *rvalue, void *data,
void *userdata);
+8
View File
@@ -19,6 +19,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#include "netdev/netdev.h"
#include "netdev/vxcan.h"
#include "netdev/wireguard.h"
#include "netdev/fou-tunnel.h"
#include "vlan-util.h"
%}
struct ConfigPerfItem;
@@ -65,6 +66,13 @@ Tunnel.CopyDSCP, config_parse_bool, 0,
Tunnel.EncapsulationLimit, config_parse_encap_limit, 0, offsetof(Tunnel, encap_limit)
Tunnel.Independent, config_parse_bool, 0, offsetof(Tunnel, independent)
Tunnel.AllowLocalRemote, config_parse_tristate, 0, offsetof(Tunnel, allow_localremote)
Tunnel.FooOverUDP, config_parse_bool, 0, offsetof(Tunnel, fou_tunnel)
Tunnel.FOUDestinationPort, config_parse_ip_port, 0, offsetof(Tunnel, fou_destination_port)
Tunnel.FOUSourcePort, config_parse_ip_port, 0, offsetof(Tunnel, encap_src_port)
Tunnel.Encapsulation, config_parse_fou_encap_type, 0, offsetof(Tunnel, fou_encap_type)
FooOverUDP.Protocol, config_parse_uint8, 0, offsetof(FouTunnel, fou_protocol)
FooOverUDP.Encapsulation, config_parse_fou_encap_type, 0, offsetof(FouTunnel, fou_encap_type)
FooOverUDP.Port, config_parse_ip_port, 0, offsetof(FouTunnel, port)
Peer.Name, config_parse_ifname, 0, offsetof(Veth, ifname_peer)
Peer.MACAddress, config_parse_hwaddr, 0, offsetof(Veth, mac_peer)
VXCAN.Peer, config_parse_ifname, 0, offsetof(VxCan, ifname_peer)
+3
View File
@@ -34,6 +34,7 @@
#include "netdev/vxcan.h"
#include "netdev/wireguard.h"
#include "netdev/netdevsim.h"
#include "netdev/fou-tunnel.h"
const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_BRIDGE] = &bridge_vtable,
@@ -62,6 +63,7 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_VXCAN] = &vxcan_vtable,
[NETDEV_KIND_WIREGUARD] = &wireguard_vtable,
[NETDEV_KIND_NETDEVSIM] = &netdevsim_vtable,
[NETDEV_KIND_FOU] = &foutnl_vtable,
};
static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
@@ -91,6 +93,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_VXCAN] = "vxcan",
[NETDEV_KIND_WIREGUARD] = "wireguard",
[NETDEV_KIND_NETDEVSIM] = "netdevsim",
[NETDEV_KIND_FOU] = "fou",
};
DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
+1
View File
@@ -43,6 +43,7 @@ typedef enum NetDevKind {
NETDEV_KIND_VXCAN,
NETDEV_KIND_WIREGUARD,
NETDEV_KIND_NETDEVSIM,
NETDEV_KIND_FOU,
_NETDEV_KIND_MAX,
_NETDEV_KIND_INVALID = -1
} NetDevKind;
+25
View File
@@ -8,6 +8,10 @@
#include "sd-netlink.h"
#if HAVE_FOU_CMD_GET
#include <linux/fou.h>
#endif
#include "conf-parser.h"
#include "missing.h"
#include "networkd-link.h"
@@ -61,6 +65,21 @@ static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_netlin
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m");
if (t->fou_tunnel) {
r = sd_netlink_message_append_u16(m, IFLA_IPTUN_ENCAP_TYPE, t->fou_encap_type);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_TYPE attribute: %m");
r = sd_netlink_message_append_u16(m, IFLA_IPTUN_ENCAP_SPORT, htobe16(t->encap_src_port));
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_SPORT attribute: %m");
r = sd_netlink_message_append_u16(m, IFLA_IPTUN_ENCAP_DPORT, htobe16(t->fou_destination_port));
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_DPORT attribute: %m");
}
return r;
}
@@ -417,6 +436,11 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
return -EINVAL;
}
if (t->fou_tunnel && t->fou_destination_port <= 0) {
log_netdev_error(netdev, "FooOverUDP missing port configured in %s. Ignoring", filename);
return -EINVAL;
}
return 0;
}
@@ -600,6 +624,7 @@ static void ipip_init(NetDev *n) {
assert(t);
t->pmtudisc = true;
t->fou_encap_type = FOU_ENCAP_DIRECT;
}
static void sit_init(NetDev *n) {
+7
View File
@@ -4,6 +4,7 @@
#include "in-addr-util.h"
#include "netdev/netdev.h"
#include "netdev/fou-tunnel.h"
typedef enum Ip6TnlMode {
NETDEV_IP6_TNL_MODE_IP6IP6,
@@ -40,10 +41,15 @@ typedef struct Tunnel {
union in_addr_union remote;
Ip6TnlMode ip6tnl_mode;
FooOverUDPEncapType fou_encap_type;
bool pmtudisc;
bool copy_dscp;
bool independent;
bool fou_tunnel;
uint16_t encap_src_port;
uint16_t fou_destination_port;
} Tunnel;
DEFINE_NETDEV_CAST(IPIP, Tunnel);
@@ -96,6 +102,7 @@ int config_parse_encap_limit(const char *unit, const char *filename,
unsigned section_line, const char *lvalue,
int ltype, const char *rvalue, void *data,
void *userdata);
int config_parse_tunnel_key(const char *unit, const char *filename,
unsigned line, const char *section,
unsigned section_line, const char *lvalue,