]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd and sd-netlink: add support for Generic netlink And FooOverUDP to IPIP tunnel
authorSusant Sahani <susant@redhat.com>
Sun, 3 Jun 2018 07:07:41 +0000 (12:37 +0530)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 23 Aug 2018 09:30:37 +0000 (11:30 +0200)
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
```

14 files changed:
man/systemd.netdev.xml
meson.build
src/basic/missing.h
src/libsystemd/sd-netlink/generic-netlink.c
src/libsystemd/sd-netlink/netlink-types.c
src/network/meson.build
src/network/netdev/fou-tunnel.c [new file with mode: 0644]
src/network/netdev/fou-tunnel.h [new file with mode: 0644]
src/network/netdev/netdev-gperf.gperf
src/network/netdev/netdev.c
src/network/netdev/netdev.h
src/network/netdev/tunnel.c
src/network/netdev/tunnel.h
src/systemd/sd-netlink.h

index d950eb578bea7bcff0090bd84cb2338fcba12031..380d0088ce1c7e0bebcd28dec48dd3cd35a06fd4 100644 (file)
 
           <row><entry><varname>netdevsim</varname></entry>
           <entry> A simulator. This simulated networking device is used for testing various networking APIs and at this time is particularly focused on testing hardware offloading related interfaces.</entry></row>
+
+          <row><entry><varname>fou</varname></entry>
+          <entry>Foo-over-UDP tunneling.</entry></row>
+
         </tbody>
       </tgroup>
     </table>
           </para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>FooOverUDP=</varname></term>
+        <listitem>
+          <para>A boolean. Specifies whether <varname>FooOverUDP=</varname> tunnel is to be configured.
+          Defaults to false. For more detail information see
+          <ulink url="https://lwn.net/Articles/614348">Foo over UDP</ulink></para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>FOUDestinationPort=</varname></term>
+        <listitem>
+          <para>The <varname>FOUDestinationPort=</varname> specifies the UDP destination port for encapsulation.
+          This field is mandatory and is not set by default.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>FOUSourcePort=</varname></term>
+        <listitem>
+          <para>The <constant>FOUSourcePort=</constant> specifies the UDP source port for encapsulation. Defaults to <varname>0</varname>,
+          that is, the source port for packets is left to the network stack to decide.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>Encapsulation=</varname></term>
+        <listitem>
+          <para>Accepts the same key as <literal>[FooOverUDP]</literal></para>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
+
+  <refsect1>
+    <title>[FooOverUDP] Section Options</title>
+
+    <para>The <literal>[FooOverUDP]</literal> section only applies for
+    netdevs of kind <literal>fou</literal> and accepts the
+    following keys:</para>
+
+    <variablelist class='network-directives'>
+      <varlistentry>
+        <term><varname>Protocol=</varname></term>
+        <listitem>
+          <para>The <varname>Protocol=</varname> specifies the protocol number of the
+          packets arriving at the UDP port. This field is mandatory and is not set by default. Valid range is 1-255.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>Encapsulation=</varname></term>
+        <listitem>
+          <para>Specifies the encapsulation mechanism used to store networking packets of various protocols inside the UDP packets. Supports the following values:
+
+          <literal>FooOverUDP</literal> provides the simplest no frills model of UDP encapsulation, it simply encapsulates
+          packets directly in the UDP payload.
+          <literal>GenericUDPEncapsulation</literal> is a generic and extensible encapsulation, it allows encapsulation of packets for any IP
+          protocol and optional data as part of the encapsulation.
+          For more detailed information see <ulink url="https://lwn.net/Articles/615044">Generic UDP Encapsulation</ulink>.
+          Defaults to <literal>FooOverUDP</literal>.
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>Port=</varname></term>
+        <listitem>
+          <para>Specifies the port number, where the IP encapsulation packets will arrive. Please take note that the packets
+          will arrive with the encapsulation will be removed. Then they will be manually fed back into the network stack, and sent ahead
+          for delivery to the real destination. This option is mandatory.</para>
+        </listitem>
+        </varlistentry>
+      </variablelist>
+  </refsect1>
   <refsect1>
     <title>[Peer] Section Options</title>
 
@@ -1379,6 +1451,32 @@ Local=192.168.223.238
 Remote=192.169.224.239
 TTL=64</programlisting>
     </example>
+    <example>
+      <title>/etc/systemd/network/1-fou-tunnel.netdev</title>
+      <programlisting>[NetDev]
+Name=fou-tun
+Kind=fou
+
+[FooOverUDP]
+Port=5555
+Protocol=4
+      </programlisting>
+    </example>
+    <example>
+      <title>/etc/systemd/network/25-fou-ipip.netdev</title>
+      <programlisting>[NetDev]
+[NetDev]
+Name=ipip-tun
+Kind=ipip
+
+[Tunnel]
+Independent=true
+Local=10.65.208.212
+Remote=10.65.208.211
+FooOverUDP=true
+FOUDestinationPort=5555
+      </programlisting>
+    </example>
     <example>
       <title>/etc/systemd/network/25-tap.netdev</title>
       <programlisting>[NetDev]
index 2209c935ad652422f81783990b97679af88c7492..f4eabe7373b5c7fb1983e13ee01c84c2fd6a86a1 100644 (file)
@@ -464,6 +464,9 @@ foreach decl : [['IFLA_INET6_ADDR_GEN_MODE',         'linux/if_link.h'],
                 ['FRA_UID_RANGE',                    'linux/fib_rules.h'],
                 ['LO_FLAGS_PARTSCAN',                'linux/loop.h'],
                 ['VXCAN_INFO_PEER',                  'linux/can/vxcan.h'],
+                ['FOU_ATTR_REMCSUM_NOPARTIAL',       'linux/fou.h'],
+                ['FOU_CMD_GET',                      'linux/fou.h'],
+                ['FOU_ENCAP_GUE',                    'linux/fou.h'],
                ]
         prefix = decl.length() > 2 ? decl[2] : ''
         have = cc.has_header_symbol(decl[1], decl[0], prefix : prefix)
index 477992fbcbad898bd7b4abda3a901ee6c10346e1..e666e2ba2d036a91938edbe759d22f3adbedc228 100644 (file)
@@ -1409,4 +1409,43 @@ struct statx {
 #define TASK_COMM_LEN 16
 #endif
 
+#ifndef FOU_GENL_NAME
+#define FOU_GENL_NAME           "fou"
+#endif
+
+#ifndef FOU_GENL_VERSION
+#define FOU_GENL_VERSION        0x1
+#endif
+
+#if !HAVE_FOU_ATTR_REMCSUM_NOPARTIAL
+#define FOU_ATTR_UNSPEC 0
+#define FOU_ATTR_PORT 1
+#define FOU_ATTR_AF 2
+#define FOU_ATTR_IPPROTO 3
+#define FOU_ATTR_TYPE 4
+#define FOU_ATTR_REMCSUM_NOPARTIAL 5
+#define __FOU_ATTR_MAX 6
+
+#define FOU_ATTR_MAX (__FOU_ATTR_MAX - 1)
+#endif
+
+#if !HAVE_FOU_CMD_GET
+#define FOU_CMD_UNSPEC 0
+#define FOU_CMD_ADD 1
+#define FOU_CMD_DEL 2
+#define FOU_CMD_GET 3
+#define __FOU_CMD_MAX 4
+
+#define FOU_CMD_MAX (__FOU_CMD_MAX - 1)
+#endif
+
+#if !HAVE_FOU_ENCAP_GUE
+#define FOU_ENCAP_UNSPEC 0
+#define FOU_ENCAP_DIRECT 1
+#define FOU_ENCAP_GUE 2
+#define __FOU_ENCAP_MAX 3
+
+#define FOU_ENCAP_MAX (__FOU_ENCAP_MAX - 1)
+#endif
+
 #include "missing_syscall.h"
index 347bf4cbd56043512874783fb3d75616a62a84eb..3445757da9b62165c38a06708ac13361cbd27cff 100644 (file)
@@ -12,6 +12,7 @@ typedef struct {
 static const genl_family genl_families[] = {
         [SD_GENL_ID_CTRL] = { .name = "", .version = 1 },
         [SD_GENL_WIREGUARD] = { .name = "wireguard", .version = 1 },
+        [SD_GENL_FOU]       = { .name = "fou", .version = 1 },
 };
 
 int sd_genl_socket_open(sd_netlink **ret) {
index c93fe9cb4c1edcc2763493c7e7301ccfd8281cbc..b50a8c8303b7569153cdae7cdaca38d4b0c1e8f7 100644 (file)
 #include <linux/if_link.h>
 #include <linux/if_tunnel.h>
 #include <linux/veth.h>
+
+#if HAVE_FOU_CMD_GET
+#include <linux/fou.h>
+#endif
+
 #if HAVE_VXCAN_INFO_PEER
 #include <linux/can/vxcan.h>
 #endif
@@ -733,9 +738,34 @@ static const NLTypeSystem genl_ctrl_id_ctrl_type_system = {
         .types = genl_ctrl_id_ctrl_cmds,
 };
 
+static const NLType genl_fou_types[] = {
+        [FOU_ATTR_PORT]              = { .type = NETLINK_TYPE_U16 },
+        [FOU_ATTR_AF]                = { .type = NETLINK_TYPE_U8 },
+        [FOU_ATTR_IPPROTO]           = { .type = NETLINK_TYPE_U8 },
+        [FOU_ATTR_TYPE]              = { .type = NETLINK_TYPE_U8 },
+        [FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG },
+};
+
+static const NLTypeSystem genl_fou_type_system = {
+        .count = ELEMENTSOF(genl_fou_types),
+        .types = genl_fou_types,
+};
+
+static const NLType genl_fou_cmds[] = {
+        [FOU_CMD_ADD] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_fou_type_system },
+        [FOU_CMD_DEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_fou_type_system },
+        [FOU_CMD_GET] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_fou_type_system },
+};
+
+static const NLTypeSystem genl_fou_cmds_type_system = {
+        .count = ELEMENTSOF(genl_fou_cmds),
+        .types = genl_fou_cmds,
+};
+
 static const NLType genl_families[] = {
-        [SD_GENL_ID_CTRL]  = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_ctrl_id_ctrl_type_system },
+        [SD_GENL_ID_CTRL]   = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_ctrl_id_ctrl_type_system },
         [SD_GENL_WIREGUARD] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_type_system },
+        [SD_GENL_FOU]       = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_fou_cmds_type_system},
 };
 
 const NLTypeSystem genl_family_type_system_root = {
index 8f63815b122feda34c4e654f884617f0802762b5..175d2f822cc3357a8337eab0e5fca333997ac1e7 100644 (file)
@@ -35,6 +35,8 @@ sources = files('''
         netdev/wireguard.h
         netdev/netdevsim.c
         netdev/netdevsim.h
+        netdev/fou-tunnel.c
+        netdev/fou-tunnel.h
         networkd-address-label.c
         networkd-address-label.h
         networkd-address-pool.c
diff --git a/src/network/netdev/fou-tunnel.c b/src/network/netdev/fou-tunnel.c
new file mode 100644 (file)
index 0000000..6ec04c2
--- /dev/null
@@ -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,
+};
diff --git a/src/network/netdev/fou-tunnel.h b/src/network/netdev/fou-tunnel.h
new file mode 100644 (file)
index 0000000..58bcab3
--- /dev/null
@@ -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);
index dfcac9adbfc31525cfee203c4864b5957ba709df..96c8fb1832dd945649347da72a6b38f8a9bcdfd5 100644 (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)
index 17bfa518dca0e6adf5a10a08e6b7c63b628f27f5..93df63b5c1d65da2f7cf3a25a994a2f957079bbd 100644 (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);
index bdab18043b12a89550947426d0e1374d82938319..d073216b148d0a0ae972482b48a6b1df3e98ec33 100644 (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;
index c15ca7471765a17c9ff267c760ff60ad4dca9a92..e39dff7b9090b719c4cc868aef1fc86fda1ac7ea 100644 (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) {
index 029d845378ffb008ed84fb90bef38c5ba3f599fe..40ddb1c0434eaa808671292ec196aa70f5c74d70 100644 (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,
index 51f0fa16b4dbedd58d9bfef29db99d3a1a924973..7650ff45320db774e6add3057dc9fc88f1ef3b2b 100644 (file)
@@ -32,7 +32,7 @@ _SD_BEGIN_DECLARATIONS;
 typedef struct sd_netlink sd_netlink;
 typedef struct sd_genl_socket sd_genl_socket;
 typedef struct sd_netlink_message sd_netlink_message;
-typedef enum {SD_GENL_ID_CTRL, SD_GENL_WIREGUARD} sd_genl_family;
+typedef enum {SD_GENL_ID_CTRL, SD_GENL_WIREGUARD, SD_GENL_FOU} sd_genl_family;
 
 /* callback */