datapath: backport kfree_skb_list()
[cascardo/ovs.git] / datapath / linux / compat / skbuff-openvswitch.c
index 5de43b3..fad1cc7 100644 (file)
@@ -3,6 +3,8 @@
 #include <linux/skbuff.h>
 #include <linux/if_vlan.h>
 
+#include "gso.h"
+
 #if !defined(HAVE_SKB_WARN_LRO) && defined(NETIF_F_LRO)
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -35,7 +37,7 @@ static inline bool head_frag(const struct sk_buff *skb)
  *     into skb_zerocopy().
  */
 unsigned int
-skb_zerocopy_headlen(const struct sk_buff *from)
+rpl_skb_zerocopy_headlen(const struct sk_buff *from)
 {
        unsigned int hlen = 0;
 
@@ -49,6 +51,7 @@ skb_zerocopy_headlen(const struct sk_buff *from)
 
        return hlen;
 }
+EXPORT_SYMBOL_GPL(rpl_skb_zerocopy_headlen);
 
 #ifndef HAVE_SKB_ZEROCOPY
 /**
@@ -70,7 +73,7 @@ skb_zerocopy_headlen(const struct sk_buff *from)
  *     -EFAULT: skb_copy_bits() found some problem with skb geometry
  */
 int
-skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen)
+rpl_skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen)
 {
        int i, j = 0;
        int plen = 0; /* length of skb->head fragment */
@@ -123,11 +126,12 @@ skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(rpl_skb_zerocopy);
 #endif
 #endif
 
 #ifndef HAVE_SKB_ENSURE_WRITABLE
-int skb_ensure_writable(struct sk_buff *skb, int write_len)
+int rpl_skb_ensure_writable(struct sk_buff *skb, int write_len)
 {
        if (!pskb_may_pull(skb, write_len))
                return -ENOMEM;
@@ -137,6 +141,7 @@ int skb_ensure_writable(struct sk_buff *skb, int write_len)
 
        return pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
 }
+EXPORT_SYMBOL_GPL(rpl_skb_ensure_writable);
 #endif
 
 #ifndef HAVE_SKB_VLAN_POP
@@ -173,7 +178,7 @@ pull:
        return err;
 }
 
-int skb_vlan_pop(struct sk_buff *skb)
+int rpl_skb_vlan_pop(struct sk_buff *skb)
 {
        u16 vlan_tci;
        __be16 vlan_proto;
@@ -205,10 +210,11 @@ int skb_vlan_pop(struct sk_buff *skb)
        __vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci);
        return 0;
 }
+EXPORT_SYMBOL_GPL(rpl_skb_vlan_pop);
 #endif
 
 #ifndef HAVE_SKB_VLAN_PUSH
-int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
+int rpl_skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
 {
        if (skb_vlan_tag_present(skb)) {
                unsigned int offset = skb->data - skb_mac_header(skb);
@@ -233,4 +239,44 @@ int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
        __vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci);
        return 0;
 }
+EXPORT_SYMBOL_GPL(rpl_skb_vlan_push);
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
+int rpl_pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
+                        gfp_t gfp_mask)
+{
+       int err;
+       int inner_mac_offset, inner_nw_offset, inner_transport_offset;
+
+       inner_mac_offset = skb_inner_mac_offset(skb);
+       inner_nw_offset = skb_inner_network_offset(skb);
+       inner_transport_offset = ovs_skb_inner_transport_offset(skb);
+
+#undef pskb_expand_head
+       err = pskb_expand_head(skb, nhead, ntail, gfp_mask);
+       if (err)
+               return err;
+
+       skb_set_inner_mac_header(skb, inner_mac_offset);
+       skb_set_inner_network_header(skb, inner_nw_offset);
+       skb_set_inner_transport_header(skb, inner_transport_offset);
+
+       return 0;
+}
+EXPORT_SYMBOL(rpl_pskb_expand_head);
+
+#endif
+
+#ifndef HAVE_KFREE_SKB_LIST
+void rpl_kfree_skb_list(struct sk_buff *segs)
+{
+       while (segs) {
+               struct sk_buff *next = segs->next;
+
+               kfree_skb(segs);
+               segs = next;
+       }
+}
+EXPORT_SYMBOL(rpl_kfree_skb_list);
 #endif