datapath: backport: ip_tunnel_core: iptunnel_handle_offloads returns int and doesn...
authorPravin B Shelar <pshelar@ovn.org>
Fri, 8 Jul 2016 04:48:57 +0000 (21:48 -0700)
committerPravin B Shelar <pshelar@ovn.org>
Sat, 9 Jul 2016 02:27:49 +0000 (19:27 -0700)
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 <pshelar@ovn.org>
Acked-by: Jesse Gross <jesse@kernel.org>
datapath/linux/compat/geneve.c
datapath/linux/compat/include/net/ip_tunnels.h
datapath/linux/compat/include/net/udp_tunnel.h
datapath/linux/compat/ip_gre.c
datapath/linux/compat/ip_tunnels_core.c
datapath/linux/compat/lisp.c
datapath/linux/compat/vxlan.c

index 8d25f7a..4559700 100644 (file)
@@ -547,10 +547,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) {
@@ -558,11 +556,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;
@@ -688,7 +684,7 @@ netdev_tx_t rpl_geneve_xmit(struct sk_buff *skb)
                err = geneve_build_skb(rt, skb, key->tun_flags, vni,
                                       info->options_len, opts, udp_csum);
                if (unlikely(err))
-                       goto err;
+                       goto tx_error;
 
                tos = ip_tunnel_ecn_encap(key->tos, iip, skb);
                ttl = key->ttl;
@@ -698,7 +694,7 @@ netdev_tx_t rpl_geneve_xmit(struct sk_buff *skb)
                err = geneve_build_skb(rt, skb, 0, geneve->vni,
                                       0, NULL, udp_csum);
                if (unlikely(err))
-                       goto err;
+                       goto tx_error;
 
                tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, iip, skb);
                ttl = geneve->ttl;
@@ -717,7 +713,7 @@ netdev_tx_t rpl_geneve_xmit(struct sk_buff *skb)
 
 tx_error:
        dev_kfree_skb(skb);
-err:
+
        if (err == -ELOOP)
                dev->stats.collisions++;
        else if (err == -ENETUNREACH)
index 26c9041..cea75a1 100644 (file)
@@ -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)
index 85aed98..23e66f1 100644 (file)
@@ -6,21 +6,10 @@
 
 #include <net/dst_metadata.h>
 #include <linux/netdev_features.h>
+
 #ifdef HAVE_UDP_TUNNEL_IPV6
 #include_next <net/udp_tunnel.h>
 
-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 <net/ip_tunnels.h>
@@ -84,20 +73,56 @@ 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)) {
+               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 +138,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,
index 67db9af..995f5da 100644 (file)
@@ -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),
index ee4fadc..cb0223e 100644 (file)
@@ -86,10 +86,12 @@ int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
        return pkt_len;
 }
 EXPORT_SYMBOL_GPL(rpl_iptunnel_xmit);
+#endif
 
-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 *))
 {
        int err;
 
@@ -103,17 +105,19 @@ struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb,
                goto error;
        }
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
        if (gso_type_mask)
                fix_segment = NULL;
 
        OVS_GSO_CB(skb)->fix_segment = fix_segment;
+#endif
 
        if (skb_is_gso(skb)) {
                err = skb_unclone(skb, GFP_ATOMIC);
                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,15 +137,12 @@ 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
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0)
 int rpl___iptunnel_pull_header(struct sk_buff *skb, int hdr_len,
                               __be16 inner_proto, bool raw_proto, bool xnet)
 {
index c726012..7c1aa31 100644 (file)
@@ -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;
index 4374a3a..4e65b43 100644 (file)
@@ -1030,6 +1030,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;
@@ -1074,9 +1075,11 @@ 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;
+       type |= udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
+       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;
        }
 
@@ -1123,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;
@@ -1162,10 +1166,13 @@ 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);
-
+       type |= udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
+       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;