datapath: Correctly update IP checksum with actions.
authorJesse Gross <jesse@nicira.com>
Tue, 7 Dec 2010 01:51:33 +0000 (17:51 -0800)
committerJesse Gross <jesse@nicira.com>
Fri, 10 Dec 2010 01:43:36 +0000 (17:43 -0800)
The update_csum() function that we currently use to update
checksums on actions is really intended for L4 checksums.  In
particular, if the packet has a partial checksum and the field
is not in the pseudo header, it doesn't do anything at all.
This doesn't make sense for the IP header because Linux doesn't
use hardware offload for it, so we always need to recompute the
checksum.  Instead, we can use the kernel function csum_replace4(),
which will always do the right thing.

Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
datapath/actions.c

index ec6a46058f1326b1963c2728047a012e411cc357..d7c571a0036cb4ef46e3c4c5d030be772d293e45 100644 (file)
@@ -273,7 +273,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);
-       update_csum(&nh->check, skb, *nwaddr, a->nw_addr, 0);
+       csum_replace4(&nh->check, *nwaddr, a->nw_addr);
 
        *nwaddr = a->nw_addr;
 
@@ -296,8 +296,8 @@ static struct sk_buff *set_nw_tos(struct sk_buff *skb,
 
                /* Set the DSCP bits and preserve the ECN bits. */
                new = a->nw_tos | (nh->tos & INET_ECN_MASK);
-               update_csum(&nh->check, skb, htons((u16)old),
-                           htons((u16)new), 0);
+               csum_replace4(&nh->check, (__force __be32)old,
+                                         (__force __be32)new);
                *f = new;
        }
        return skb;