datapath: compat: introduce ovs_iptunnel_handle_offloads()
[cascardo/ovs.git] / datapath / linux / compat / gso.c
index 96b5d3d..5079f79 100644 (file)
@@ -294,3 +294,54 @@ int rpl_ip_local_out(struct sk_buff *skb)
        return ret;
 }
 #endif /* 3.16 */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
+struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb,
+                                             bool csum_help,
+                                            void (*fix_segment)(struct sk_buff *))
+{
+       int err;
+
+       /* XXX: synchronize inner header reset for compat and non compat code
+        * so that we can do it here.
+        */
+       /*
+        skb_reset_inner_headers(skb);
+        */
+
+       /* OVS compat code does not maintain encapsulation bit.
+        * skb->encapsulation = 1; */
+
+       if (skb_is_gso(skb)) {
+               if (skb_is_encapsulated(skb)) {
+                       err = -ENOSYS;
+                       goto error;
+               }
+
+               OVS_GSO_CB(skb)->fix_segment = fix_segment;
+               return skb;
+       }
+
+       /* If packet is not gso and we are resolving any partial checksum,
+        * clear encapsulation flag. This allows setting CHECKSUM_PARTIAL
+        * on the outer header without confusing devices that implement
+        * NETIF_F_IP_CSUM with encapsulation.
+        */
+       /*
+       if (csum_help)
+               skb->encapsulation = 0;
+       */
+
+       if (skb->ip_summed == CHECKSUM_PARTIAL && csum_help) {
+               err = skb_checksum_help(skb);
+               if (unlikely(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);
+}
+#endif /* 3.12 */