From patchwork Thu Jun 30 08:06:22 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pravin Shelar X-Patchwork-Id: 642415 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (archives.nicira.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 3rgBwT5Nf4z9s9n for ; Thu, 30 Jun 2016 18:07:21 +1000 (AEST) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id E6B86106DC; Thu, 30 Jun 2016 01:07:16 -0700 (PDT) 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 9C03A106D4 for ; Thu, 30 Jun 2016 01:07:15 -0700 (PDT) Received: from bar6.cudamail.com (localhost [127.0.0.1]) by mx3v3.cudamail.com (Postfix) with ESMTPS id 32D52161140 for ; Thu, 30 Jun 2016 02:07:15 -0600 (MDT) X-ASG-Debug-ID: 1467274034-0b32371673ebd90001-byXFYA Received: from mx1-pf1.cudamail.com ([192.168.24.1]) by bar6.cudamail.com with ESMTP id ZPfCzXeeKRsdFzGk (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 30 Jun 2016 02:07:14 -0600 (MDT) X-Barracuda-Envelope-From: pshelar@ovn.org X-Barracuda-RBL-Trusted-Forwarder: 192.168.24.1 Received: from unknown (HELO relay5-d.mail.gandi.net) (217.70.183.197) by mx1-pf1.cudamail.com with ESMTPS (DHE-RSA-AES256-SHA encrypted); 30 Jun 2016 08:07:13 -0000 Received-SPF: pass (mx1-pf1.cudamail.com: SPF record at ovn.org designates 217.70.183.197 as permitted sender) X-Barracuda-Apparent-Source-IP: 217.70.183.197 X-Barracuda-RBL-IP: 217.70.183.197 Received: from mfilter42-d.gandi.net (mfilter42-d.gandi.net [217.70.178.172]) by relay5-d.mail.gandi.net (Postfix) with ESMTP id 8E3CC41C0C1; Thu, 30 Jun 2016 10:07:12 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at mfilter42-d.gandi.net Received: from relay5-d.mail.gandi.net ([IPv6:::ffff:217.70.183.197]) by mfilter42-d.gandi.net (mfilter42-d.gandi.net [::ffff:10.0.15.180]) (amavisd-new, port 10024) with ESMTP id GIlGVmPFk8Fe; Thu, 30 Jun 2016 10:07:10 +0200 (CEST) X-Originating-IP: 24.130.10.65 Received: from localhost.localdomain.localdomain (c-24-130-10-65.hsd1.ca.comcast.net [24.130.10.65]) (Authenticated sender: pshelar@ovn.org) by relay5-d.mail.gandi.net (Postfix) with ESMTPSA id 8CC5041C0BC; Thu, 30 Jun 2016 10:07:09 +0200 (CEST) X-CudaMail-Envelope-Sender: pshelar@ovn.org From: Pravin B Shelar To: dev@openvswitch.org X-CudaMail-Whitelist-To: dev@openvswitch.org X-CudaMail-MID: CM-E1-629002197 X-CudaMail-DTE: 063016 X-CudaMail-Originating-IP: 217.70.183.197 Date: Thu, 30 Jun 2016 01:06:22 -0700 X-ASG-Orig-Subj: [##CM-E1-629002197##][PATCH v2 05/24] datapath: backport: ip_tunnel_core: iptunnel_handle_offloads returns int and doesn't free skb Message-Id: <1467274002-61390-5-git-send-email-pshelar@ovn.org> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1467274002-61390-1-git-send-email-pshelar@ovn.org> References: <1467274002-61390-1-git-send-email-pshelar@ovn.org> X-Barracuda-Connect: UNKNOWN[192.168.24.1] X-Barracuda-Start-Time: 1467274034 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-ASG-Whitelist: Header =?UTF-8?B?eFwtY3VkYW1haWxcLXdoaXRlbGlzdFwtdG8=?= X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 Subject: [ovs-dev] [PATCH v2 05/24] datapath: backport: ip_tunnel_core: iptunnel_handle_offloads returns int and doesn't free skb 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" There is return type change in upstream handle-offload functions. Following patch brings these changes in. This is backport of aed069df ("ip_tunnel_core: iptunnel_handle_offloads returns int and doesn't free skb") I have also removed duplicate definitions of tunnel_handle_offloads() from ip-tunnel header. Signed-off-by: Pravin B Shelar --- datapath/linux/compat/geneve.c | 11 ++-- datapath/linux/compat/include/net/ip_tunnels.h | 35 ++++++----- datapath/linux/compat/include/net/udp_tunnel.h | 83 ++++++++++++++------------ datapath/linux/compat/ip_gre.c | 20 +++---- datapath/linux/compat/ip_tunnels_core.c | 13 ++-- datapath/linux/compat/lisp.c | 7 +-- datapath/linux/compat/utils.c | 3 + datapath/linux/compat/vxlan.c | 19 +++--- 8 files changed, 102 insertions(+), 89 deletions(-) diff --git a/datapath/linux/compat/geneve.c b/datapath/linux/compat/geneve.c index 5983e6a..576d7b8 100644 --- a/datapath/linux/compat/geneve.c +++ b/datapath/linux/compat/geneve.c @@ -548,10 +548,8 @@ static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb, + GENEVE_BASE_HLEN + opt_len + sizeof(struct iphdr) + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0); err = skb_cow_head(skb, min_headroom); - if (unlikely(err)) { - kfree_skb(skb); + if (unlikely(err)) goto free_rt; - } skb = vlan_hwaccel_push_inside(skb); if (!skb) { @@ -559,11 +557,9 @@ static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb, goto free_rt; } - skb = udp_tunnel_handle_offloads(skb, csum, 0, false); - if (IS_ERR(skb)) { - err = PTR_ERR(skb); + err = udp_tunnel_handle_offloads(skb, csum, false); + if (err) goto free_rt; - } gnvh = (struct genevehdr *)__skb_push(skb, sizeof(*gnvh) + opt_len); gnvh->ver = GENEVE_VER; gnvh->opt_len = opt_len / 4; @@ -579,6 +575,7 @@ static int geneve_build_skb(struct rtable *rt, struct sk_buff *skb, return 0; free_rt: + kfree_skb(skb); ip_rt_put(rt); return err; } diff --git a/datapath/linux/compat/include/net/ip_tunnels.h b/datapath/linux/compat/include/net/ip_tunnels.h index 26c9041..cea75a1 100644 --- a/datapath/linux/compat/include/net/ip_tunnels.h +++ b/datapath/linux/compat/include/net/ip_tunnels.h @@ -31,11 +31,27 @@ static inline int rpl_iptunnel_pull_header(struct sk_buff *skb, int hdr_len, } #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) -struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb, - bool csum_help, int gso_type_mask, - void (*fix_segment)(struct sk_buff *)); +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +int ovs_iptunnel_handle_offloads(struct sk_buff *skb, + bool csum_help, int gso_type_mask, + void (*fix_segment)(struct sk_buff *)); + +/* This is is required to compile upstream gre.h. gre_handle_offloads() + * is defined in gre.h and needs iptunnel_handle_offloads(). This provides + * default signature for this function. + * rpl prefix is to make OVS build happy. + */ +#define iptunnel_handle_offloads rpl_iptunnel_handle_offloads +struct sk_buff *rpl_iptunnel_handle_offloads(struct sk_buff *skb, + bool csum_help, + int gso_type_mask); +#else + +#define ovs_iptunnel_handle_offloads(skb, csum_help, gso_type_mask, fix_segment) \ + iptunnel_handle_offloads(skb, gso_type_mask) +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) #define iptunnel_xmit rpl_iptunnel_xmit int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, __be32 src, __be32 dst, __u8 proto, __u8 tos, __u8 ttl, @@ -43,9 +59,6 @@ int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, #else -#define ovs_iptunnel_handle_offloads(skb, csum_help, gso_type_mask, fix_segment) \ - iptunnel_handle_offloads(skb, csum_help, gso_type_mask) - #define rpl_iptunnel_xmit iptunnel_xmit int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, __be32 src, __be32 dst, __u8 proto, __u8 tos, __u8 ttl, @@ -53,14 +66,6 @@ int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, #endif /* 3.18 */ -/* This is not required for OVS on kernel older than 3.18, but gre.h - * header file needs this declaration for function gre_handle_offloads(). - * So it is defined for all kernel version. - */ -#define rpl_iptunnel_handle_offloads iptunnel_handle_offloads -struct sk_buff *rpl_iptunnel_handle_offloads(struct sk_buff *skb, bool gre_csum, - int gso_type_mask); - #ifndef TUNNEL_CSUM #define TUNNEL_CSUM __cpu_to_be16(0x01) #define TUNNEL_ROUTING __cpu_to_be16(0x02) diff --git a/datapath/linux/compat/include/net/udp_tunnel.h b/datapath/linux/compat/include/net/udp_tunnel.h index 85aed98..65adc02 100644 --- a/datapath/linux/compat/include/net/udp_tunnel.h +++ b/datapath/linux/compat/include/net/udp_tunnel.h @@ -6,21 +6,10 @@ #include #include + #ifdef HAVE_UDP_TUNNEL_IPV6 #include_next -static inline struct sk_buff * -rpl_udp_tunnel_handle_offloads(struct sk_buff *skb, bool udp_csum, - int type, bool is_vxlan) -{ - if (skb_is_gso(skb) && skb_is_encapsulated(skb)) { - kfree_skb(skb); - return ERR_PTR(-ENOSYS); - } - return udp_tunnel_handle_offloads(skb, udp_csum); -} -#define udp_tunnel_handle_offloads rpl_udp_tunnel_handle_offloads - #else #include @@ -84,20 +73,58 @@ int rpl_udp_tunnel_xmit_skb(struct rtable *rt, #define udp_tunnel_sock_release rpl_udp_tunnel_sock_release void rpl_udp_tunnel_sock_release(struct socket *sock); +#define udp_tunnel_encap_enable(sock) udp_encap_enable() + +#if IS_ENABLED(CONFIG_IPV6) +#define udp_tunnel6_xmit_skb rpl_udp_tunnel6_xmit_skb +int rpl_udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk, + struct sk_buff *skb, + struct net_device *dev, struct in6_addr *saddr, + struct in6_addr *daddr, + __u8 prio, __u8 ttl, __be16 src_port, + __be16 dst_port, bool nocheck); +#endif + +static inline void udp_tunnel_gro_complete(struct sk_buff *skb, int nhoff) +{ + struct udphdr *uh; + + uh = (struct udphdr *)(skb->data + nhoff - sizeof(struct udphdr)); + skb_shinfo(skb)->gso_type |= uh->check ? + SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0) +/* this is to handle the return type change in handle-offload + * functions. + */ +static inline int +rpl_udp_tunnel_handle_offloads(struct sk_buff *skb, bool udp_csum, + bool is_vxlan) +{ + if (skb_is_gso(skb) && skb_is_encapsulated(skb)) { + kfree_skb(skb); + return -ENOSYS; + } + return udp_tunnel_handle_offloads(skb, udp_csum); +} + +#else void ovs_udp_gso(struct sk_buff *skb); void ovs_udp_csum_gso(struct sk_buff *skb); -#define udp_tunnel_encap_enable(sock) udp_encap_enable() -static inline struct sk_buff *udp_tunnel_handle_offloads(struct sk_buff *skb, - bool udp_csum, - int type, - bool is_vxlan) +static inline int rpl_udp_tunnel_handle_offloads(struct sk_buff *skb, + bool udp_csum, + bool is_vxlan) { + int type = 0; + void (*fix_segment)(struct sk_buff *); if (skb_is_gso(skb) && skb_is_encapsulated(skb)) { kfree_skb(skb); - return ERR_PTR(-ENOSYS); + return -ENOSYS; } type |= udp_csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; @@ -113,27 +140,9 @@ static inline struct sk_buff *udp_tunnel_handle_offloads(struct sk_buff *skb, return ovs_iptunnel_handle_offloads(skb, udp_csum, type, fix_segment); } - -#if IS_ENABLED(CONFIG_IPV6) -#define udp_tunnel6_xmit_skb rpl_udp_tunnel6_xmit_skb -int rpl_udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb, - struct net_device *dev, struct in6_addr *saddr, - struct in6_addr *daddr, - __u8 prio, __u8 ttl, __be16 src_port, - __be16 dst_port, bool nocheck); -#endif - -static inline void udp_tunnel_gro_complete(struct sk_buff *skb, int nhoff) -{ - struct udphdr *uh; - - uh = (struct udphdr *)(skb->data + nhoff - sizeof(struct udphdr)); - skb_shinfo(skb)->gso_type |= uh->check ? - SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; -} #endif +#define udp_tunnel_handle_offloads rpl_udp_tunnel_handle_offloads static inline void ovs_udp_tun_rx_dst(struct ip_tunnel_info *info, struct sk_buff *skb, unsigned short family, diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_gre.c index 67db9af..995f5da 100644 --- a/datapath/linux/compat/ip_gre.c +++ b/datapath/linux/compat/ip_gre.c @@ -171,7 +171,8 @@ static int gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) return 0; } -#ifndef HAVE_GRE_HANDLE_OFFLOADS +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) +/* gre_handle_offloads() has different return type on older kernsl. */ static void gre_nop_fix(struct sk_buff *skb) { } static void gre_csum_fix(struct sk_buff *skb) @@ -193,7 +194,7 @@ static bool is_gre_gso(struct sk_buff *skb) return skb_is_gso(skb); } -static struct sk_buff *rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum) +static int rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum) { int type = gre_csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE; gso_fix_segment_t fix_segment; @@ -213,12 +214,11 @@ static bool is_gre_gso(struct sk_buff *skb) (SKB_GSO_GRE | SKB_GSO_GRE_CSUM); } -static struct sk_buff *rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum) +static int rpl_gre_handle_offloads(struct sk_buff *skb, bool gre_csum) { - if (skb_is_gso(skb) && skb_is_encapsulated(skb)) { - kfree_skb(skb); - return ERR_PTR(-ENOSYS); - } + if (skb_is_gso(skb) && skb_is_encapsulated(skb)) + return -ENOSYS; + #undef gre_handle_offloads return gre_handle_offloads(skb, gre_csum); } @@ -318,11 +318,9 @@ netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb) } /* Push Tunnel header. */ - skb = rpl_gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)); - if (IS_ERR(skb)) { - skb = NULL; + err = rpl_gre_handle_offloads(skb, !!(tun_info->key.tun_flags & TUNNEL_CSUM)); + if (err) goto err_free_rt; - } flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY); build_header(skb, tunnel_hlen, flags, htons(ETH_P_TEB), diff --git a/datapath/linux/compat/ip_tunnels_core.c b/datapath/linux/compat/ip_tunnels_core.c index ee4fadc..98910cf 100644 --- a/datapath/linux/compat/ip_tunnels_core.c +++ b/datapath/linux/compat/ip_tunnels_core.c @@ -87,9 +87,9 @@ int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, } EXPORT_SYMBOL_GPL(rpl_iptunnel_xmit); -struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb, - bool csum_help, int gso_type_mask, - void (*fix_segment)(struct sk_buff *)) +int ovs_iptunnel_handle_offloads(struct sk_buff *skb, + bool csum_help, int gso_type_mask, + void (*fix_segment)(struct sk_buff *)) { int err; @@ -113,7 +113,7 @@ struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb, if (unlikely(err)) goto error; skb_shinfo(skb)->gso_type |= gso_type_mask; - return skb; + return 0; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) @@ -133,10 +133,9 @@ struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb, } else if (skb->ip_summed != CHECKSUM_PARTIAL) skb->ip_summed = CHECKSUM_NONE; - return skb; + return 0; error: - kfree_skb(skb); - return ERR_PTR(err); + return err; } EXPORT_SYMBOL_GPL(ovs_iptunnel_handle_offloads); #endif diff --git a/datapath/linux/compat/lisp.c b/datapath/linux/compat/lisp.c index 246a0fa..67bfe10 100644 --- a/datapath/linux/compat/lisp.c +++ b/datapath/linux/compat/lisp.c @@ -344,12 +344,9 @@ netdev_tx_t rpl_lisp_xmit(struct sk_buff *skb) skb_reset_mac_header(skb); skb->vlan_tci = 0; - skb = udp_tunnel_handle_offloads(skb, false, 0, false); - if (IS_ERR(skb)) { - err = PTR_ERR(skb); - skb = NULL; + err = udp_tunnel_handle_offloads(skb, false, false); + if (err) goto err_free_rt; - } src_port = htons(get_src_port(net, skb)); dst_port = lisp_dev->dst_port; diff --git a/datapath/linux/compat/utils.c b/datapath/linux/compat/utils.c index 7008ecf..7113e09 100644 --- a/datapath/linux/compat/utils.c +++ b/datapath/linux/compat/utils.c @@ -72,6 +72,9 @@ void __percpu *__alloc_percpu_gfp(size_t size, size_t align, gfp_t gfp) void __percpu *p; int i; + /* older kernel do not allow all GFP flags, specifically atomic + * allocation. + */ if (gfp & ~(GFP_KERNEL | __GFP_ZERO)) return NULL; p = __alloc_percpu(size, align); diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c index a25db87..b0d156f 100644 --- a/datapath/linux/compat/vxlan.c +++ b/datapath/linux/compat/vxlan.c @@ -1031,6 +1031,7 @@ static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk, __be16 src_port, __be16 dst_port, __be32 vni, struct vxlan_metadata *md, bool xnet, u32 vxflags) { + void (*fix_segment)(struct sk_buff *); struct vxlanhdr *vxh; int min_headroom; int err; @@ -1075,9 +1076,10 @@ static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk, goto err; } - skb = udp_tunnel_handle_offloads(skb, udp_sum, type, true); - if (IS_ERR(skb)) { - err = -EINVAL; + fix_segment = udp_sum ? ovs_udp_gso : ovs_udp_csum_gso; + err = ovs_iptunnel_handle_offloads(skb, udp_sum, type, fix_segment); + if (err) { + kfree_skb(skb); goto err; } @@ -1124,6 +1126,7 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk __be16 src_port, __be16 dst_port, __be32 vni, struct vxlan_metadata *md, bool xnet, u32 vxflags) { + void (*fix_segment)(struct sk_buff *); struct vxlanhdr *vxh; int min_headroom; int err; @@ -1163,10 +1166,12 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk if (WARN_ON(!skb)) return -ENOMEM; - skb = udp_tunnel_handle_offloads(skb, udp_sum, type, true); - if (IS_ERR(skb)) - return PTR_ERR(skb); - + fix_segment = udp_sum ? ovs_udp_gso : ovs_udp_csum_gso; + err = ovs_iptunnel_handle_offloads(skb, udp_sum, type, fix_segment); + if (err) { + kfree_skb(skb); + return err; + } vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); vxh->vx_flags = htonl(VXLAN_HF_VNI); vxh->vx_vni = vni;