Annotation of sys/netinet/in_cksum.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: in_cksum.c,v 1.6 2003/12/10 07:22:43 itojun Exp $ */
2: /* $NetBSD: in_cksum.c,v 1.11 1996/04/08 19:55:37 jonathan Exp $ */
3:
4: /*
5: * Copyright (c) 1988, 1992, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. Neither the name of the University nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: *
32: * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
33: */
34:
35: #include <sys/param.h>
36: #include <sys/mbuf.h>
37: #include <sys/systm.h>
38: #include <netinet/in.h>
39:
40: /*
41: * Checksum routine for Internet Protocol family headers (Portable Version).
42: *
43: * This routine is very heavily used in the network
44: * code and should be modified for each CPU to be as fast as possible.
45: */
46:
47: #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
48: #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
49:
50: int
51: in_cksum(m, len)
52: struct mbuf *m;
53: int len;
54: {
55: u_int16_t *w;
56: int sum = 0;
57: int mlen = 0;
58: int byte_swapped = 0;
59:
60: union {
61: u_int8_t c[2];
62: u_int16_t s;
63: } s_util;
64: union {
65: u_int16_t s[2];
66: u_int32_t l;
67: } l_util;
68:
69: for (;m && len; m = m->m_next) {
70: if (m->m_len == 0)
71: continue;
72: w = mtod(m, u_int16_t *);
73: if (mlen == -1) {
74: /*
75: * The first byte of this mbuf is the continuation
76: * of a word spanning between this mbuf and the
77: * last mbuf.
78: *
79: * s_util.c[0] is already saved when scanning previous
80: * mbuf.
81: */
82: s_util.c[1] = *(u_int8_t *)w;
83: sum += s_util.s;
84: w = (u_int16_t *)((u_int8_t *)w + 1);
85: mlen = m->m_len - 1;
86: len--;
87: } else
88: mlen = m->m_len;
89: if (len < mlen)
90: mlen = len;
91: len -= mlen;
92: /*
93: * Force to even boundary.
94: */
95: if ((1 & (long) w) && (mlen > 0)) {
96: REDUCE;
97: sum <<= 8;
98: s_util.c[0] = *(u_int8_t *)w;
99: w = (u_int16_t *)((int8_t *)w + 1);
100: mlen--;
101: byte_swapped = 1;
102: }
103: /*
104: * Unroll the loop to make overhead from
105: * branches &c small.
106: */
107: while ((mlen -= 32) >= 0) {
108: sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
109: sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
110: sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
111: sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
112: w += 16;
113: }
114: mlen += 32;
115: while ((mlen -= 8) >= 0) {
116: sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
117: w += 4;
118: }
119: mlen += 8;
120: if (mlen == 0 && byte_swapped == 0)
121: continue;
122: REDUCE;
123: while ((mlen -= 2) >= 0) {
124: sum += *w++;
125: }
126: if (byte_swapped) {
127: REDUCE;
128: sum <<= 8;
129: byte_swapped = 0;
130: if (mlen == -1) {
131: s_util.c[1] = *(u_int8_t *)w;
132: sum += s_util.s;
133: mlen = 0;
134: } else
135: mlen = -1;
136: } else if (mlen == -1)
137: s_util.c[0] = *(u_int8_t *)w;
138: }
139: if (len)
140: printf("cksum: out of data\n");
141: if (mlen == -1) {
142: /* The last mbuf has odd # of bytes. Follow the
143: standard (the odd byte may be shifted left by 8 bits
144: or not as determined by endian-ness of the machine) */
145: s_util.c[1] = 0;
146: sum += s_util.s;
147: }
148: REDUCE;
149: return (~sum & 0xffff);
150: }
CVSweb