From 20897a0d6ea12bbc08f70146cc7ad4540b65a0fa Mon Sep 17 00:00:00 2001 From: Andreas Rammhold Date: Fri, 10 Jun 2016 01:57:51 +0200 Subject: networkd: added support for vrf interfaces (#3316) --- Makefile.am | 2 ++ configure.ac | 1 + man/systemd.netdev.xml | 13 ++++++++ src/basic/missing.h | 4 +++ src/libsystemd/sd-netlink/netlink-types.c | 8 +++++ src/libsystemd/sd-netlink/netlink-types.h | 1 + src/network/networkd-netdev-gperf.gperf | 2 ++ src/network/networkd-netdev-vrf.c | 50 +++++++++++++++++++++++++++++++ src/network/networkd-netdev-vrf.h | 33 ++++++++++++++++++++ src/network/networkd-netdev.c | 4 +++ src/network/networkd-netdev.h | 1 + src/network/networkd.h | 1 + 12 files changed, 120 insertions(+) create mode 100644 src/network/networkd-netdev-vrf.c create mode 100644 src/network/networkd-netdev-vrf.h 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 ffc6eedcdd..f4fcc4f113 100644 --- a/configure.ac +++ b/configure.ac @@ -325,6 +325,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 @@ vxlan A virtual extensible LAN (vxlan), for connecting Cloud computing deployments. + + vrf + A Virtual Routing and Forwarding (VRF) interface to create seperate routing and forwarding domains. + @@ -1137,7 +1141,16 @@ Name=dummy-test Kind=dummy MACAddress=12:34:56:78:9a:bc + + /etc/systemd/network/25-vrf.netdev + Create an VRF interface with table 42. + [NetDev] +Name=vrf-test +Kind=vrf +[VRF] +TableId=42 + See Also 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-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..8bbb0aecb1 --- /dev/null +++ b/src/network/networkd-netdev-vrf.c @@ -0,0 +1,50 @@ +/*** + This file is part of systemd. + + Copyright 2016 Andreas Rammhold + + 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 . +***/ + +#include + +#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 = "Match\0NetDev\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 + + 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 . +***/ + +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..b55d76a53c 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); 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.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" -- cgit v1.2.3-54-g00ecf From 6cb955c6a18d7e122ca24ca4873343ca41feeb50 Mon Sep 17 00:00:00 2001 From: Andreas Rammhold Date: Mon, 13 Jun 2016 01:05:49 +0200 Subject: networkd: vrf: add support for enslaving devices to VRFs --- man/systemd.network.xml | 17 +++++++++++++++++ src/network/networkd-link.c | 23 ++++++++++++++++++++++- src/network/networkd-netdev-vrf.c | 2 +- src/network/networkd-netdev.c | 4 ++-- src/network/networkd-network-gperf.gperf | 1 + src/network/networkd-network.c | 6 +++++- src/network/networkd-network.h | 1 + 7 files changed, 49 insertions(+), 5 deletions(-) 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 @@ -578,6 +578,12 @@ The name of the bond to add the link to. + + VRF= + + The name of the VRF to add the link to. + + VLAN= @@ -1276,6 +1282,17 @@ Name=bond1 [Network] DHCP=yes + + + + + /etc/systemd/network/25-vrf.network + 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. + [Match] +Name=bond1 + +[Network] +VRF=vrf-test 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-vrf.c b/src/network/networkd-netdev-vrf.c index 8bbb0aecb1..89bd142e8c 100644 --- a/src/network/networkd-netdev-vrf.c +++ b/src/network/networkd-netdev-vrf.c @@ -44,7 +44,7 @@ static int netdev_vrf_fill_message_create(NetDev *netdev, Link *link, sd_netlink const NetDevVTable vrf_vtable = { .object_size = sizeof(Vrf), - .sections = "Match\0NetDev\0VRF\0", + .sections = "NetDev\0VRF\0", .fill_message_create = netdev_vrf_fill_message_create, .create_type = NETDEV_CREATE_MASTER, }; diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index b55d76a53c..b192884fd9 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -202,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); @@ -285,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-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); @@ -470,6 +470,10 @@ int config_parse_netdev(const char *unit, case NETDEV_KIND_BOND: network->bond = netdev; + break; + case NETDEV_KIND_VRF: + network->vrf = netdev; + break; case NETDEV_KIND_VLAN: case NETDEV_KIND_MACVLAN: 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 */ -- cgit v1.2.3-54-g00ecf