diff options
author | Susant Sahani <145210+ssahani@users.noreply.github.com> | 2017-11-22 12:53:22 +0530 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2017-11-22 08:23:22 +0100 |
commit | d6df583c87cee0bfae2d756ea93ac7533e6a53fe (patch) | |
tree | 97d0db3b4d9cc0315cfe0699a1e8b0ccfc62333e | |
parent | a217a4bcc5dd773f5452988ca35e3d830cf90781 (diff) | |
download | systemd-d6df583c87cee0bfae2d756ea93ac7533e6a53fe.tar.gz |
networkd: introduce vxcan netdev. (#7150)
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.
-rw-r--r-- | man/systemd.netdev.xml | 20 | ||||
-rw-r--r-- | meson.build | 1 | ||||
-rw-r--r-- | src/basic/missing.h | 4 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-types.c | 12 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-types.h | 1 | ||||
-rw-r--r-- | src/network/meson.build | 2 | ||||
-rw-r--r-- | src/network/netdev/netdev-gperf.gperf | 2 | ||||
-rw-r--r-- | src/network/netdev/netdev.c | 3 | ||||
-rw-r--r-- | src/network/netdev/netdev.h | 1 | ||||
-rw-r--r-- | src/network/netdev/vxcan.c | 89 | ||||
-rw-r--r-- | src/network/netdev/vxcan.h | 38 |
11 files changed, 173 insertions, 0 deletions
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 @@ <row><entry><varname>vcan</varname></entry> <entry>The virtual CAN driver (vcan). Similar to the network loopback devices, vcan offers a virtual local CAN interface.</entry></row> + <row><entry><varname>vxcan</varname></entry> + <entry>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. + </entry></row> + </tbody> </tgroup> </table> @@ -895,6 +899,22 @@ </variablelist> </refsect1> <refsect1> + <title>[VXCAN] Section Options</title> + <para>The <literal>[VXCAN]</literal> section only applies for + netdevs of kind <literal>vxcan</literal> and accepts the + following key:</para> + + <variablelist class='network-directives'> + <varlistentry> + <term><varname>Peer=</varname></term> + <listitem> + <para>The peer interface name used when creating the netdev. + This option is compulsory.</para> + </listitem> + </varlistentry> + </variablelist> + </refsect1> + <refsect1> <title>[Tun] Section Options</title> <para>The <literal>[Tun]</literal> section only applies for 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 <linux/if_tunnel.h> #include <linux/fib_rules.h> +#if HAVE_VXCAN_INFO_PEER +#include <linux/can/vxcan.h> +#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 <http://www.gnu.org/licenses/>. +***/ + +#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 <http://www.gnu.org/licenses/>. +***/ + +typedef struct VxCan VxCan; + +#if HAVE_VXCAN_INFO_PEER +#include <linux/can/vxcan.h> +#endif + +#include "netdev/netdev.h" + +struct VxCan { + NetDev meta; + + char *ifname_peer; +}; + +DEFINE_NETDEV_CAST(VXCAN, VxCan); + +extern const NetDevVTable vxcan_vtable; |