datapath: gre: Reset fix_segment pointer.
[cascardo/ovs.git] / datapath / linux / compat / gre.c
index c7f2551..fe81380 100644 (file)
  */
 
 #include <linux/version.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
-
 #include <linux/kconfig.h>
-#if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX)
-
 #include <linux/module.h>
 #include <linux/if.h>
 #include <linux/if_tunnel.h>
 
 #include "gso.h"
 
+#if IS_ENABLED(CONFIG_NET_IPGRE_DEMUX)
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
+
 #ifndef HAVE_GRE_CISCO_REGISTER
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
@@ -236,7 +236,7 @@ static const struct gre_protocol ipgre_protocol = {
        .handler        =       gre_cisco_rcv,
 };
 
-int gre_cisco_register(struct gre_cisco_protocol *newp)
+int rpl_gre_cisco_register(struct gre_cisco_protocol *newp)
 {
        int err;
 
@@ -250,8 +250,9 @@ int gre_cisco_register(struct gre_cisco_protocol *newp)
        return (cmpxchg((struct gre_cisco_protocol **)&gre_cisco_proto, NULL, newp) == NULL) ?
                0 : -EBUSY;
 }
+EXPORT_SYMBOL_GPL(rpl_gre_cisco_register);
 
-int gre_cisco_unregister(struct gre_cisco_protocol *proto)
+int rpl_gre_cisco_unregister(struct gre_cisco_protocol *proto)
 {
        int ret;
 
@@ -265,12 +266,13 @@ int gre_cisco_unregister(struct gre_cisco_protocol *proto)
        ret = gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
        return ret;
 }
+EXPORT_SYMBOL_GPL(rpl_gre_cisco_unregister);
 
 #endif /* !HAVE_GRE_CISCO_REGISTER */
 
-#ifndef USE_KERNEL_TUNNEL_API
-
 /* GRE TX side. */
+static void gre_nop_fix(struct sk_buff *skb) { }
+
 static void gre_csum_fix(struct sk_buff *skb)
 {
        struct gre_base_hdr *greh;
@@ -285,38 +287,12 @@ static void gre_csum_fix(struct sk_buff *skb)
                                                     skb->len - gre_offset, 0));
 }
 
-struct sk_buff *gre_handle_offloads(struct sk_buff *skb, bool gre_csum)
-{
-       int err;
-
-       skb_reset_inner_headers(skb);
-
-       if (skb_is_gso(skb)) {
-               if (gre_csum)
-                       OVS_GSO_CB(skb)->fix_segment = gre_csum_fix;
-               else
-                       OVS_GSO_CB(skb)->fix_segment = NULL;
-       } else {
-               if (skb->ip_summed == CHECKSUM_PARTIAL && gre_csum) {
-                       err = skb_checksum_help(skb);
-                       if (err)
-                               goto error;
-
-               } else if (skb->ip_summed != CHECKSUM_PARTIAL)
-                       skb->ip_summed = CHECKSUM_NONE;
-       }
-       return skb;
-error:
-       kfree_skb(skb);
-       return ERR_PTR(err);
-}
-
 static bool is_gre_gso(struct sk_buff *skb)
 {
        return skb_is_gso(skb);
 }
 
-void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
+void rpl_gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
                      int hdr_len)
 {
        struct gre_base_hdr *greh;
@@ -344,9 +320,35 @@ void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
                                                skb->len, 0));
                }
        }
+
+       ovs_skb_set_inner_protocol(skb, tpi->proto);
+}
+EXPORT_SYMBOL_GPL(rpl_gre_build_header);
+
+struct sk_buff *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;
+
+       if (gre_csum)
+               fix_segment = gre_csum_fix;
+       else
+               fix_segment = gre_nop_fix;
+
+       return ovs_iptunnel_handle_offloads(skb, gre_csum, type, fix_segment);
+}
+#else
+struct sk_buff *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);
+       }
+       skb_clear_ovs_gso_cb(skb);
+#undef gre_handle_offloads
+       return gre_handle_offloads(skb, gre_csum);
 }
 #endif
+EXPORT_SYMBOL_GPL(rpl_gre_handle_offloads);
 
 #endif /* CONFIG_NET_IPGRE_DEMUX */
-
-#endif /* 3.12 */