net: core: add function for incremental IPv6 pseudo header checksum updates
authorPatrick McHardy <kaber@trash.net>
Sun, 26 Aug 2012 17:14:10 +0000 (19:14 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 30 Aug 2012 01:00:16 +0000 (03:00 +0200)
Add inet_proto_csum_replace16 for incrementally updating IPv6 pseudo header
checksums for IPv6 NAT.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Acked-by: David S. Miller <davem@davemloft.net>
include/net/checksum.h
net/core/utils.c

index ba55d8b8c87cb5438f87fad5ae01d2aee77d59ab..600d1d705bb86f23b00a8d0feebabe6ea303934d 100644 (file)
@@ -109,6 +109,9 @@ static inline void csum_replace2(__sum16 *sum, __be16 from, __be16 to)
 struct sk_buff;
 extern void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
                                     __be32 from, __be32 to, int pseudohdr);
+extern void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
+                                     const __be32 *from, const __be32 *to,
+                                     int pseudohdr);
 
 static inline void inet_proto_csum_replace2(__sum16 *sum, struct sk_buff *skb,
                                            __be16 from, __be16 to,
index 39895a65e54ae59d35144c656c37483b43efcf87..f5613d569c23a17a806d8579d08a3b103735a84a 100644 (file)
@@ -294,6 +294,26 @@ void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
 }
 EXPORT_SYMBOL(inet_proto_csum_replace4);
 
+void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
+                              const __be32 *from, const __be32 *to,
+                              int pseudohdr)
+{
+       __be32 diff[] = {
+               ~from[0], ~from[1], ~from[2], ~from[3],
+               to[0], to[1], to[2], to[3],
+       };
+       if (skb->ip_summed != CHECKSUM_PARTIAL) {
+               *sum = csum_fold(csum_partial(diff, sizeof(diff),
+                                ~csum_unfold(*sum)));
+               if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
+                       skb->csum = ~csum_partial(diff, sizeof(diff),
+                                                 ~skb->csum);
+       } else if (pseudohdr)
+               *sum = ~csum_fold(csum_partial(diff, sizeof(diff),
+                                 csum_unfold(*sum)));
+}
+EXPORT_SYMBOL(inet_proto_csum_replace16);
+
 int mac_pton(const char *s, u8 *mac)
 {
        int i;