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