From patchwork Thu Oct 1 14:44:42 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Benc X-Patchwork-Id: 525069 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 B1503140D16 for ; Fri, 2 Oct 2015 00:45:46 +1000 (AEST) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id DE37E10D89; Thu, 1 Oct 2015 07:45:20 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v1.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id AB5BB10D7E for ; Thu, 1 Oct 2015 07:45:19 -0700 (PDT) Received: from bar4.cudamail.com (bar2 [192.168.15.2]) by mx3v1.cudamail.com (Postfix) with ESMTP id 2717DD49E6 for ; Thu, 1 Oct 2015 08:45:19 -0600 (MDT) X-ASG-Debug-ID: 1443710718-03dc2103720b2b0001-byXFYA Received: from mx3-pf3.cudamail.com ([192.168.14.3]) by bar4.cudamail.com with ESMTP id pKiEBIX8gRWcC73g (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 01 Oct 2015 08:45:18 -0600 (MDT) X-Barracuda-Envelope-From: jbenc@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); 1 Oct 2015 14:45:17 -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-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (Postfix) with ESMTPS id 08D5F8C1DA; Thu, 1 Oct 2015 14:45:17 +0000 (UTC) Received: from griffin.upir.cz (ovpn-204-67.brq.redhat.com [10.40.204.67]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t91Ej86K002275; Thu, 1 Oct 2015 10:45:15 -0400 X-CudaMail-Envelope-Sender: jbenc@redhat.com From: Jiri Benc To: netdev@vger.kernel.org X-CudaMail-MID: CM-V3-930024253 X-CudaMail-DTE: 100115 X-CudaMail-Originating-IP: 209.132.183.28 Date: Thu, 1 Oct 2015 16:44:42 +0200 X-ASG-Orig-Subj: [##CM-V3-930024253##][PATCH net-next v2 4/4] openvswitch: IPv6 support for ovs_tunnel_get_egress_info Message-Id: <8eeae62b794d6d7486cedd8178414d2fdfb6e4f8.1443710454.git.jbenc@redhat.com> In-Reply-To: References: X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-GBUdb-Analysis: 0, 209.132.183.28, Ugly c=0.297854 p=-0.333333 Source Normal X-MessageSniffer-Rules: 0-0-0-15122-c X-Barracuda-Connect: UNKNOWN[192.168.14.3] X-Barracuda-Start-Time: 1443710718 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.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=3.0 tests=BSF_SC0_MISMATCH_TO, BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.23077 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Cc: dev@openvswitch.org Subject: [ovs-dev] [PATCH net-next v2 4/4] openvswitch: IPv6 support for ovs_tunnel_get_egress_info 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" For compat tunnel interfaces, reject IPv6 keys. Also fixes a related thinko in vport-vxlan: upcall->egress_tun_info is not yet set at the point where it is used, thus the obtained family is incorrect. As this is IPv4 anyway, just use AF_INET. Signed-off-by: Jiri Benc --- New patch in v2 of the set. --- net/openvswitch/vport-geneve.c | 4 ++- net/openvswitch/vport-gre.c | 4 ++- net/openvswitch/vport-vxlan.c | 6 ++-- net/openvswitch/vport.c | 62 ++++++++++++++++++++++++++++-------------- net/openvswitch/vport.h | 26 ++++++++++++++++++ 5 files changed, 77 insertions(+), 25 deletions(-) diff --git a/net/openvswitch/vport-geneve.c b/net/openvswitch/vport-geneve.c index 2735e9c4a3b8..601fa3fbb19a 100644 --- a/net/openvswitch/vport-geneve.c +++ b/net/openvswitch/vport-geneve.c @@ -60,7 +60,9 @@ static int geneve_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, __be16 dport = htons(geneve_port->port_no); __be16 sport = udp_flow_src_port(net, skb, 1, USHRT_MAX, true); - return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp), + /* Only IPv4 supported in the compat layer. Pass NULL ipv6 socket. */ + return ovs_tunnel_get_egress_info(upcall, + ovs_dp_get_net(vport->dp), NULL, skb, IPPROTO_UDP, sport, dport); } diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c index 4d24481669c9..a3cf5695031d 100644 --- a/net/openvswitch/vport-gre.c +++ b/net/openvswitch/vport-gre.c @@ -87,7 +87,9 @@ static struct vport *gre_create(const struct vport_parms *parms) static int gre_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, struct dp_upcall_info *upcall) { - return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp), + /* Only IPv4 supported. Pass NULL ipv6 socket. */ + return ovs_tunnel_get_egress_info(upcall, + ovs_dp_get_net(vport->dp), NULL, skb, IPPROTO_GRE, 0, 0); } diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c index fb3cdb85905d..0973acb5432c 100644 --- a/net/openvswitch/vport-vxlan.c +++ b/net/openvswitch/vport-vxlan.c @@ -151,8 +151,7 @@ static int vxlan_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, { struct vxlan_dev *vxlan = netdev_priv(vport->dev); struct net *net = ovs_dp_get_net(vport->dp); - unsigned short family = ip_tunnel_info_af(upcall->egress_tun_info); - __be16 dst_port = vxlan_dev_dst_port(vxlan, family); + __be16 dst_port = vxlan_dev_dst_port(vxlan, AF_INET); __be16 src_port; int port_min; int port_max; @@ -160,7 +159,8 @@ static int vxlan_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, inet_get_local_port_range(net, &port_min, &port_max); src_port = udp_flow_src_port(net, skb, 0, 0, true); - return ovs_tunnel_get_egress_info(upcall, net, + /* Only IPv4 supported in the compat layer. Pass NULL ipv6 socket. */ + return ovs_tunnel_get_egress_info(upcall, net, NULL, skb, IPPROTO_UDP, src_port, dst_port); } diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index dc81dc619aa2..c58d95eed5fd 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c @@ -489,6 +489,7 @@ EXPORT_SYMBOL_GPL(ovs_vport_deferred_free); int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall, struct net *net, + struct sock *ipv6_sk, struct sk_buff *skb, u8 ipproto, __be16 tp_src, @@ -498,13 +499,9 @@ int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall, const struct ip_tunnel_info *tun_info = skb_tunnel_info(skb); const struct ip_tunnel_key *tun_key; u32 skb_mark = skb->mark; - struct rtable *rt; - struct flowi4 fl; if (unlikely(!tun_info)) return -EINVAL; - if (ip_tunnel_info_af(tun_info) != AF_INET) - return -EINVAL; tun_key = &tun_info->key; @@ -512,22 +509,47 @@ int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall, * The process may need to be changed if the corresponding process * in vports ops changed. */ - rt = ovs_tunnel_route_lookup(net, tun_key, skb_mark, &fl, ipproto); - if (IS_ERR(rt)) - return PTR_ERR(rt); - - ip_rt_put(rt); - - /* Generate egress_tun_info based on tun_info, - * saddr, tp_src and tp_dst - */ - ip_tunnel_key_init(&egress_tun_info->key, - fl.saddr, tun_key->u.ipv4.dst, - tun_key->tos, - tun_key->ttl, - tp_src, tp_dst, - tun_key->tun_id, - tun_key->tun_flags); + if (ip_tunnel_info_af(tun_info) == AF_INET) { + struct rtable *rt; + struct flowi4 fl; + + rt = ovs_tunnel_route_lookup(net, tun_key, skb_mark, &fl, ipproto); + if (IS_ERR(rt)) + return PTR_ERR(rt); + + ip_rt_put(rt); + + /* Generate egress_tun_info based on tun_info, + * saddr, tp_src and tp_dst + */ + ip_tunnel_key_init(&egress_tun_info->key, + fl.saddr, tun_key->u.ipv4.dst, + tun_key->tos, + tun_key->ttl, + tp_src, tp_dst, + tun_key->tun_id, + tun_key->tun_flags); + } else { + struct dst_entry *ndst; + struct flowi6 fl6; + + if (!ipv6_sk) + return -EPFNOSUPPORT; + + ndst = ovs_tunnel6_route_lookup(net, ipv6_sk, tun_key, + skb_mark, &fl6, ipproto); + if (IS_ERR(ndst)) + return PTR_ERR(ndst); + dst_release(ndst); + + ip6_tunnel_key_init(&egress_tun_info->key, + &fl6.saddr, &tun_key->u.ipv6.dst, + tun_key->tos, + tun_key->ttl, + tp_src, tp_dst, + tun_key->tun_id, + tun_key->tun_flags); + } egress_tun_info->options_len = tun_info->options_len; egress_tun_info->mode = tun_info->mode; upcall->egress_tun_opts = ip_tunnel_info_opts(egress_tun_info); diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h index a413f3ae6a7b..8445d931e863 100644 --- a/net/openvswitch/vport.h +++ b/net/openvswitch/vport.h @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include "datapath.h" @@ -55,6 +57,7 @@ u32 ovs_vport_find_upcall_portid(const struct vport *, struct sk_buff *); int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall, struct net *net, + struct sock *ipv6_sk, struct sk_buff *, u8 ipproto, __be16 tp_src, @@ -234,6 +237,29 @@ static inline struct rtable *ovs_tunnel_route_lookup(struct net *net, return rt; } +static inline struct dst_entry *ovs_tunnel6_route_lookup(struct net *net, + struct sock *sk, + const struct ip_tunnel_key *key, + u32 mark, + struct flowi6 *fl6, + u8 protocol) +{ + struct dst_entry *dst; + int err; + + memset(fl6, 0, sizeof(*fl6)); + fl6->daddr = key->u.ipv6.dst; + fl6->saddr = key->u.ipv6.src; + fl6->flowi6_tos = RT_TOS(key->tos); + fl6->flowi6_mark = mark; + fl6->flowi6_proto = protocol; + + err = ipv6_stub->ipv6_dst_lookup(net, sk, &dst, fl6); + if (err) + return ERR_PTR(err); + return dst; +} + static inline void ovs_vport_send(struct vport *vport, struct sk_buff *skb) { vport->ops->send(vport, skb);