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 402041180cf79ea310f2ded3e5895bf9f550e4a9..fed9830fe773c1244970a56cab232f4331364529 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 04bc65444494ab4350e0a8450ebfe65f51a4dc08..9dfca36594d6738f483604ef99cf8c9ffa61b468 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 */