From patchwork Wed Nov 25 13:31:08 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thadeu Lima de Souza Cascardo X-Patchwork-Id: 548557 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (unknown [IPv6:2600:3c00::f03c:91ff:fe6e:bdf7]) by ozlabs.org (Postfix) with ESMTP id 1E27D1402E2 for ; Thu, 26 Nov 2015 00:32:29 +1100 (AEDT) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 512B810B41; Wed, 25 Nov 2015 05:31:50 -0800 (PST) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v3.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id 70C6010B1A for ; Wed, 25 Nov 2015 05:31:47 -0800 (PST) Received: from bar4.cudamail.com (localhost [127.0.0.1]) by mx3v3.cudamail.com (Postfix) with ESMTPS id DD879161628 for ; Wed, 25 Nov 2015 06:31:46 -0700 (MST) X-ASG-Debug-ID: 1448458306-03dc21603f110420001-byXFYA Received: from mx3-pf3.cudamail.com ([192.168.14.3]) by bar4.cudamail.com with ESMTP id yy0ohOPHOlZEZrN5 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 25 Nov 2015 06:31:46 -0700 (MST) X-Barracuda-Envelope-From: cascardo@redhat.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.14.3 Received: from unknown (HELO mx1.redhat.com) (209.132.183.28) by mx3-pf3.cudamail.com with ESMTPS (DHE-RSA-AES256-SHA encrypted); 25 Nov 2015 13:34:48 -0000 Received-SPF: pass (mx3-pf3.cudamail.com: SPF record at _spf1.redhat.com designates 209.132.183.28 as permitted sender) X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-Barracuda-RBL-IP: 209.132.183.28 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id 6C6986565F for ; Wed, 25 Nov 2015 13:31:38 +0000 (UTC) Received: from indiana.gru.redhat.com (ovpn-113-86.phx2.redhat.com [10.3.113.86]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id tAPDVRE6029492 for ; Wed, 25 Nov 2015 08:31:37 -0500 X-CudaMail-Envelope-Sender: cascardo@redhat.com From: Thadeu Lima de Souza Cascardo To: dev@openvswitch.org X-CudaMail-MID: CM-V3-1124010281 X-CudaMail-DTE: 112515 X-CudaMail-Originating-IP: 209.132.183.28 Date: Wed, 25 Nov 2015 11:31:08 -0200 X-ASG-Orig-Subj: [##CM-V3-1124010281##][PATCH v2 05/14] tunneling: add IPv6 support to netdev_tunnel_config Message-Id: <1448458277-28154-6-git-send-email-cascardo@redhat.com> In-Reply-To: <1448458277-28154-1-git-send-email-cascardo@redhat.com> References: <1448458277-28154-1-git-send-email-cascardo@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-GBUdb-Analysis: 0, 209.132.183.28, Ugly c=0.271956 p=-0.142857 Source Normal X-MessageSniffer-Rules: 0-0-0-15717-c X-Barracuda-Connect: UNKNOWN[192.168.14.3] X-Barracuda-Start-Time: 1448458306 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=3.5 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=4.0 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.24709 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Subject: [ovs-dev] [PATCH v2 05/14] tunneling: add IPv6 support to netdev_tunnel_config X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" From: Jiri Benc Allow configuration of IPv6 tunnel endpoints. v2: [cascardo: removed support for netlink datapath configuration] [cascardo: use IPv4 mapped IPv6 addresses] [cascardo: use only flow, instead of flow and flow6] v3: Fix style and avoid cast at parse_tunnel_ip as suggested by Ben Pfaff. Also, take advantage that smap_add_ipv6 now supports IPv4-mapped addresses. Signed-off-by: Jiri Benc Signed-off-by: Thadeu Lima de Souza Cascardo Co-authored-by: Thadeu Lima de Souza Cascardo Cc: Ben Pfaff --- lib/netdev-vport.c | 89 +++++++++++++++++++++++++++++++++++++----------------- lib/netdev.h | 4 +-- ofproto/tunnel.c | 8 ++--- 3 files changed, 66 insertions(+), 35 deletions(-) diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index 07b72b3..204a896 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -222,7 +222,7 @@ netdev_vport_route_changed(void) ovs_mutex_lock(&netdev->mutex); /* Finds all tunnel vports. */ - if (netdev->tnl_cfg.ip_dst) { + if (ipv6_addr_is_set(&netdev->tnl_cfg.ipv6_dst)) { if (tunnel_check_status_change__(netdev)) { netdev_change_seq_changed(netdev_); } @@ -316,12 +316,12 @@ tunnel_check_status_change__(struct netdev_vport *netdev) { char iface[IFNAMSIZ]; bool status = false; - ovs_be32 route; - ovs_be32 gw; + struct in6_addr *route; + struct in6_addr gw; iface[0] = '\0'; - route = netdev->tnl_cfg.ip_dst; - if (ovs_router_lookup4(route, iface, &gw)) { + route = &netdev->tnl_cfg.ipv6_dst; + if (ovs_router_lookup(route, iface, &gw)) { struct netdev *egress_netdev; if (!netdev_open(iface, "system", &egress_netdev)) { @@ -425,12 +425,44 @@ parse_key(const struct smap *args, const char *name, } static int +parse_tunnel_ip(const char *value, bool accept_mcast, bool *flow, + struct in6_addr *ipv6, uint16_t *protocol) +{ + if (!strcmp(value, "flow")) { + *flow = true; + *protocol = 0; + return 0; + } + if (addr_is_ipv6(value)) { + if (lookup_ipv6(value, ipv6)) { + return ENOENT; + } + if (!accept_mcast && ipv6_addr_is_multicast(ipv6)) { + return EINVAL; + } + *protocol = ETH_TYPE_IPV6; + } else { + struct in_addr ip; + if (lookup_ip(value, &ip)) { + return ENOENT; + } + if (!accept_mcast && ip_is_multicast(ip.s_addr)) { + return EINVAL; + } + in6_addr_set_mapped_ipv4(ipv6, ip.s_addr); + *protocol = ETH_TYPE_IP; + } + return 0; +} + +static int set_tunnel_config(struct netdev *dev_, const struct smap *args) { struct netdev_vport *dev = netdev_vport_cast(dev_); const char *name = netdev_get_name(dev_); const char *type = netdev_get_type(dev_); bool ipsec_mech_set, needs_dst_port, has_csum; + uint16_t dst_proto = 0, src_proto = 0; struct netdev_tunnel_config tnl_cfg; struct smap_node *node; @@ -462,28 +494,26 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args) SMAP_FOR_EACH (node, args) { if (!strcmp(node->key, "remote_ip")) { - struct in_addr in_addr; - if (!strcmp(node->value, "flow")) { - tnl_cfg.ip_dst_flow = true; - tnl_cfg.ip_dst = htonl(0); - } else if (lookup_ip(node->value, &in_addr)) { + int err; + err = parse_tunnel_ip(node->value, false, &tnl_cfg.ip_dst_flow, + &tnl_cfg.ipv6_dst, &dst_proto); + switch (err) { + case ENOENT: VLOG_WARN("%s: bad %s 'remote_ip'", name, type); - } else if (ip_is_multicast(in_addr.s_addr)) { - VLOG_WARN("%s: multicast remote_ip="IP_FMT" not allowed", - name, IP_ARGS(in_addr.s_addr)); + break; + case EINVAL: + VLOG_WARN("%s: multicast remote_ip=%s not allowed", + name, node->value); return EINVAL; - } else { - tnl_cfg.ip_dst = in_addr.s_addr; } } else if (!strcmp(node->key, "local_ip")) { - struct in_addr in_addr; - if (!strcmp(node->value, "flow")) { - tnl_cfg.ip_src_flow = true; - tnl_cfg.ip_src = htonl(0); - } else if (lookup_ip(node->value, &in_addr)) { + int err; + err = parse_tunnel_ip(node->value, true, &tnl_cfg.ip_src_flow, + &tnl_cfg.ipv6_src, &src_proto); + switch (err) { + case ENOENT: VLOG_WARN("%s: bad %s 'local_ip'", name, type); - } else { - tnl_cfg.ip_src = in_addr.s_addr; + break; } } else if (!strcmp(node->key, "tos")) { if (!strcmp(node->value, "inherit")) { @@ -601,7 +631,7 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args) } } - if (!tnl_cfg.ip_dst && !tnl_cfg.ip_dst_flow) { + if (!ipv6_addr_is_set(&tnl_cfg.ipv6_dst) && !tnl_cfg.ip_dst_flow) { VLOG_ERR("%s: %s type requires valid 'remote_ip' argument", name, type); return EINVAL; @@ -611,6 +641,11 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args) name, type); return EINVAL; } + if (src_proto && dst_proto && src_proto != dst_proto) { + VLOG_ERR("%s: 'remote_ip' and 'local_ip' has to be of the same address family", + name); + return EINVAL; + } if (!tnl_cfg.ttl) { tnl_cfg.ttl = DEFAULT_TTL; } @@ -644,14 +679,14 @@ get_tunnel_config(const struct netdev *dev, struct smap *args) tnl_cfg = netdev->tnl_cfg; ovs_mutex_unlock(&netdev->mutex); - if (tnl_cfg.ip_dst) { - smap_add_format(args, "remote_ip", IP_FMT, IP_ARGS(tnl_cfg.ip_dst)); + if (ipv6_addr_is_set(&tnl_cfg.ipv6_dst)) { + smap_add_ipv6(args, "remote_ip", &tnl_cfg.ipv6_dst); } else if (tnl_cfg.ip_dst_flow) { smap_add(args, "remote_ip", "flow"); } - if (tnl_cfg.ip_src) { - smap_add_format(args, "local_ip", IP_FMT, IP_ARGS(tnl_cfg.ip_src)); + if (ipv6_addr_is_set(&tnl_cfg.ipv6_src)) { + smap_add_ipv6(args, "local_ip", &tnl_cfg.ipv6_src); } else if (tnl_cfg.ip_src_flow) { smap_add(args, "local_ip", "flow"); } diff --git a/lib/netdev.h b/lib/netdev.h index 0fbcb65..622e2ae 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -118,8 +118,8 @@ struct netdev_tunnel_config { bool ip_src_flow; bool ip_dst_flow; - ovs_be32 ip_src; - ovs_be32 ip_dst; + struct in6_addr ipv6_src; + struct in6_addr ipv6_dst; uint32_t exts; diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c index 9fa6e64..d1cf4bd 100644 --- a/ofproto/tunnel.c +++ b/ofproto/tunnel.c @@ -160,12 +160,8 @@ tnl_port_add__(const struct ofport_dpif *ofport, const struct netdev *netdev, tnl_port->change_seq = netdev_get_change_seq(tnl_port->netdev); tnl_port->match.in_key = cfg->in_key; - if (cfg->ip_src) { - in6_addr_set_mapped_ipv4(&tnl_port->match.ipv6_src, cfg->ip_src); - } - if (cfg->ip_dst) { - in6_addr_set_mapped_ipv4(&tnl_port->match.ipv6_dst, cfg->ip_dst); - } + tnl_port->match.ipv6_src = cfg->ipv6_src; + tnl_port->match.ipv6_dst = cfg->ipv6_dst; tnl_port->match.ip_src_flow = cfg->ip_src_flow; tnl_port->match.ip_dst_flow = cfg->ip_dst_flow; tnl_port->match.pkt_mark = cfg->ipsec ? IPSEC_MARK : 0;