[LEDE-DEV] [PATCH netifd v2] system-linux: add VXLAN support
Matthias Schiffer
mschiffer at universe-factory.net
Mon Feb 27 14:53:53 PST 2017
VXLAN shares many attributes with the tunnel devices, so it is implemented
as a new tunnel type. The 'remote' attribute can be used for an unicast
peer or a multicast group.
The IANA-assigned port 4789 is used by default, instead of the non-standard
port Linux defaults to.
Signed-off-by: Matthias Schiffer <mschiffer at universe-factory.net>
---
Updated to use a nested JSON object for the VXLAN-specific attributes -
although one could argue that MAC address, port and "ID" aren't very
specific after all, at least I can see us using the same attributes if we
ever add L2TPv3 support to netifd...
The vxlan package in my staging tree has been updated as well.
system-linux.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
system.c | 12 +++++
system.h | 10 ++++
3 files changed, 181 insertions(+), 1 deletion(-)
diff --git a/system-linux.c b/system-linux.c
index f4d6c25..b57f438 100644
--- a/system-linux.c
+++ b/system-linux.c
@@ -4,6 +4,7 @@
* Copyright (C) 2013 Jo-Philipp Wich <jow at openwrt.org>
* Copyright (C) 2013 Steven Barth <steven at midlink.org>
* Copyright (C) 2014 Gioacchino Mazzurco <gio at eigenlab.org>
+ * Copyright (C) 2017 Matthias Schiffer <mschiffer at universe-factory.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -25,6 +26,7 @@
#include <net/if_arp.h>
#include <arpa/inet.h>
+#include <netinet/ether.h>
#include <netinet/in.h>
#include <linux/rtnetlink.h>
@@ -2540,6 +2542,155 @@ failure:
}
#endif
+#ifdef IFLA_VXLAN_MAX
+static int system_add_vxlan(const char *name, const unsigned int link, struct blob_attr **tb, bool v6)
+{
+ struct blob_attr *tb_data[__TUNNEL_ATTR_MAX];
+ struct nl_msg *msg;
+ struct nlattr *linkinfo, *data;
+ struct ifinfomsg iim = { .ifi_family = AF_UNSPEC, };
+ struct blob_attr *cur;
+ int ret = 0;
+
+ if ((cur = tb[TUNNEL_ATTR_DATA]))
+ blobmsg_parse(vxlan_data_attr_list.params, __VXLAN_DATA_ATTR_MAX, tb_data,
+ blobmsg_data(cur), blobmsg_len(cur));
+ else
+ return -EINVAL;
+
+ msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
+
+ if (!msg)
+ return -1;
+
+ nlmsg_append(msg, &iim, sizeof(iim), 0);
+
+ nla_put_string(msg, IFLA_IFNAME, name);
+
+ if ((cur = tb_data[VXLAN_DATA_ATTR_MACADDR])) {
+ struct ether_addr *ea = ether_aton(blobmsg_get_string(cur));
+ if (!ea) {
+ ret = -EINVAL;
+ goto failure;
+ }
+
+ nla_put(msg, IFLA_ADDRESS, ETH_ALEN, ea);
+ }
+
+ if ((cur = tb[TUNNEL_ATTR_MTU])) {
+ uint32_t mtu = blobmsg_get_u32(cur);
+ nla_put_u32(msg, IFLA_MTU, mtu);
+ }
+
+ if (!(linkinfo = nla_nest_start(msg, IFLA_LINKINFO))) {
+ ret = -ENOMEM;
+ goto failure;
+ }
+
+ nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
+
+ if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) {
+ ret = -ENOMEM;
+ goto failure;
+ }
+
+ if (link)
+ nla_put_u32(msg, IFLA_VXLAN_LINK, link);
+
+ if ((cur = tb_data[VXLAN_DATA_ATTR_ID])) {
+ uint32_t id = blobmsg_get_u32(cur);
+ if (id >= (1u << 24) - 1) {
+ ret = -EINVAL;
+ goto failure;
+ }
+
+ nla_put_u32(msg, IFLA_VXLAN_ID, id);
+ }
+
+ if (v6) {
+ struct in6_addr in6buf;
+ if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
+ if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
+ ret = -EINVAL;
+ goto failure;
+ }
+ nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(in6buf), &in6buf);
+ }
+
+ if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
+ if (inet_pton(AF_INET6, blobmsg_data(cur), &in6buf) < 1) {
+ ret = -EINVAL;
+ goto failure;
+ }
+ nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(in6buf), &in6buf);
+ }
+ } else {
+ struct in_addr inbuf;
+
+ if ((cur = tb[TUNNEL_ATTR_LOCAL])) {
+ if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
+ ret = -EINVAL;
+ goto failure;
+ }
+ nla_put(msg, IFLA_VXLAN_LOCAL, sizeof(inbuf), &inbuf);
+ }
+
+ if ((cur = tb[TUNNEL_ATTR_REMOTE])) {
+ if (inet_pton(AF_INET, blobmsg_data(cur), &inbuf) < 1) {
+ ret = -EINVAL;
+ goto failure;
+ }
+ nla_put(msg, IFLA_VXLAN_GROUP, sizeof(inbuf), &inbuf);
+ }
+ }
+
+ uint32_t port = 4789;
+ if ((cur = tb_data[VXLAN_DATA_ATTR_PORT])) {
+ port = blobmsg_get_u32(cur);
+ if (port < 1 || port > 65535) {
+ ret = -EINVAL;
+ goto failure;
+ }
+ }
+ nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
+
+ if ((cur = tb[TUNNEL_ATTR_TOS])) {
+ char *str = blobmsg_get_string(cur);
+ unsigned tos = 1;
+
+ if (strcmp(str, "inherit")) {
+ if (!system_tos_aton(str, &tos))
+ return -EINVAL;
+ }
+
+ nla_put_u8(msg, IFLA_VXLAN_TOS, tos);
+ }
+
+ if ((cur = tb[TUNNEL_ATTR_TTL])) {
+ uint32_t ttl = blobmsg_get_u32(cur);
+ if (ttl < 1 || ttl > 255) {
+ ret = -EINVAL;
+ goto failure;
+ }
+
+ nla_put_u8(msg, IFLA_VXLAN_TTL, ttl);
+ }
+
+ nla_nest_end(msg, data);
+ nla_nest_end(msg, linkinfo);
+
+ ret = system_rtnl_call(msg);
+ if (ret)
+ D(SYSTEM, "Error adding vxlan '%s': %d\n", name, ret);
+
+ return ret;
+
+failure:
+ nlmsg_free(msg);
+ return ret;
+}
+#endif
+
static int system_add_proto_tunnel(const char *name, const uint8_t proto, const unsigned int link, struct blob_attr **tb)
{
struct blob_attr *cur;
@@ -2609,7 +2760,8 @@ static int __system_del_ip_tunnel(const char *name, struct blob_attr **tb)
if (!strcmp(str, "greip") || !strcmp(str, "gretapip") ||
!strcmp(str, "greip6") || !strcmp(str, "gretapip6") ||
- !strcmp(str, "vtiip") || !strcmp(str, "vtiip6"))
+ !strcmp(str, "vtiip") || !strcmp(str, "vtiip6") ||
+ !strcmp(str, "vxlan") || !strcmp(str, "vxlan6"))
return system_link_del(name);
else
return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
@@ -2833,6 +2985,12 @@ failure:
} else if (!strcmp(str, "vtiip6")) {
return system_add_vti_tunnel(name, "vti6", link, tb, true);
#endif
+#ifdef IFLA_VXLAN_MAX
+ } else if(!strcmp(str, "vxlan")) {
+ return system_add_vxlan(name, link, tb, false);
+ } else if(!strcmp(str, "vxlan6")) {
+ return system_add_vxlan(name, link, tb, true);
+#endif
#endif
} else if (!strcmp(str, "ipip")) {
return system_add_proto_tunnel(name, IPPROTO_IPIP, link, tb);
diff --git a/system.c b/system.c
index e57084f..52172c3 100644
--- a/system.c
+++ b/system.c
@@ -28,6 +28,7 @@ static const struct blobmsg_policy tunnel_attrs[__TUNNEL_ATTR_MAX] = {
[TUNNEL_ATTR_LINK] = { .name = "link", .type = BLOBMSG_TYPE_STRING },
[TUNNEL_ATTR_FMRS] = { .name = "fmrs", .type = BLOBMSG_TYPE_ARRAY },
[TUNNEL_ATTR_INFO] = { .name = "info", .type = BLOBMSG_TYPE_STRING },
+ [TUNNEL_ATTR_DATA] = { .name = "data", .type = BLOBMSG_TYPE_TABLE },
};
const struct uci_blob_param_list tunnel_attr_list = {
@@ -35,6 +36,17 @@ const struct uci_blob_param_list tunnel_attr_list = {
.params = tunnel_attrs,
};
+static const struct blobmsg_policy vxlan_data_attrs[__VXLAN_DATA_ATTR_MAX] = {
+ [VXLAN_DATA_ATTR_ID] = { .name = "id", .type = BLOBMSG_TYPE_INT32 },
+ [VXLAN_DATA_ATTR_PORT] = { .name = "port", .type = BLOBMSG_TYPE_INT32 },
+ [VXLAN_DATA_ATTR_MACADDR] = { .name = "macaddr", .type = BLOBMSG_TYPE_STRING },
+};
+
+const struct uci_blob_param_list vxlan_data_attr_list = {
+ .n_params = __VXLAN_DATA_ATTR_MAX,
+ .params = vxlan_data_attrs,
+};
+
void system_fd_set_cloexec(int fd)
{
#ifdef FD_CLOEXEC
diff --git a/system.h b/system.h
index 6077b95..6501d15 100644
--- a/system.h
+++ b/system.h
@@ -35,11 +35,21 @@ enum tunnel_param {
TUNNEL_ATTR_LINK,
TUNNEL_ATTR_FMRS,
TUNNEL_ATTR_INFO,
+ TUNNEL_ATTR_DATA,
__TUNNEL_ATTR_MAX
};
extern const struct uci_blob_param_list tunnel_attr_list;
+enum vxlan_data {
+ VXLAN_DATA_ATTR_ID,
+ VXLAN_DATA_ATTR_PORT,
+ VXLAN_DATA_ATTR_MACADDR,
+ __VXLAN_DATA_ATTR_MAX
+};
+
+extern const struct uci_blob_param_list vxlan_data_attr_list;
+
enum bridge_opt {
/* stp and forward delay always set */
BRIDGE_OPT_AGEING_TIME = (1 << 0),
--
2.11.1
More information about the Lede-dev
mailing list