Merge branch 'master' of git://openvswitch.org/openvswitch
[sliver-openvswitch.git] / datapath / linux / compat / gso.c
index 7379a57..30332a2 100644 (file)
@@ -36,7 +36,7 @@
 
 #include "gso.h"
 
-static __be16 skb_network_protocol(struct sk_buff *skb)
+static __be16 __skb_network_protocol(struct sk_buff *skb)
 {
        __be16 type = skb->protocol;
        int vlan_depth = ETH_HLEN;
@@ -65,10 +65,11 @@ static struct sk_buff *tnl_skb_gso_segment(struct sk_buff *skb,
        struct sk_buff *skb1 = skb;
        struct sk_buff *segs;
        __be16 proto = skb->protocol;
+       char cb[sizeof(skb->cb)];
 
        /* setup whole inner packet to get protocol. */
        __skb_pull(skb, mac_offset);
-       skb->protocol = skb_network_protocol(skb);
+       skb->protocol = __skb_network_protocol(skb);
 
        /* setup l3 packet to gso, to get around segmentation bug on older kernel.*/
        __skb_pull(skb, (pkt_hlen - mac_offset));
@@ -76,6 +77,10 @@ static struct sk_buff *tnl_skb_gso_segment(struct sk_buff *skb,
        skb_reset_network_header(skb);
        skb_reset_transport_header(skb);
 
+       /* From 3.9 kernel skb->cb is used by skb gso. Therefore
+        * make copy of it to restore it back. */
+       memcpy(cb, skb->cb, sizeof(cb));
+
        segs = __skb_gso_segment(skb, 0, tx_path);
        if (!segs || IS_ERR(segs))
                goto free;
@@ -89,6 +94,7 @@ static struct sk_buff *tnl_skb_gso_segment(struct sk_buff *skb,
                skb->mac_len = 0;
 
                memcpy(ip_hdr(skb), iph, pkt_hlen);
+               memcpy(skb->cb, cb, sizeof(cb));
                if (OVS_GSO_CB(skb)->fix_segment)
                        OVS_GSO_CB(skb)->fix_segment(skb);
 
@@ -103,7 +109,7 @@ free:
 int rpl_ip_local_out(struct sk_buff *skb)
 {
        int ret = NETDEV_TX_OK;
-       int id;
+       int id = -1;
 
        if (skb_is_gso(skb)) {
                struct iphdr *iph;
@@ -119,7 +125,6 @@ int rpl_ip_local_out(struct sk_buff *skb)
                err = skb_checksum_help(skb);
                if (unlikely(err))
                        return 0;
-               id = -1;
        }
 
        while (skb) {