]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Added support for xfrm interfaces
author1848 <nomail>
Mon, 8 Jul 2019 15:09:46 +0000 (17:09 +0200)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 10 Jul 2019 14:02:19 +0000 (23:02 +0900)
18 files changed:
man/systemd.netdev.xml
man/systemd.network.xml
src/libsystemd/sd-netlink/netlink-types.c
src/libsystemd/sd-netlink/netlink-types.h
src/network/meson.build
src/network/netdev/netdev-gperf.gperf
src/network/netdev/netdev.c
src/network/netdev/netdev.h
src/network/netdev/xfrm.c [new file with mode: 0644]
src/network/netdev/xfrm.h [new file with mode: 0644]
src/network/networkd-link.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
test/fuzz/fuzz-netdev-parser/27-xfrm.netdev [new file with mode: 0644]
test/fuzz/fuzz-netdev-parser/directives.netdev
test/fuzz/fuzz-network-parser/27-xfrm.network [new file with mode: 0644]
test/fuzz/fuzz-network-parser/directives.network

index d083fb9a6f406e52e595052a5fc72a213292d26f..3cce776cc226b1f7f74dbcd5d826e3a86719de3a 100644 (file)
           <row><entry><varname>fou</varname></entry>
           <entry>Foo-over-UDP tunneling.</entry></row>
 
+          <row><entry><varname>xfrm</varname></entry>
+          <entry>A virtual tunnel interface like vti/vti6 but with several advantages.</entry></row>
+
         </tbody>
       </tgroup>
     </table>
     Linux Ethernet Bonding Driver HOWTO</ulink></para>
   </refsect1>
 
+  <refsect1>
+    <title>[Xfrm] Section Options</title>
+
+    <para>The <literal>[Xfrm]</literal> section accepts the following
+    keys:</para>
+
+    <variablelist class='network-directives'>
+      <varlistentry>
+        <term><varname>InterfaceId=</varname></term>
+        <listitem>
+          <para>Sets the ID/key of the xfrm interface which needs to be associated with a SA/policy.
+          Can be decimal or hexadecimal, valid range is 0-0xffffffff, defaults to 0.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>Independent=</varname></term>
+        <listitem>
+          <para>Takes a boolean. If set to <literal>no</literal>, the xfrm interface should have an
+          underlying device which can be used for hardware offloading. Defaults to <literal>no</literal>.
+          See <citerefentry><refentrytitle>systemd.network</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+          for how to configure the underlying device.</para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+
+    <para>For more detail information see
+      <ulink url="https://lwn.net/Articles/757391">
+        Virtual xfrm interfaces</ulink></para>
+  </refsect1>
+
   <refsect1>
     <title>[VRF] Section Options</title>
     <para>The <literal>[VRF]</literal> section only applies for
@@ -2048,6 +2081,16 @@ PublicKey=RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=
 AllowedIPs=fd31:bf08:57cb::/48,192.168.26.0/24
 Endpoint=wireguard.example.com:51820</programlisting>
     </example>
+
+    <example>
+      <title>/etc/systemd/network/27-xfrm.netdev</title>
+      <programlisting>[Xfrm]
+Name=xfrm0
+Kind=xfrm
+
+[Xfrm]
+Independent=yes</programlisting>
+    </example>
   </refsect1>
 
   <refsect1>
index d32b60a2c9feb9f19db2aecd5af32536232cd0e6..c48b294551be95f8cb609eb1a3ed88e8578df4e9 100644 (file)
           </para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>Xfrm=</varname></term>
+        <listitem>
+          <para>The name of the xfrm to create on the link. See
+            <citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+            This option may be specified more than once.</para>
+        </listitem>
+      </varlistentry>
       <varlistentry>
         <term><varname>KeepConfiguration=</varname></term>
         <listitem>
@@ -2338,6 +2346,29 @@ Name=enp0s25
 MACVTAP=macvtap-test
 </programlisting>
     </example>
