From d6df583c87cee0bfae2d756ea93ac7533e6a53fe Mon Sep 17 00:00:00 2001
From: Susant Sahani <145210+ssahani@users.noreply.github.com>
Date: Wed, 22 Nov 2017 12:53:22 +0530
Subject: 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.
---
man/systemd.netdev.xml | 20 +++++++
meson.build | 1 +
src/basic/missing.h | 4 ++
src/libsystemd/sd-netlink/netlink-types.c | 12 +++++
src/libsystemd/sd-netlink/netlink-types.h | 1 +
src/network/meson.build | 2 +
src/network/netdev/netdev-gperf.gperf | 2 +
src/network/netdev/netdev.c | 3 ++
src/network/netdev/netdev.h | 1 +
src/network/netdev/vxcan.c | 89 +++++++++++++++++++++++++++++++
src/network/netdev/vxcan.h | 38 +++++++++++++
11 files changed, 173 insertions(+)
create mode 100644 src/network/netdev/vxcan.c
create mode 100644 src/network/netdev/vxcan.h
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;
--
cgit v1.2.1