From e7d737d175dfe53436b356445ecb154541d2afff Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Mon, 6 Dec 2010 18:03:37 -0800 Subject: [PATCH] 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 Acked-by: Ben Pfaff --- 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 d7c571a0..9f738e4c 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 bf931798..7d653961 100644 --- a/datapath/checksum.h +++ b/datapath/checksum.h @@ -12,6 +12,8 @@ #include #include +#include + #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 */ -- 2.30.2