datapath: Add function to copy skb checksum bits.
authorJesse Gross <jesse@nicira.com>
Wed, 7 Apr 2010 17:55:28 +0000 (13:55 -0400)
committerJesse Gross <jesse@nicira.com>
Mon, 19 Apr 2010 13:11:57 +0000 (09:11 -0400)
Some kernels don't copy the checksum offload state in the skb
header when doing different types of copies.  Xen adds even more
fields, which are also not consistently copied.  The result is
uninitialized memory and random outcomes.  This adds a function to
consistently copy these bits across all kernel versions.

datapath/actions.c
datapath/actions.h

index 4020411..fed9830 100644 (file)
@@ -33,19 +33,7 @@ make_writable(struct sk_buff *skb, unsigned min_headroom, gfp_t gfp)
 
                nskb = skb_copy_expand(skb, headroom, skb_tailroom(skb), gfp);
                if (nskb) {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
-                       /* Before 2.6.24 these fields were not copied when
-                        * doing an skb_copy_expand. */
-                       nskb->ip_summed = skb->ip_summed;
-                       nskb->csum = skb->csum;
-#endif
-#if defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID)
-                       /* These fields are copied in skb_clone but not in
-                        * skb_copy or related functions.  We need to manually
-                        * copy them over here. */
-                       nskb->proto_data_valid = skb->proto_data_valid;
-                       nskb->proto_csum_blank = skb->proto_csum_blank;
-#endif
+                       set_skb_csum_bits(skb, nskb);
                        kfree_skb(skb);
                        return nskb;
                }
index 04bc654..9dfca36 100644 (file)
@@ -10,6 +10,7 @@
 #define ACTIONS_H 1
 
 #include <linux/gfp.h>
+#include <linux/skbuff.h>
 
 struct datapath;
 struct sk_buff;
@@ -21,4 +22,22 @@ int execute_actions(struct datapath *dp, struct sk_buff *skb,
                    const union odp_action *, int n_actions,
                    gfp_t gfp);
 
+static inline void
+set_skb_csum_bits(const struct sk_buff *old_skb, struct sk_buff *new_skb)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+       /* Before 2.6.24 these fields were not copied when
+        * doing an skb_copy_expand. */
+       new_skb->ip_summed = old_skb->ip_summed;
+       new_skb->csum = old_skb->csum;
+#endif
+#if defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID)
+       /* These fields are copied in skb_clone but not in
+        * skb_copy or related functions.  We need to manually
+        * copy them over here. */
+       new_skb->proto_data_valid = old_skb->proto_data_valid;
+       new_skb->proto_csum_blank = old_skb->proto_csum_blank;
+#endif
+}
+
 #endif /* actions.h */