+
+    <example>
+      <title>A Xfrm interface with physical underlying device.</title>
+
+      <programlisting># /etc/systemd/network/27-xfrm.netdev
+[NetDev]
+Name=xfrm0
+
+[Xfrm]
+InterfaceId=7</programlisting>
+
+      <programlisting># /etc/systemd/network/27-eth0.network
+[Match]
+Name=eth0
+
+[Network]
+Xfrm=xfrm0</programlisting>
+
+      <para>This creates a <literal>xfrm0</literal> interface and binds it to the <literal>eth0</literal> device.
+      This allows hardware based ipsec offloading to the <literal>eth0</literal> nic.
+      If offloading is not needed, xfrm interfaces can be assigned to the <literal>lo</literal> device.
+      </para>
+    </example>
   </refsect1>
 
   <refsect1>
index 68507739776df0a350f4f951912973fd52db4cdf..450e298f2cac605c33e52f6cd8814cfc3f88a635 100644 (file)
@@ -327,6 +327,11 @@ static const NLType rtnl_link_info_data_macsec_types[] = {
         [IFLA_MACSEC_VALIDATION]     = { .type = NETLINK_TYPE_U8 },
 };
 
+static const NLType rtnl_link_info_data_xfrm_types[] = {
+        [IFLA_XFRM_LINK]         = { .type = NETLINK_TYPE_U32 },
+        [IFLA_XFRM_IF_ID]        = { .type = NETLINK_TYPE_U32 }
+};
+
 /* these strings must match the .kind entries in the kernel */
 static const char* const nl_union_link_info_data_table[] = {
         [NL_UNION_LINK_INFO_DATA_BOND] = "bond",
@@ -358,6 +363,7 @@ static const char* const nl_union_link_info_data_table[] = {
         [NL_UNION_LINK_INFO_DATA_CAN] = "can",
         [NL_UNION_LINK_INFO_DATA_MACSEC] = "macsec",
         [NL_UNION_LINK_INFO_DATA_NLMON] = "nlmon",
+        [NL_UNION_LINK_INFO_DATA_XFRM] = "xfrm",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
@@ -411,6 +417,8 @@ static const NLTypeSystem rtnl_link_info_data_type_systems[] = {
                                                        .types = rtnl_link_info_data_can_types },
         [NL_UNION_LINK_INFO_DATA_MACSEC] =           { .count = ELEMENTSOF(rtnl_link_info_data_macsec_types),
                                                        .types = rtnl_link_info_data_macsec_types },
+        [NL_UNION_LINK_INFO_DATA_XFRM] =             { .count = ELEMENTSOF(rtnl_link_info_data_xfrm_types),
+                                                       .types = rtnl_link_info_data_xfrm_types },
 };
 
 static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = {
index fed43ae43c09640a23f54f033c497fcc82986908..efc59a0a4bc0dbbd281276f12475a97176b49f44 100644 (file)
@@ -83,6 +83,7 @@ typedef enum NLUnionLinkInfoData {
         NL_UNION_LINK_INFO_DATA_CAN,
         NL_UNION_LINK_INFO_DATA_MACSEC,
         NL_UNION_LINK_INFO_DATA_NLMON,
+        NL_UNION_LINK_INFO_DATA_XFRM,
         _NL_UNION_LINK_INFO_DATA_MAX,
         _NL_UNION_LINK_INFO_DATA_INVALID = -1
 } NLUnionLinkInfoData;
index 14951c544c23accbaad90cd61a2e8e6eedecd23b..32317c7c9f8b5ba367188141a75d7efc2dedf92d 100644 (file)
@@ -43,6 +43,8 @@ sources = files('''
         netdev/l2tp-tunnel.h
         netdev/macsec.c
         netdev/macsec.h
+        netdev/xfrm.c
+        netdev/xfrm.h
         networkd-address-label.c
         networkd-address-label.h
         networkd-address-pool.c
index 0cf6949968b759c7dace9f964c6a73df5c93b414..33f7b3058d5ed8dcfb3df660db17499eb8c2c657 100644 (file)
@@ -22,6 +22,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
 #include "netdev/wireguard.h"
 #include "netdev/fou-tunnel.h"
 #include "netdev/l2tp-tunnel.h"
+#include "netdev/xfrm.h"
 #include "vlan-util.h"
 %}
 struct ConfigPerfItem;
@@ -218,3 +219,5 @@ WireGuardPeer.PublicKey,                  config_parse_wireguard_public_key,
 WireGuardPeer.PresharedKey,               config_parse_wireguard_preshared_key,      0,                             0
 WireGuardPeer.PresharedKeyFile,           config_parse_wireguard_preshared_key_file, 0,                             0
 WireGuardPeer.PersistentKeepalive,        config_parse_wireguard_keepalive,          0,                             0
+Xfrm.InterfaceId,                         config_parse_uint32,                       0,                             offsetof(Xfrm, if_id)
+Xfrm.Independent,                         config_parse_bool,                         0,                             offsetof(Xfrm, independent)
index 542923760355d4cf7764c52f89395b7161cc302b..7735b455b79d57e1462a22535aae51e2308bb865 100644 (file)
@@ -29,6 +29,7 @@
 #include "netdev/vxcan.h"
 #include "netdev/vxlan.h"
 #include "netdev/wireguard.h"
+#include "netdev/xfrm.h"
 #include "netlink-util.h"
 #include "network-internal.h"
 #include "networkd-link.h"
@@ -72,6 +73,7 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_L2TP] = &l2tptnl_vtable,
         [NETDEV_KIND_MACSEC] = &macsec_vtable,
         [NETDEV_KIND_NLMON] = &nlmon_vtable,
+        [NETDEV_KIND_XFRM] = &xfrm_vtable,
 };
 
 static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
@@ -107,6 +109,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_L2TP] = "l2tp",
         [NETDEV_KIND_MACSEC] = "macsec",
         [NETDEV_KIND_NLMON] = "nlmon",
+        [NETDEV_KIND_XFRM] = "xfrm",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
@@ -807,6 +810,9 @@ int netdev_load_one(Manager *manager, const char *filename) {
         case NETDEV_KIND_ERSPAN:
                 independent = ERSPAN(netdev)->independent;
                 break;
+        case NETDEV_KIND_XFRM:
+                independent = XFRM(netdev)->independent;
+                break;
         default:
                 break;
         }
index 57fabbef40ddfc36bfb63a991a3c90294a6a560a..d63b1912d86f4ce295409c53ed1c443447c4c334 100644 (file)
@@ -50,6 +50,7 @@ typedef enum NetDevKind {
         NETDEV_KIND_L2TP,
         NETDEV_KIND_MACSEC,
         NETDEV_KIND_NLMON,
+        NETDEV_KIND_XFRM,
         _NETDEV_KIND_MAX,
         _NETDEV_KIND_TUNNEL, /* Used by config_parse_stacked_netdev() */
         _NETDEV_KIND_INVALID = -1
diff --git a/src/network/netdev/xfrm.c b/src/network/netdev/xfrm.c
new file mode 100644 (file)
index 0000000..c60b0b1
--- /dev/null
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "missing_network.h"
+#include "netdev/xfrm.h"
+
+static int xfrm_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *message) {
+        int if_idx, r;
+        Xfrm *x;
+
+        assert(netdev);
+        assert(message);
+
+        x = XFRM(netdev);
+
+        if (x->independent)
+                if_idx = LOOPBACK_IFINDEX;
+        else {
+                assert(link);
+                if (link->ifindex == 0)
+                        return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(ENODEV), "Could not get interface index: %m");
+                if_idx = link->ifindex;
+        }
+
+        r = sd_netlink_message_append_u32(message, IFLA_XFRM_LINK, if_idx);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_XFRM_LINK: %m");
+
+        r = sd_netlink_message_append_u32(message, IFLA_XFRM_IF_ID, x->if_id);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_XFRM_IF_ID: %m");
+
+        return 0;
+}
+
+const NetDevVTable xfrm_vtable = {
+        .object_size = sizeof(Xfrm),
+        .sections = "Match\0NetDev\0Xfrm\0",
+        .fill_message_create = xfrm_fill_message_create,
+        .create_type = NETDEV_CREATE_STACKED
+};
diff --git a/src/network/netdev/xfrm.h b/src/network/netdev/xfrm.h
new file mode 100644 (file)
index 0000000..47355a5
--- /dev/null
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "netdev/netdev.h"
+
+typedef struct Xfrm {
+        NetDev meta;
+
+        uint32_t if_id;
+        bool independent;
+} Xfrm;
+
+DEFINE_NETDEV_CAST(XFRM, Xfrm);
+extern const NetDevVTable xfrm_vtable;
index 5f91d66dc09236933e9f1ce84b98d3725b138439..e92ffda721c0f22ce397f69a5740c4c8b0791d1a 100644 (file)
@@ -158,7 +158,9 @@ bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask) {
         if (!link->network)
                 return false;
 
-        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "ip6gre", "ip6tnl", "sit", "vti", "vti6", "can", "vcan", "vxcan", "nlmon"))
+        if (STRPTR_IN_SET(link->kind,
+                          "vrf", "wireguard", "ipip", "gre", "ip6gre","ip6tnl", "sit", "vti",
+                          "vti6", "can", "vcan", "vxcan", "nlmon", "xfrm"))
                 return false;
 
         /* L3 or L3S mode do not support ARP. */
index e6723f2e90b44ca6207d0d31aecde0cfc670941e..5a2f3f4ea9f640520e5b2de00143069908c656dc 100644 (file)
@@ -55,6 +55,7 @@ Network.VXLAN,                          config_parse_stacked_netdev,
 Network.L2TP,                           config_parse_stacked_netdev,                     NETDEV_KIND_L2TP,              offsetof(Network, stacked_netdev_names)
 Network.MACsec,                         config_parse_stacked_netdev,                     NETDEV_KIND_MACSEC,            offsetof(Network, stacked_netdev_names)
 Network.Tunnel,                         config_parse_stacked_netdev,                     _NETDEV_KIND_TUNNEL,           offsetof(Network, stacked_netdev_names)
+Network.Xfrm,                           config_parse_stacked_netdev,                     NETDEV_KIND_XFRM,              offsetof(Network, stacked_netdev_names)
 Network.VRF,                            config_parse_ifname,                             0,                             offsetof(Network, vrf_name)
 Network.DHCP,                           config_parse_dhcp,                               0,                             offsetof(Network, dhcp)
 Network.DHCPServer,                     config_parse_bool,                               0,                             offsetof(Network, dhcp_server)
index 0b5205e8e28b28eeffe46bfe892d7964af7eef84..3f1753049ceadabb18014edc52bdd89fa67cb453 100644 (file)
@@ -693,7 +693,8 @@ int config_parse_stacked_netdev(const char *unit,
         assert(IN_SET(kind,
                       NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
                       NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN,
-                      NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL));
+                      NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL,
+                      NETDEV_KIND_XFRM));
 
         if (!ifname_valid(rvalue)) {
                 log_syntax(unit, LOG_ERR, filename, line, 0,
index 72f1b946662067b4a6c181f9e7cbe5840680b910..a16ec7413132332601bd9ae340fded3a5d226b21 100644 (file)
@@ -69,6 +69,7 @@ struct Network {
         NetDev *bridge;
         NetDev *bond;
         NetDev *vrf;
+        NetDev *xfrm;
         Hashmap *stacked_netdevs;
         char *bridge_name;
         char *bond_name;
diff --git a/test/fuzz/fuzz-netdev-parser/27-xfrm.netdev b/test/fuzz/fuzz-netdev-parser/27-xfrm.netdev
new file mode 100644 (file)
index 0000000..cdcb2d2
--- /dev/null
@@ -0,0 +1,7 @@
+[NetDev]
+Name=xfrm99
+Kind=xfrm
+
+[Xfrm]
+InterfaceId=7
+Independent=false
index be1b197024b5d46b70dfb7fd19c0e6858077c32a..07e54d9e44f5d0c201c47407ccc981aad4a4d7af 100644 (file)
@@ -207,3 +207,6 @@ KeyId=
 Key=
 KeyFile=
 Activate=
+[Xfrm]
+Independent=
+InterfaceId=
diff --git a/test/fuzz/fuzz-network-parser/27-xfrm.network b/test/fuzz/fuzz-network-parser/27-xfrm.network
new file mode 100644 (file)
index 0000000..fa26c84
--- /dev/null
@@ -0,0 +1,5 @@
+[Match]
+Name=eth0
+
+[Network]
+Xfrm=xfrm99
index 26dd83d8dad15ee7fc20c7030b20e6846764f504..ddafaa7840cc528b417017276b80f4cb596d66a0 100644 (file)
@@ -121,6 +121,7 @@ DNSSEC=
 IPv6HopLimit=
 IPForward=
 IPv6Token=
+Xfrm=
 Description=
 VXLAN=
 L2TP=