summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/systemd.netdev.xml43
-rw-r--r--man/systemd.network.xml31
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.c8
-rw-r--r--src/libsystemd/sd-netlink/netlink-types.h1
-rw-r--r--src/network/meson.build2
-rw-r--r--src/network/netdev/netdev-gperf.gperf3
-rw-r--r--src/network/netdev/netdev.c6
-rw-r--r--src/network/netdev/netdev.h1
-rw-r--r--src/network/netdev/xfrm.c40
-rw-r--r--src/network/netdev/xfrm.h14
-rw-r--r--src/network/networkd-link.c7
-rw-r--r--src/network/networkd-network-gperf.gperf1
-rw-r--r--src/network/networkd-network.c3
-rw-r--r--src/network/networkd-network.h1
-rw-r--r--test/fuzz/fuzz-netdev-parser/27-xfrm.netdev7
-rw-r--r--test/fuzz/fuzz-netdev-parser/directives.netdev3
-rw-r--r--test/fuzz/fuzz-network-parser/27-xfrm.network5
-rw-r--r--test/fuzz/fuzz-network-parser/directives.network1
18 files changed, 172 insertions, 5 deletions
diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index d083fb9a6f..3cce776cc2 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -179,6 +179,9 @@
<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>
@@ -1849,6 +1852,36 @@
</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
netdevs of kind <literal>vrf</literal> and accepts the
@@ -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>
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index d32b60a2c9..c48b294551 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -857,6 +857,14 @@
</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>
<para>Takes a boolean or one of <literal>static</literal>, <literal>dhcp-on-stop</literal>,
@@ -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>
diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c
index 6850773977..450e298f2c 100644
--- a/src/libsystemd/sd-netlink/netlink-types.c
+++ b/src/libsystemd/sd-netlink/netlink-types.c
@@ -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 = {
diff --git a/src/libsystemd/sd-netlink/netlink-types.h b/src/libsystemd/sd-netlink/netlink-types.h
index fed43ae43c..efc59a0a4b 100644
--- a/src/libsystemd/sd-netlink/netlink-types.h
+++ b/src/libsystemd/sd-netlink/netlink-types.h
@@ -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;
diff --git a/src/network/meson.build b/src/network/meson.build
index 14951c544c..32317c7c9f 100644
--- a/src/network/meson.build
+++ b/src/network/meson.build
@@ -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
diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf
index 0cf6949968..33f7b3058d 100644
--- a/src/network/netdev/netdev-gperf.gperf
+++ b/src/network/netdev/netdev-gperf.gperf
@@ -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)
diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c
index 5429237603..7735b455b7 100644
--- a/src/network/netdev/netdev.c
+++ b/src/network/netdev/netdev.c
@@ -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;
}
diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h
index 57fabbef40..d63b1912d8 100644
--- a/src/network/netdev/netdev.h
+++ b/src/network/netdev/netdev.h
@@ -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
index 0000000000..c60b0b1ab7
--- /dev/null
+++ b/src/network/netdev/xfrm.c
@@ -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
index 0000000000..47355a53d8
--- /dev/null
+++ b/src/network/netdev/xfrm.h
@@ -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;
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 5f91d66dc0..a48b850e99 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -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. */
@@ -168,9 +170,6 @@ bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask) {
if (link->network->bond)
return false;
- if (link->network->bond)
- return false;
-
return link->network->link_local & mask;
}
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index e6723f2e90..5a2f3f4ea9 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -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)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 0b5205e8e2..3f1753049c 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -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,
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 72f1b94666..a16ec74131 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -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
index 0000000000..cdcb2d22cd
--- /dev/null
+++ b/test/fuzz/fuzz-netdev-parser/27-xfrm.netdev
@@ -0,0 +1,7 @@
+[NetDev]
+Name=xfrm99
+Kind=xfrm
+
+[Xfrm]
+InterfaceId=7
+Independent=false
diff --git a/test/fuzz/fuzz-netdev-parser/directives.netdev b/test/fuzz/fuzz-netdev-parser/directives.netdev
index be1b197024..07e54d9e44 100644
--- a/test/fuzz/fuzz-netdev-parser/directives.netdev
+++ b/test/fuzz/fuzz-netdev-parser/directives.netdev
@@ -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
index 0000000000..fa26c84e53
--- /dev/null
+++ b/test/fuzz/fuzz-network-parser/27-xfrm.network
@@ -0,0 +1,5 @@
+[Match]
+Name=eth0
+
+[Network]
+Xfrm=xfrm99
diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network
index 26dd83d8da..ddafaa7840 100644
--- a/test/fuzz/fuzz-network-parser/directives.network
+++ b/test/fuzz/fuzz-network-parser/directives.network
@@ -121,6 +121,7 @@ DNSSEC=
IPv6HopLimit=
IPForward=
IPv6Token=
+Xfrm=
Description=
VXLAN=
L2TP=