]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netinet/in_cksum.c
ac8b2648c8cdc751495bd8cabe8b7c4fea115a32
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * Copyright (c) 1988, 1992, 1993
25 * The Regents of the University of California. All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
58 #include <sys/param.h>
60 #include <sys/kdebug.h>
62 #define DBG_FNC_IN_CKSUM NETDBG_CODE(DBG_NETIP, (3 << 8))
65 * Checksum routine for Internet Protocol family headers (Portable Version).
67 * This routine is very heavily used in the network
68 * code and should be modified for each CPU to be as fast as possible.
87 #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
92 sum = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
97 l_util.l = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
98 sum = l_util.s[0] + l_util.s[1]; \
102 #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
107 __inline
unsigned short
108 in_addword(u_short a
, u_short b
)
111 u_int32_t sum
= a
+ b
;
116 __inline
unsigned short
117 in_pseudo(u_int a
, u_int b
, u_int c
)
123 sum
= (u_int64_t
) a
+ b
+ c
;
131 register struct mbuf
*m
;
135 register int sum
= 0;
136 register int mlen
= 0;
137 int starting_on_odd
= 0;
140 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_START
, len
,0,0,0,0);
142 for (;m
&& len
; m
= m
->m_next
) {
146 w
= mtod(m
, u_short
*);
151 sum
= xsum_assym(w
, mlen
, sum
, starting_on_odd
);
162 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_END
, 0,0,0,0,0);
163 return (~sum
& 0xffff);
167 in_cksum_skip(m
, len
, skip
)
168 register struct mbuf
*m
;
173 register int sum
= 0;
174 register int mlen
= 0;
175 int starting_on_odd
= 0;
178 for (; skip
&& m
; m
= m
->m_next
) {
179 if (m
->m_len
> skip
) {
180 mlen
= m
->m_len
- skip
;
181 w
= (u_short
*)(m
->m_data
+skip
);
187 for (;m
&& len
; m
= m
->m_next
) {
191 w
= mtod(m
, u_short
*);
196 sum
= xsum_assym(w
, mlen
, sum
, starting_on_odd
);
207 return (~sum
& 0xffff);
212 in_addword(u_short a
, u_short b
)
215 u_int32_t sum
= a
+ b
;
221 in_pseudo(u_int a
, u_int b
, u_int c
)
227 sum
= (u_int64_t
) a
+ b
+ c
;
235 register struct mbuf
*m
;
239 register int sum
= 0;
240 register int mlen
= 0;
241 int byte_swapped
= 0;
245 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_START
, len
,0,0,0,0);
247 for (;m
&& len
; m
= m
->m_next
) {
250 w
= mtod(m
, u_short
*);
253 * The first byte of this mbuf is the continuation
254 * of a word spanning between this mbuf and the
257 * s_util.c[0] is already saved when scanning previous
260 s_util
.c
[1] = *(char *)w
;
262 w
= (u_short
*)((char *)w
+ 1);
271 * Force to even boundary.
273 if ((1 & (int) w
) && (mlen
> 0)) {
276 s_util
.c
[0] = *(u_char
*)w
;
277 w
= (u_short
*)((char *)w
+ 1);
282 * Unroll the loop to make overhead from
285 while ((mlen
-= 32) >= 0) {
286 sum
+= w
[0]; sum
+= w
[1]; sum
+= w
[2]; sum
+= w
[3];
287 sum
+= w
[4]; sum
+= w
[5]; sum
+= w
[6]; sum
+= w
[7];
288 sum
+= w
[8]; sum
+= w
[9]; sum
+= w
[10]; sum
+= w
[11];
289 sum
+= w
[12]; sum
+= w
[13]; sum
+= w
[14]; sum
+= w
[15];
293 while ((mlen
-= 8) >= 0) {
294 sum
+= w
[0]; sum
+= w
[1]; sum
+= w
[2]; sum
+= w
[3];
298 if (mlen
== 0 && byte_swapped
== 0)
301 while ((mlen
-= 2) >= 0) {
309 s_util
.c
[1] = *(char *)w
;
314 } else if (mlen
== -1)
315 s_util
.c
[0] = *(char *)w
;
318 printf("cksum: out of data\n");
320 /* The last mbuf has odd # of bytes. Follow the
321 standard (the odd byte may be shifted left by 8 bits
322 or not as determined by endian-ness of the machine) */
327 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_END
, 0,0,0,0,0);
328 return (~sum
& 0xffff);
332 in_cksum_skip(m
, len
, skip
)
333 register struct mbuf
*m
;
334 register u_short len
;
335 register u_short skip
;
338 register int sum
= 0;
339 register int mlen
= 0;
340 int byte_swapped
= 0;
344 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_START
, len
,0,0,0,0);
347 for (; skip
&& m
; m
= m
->m_next
) {
348 if (m
->m_len
> skip
) {
349 mlen
= m
->m_len
- skip
;
350 w
= (u_short
*)(m
->m_data
+skip
);
356 for (;m
&& len
; m
= m
->m_next
) {
359 w
= mtod(m
, u_short
*);
363 * The first byte of this mbuf is the continuation
364 * of a word spanning between this mbuf and the
367 * s_util.c[0] is already saved when scanning previous
370 s_util
.c
[1] = *(char *)w
;
372 w
= (u_short
*)((char *)w
+ 1);
384 * Force to even boundary.
386 if ((1 & (int) w
) && (mlen
> 0)) {
389 s_util
.c
[0] = *(u_char
*)w
;
390 w
= (u_short
*)((char *)w
+ 1);
395 * Unroll the loop to make overhead from
398 while ((mlen
-= 32) >= 0) {
399 sum
+= w
[0]; sum
+= w
[1]; sum
+= w
[2]; sum
+= w
[3];
400 sum
+= w
[4]; sum
+= w
[5]; sum
+= w
[6]; sum
+= w
[7];
401 sum
+= w
[8]; sum
+= w
[9]; sum
+= w
[10]; sum
+= w
[11];
402 sum
+= w
[12]; sum
+= w
[13]; sum
+= w
[14]; sum
+= w
[15];
406 while ((mlen
-= 8) >= 0) {
407 sum
+= w
[0]; sum
+= w
[1]; sum
+= w
[2]; sum
+= w
[3];
411 if (mlen
== 0 && byte_swapped
== 0)
414 while ((mlen
-= 2) >= 0) {
422 s_util
.c
[1] = *(char *)w
;
427 } else if (mlen
== -1)
428 s_util
.c
[0] = *(char *)w
;
431 printf("cksum: out of data\n");
433 /* The last mbuf has odd # of bytes. Follow the
434 standard (the odd byte may be shifted left by 8 bits
435 or not as determined by endian-ness of the machine) */
440 KERNEL_DEBUG(DBG_FNC_IN_CKSUM
| DBG_FUNC_END
, 0,0,0,0,0);
441 return (~sum
& 0xffff);