1 #ifndef _ASM_X86_CHECKSUM_64_H
2 #define _ASM_X86_CHECKSUM_64_H
6 * Copyright 2002 by Andi Kleen, SuSE Labs
7 * with some code from asm-x86/checksum.h
10 #include <linux/compiler.h>
11 #include <linux/uaccess.h>
12 #include <asm/byteorder.h>
15 * csum_fold - Fold and invert a 32bit checksum.
16 * sum: 32bit unfolded sum
18 * Fold a 32bit running checksum to 16bit and invert it. This is usually
19 * the last step before putting a checksum into a packet.
20 * Make sure not to mix with 64bit checksums.
22 static inline __sum16
csum_fold(__wsum sum
)
27 : "r" ((__force u32
)sum
<< 16),
28 "0" ((__force u32
)sum
& 0xffff0000));
29 return (__force __sum16
)(~(__force u32
)sum
>> 16);
33 * This is a version of ip_compute_csum() optimized for IP headers,
34 * which always checksum on 4 octet boundaries.
36 * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
41 * ip_fast_csum - Compute the IPv4 header checksum efficiently.
43 * ihl: length of header / 4
45 static inline __sum16
ip_fast_csum(const void *iph
, unsigned int ihl
)
49 asm(" movl (%1), %0\n"
55 "1: adcl 16(%1), %0\n"
66 /* Since the input registers which are loaded with iph and ihl
67 are modified, we must also specify them as outputs, or gcc
68 will assume they contain their original values. */
69 : "=r" (sum
), "=r" (iph
), "=r" (ihl
)
70 : "1" (iph
), "2" (ihl
)
72 return (__force __sum16
)sum
;
76 * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.
77 * @saddr: source address
78 * @daddr: destination address
79 * @len: length of packet
80 * @proto: ip protocol of packet
81 * @sum: initial sum to be added in (32bit unfolded)
83 * Returns the pseudo header checksum the input data. Result is
87 csum_tcpudp_nofold(__be32 saddr
, __be32 daddr
, __u32 len
,
88 __u8 proto
, __wsum sum
)
95 : "g" (daddr
), "g" (saddr
),
96 "g" ((len
+ proto
)<<8), "0" (sum
));
102 * csum_tcpup_magic - Compute an IPv4 pseudo header checksum.
103 * @saddr: source address
104 * @daddr: destination address
105 * @len: length of packet
106 * @proto: ip protocol of packet
107 * @sum: initial sum to be added in (32bit unfolded)
109 * Returns the 16bit pseudo header checksum the input data already
110 * complemented and ready to be filled in.
112 static inline __sum16
csum_tcpudp_magic(__be32 saddr
, __be32 daddr
,
113 __u32 len
, __u8 proto
,
116 return csum_fold(csum_tcpudp_nofold(saddr
, daddr
, len
, proto
, sum
));
120 * csum_partial - Compute an internet checksum.
121 * @buff: buffer to be checksummed
122 * @len: length of buffer.
123 * @sum: initial sum to be added in (32bit unfolded)
125 * Returns the 32bit unfolded internet checksum of the buffer.
126 * Before filling it in it needs to be csum_fold()'ed.
127 * buff should be aligned to a 64bit boundary if possible.
129 extern __wsum
csum_partial(const void *buff
, int len
, __wsum sum
);
131 #define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER 1
132 #define HAVE_CSUM_COPY_USER 1
135 /* Do not call this directly. Use the wrappers below */
136 extern __visible __wsum
csum_partial_copy_generic(const void *src
, const void *dst
,
138 int *src_err_ptr
, int *dst_err_ptr
);
141 extern __wsum
csum_partial_copy_from_user(const void __user
*src
, void *dst
,
142 int len
, __wsum isum
, int *errp
);
143 extern __wsum
csum_partial_copy_to_user(const void *src
, void __user
*dst
,
144 int len
, __wsum isum
, int *errp
);
145 extern __wsum
csum_partial_copy_nocheck(const void *src
, void *dst
,
146 int len
, __wsum sum
);
148 /* Old names. To be removed. */
149 #define csum_and_copy_to_user csum_partial_copy_to_user
150 #define csum_and_copy_from_user csum_partial_copy_from_user
153 * ip_compute_csum - Compute an 16bit IP checksum.
154 * @buff: buffer address.
155 * @len: length of buffer.
157 * Returns the 16bit folded/inverted checksum of the passed buffer.
160 extern __sum16
ip_compute_csum(const void *buff
, int len
);
163 * csum_ipv6_magic - Compute checksum of an IPv6 pseudo header.
164 * @saddr: source address
165 * @daddr: destination address
166 * @len: length of packet
167 * @proto: protocol of packet
168 * @sum: initial sum (32bit unfolded) to be added in
170 * Computes an IPv6 pseudo header checksum. This sum is added the checksum
171 * into UDP/TCP packets and contains some link layer information.
172 * Returns the unfolded 32bit checksum.
177 #define _HAVE_ARCH_IPV6_CSUM 1
179 csum_ipv6_magic(const struct in6_addr
*saddr
, const struct in6_addr
*daddr
,
180 __u32 len
, __u8 proto
, __wsum sum
);
182 static inline unsigned add32_with_carry(unsigned a
, unsigned b
)
187 : "0" (a
), "rm" (b
));
191 #define HAVE_ARCH_CSUM_ADD
192 static inline __wsum
csum_add(__wsum csum
, __wsum addend
)
194 return (__force __wsum
)add32_with_carry((__force
unsigned)csum
,
195 (__force
unsigned)addend
);
198 #endif /* _ASM_X86_CHECKSUM_64_H */