summaryrefslogtreecommitdiff
path: root/datapath/checksum.h
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2010-12-06 18:03:37 -0800
committerJesse Gross <jesse@nicira.com>2010-12-09 17:43:36 -0800
commite7d737d175dfe53436b356445ecb154541d2afff (patch)
treebf13c9127526ab579027bc46d93f3751063593c2 /datapath/checksum.h
parent2986c21ea17a4f31ce153dea12d1f39d05ae5996 (diff)
downloadopenvswitch-e7d737d175dfe53436b356445ecb154541d2afff.tar.gz
datapath: Try to avoid custom checksum update function.
Our update_csum() function was exactly the same as inet_proto_csum_replace4() with the one exception that it uses our checksum status fields on older kernels that need it. Unfortunately, we can't completely move the code to the compat directory because it relies on fields in OVS CB but we can at least exile it to checksum.h. Signed-off-by: Jesse Gross <jesse@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'datapath/checksum.h')
-rw-r--r--datapath/checksum.h25
1 files changed, 25 insertions, 0 deletions
diff --git a/datapath/checksum.h b/datapath/checksum.h
index bf931798a..7d653961e 100644
--- a/datapath/checksum.h
+++ b/datapath/checksum.h
@@ -12,6 +12,8 @@
#include <linux/skbuff.h>
#include <linux/version.h>
+#include <net/checksum.h>
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) || \
(defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID))
#define NEED_CSUM_NORMALIZE
@@ -100,4 +102,27 @@ static inline void set_skb_csum_pointers(struct sk_buff *skb, u16 csum_start,
#endif
}
+#if defined(NEED_CSUM_NORMALIZE) || LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+/* This is really compatibility code that belongs in the compat directory.
+ * However, it needs access to our normalized checksum values, so put it here.
+ */
+#define inet_proto_csum_replace4 rpl_inet_proto_csum_replace4
+static inline void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
+ __be32 from, __be32 to,
+ int pseudohdr)
+{
+ __be32 diff[] = { ~from, to };
+
+ if (get_ip_summed(skb) != OVS_CSUM_PARTIAL) {
+ *sum = csum_fold(csum_partial((char *)diff, sizeof(diff),
+ ~csum_unfold(*sum)));
+ if (get_ip_summed(skb) == OVS_CSUM_COMPLETE && pseudohdr)
+ skb->csum = ~csum_partial((char *)diff, sizeof(diff),
+ ~skb->csum);
+ } else if (pseudohdr)
+ *sum = ~csum_fold(csum_partial((char *)diff, sizeof(diff),
+ csum_unfold(*sum)));
+}
+#endif
+
#endif /* checksum.h */