1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/module.h>
14#include <linux/string.h>
15
16#include <asm/byteorder.h>
17
18static inline unsigned short
19from64to16 (unsigned long x)
20{
21
22 x = (x & 0xffffffff) + (x >> 32);
23
24 x = (x & 0xffff) + (x >> 16);
25
26 x = (x & 0xffff) + (x >> 16);
27
28 x = (x & 0xffff) + (x >> 16);
29 return x;
30}
31
32
33
34
35
36__sum16
37csum_tcpudp_magic (__be32 saddr, __be32 daddr, unsigned short len,
38 unsigned short proto, __wsum sum)
39{
40 return (__force __sum16)~from64to16(
41 (__force u64)saddr + (__force u64)daddr +
42 (__force u64)sum + ((len + proto) << 8));
43}
44
45EXPORT_SYMBOL(csum_tcpudp_magic);
46
47__wsum
48csum_tcpudp_nofold (__be32 saddr, __be32 daddr, unsigned short len,
49 unsigned short proto, __wsum sum)
50{
51 unsigned long result;
52
53 result = (__force u64)saddr + (__force u64)daddr +
54 (__force u64)sum + ((len + proto) << 8);
55
56
57
58 result = (result & 0xffffffff) + (result >> 32);
59
60 result = (result & 0xffffffff) + (result >> 32);
61 return (__force __wsum)result;
62}
63EXPORT_SYMBOL(csum_tcpudp_nofold);
64
65extern unsigned long do_csum (const unsigned char *, long);
66
67
68
69
70
71
72
73
74
75
76
77
78
79__wsum csum_partial(const void *buff, int len, __wsum sum)
80{
81 u64 result = do_csum(buff, len);
82
83
84 result += (__force u32)sum;
85
86 result = (result & 0xffffffff) + (result >> 32);
87 return (__force __wsum)result;
88}
89
90EXPORT_SYMBOL(csum_partial);
91
92
93
94
95
96__sum16 ip_compute_csum (const void *buff, int len)
97{
98 return (__force __sum16)~do_csum(buff,len);
99}
100
101EXPORT_SYMBOL(ip_compute_csum);
102