From 55202157525bfad96a12beef72684957df64b45e Mon Sep 17 00:00:00 2001
From: Kyle Mestery <kmestery@cisco.com>
Date: Wed, 31 Jul 2013 17:18:19 -0400
Subject: [PATCH 3/5] datapath: Support for Linux kernel 3.9.

In certain cases we need to ensure we save off skb->cb before
calling __skb_gso_segment() since in kernels >= 3.9 skb->cb is
used by this routine.

Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Signed-off-by: Kyle Mestery <kmestery@cisco.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
---
 FAQ                 | 2 ++
 datapath/datapath.c | 4 ++--
 datapath/tunnel.c   | 7 +++++++
 3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/FAQ b/FAQ
index 36e1fea..d7bab1d 100644
--- a/FAQ
+++ b/FAQ
@@ -147,6 +147,8 @@ A: The following table lists the Linux kernel versions against which the
        1.8.x      2.6.18 to 3.4
        1.9.x      2.6.18 to 3.8
        1.10.x     2.6.18 to 3.8
+       1.11.x     2.6.18 to 3.8
+       1.12.x     2.6.18 to 3.9
 
    Open vSwitch userspace should also work with the Linux kernel module
    built into Linux 3.3 and later.
diff --git a/datapath/datapath.c b/datapath/datapath.c
index 5cf62f8..688773d 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -61,8 +61,8 @@
 #include "vport-internal_dev.h"
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) || \
-    LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)
-#error Kernels before 2.6.18 or after 3.8 are not supported by this version of Open vSwitch.
+    LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+#error Kernels before 2.6.18 or after 3.9 are not supported by this version of Open vSwitch.
 #endif
 
 #define REHASH_FLOW_INTERVAL (10 * 60 * HZ)
diff --git a/datapath/tunnel.c b/datapath/tunnel.c
index 34e0210..5f7fc6a 100644
--- a/datapath/tunnel.c
+++ b/datapath/tunnel.c
@@ -166,6 +166,9 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb,
 
 	if (skb_is_gso(skb)) {
 		struct sk_buff *nskb;
+		char cb[sizeof(skb->cb)];
+
+		memcpy(cb, skb->cb, sizeof(cb));
 
 		nskb = skb_gso_segment(skb, 0);
 		if (IS_ERR(nskb)) {
@@ -176,6 +179,10 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb,
 
 		consume_skb(skb);
 		skb = nskb;
+		while (nskb) {
+			memcpy(nskb->cb, cb, sizeof(cb));
+			nskb = nskb->next;
+		}
 	} else if (get_ip_summed(skb) == OVS_CSUM_PARTIAL) {
 		/* Pages aren't locked and could change at any time.
 		 * If this happens after we compute the checksum, the
-- 
1.8.3.2

