From ff6402a9f0d9ee4c29567b62938c82924d502b92 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Wed, 7 Apr 2010 13:55:28 -0400 Subject: [PATCH] datapath: Add function to copy skb checksum bits. 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 | 14 +------------- datapath/actions.h | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/datapath/actions.c b/datapath/actions.c index 40204118..fed9830f 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -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; } diff --git a/datapath/actions.h b/datapath/actions.h index 04bc6544..9dfca365 100644 --- a/datapath/actions.h +++ b/datapath/actions.h @@ -10,6 +10,7 @@ #define ACTIONS_H 1 #include +#include 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 */ -- 2.30.2