diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml index 32048054bc..c92792341b 100644 --- a/man/systemd.netdev.xml +++ b/man/systemd.netdev.xml @@ -180,6 +180,10 @@ vcan The virtual CAN driver (vcan). Similar to the network loopback devices, vcan offers a virtual local CAN interface. + vxcan + The virtual CAN tunnel driver (vxcan). Similar to the virtual ethernet driver veth, vxcan implements a local CAN traffic tunnel between two virtual CAN network devices. When creating a vxcan, two vxcan devices are created as pair. When one end receives the packet it appears on its pair and vice versa. The vxcan can be used for cross namespace communication. + + @@ -894,6 +898,22 @@ + + [VXCAN] Section Options + The [VXCAN] section only applies for + netdevs of kind vxcan and accepts the + following key: + + + + Peer= + + The peer interface name used when creating the netdev. + This option is compulsory. + + + + [Tun] Section Options diff --git a/meson.build b/meson.build index 6f3f319385..7e997b195a 100644 --- a/meson.build +++ b/meson.build @@ -427,6 +427,7 @@ foreach decl : [['IFLA_INET6_ADDR_GEN_MODE', 'linux/if_link.h'], ['IFA_FLAGS', 'linux/if_addr.h'], ['FRA_UID_RANGE', 'linux/fib_rules.h'], ['LO_FLAGS_PARTSCAN', 'linux/loop.h'], + ['VXCAN_INFO_PEER', 'linux/can/vxcan.h'], ] prefix = decl.length() > 2 ? decl[2] : '' have = cc.has_header_symbol(decl[1], decl[0], prefix : prefix) diff --git a/src/basic/missing.h b/src/basic/missing.h index 3936091ccc..52c7ce57a0 100644 --- a/src/basic/missing.h +++ b/src/basic/missing.h @@ -956,6 +956,10 @@ struct input_mask { #define IFLA_VRF_TABLE 1 #endif +#if !HAVE_VXCAN_INFO_PEER +#define VXCAN_INFO_PEER 1 +#endif + #if !HAVE_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 9e454702d5..f8be296d37 100644 --- a/src/libsystemd/sd-netlink/netlink-types.c +++ b/src/libsystemd/sd-netlink/netlink-types.c @@ -37,6 +37,10 @@ #include #include +#if HAVE_VXCAN_INFO_PEER +#include +#endif + #include "macro.h" #include "missing.h" #include "netlink-types.h" @@ -92,6 +96,10 @@ static const NLType rtnl_link_info_data_veth_types[] = { [VETH_INFO_PEER] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, }; +static const NLType rtnl_link_info_data_vxcan_types[] = { + [VXCAN_INFO_PEER] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) }, +}; + static const NLType rtnl_link_info_data_ipvlan_types[] = { [IFLA_IPVLAN_MODE] = { .type = NETLINK_TYPE_U16 }, }; @@ -328,6 +336,8 @@ static const char* const nl_union_link_info_data_table[] = { [NL_UNION_LINK_INFO_DATA_VRF] = "vrf", [NL_UNION_LINK_INFO_DATA_VCAN] = "vcan", [NL_UNION_LINK_INFO_DATA_GENEVE] = "geneve", + [NL_UNION_LINK_INFO_DATA_VXCAN] = "vxcan", + }; DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData); @@ -371,6 +381,8 @@ static const NLTypeSystem rtnl_link_info_data_type_systems[] = { .types = rtnl_link_info_data_vrf_types }, [NL_UNION_LINK_INFO_DATA_GENEVE] = { .count = ELEMENTSOF(rtnl_link_info_data_geneve_types), .types = rtnl_link_info_data_geneve_types }, + [NL_UNION_LINK_INFO_DATA_VXCAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vxcan_types), + .types = rtnl_link_info_data_vxcan_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 ee20edac6f..57b46339f9 100644 --- a/src/libsystemd/sd-netlink/netlink-types.h +++ b/src/libsystemd/sd-netlink/netlink-types.h @@ -90,6 +90,7 @@ typedef enum NLUnionLinkInfoData { NL_UNION_LINK_INFO_DATA_VRF, NL_UNION_LINK_INFO_DATA_VCAN, NL_UNION_LINK_INFO_DATA_GENEVE, + NL_UNION_LINK_INFO_DATA_VXCAN, _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 cc4cbdd996..ed68faca0c 100644 --- a/src/network/meson.build +++ b/src/network/meson.build @@ -44,6 +44,8 @@ sources = files(''' netdev/vxlan.h netdev/geneve.c netdev/geneve.h + netdev/vxcan.c + netdev/vxcan.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 89f600ef62..628e6648b7 100644 --- a/src/network/netdev/netdev-gperf.gperf +++ b/src/network/netdev/netdev-gperf.gperf @@ -17,6 +17,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") #include "netdev/vxlan.h" #include "netdev/vrf.h" #include "netdev/netdev.h" +#include "netdev/vxcan.h" #include "vlan-util.h" %} struct ConfigPerfItem; @@ -62,6 +63,7 @@ Tunnel.EncapsulationLimit, config_parse_encap_limit, 0, Tunnel.Independent, config_parse_bool, 0, offsetof(Tunnel, independent) 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) VXLAN.Id, config_parse_uint64, 0, offsetof(VxLan, id) VXLAN.Group, config_parse_vxlan_address, 0, offsetof(VxLan, remote) VXLAN.Local, config_parse_vxlan_address, 0, offsetof(VxLan, local) diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index f148bb43c3..5530760e19 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -48,6 +48,7 @@ #include "netdev/dummy.h" #include "netdev/vrf.h" #include "netdev/vcan.h" +#include "netdev/vxcan.h" const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = { [NETDEV_KIND_BRIDGE] = &bridge_vtable, @@ -73,6 +74,7 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = { [NETDEV_KIND_VRF] = &vrf_vtable, [NETDEV_KIND_VCAN] = &vcan_vtable, [NETDEV_KIND_GENEVE] = &geneve_vtable, + [NETDEV_KIND_VXCAN] = &vxcan_vtable, }; static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = { @@ -99,6 +101,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = { [NETDEV_KIND_VRF] = "vrf", [NETDEV_KIND_VCAN] = "vcan", [NETDEV_KIND_GENEVE] = "geneve", + [NETDEV_KIND_VXCAN] = "vxcan", }; DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind); diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h index 4605308ac4..ec65251464 100644 --- a/src/network/netdev/netdev.h +++ b/src/network/netdev/netdev.h @@ -59,6 +59,7 @@ typedef enum NetDevKind { NETDEV_KIND_VRF, NETDEV_KIND_VCAN, NETDEV_KIND_GENEVE, + NETDEV_KIND_VXCAN, _NETDEV_KIND_MAX, _NETDEV_KIND_INVALID = -1 } NetDevKind; diff --git a/src/network/netdev/vxcan.c b/src/network/netdev/vxcan.c new file mode 100644 index 0000000000..a41ca7e256 --- /dev/null +++ b/src/network/netdev/vxcan.c @@ -0,0 +1,89 @@ +/*** + This file is part of systemd. + + Copyright 2017 Susant Sahani + + 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 "netdev/vxcan.h" +#include "missing.h" + +static int netdev_vxcan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { + VxCan *v; + int r; + + assert(netdev); + assert(!link); + assert(m); + + v = VXCAN(netdev); + + assert(v); + + r = sd_netlink_message_open_container(m, VXCAN_INFO_PEER); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append VXCAN_INFO_PEER attribute: %m"); + + if (v->ifname_peer) { + r = sd_netlink_message_append_string(m, IFLA_IFNAME, v->ifname_peer); + if (r < 0) + return log_error_errno(r, "Failed to add vxcan netlink interface peer name: %m"); + } + + r = sd_netlink_message_close_container(m); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append VXCAN_INFO_PEER attribute: %m"); + + return r; +} + +static int netdev_vxcan_verify(NetDev *netdev, const char *filename) { + VxCan *v; + + assert(netdev); + assert(filename); + + v = VXCAN(netdev); + + assert(v); + + if (!v->ifname_peer) { + log_warning("VxCan NetDev without peer name configured in %s. Ignoring", filename); + return -EINVAL; + } + + return 0; +} + +static void vxcan_done(NetDev *n) { + VxCan *v; + + assert(n); + + v = VXCAN(n); + + assert(v); + + free(v->ifname_peer); +} + +const NetDevVTable vxcan_vtable = { + .object_size = sizeof(VxCan), + .sections = "Match\0NetDev\0VXCAN\0", + .done = vxcan_done, + .fill_message_create = netdev_vxcan_fill_message_create, + .create_type = NETDEV_CREATE_INDEPENDENT, + .config_verify = netdev_vxcan_verify, +}; diff --git a/src/network/netdev/vxcan.h b/src/network/netdev/vxcan.h new file mode 100644 index 0000000000..f37213513f --- /dev/null +++ b/src/network/netdev/vxcan.h @@ -0,0 +1,38 @@ +#pragma once + +/*** + This file is part of systemd. + + Copyright 2017 Susant Sahani + + 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 VxCan VxCan; + +#if HAVE_VXCAN_INFO_PEER +#include +#endif + +#include "netdev/netdev.h" + +struct VxCan { + NetDev meta; + + char *ifname_peer; +}; + +DEFINE_NETDEV_CAST(VXCAN, VxCan); + +extern const NetDevVTable vxcan_vtable;