]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netinet/in_cksum.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1988, 1992, 1993
27 * The Regents of the University of California. All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by the University of
40 * California, Berkeley and its contributors.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
60 #include <sys/param.h>
62 #include <sys/kdebug.h>
64 #define DBG_FNC_IN_CKSUM NETDBG_CODE(DBG_NETIP, (3 << 8))
67 * Checksum routine for Internet Protocol family headers (Portable Version).
69 * This routine is very heavily used in the network
70 * code and should be modified for each CPU to be as fast as possible.
89 #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
94 sum = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
99 l_util.l = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
100 sum = l_util.s[0] + l_util.s[1]; \
104 #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
109 __inline
unsigned short
110 in_addword(u_short a
, u_short b
)
113 u_int32_t sum
= a
+ b
;
118 __inline
unsigned short
119 in_pseudo(u_int a
, u_int b
, u_int c
)
125 sum
= (u_int64_t
) a
+ b
+ c
;
133 register struct mbuf
*m
;
137 register int sum
= 0;
138 register int mlen
= 0;
139 int starting_on_odd
= 0;
142 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_START
, len
,0,0,0,0);
144 for (;m
&& len
; m
= m
->m_next
) {
148 w
= mtod(m
, u_short
*);
153 sum
= xsum_assym(w
, mlen
, sum
, starting_on_odd
);
164 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_END
, 0,0,0,0,0);
165 return (~sum
& 0xffff);
169 in_cksum_skip(m
, len
, skip
)
170 register struct mbuf
*m
;
175 register int sum
= 0;
176 register int mlen
= 0;
177 int starting_on_odd
= 0;
180 for (; skip
&& m
; m
= m
->m_next
) {
181 if (m
->m_len
> skip
) {
182 mlen
= m
->m_len
- skip
;
183 w
= (u_short
*)(m
->m_data
+skip
);
189 for (;m
&& len
; m
= m
->m_next
) {
193 w
= mtod(m
, u_short
*);
198 sum
= xsum_assym(w
, mlen
, sum
, starting_on_odd
);
209 return (~sum
& 0xffff);
214 in_addword(u_short a
, u_short b
)
217 u_int32_t sum
= a
+ b
;
223 in_pseudo(u_int a
, u_int b
, u_int c
)
229 sum
= (u_int64_t
) a
+ b
+ c
;
237 register struct mbuf
*m
;
241 register int sum
= 0;
242 register int mlen
= 0;
243 int byte_swapped
= 0;
247 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_START
, len
,0,0,0,0);
249 for (;m
&& len
; m
= m
->m_next
) {
252 w
= mtod(m
, u_short
*);
255 * The first byte of this mbuf is the continuation
256 * of a word spanning between this mbuf and the
259 * s_util.c[0] is already saved when scanning previous
262 s_util
.c
[1] = *(char *)w
;
264 w
= (u_short
*)((char *)w
+ 1);
273 * Force to even boundary.
275 if ((1 & (int) w
) && (mlen
> 0)) {
278 s_util
.c
[0] = *(u_char
*)w
;
279 w
= (u_short
*)((char *)w
+ 1);
284 * Unroll the loop to make overhead from
287 while ((mlen
-= 32) >= 0) {
288 sum
+= w
[0]; sum
+= w
[1]; sum
+= w
[2]; sum
+= w
[3];
289 sum
+= w
[4]; sum
+= w
[5]; sum
+= w
[6]; sum
+= w
[7];
290 sum
+= w
[8]; sum
+= w
[9]; sum
+= w
[10]; sum
+= w
[11];
291 sum
+= w
[12]; sum
+= w
[13]; sum
+= w
[14]; sum
+= w
[15];
295 while ((mlen
-= 8) >= 0) {
296 sum
+= w
[0]; sum
+= w
[1]; sum
+= w
[2]; sum
+= w
[3];
300 if (mlen
== 0 && byte_swapped
== 0)
303 while ((mlen
-= 2) >= 0) {
311 s_util
.c
[1] = *(char *)w
;
316 } else if (mlen
== -1)
317 s_util
.c
[0] = *(char *)w
;
320 printf("cksum: out of data\n");
322 /* The last mbuf has odd # of bytes. Follow the
323 standard (the odd byte may be shifted left by 8 bits
324 or not as determined by endian-ness of the machine) */
329 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_END
, 0,0,0,0,0);
330 return (~sum
& 0xffff);
334 in_cksum_skip(m
, len
, skip
)
335 register struct mbuf
*m
;
336 register u_short len
;
337 register u_short skip
;
340 register int sum
= 0;
341 register int mlen
= 0;
342 int byte_swapped
= 0;
346 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_START
, len
,0,0,0,0);
349 for (; skip
&& m
; m
= m
->m_next
) {
350 if (m
->m_len
> skip
) {
351 mlen
= m
->m_len
- skip
;
352 w
= (u_short
*)(m
->m_data
+skip
);
358 for (;m
&& len
; m
= m
->m_next
) {
361 w
= mtod(m
, u_short
*);
365 * The first byte of this mbuf is the continuation
366 * of a word spanning between this mbuf and the
369 * s_util.c[0] is already saved when scanning previous
372 s_util
.c
[1] = *(char *)w
;
374 w
= (u_short
*)((char *)w
+ 1);
386 * Force to even boundary.
388 if ((1 & (int) w
) && (mlen
> 0)) {
391 s_util
.c
[0] = *(u_char
*)w
;
392 w
= (u_short
*)((char *)w
+ 1);
397 * Unroll the loop to make overhead from
400 while ((mlen
-= 32) >= 0) {
401 sum
+= w
[0]; sum
+= w
[1]; sum
+= w
[2]; sum
+= w
[3];
402 sum
+= w
[4]; sum
+= w
[5]; sum
+= w
[6]; sum
+= w
[7];
403 sum
+= w
[8]; sum
+= w
[9]; sum
+= w
[10]; sum
+= w
[11];
404 sum
+= w
[12]; sum
+= w
[13]; sum
+= w
[14]; sum
+= w
[15];
408 while ((mlen
-= 8) >= 0) {
409 sum
+= w
[0]; sum
+= w
[1]; sum
+= w
[2]; sum
+= w
[3];
413 if (mlen
== 0 && byte_swapped
== 0)
416 while ((mlen
-= 2) >= 0) {
424 s_util
.c
[1] = *(char *)w
;
429 } else if (mlen
== -1)
430 s_util
.c
[0] = *(char *)w
;
433 printf("cksum: out of data\n");
435 /* The last mbuf has odd # of bytes. Follow the
436 standard (the odd byte may be shifted left by 8 bits
437 or not as determined by endian-ness of the machine) */
442 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_END
, 0,0,0,0,0);
443 return (~sum
& 0xffff);