]> Pileus Git - ~andy/linux/blobdiff - include/net/ip6_checksum.h
ipv6: Separate tcp offload functionality
[~andy/linux] / include / net / ip6_checksum.h
index 68e2b32cf1d6f1ed421a579c1cd19e707b3df80d..652d3d309357c8d587c313817c61261479c78e0e 100644 (file)
@@ -31,6 +31,8 @@
 #include <net/ip.h>
 #include <asm/checksum.h>
 #include <linux/in6.h>
+#include <linux/tcp.h>
+#include <linux/ipv6.h>
 
 #ifndef _HAVE_ARCH_IPV6_CSUM
 
@@ -87,8 +89,41 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
        carry = (sum < uproto);
        sum += carry;
 
-       return csum_fold((__force __wsum)csum);
+       return csum_fold((__force __wsum)sum);
 }
 
 #endif
+
+static __inline__ __sum16 tcp_v6_check(int len,
+                                  const struct in6_addr *saddr,
+                                  const struct in6_addr *daddr,
+                                  __wsum base)
+{
+       return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
+}
+
+static inline void __tcp_v6_send_check(struct sk_buff *skb,
+                                      const struct in6_addr *saddr,
+                                      const struct in6_addr *daddr)
+{
+       struct tcphdr *th = tcp_hdr(skb);
+
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
+               th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
+               skb->csum_start = skb_transport_header(skb) - skb->head;
+               skb->csum_offset = offsetof(struct tcphdr, check);
+       } else {
+               th->check = tcp_v6_check(skb->len, saddr, daddr,
+                                        csum_partial(th, th->doff << 2,
+                                                     skb->csum));
+       }
+}
+
+static inline void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb)
+{
+       struct ipv6_pinfo *np = inet6_sk(sk);
+
+       __tcp_v6_send_check(skb, &np->saddr, &np->daddr);
+}
+
 #endif