[ovs-dev] [PATCH 09/19] datapath: Try to avoid custom checksum update function.

Jesse Gross jesse at nicira.com
Thu Dec 9 06:14:07 UTC 2010


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 at nicira.com>
---
 datapath/actions.c  |   24 ++----------------------
 datapath/checksum.h |   25 +++++++++++++++++++++++++
 2 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/datapath/actions.c b/datapath/actions.c
index d7c571a..9f738e4 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -213,26 +213,6 @@ static struct sk_buff *set_dl_addr(struct sk_buff *skb,
 	return skb;
 }
 
-/* Updates 'sum', which is a field in 'skb''s data, given that a 4-byte field
- * covered by the sum has been changed from 'from' to 'to'.  If set,
- * 'pseudohdr' indicates that the field is in the TCP or UDP pseudo-header.
- * Based on nf_proto_csum_replace4. */
-static void update_csum(__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)));
-}
-
 static bool is_ip(struct sk_buff *skb, const struct odp_flow_key *key)
 {
 	return (key->dl_type == htons(ETH_P_IP) &&
@@ -272,7 +252,7 @@ static struct sk_buff *set_nw_addr(struct sk_buff *skb,
 
 	check = get_l4_checksum(skb, key);
 	if (likely(check))
-		update_csum(check, skb, *nwaddr, a->nw_addr, 1);
+		inet_proto_csum_replace4(check, skb, *nwaddr, a->nw_addr, 1);
 	csum_replace4(&nh->check, *nwaddr, a->nw_addr);
 
 	*nwaddr = a->nw_addr;
@@ -332,7 +312,7 @@ static struct sk_buff *set_tp_port(struct sk_buff *skb,
 	 */
 	th = udp_hdr(skb);
 	port = a->type == ODPAT_SET_TP_SRC ? &th->source : &th->dest;
-	update_csum(check, skb, *port, a->tp_port, 0);
+	inet_proto_csum_replace2(check, skb, *port, a->tp_port, 0);
 	*port = a->tp_port;
 
 	return skb;
diff --git a/datapath/checksum.h b/datapath/checksum.h
index bf93179..7d65396 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 */
-- 
1.7.1





More information about the dev mailing list