From patchwork Mon Feb 27 22:53:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthias Schiffer X-Patchwork-Id: 733197 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3vXH8n2x3zz9s8R for ; Tue, 28 Feb 2017 09:54:49 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="dhK54lTj"; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:Subject:Message-Id: Date:To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=sxto/JNsm5QicpKTq9ubHjeUnY8lgva+xRQTIMTWKr0=; b=dhK54lTjLEt7dq Ivd39UxAOEwO58mMgj4X74zaMJHJern536pdCNIDMgt2wMpvxbI0qHu6wx1Me8kjEkWtm7aBE6SWa H6TXT8B7NYU9uY0duKBKqVz5jz+tXjw9cZ3xSDlUjdDlxBEJpWTyEWJUQnNclrw/VVQDVWb4WxR3u iOAOyCGd92daDdmyU1nZz28RDojMbDc6qyDKy7omgfxNnyNy8SMGIOpmUUNn/e0CFTmMck9/6tgYh xtlxvB1EFmjMQvxrMxXyxRj42EVOsoEUqqJ/n3srICFKuOvnkqKXzzOIqzAl/s8KIbUgEzUPOFVOD byn/G47NQFOXIpd8qHXQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1ciUBf-0007WB-6o; Mon, 27 Feb 2017 22:54:35 +0000 Received: from chaos.universe-factory.net ([2a02:2918:505:100::22]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1ciUBZ-0007UH-JJ for lede-dev@lists.infradead.org; Mon, 27 Feb 2017 22:54:33 +0000 Received: from localhost.localdomain (unknown [IPv6:fd1b:c28a:2fd6::2]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by chaos.universe-factory.net (Postfix) with ESMTPSA id 08E5E185D18; Mon, 27 Feb 2017 23:53:59 +0100 (CET) From: Matthias Schiffer To: nbd@nbd.name, dedeckeh@gmail.com Date: Mon, 27 Feb 2017 23:53:53 +0100 Message-Id: <852fffbc5cda64660be55eea03e15284c4c4873d.1488235763.git.mschiffer@universe-factory.net> X-Mailer: git-send-email 2.11.1 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170227_145430_005536_CD9E103D X-CRM114-Status: GOOD ( 18.15 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Subject: [LEDE-DEV] [PATCH netifd v2] system-linux: add VXLAN support X-BeenThere: lede-dev@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: lede-dev@lists.infradead.org MIME-Version: 1.0 Sender: "Lede-dev" Errors-To: lede-dev-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org 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 --- 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 * Copyright (C) 2013 Steven Barth * Copyright (C) 2014 Gioacchino Mazzurco + * Copyright (C) 2017 Matthias Schiffer * * 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 #include +#include #include #include @@ -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),