summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac1
-rw-r--r--man/systemd.netdev.xml13
-rw-r--r--man/systemd.network.xml17
-rw-r--r--src/basic/missing.h4
-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/networkd-link.c23
-rw-r--r--src/network/networkd-netdev-gperf.gperf2
-rw-r--r--src/network/networkd-netdev-vrf.c50
-rw-r--r--src/network/networkd-netdev-vrf.h33
-rw-r--r--src/network/networkd-netdev.c8
-rw-r--r--src/network/networkd-netdev.h1
-rw-r--r--src/network/networkd-network-gperf.gperf1
-rw-r--r--src/network/networkd-network.c6
-rw-r--r--src/network/networkd-network.h1
-rw-r--r--src/network/networkd.h1
17 files changed, 168 insertions, 4 deletions
diff --git a/Makefile.am b/Makefile.am
index 8960513ffe..50e01af667 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5462,6 +5462,8 @@ libnetworkd_core_la_SOURCES = \
src/network/networkd-link.c \
src/network/networkd-netdev.h \
src/network/networkd-netdev.c \
+ src/network/networkd-netdev-vrf.h \
+ src/network/networkd-netdev-vrf.c \
src/network/networkd-netdev-tunnel.h \
src/network/networkd-netdev-tunnel.c \
src/network/networkd-netdev-veth.h \
diff --git a/configure.ac b/configure.ac
index 7fd78bfb60..072b17f01a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -326,6 +326,7 @@ AC_CHECK_TYPES([char16_t, char32_t, key_serial_t],
AC_CHECK_DECLS([IFLA_INET6_ADDR_GEN_MODE,
IN6_ADDR_GEN_MODE_STABLE_PRIVACY,
+ IFLA_VRF_TABLE,
IFLA_MACVLAN_FLAGS,
IFLA_IPVLAN_MODE,
IFLA_VTI_REMOTE,
diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index 3cc58ca854..2be1efee2f 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -161,6 +161,10 @@
<row><entry><varname>vxlan</varname></entry>
<entry>A virtual extensible LAN (vxlan), for connecting Cloud computing deployments.</entry></row>
+
+ <row><entry><varname>vrf</varname></entry>
+ <entry>A Virtual Routing and Forwarding (<ulink url="https://www.kernel.org/doc/Documentation/networking/vrf.txt">VRF</ulink>) interface to create seperate routing and forwarding domains.</entry></row>
+
</tbody>
</tgroup>
</table>
@@ -1137,7 +1141,16 @@ Name=dummy-test
Kind=dummy
MACAddress=12:34:56:78:9a:bc</programlisting>
</example>
+ <example>
+ <title>/etc/systemd/network/25-vrf.netdev</title>
+ <para>Create an VRF interface with table 42.</para>
+ <programlisting>[NetDev]
+Name=vrf-test
+Kind=vrf
+[VRF]
+TableId=42</programlisting>
+ </example>
</refsect1>
<refsect1>
<title>See Also</title>
diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index ea98c821fa..edf227c134 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -579,6 +579,12 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term><varname>VRF=</varname></term>
+ <listitem>
+ <para>The name of the VRF to add the link to.</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><varname>VLAN=</varname></term>
<listitem>
<para>The name of a VLAN to create on the link. This
@@ -1279,6 +1285,17 @@ DHCP=yes
</programlisting>
</example>
+ <example>
+ <title>/etc/systemd/network/25-vrf.network</title>
+ <para>Add the bond1 interface to the VRF master interface vrf-test. This will redirect routes generated on this interface to be within the routing table defined during VRF creation. Traffic won't be redirected towards the VRFs routing table unless specific ip-rules are added.</para>
+ <programlisting>[Match]
+Name=bond1
+
+[Network]
+VRF=vrf-test
+</programlisting>
+ </example>
+
</refsect1>
<refsect1>
diff --git a/src/basic/missing.h b/src/basic/missing.h
index 53dfa1c801..b1272f8799 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -837,6 +837,10 @@ struct btrfs_ioctl_quota_ctl_args {
#define IFLA_BRPORT_PROXYARP 10
#endif
+#if !HAVE_DECL_IFLA_VRF_TABLE
+#define IFLA_VRF_TABLE 1
+#endif
+
#if !HAVE_DECL_NDA_IFINDEX
#define NDA_UNSPEC 0
#define NDA_DST 1
diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c
index 3a4bac2ced..566a050432 100644
--- a/src/libsystemd/sd-netlink/netlink-types.c
+++ b/src/libsystemd/sd-netlink/netlink-types.c
@@ -278,6 +278,10 @@ static const NLType rtnl_link_info_data_ip6tnl_types[] = {
[IFLA_IPTUN_FLOWINFO] = { .type = NETLINK_TYPE_U32 },
};
+static const NLType rtnl_link_info_data_vrf_types[] = {
+ [IFLA_VRF_TABLE] = { .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",
@@ -298,6 +302,7 @@ static const char* const nl_union_link_info_data_table[] = {
[NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = "vti",
[NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = "vti6",
[NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = "ip6tnl",
+ [NL_UNION_LINK_INFO_DATA_VRF] = "vrf",
};
DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
@@ -338,6 +343,9 @@ static const NLTypeSystem rtnl_link_info_data_type_systems[] = {
[NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types),
.types = rtnl_link_info_data_ip6tnl_types },
+ [NL_UNION_LINK_INFO_DATA_VRF] = { .count = ELEMENTSOF(rtnl_link_info_data_vrf_types),
+ .types = rtnl_link_info_data_vrf_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 ecb20bfcdc..7c0e598b26 100644
--- a/src/libsystemd/sd-netlink/netlink-types.h
+++ b/src/libsystemd/sd-netlink/netlink-types.h
@@ -86,6 +86,7 @@ typedef enum NLUnionLinkInfoData {
NL_UNION_LINK_INFO_DATA_VTI_TUNNEL,
NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL,
NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL,
+ NL_UNION_LINK_INFO_DATA_VRF,
_NL_UNION_LINK_INFO_DATA_MAX,
_NL_UNION_LINK_INFO_DATA_INVALID = -1
} NLUnionLinkInfoData;
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 044f934e5f..1842685180 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1600,7 +1600,7 @@ static int link_up(Link *link) {
return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
/* set it free if not enslaved with networkd */
- if (!link->network->bridge && !link->network->bond) {
+ if (!link->network->bridge && !link->network->bond && !link->network->vrf) {
r = sd_netlink_message_append_u32(req, IFLA_MASTER, 0);
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_MASTER attribute: %m");
@@ -2055,6 +2055,7 @@ static int link_enter_join_netdev(Link *link) {
if (!link->network->bridge &&
!link->network->bond &&
+ !link->network->vrf &&
hashmap_isempty(link->network->stacked_netdevs))
return link_joined(link);
@@ -2101,6 +2102,26 @@ static int link_enter_join_netdev(Link *link) {
link->enslaving++;
}
+ if (link->network->vrf) {
+ log_struct(LOG_DEBUG,
+ LOG_LINK_INTERFACE(link),
+ LOG_NETDEV_INTERFACE(link->network->vrf),
+ LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->vrf->ifname),
+ NULL);
+ r = netdev_join(link->network->vrf, link, netdev_join_handler);
+ if (r < 0) {
+ log_struct_errno(LOG_WARNING, r,
+ LOG_LINK_INTERFACE(link),
+ LOG_NETDEV_INTERFACE(link->network->vrf),
+ LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->vrf->ifname),
+ NULL);
+ link_enter_failed(link);
+ return r;
+ }
+
+ link->enslaving++;
+ }
+
HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
log_struct(LOG_DEBUG,
diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf
index bf93b0d9fa..9d69f61376 100644
--- a/src/network/networkd-netdev-gperf.gperf
+++ b/src/network/networkd-netdev-gperf.gperf
@@ -11,6 +11,7 @@
#include "networkd-netdev-veth.h"
#include "networkd-netdev-vlan.h"
#include "networkd-netdev-vxlan.h"
+#include "networkd-netdev-vrf.h"
#include "networkd-netdev.h"
#include "vlan-util.h"
%}
@@ -105,3 +106,4 @@ Bridge.ForwardDelaySec, config_parse_sec, 0,
Bridge.MulticastQuerier, config_parse_tristate, 0, offsetof(Bridge, mcast_querier)
Bridge.MulticastSnooping, config_parse_tristate, 0, offsetof(Bridge, mcast_snooping)
Bridge.VLANFiltering, config_parse_tristate, 0, offsetof(Bridge, vlan_filtering)
+VRF.TableId, config_parse_uint32, 0, offsetof(Vrf, table_id)
diff --git a/src/network/networkd-netdev-vrf.c b/src/network/networkd-netdev-vrf.c
new file mode 100644
index 0000000000..89bd142e8c
--- /dev/null
+++ b/src/network/networkd-netdev-vrf.c
@@ -0,0 +1,50 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2016 Andreas Rammhold <andreas@rammhold.de>
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <net/if.h>
+
+#include "sd-netlink.h"
+#include "missing.h"
+#include "networkd-netdev-vrf.h"
+
+static int netdev_vrf_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
+ Vrf *v;
+ int r;
+
+ assert(netdev);
+ assert(!link);
+ assert(m);
+
+ v = VRF(netdev);
+
+ assert(v);
+
+ r = sd_netlink_message_append_u32(m, IFLA_VRF_TABLE, v->table_id);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IPLA_VRF_TABLE attribute: %m");
+
+ return r;
+}
+
+const NetDevVTable vrf_vtable = {
+ .object_size = sizeof(Vrf),
+ .sections = "NetDev\0VRF\0",
+ .fill_message_create = netdev_vrf_fill_message_create,
+ .create_type = NETDEV_CREATE_MASTER,
+};
diff --git a/src/network/networkd-netdev-vrf.h b/src/network/networkd-netdev-vrf.h
new file mode 100644
index 0000000000..3d92a26a4d
--- /dev/null
+++ b/src/network/networkd-netdev-vrf.h
@@ -0,0 +1,33 @@
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2016 Andreas Rammhold <andreas@rammhold.de>
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+typedef struct Vrf Vrf;
+
+#include "networkd-netdev.h"
+
+struct Vrf {
+ NetDev meta;
+
+ uint32_t table_id;
+};
+
+DEFINE_NETDEV_CAST(VRF, Vrf);
+extern const NetDevVTable vrf_vtable;
diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index 851a36290c..b192884fd9 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -55,6 +55,8 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_TUN] = &tun_vtable,
[NETDEV_KIND_TAP] = &tap_vtable,
[NETDEV_KIND_IP6TNL] = &ip6tnl_vtable,
+ [NETDEV_KIND_VRF] = &vrf_vtable,
+
};
static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
@@ -78,6 +80,8 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_TUN] = "tun",
[NETDEV_KIND_TAP] = "tap",
[NETDEV_KIND_IP6TNL] = "ip6tnl",
+ [NETDEV_KIND_VRF] = "vrf",
+
};
DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
@@ -198,7 +202,7 @@ static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_netlink_message_h
assert(netdev->state == NETDEV_STATE_READY);
assert(netdev->manager);
assert(netdev->manager->rtnl);
- assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND));
+ assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF));
assert(link);
assert(callback);
@@ -281,7 +285,7 @@ int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t call
assert(netdev);
assert(netdev->manager);
assert(netdev->manager->rtnl);
- assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND));
+ assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF));
if (netdev->state == NETDEV_STATE_READY) {
r = netdev_enslave_ready(netdev, link, callback);
diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h
index 20244c0309..b92a973b85 100644
--- a/src/network/networkd-netdev.h
+++ b/src/network/networkd-netdev.h
@@ -55,6 +55,7 @@ typedef enum NetDevKind {
NETDEV_KIND_DUMMY,
NETDEV_KIND_TUN,
NETDEV_KIND_TAP,
+ NETDEV_KIND_VRF,
_NETDEV_KIND_MAX,
_NETDEV_KIND_INVALID = -1
} NetDevKind;
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 0b0aa58f67..affc0d00e9 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -37,6 +37,7 @@ Network.MACVTAP, config_parse_netdev,
Network.IPVLAN, config_parse_netdev, 0, 0
Network.VXLAN, config_parse_netdev, 0, 0
Network.Tunnel, config_parse_tunnel, 0, 0
+Network.VRF, config_parse_netdev, 0, 0
Network.DHCP, config_parse_dhcp, 0, offsetof(Network, dhcp)
Network.DHCPServer, config_parse_bool, 0, offsetof(Network, dhcp_server)
Network.LinkLocalAddressing, config_parse_address_family_boolean, 0, offsetof(Network, link_local)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 84bdf75b38..2b764d4f24 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -244,8 +244,8 @@ void network_free(Network *network) {
strv_free(network->bind_carrier);
netdev_unref(network->bridge);
-
netdev_unref(network->bond);
+ netdev_unref(network->vrf);
HASHMAP_FOREACH(netdev, network->stacked_netdevs, i) {
hashmap_remove(network->stacked_netdevs, netdev->ifname);
@@ -471,6 +471,10 @@ int config_parse_netdev(const char *unit,
network->bond = netdev;
break;
+ case NETDEV_KIND_VRF:
+ network->vrf = netdev;
+
+ break;
case NETDEV_KIND_VLAN:
case NETDEV_KIND_MACVLAN:
case NETDEV_KIND_MACVTAP:
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 38688cc400..08ee939faa 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -104,6 +104,7 @@ struct Network {
NetDev *bridge;
NetDev *bond;
+ NetDev *vrf;
Hashmap *stacked_netdevs;
/* DHCP Client Support */
diff --git a/src/network/networkd.h b/src/network/networkd.h
index ab512f0d08..c4bd712147 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -41,6 +41,7 @@
#include "networkd-netdev-tuntap.h"
#include "networkd-netdev-veth.h"
#include "networkd-netdev-vlan.h"
+#include "networkd-netdev-vrf.h"
#include "networkd-netdev-vxlan.h"
#include "networkd-network.h"
#include "networkd-util.h"