From: Jesse Gross Date: Tue, 7 Dec 2010 01:51:33 +0000 (-0800) Subject: datapath: Correctly update IP checksum with actions. X-Git-Tag: v1.1.0~683 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=8b69563f9744877ea15bf8cb69a6bdebf8e7f477;p=sliver-openvswitch.git datapath: Correctly update IP checksum with actions. 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 Acked-by: Ben Pfaff --- diff --git a/datapath/actions.c b/datapath/actions.c index ec6a46058..d7c571a00 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -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;