datapath: Try to avoid custom checksum update function.
authorJesse Gross <jesse@nicira.com>
Tue, 7 Dec 2010 02:03:37 +0000 (18:03 -0800)
committerJesse Gross <jesse@nicira.com>
Fri, 10 Dec 2010 01:43:36 +0000 (17:43 -0800)
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>
datapath/actions.c
datapath/checksum.h

index d7c571a0036cb4ef46e3c4c5d030be772d293e45..9f738e4c1b7721adcad3be4fef292fc86aab21c2 100644 (file)
@@ -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;
index bf931798a381e35b54f40b936eb19ebffdc6564c..7d653961eb5000f3451f629364886713139cae91 100644 (file)
@@ -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 */