|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that the above copyright notice and this paragraph are
7: * duplicated in all such forms and that any documentation,
8: * advertising materials, and other materials related to such
9: * distribution and use acknowledge that the software was developed
10: * by the University of California, Berkeley. The name of the
11: * University may not be used to endorse or promote products derived
12: * from this software without specific prior written permission.
13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16: *
17: * @(#)ns_cksum.c 7.3 (Berkeley) 6/29/88
18: */
19:
20: #include "types.h"
21: #include "mbuf.h"
22: /*
23: * Checksum routine for Network Systems Protocol Packets (Big-Endian).
24: *
25: * This routine is very heavily used in the network
26: * code and should be modified for each CPU to be as fast as possible.
27: */
28:
29: #define ADDCARRY(x) { if ((x) > 65535) (x) -= 65535; }
30: #define FOLD(x) {l_util.l = (x); (x) = l_util.s[0] + l_util.s[1]; ADDCARRY(x);}
31:
32: u_short
33: ns_cksum(m, len)
34: register struct mbuf *m;
35: register int len;
36: {
37: register u_short *w;
38: register int sum = 0;
39: register int mlen = 0;
40: register int sum2;
41:
42: union {
43: u_short s[2];
44: long l;
45: } l_util;
46:
47: for (;m && len; m = m->m_next) {
48: if (m->m_len == 0)
49: continue;
50: /*
51: * Each trip around loop adds in
52: * word from one mbuf segment.
53: */
54: w = mtod(m, u_short *);
55: if (mlen == -1) {
56: /*
57: * There is a byte left from the last segment;
58: * ones-complement add it into the checksum.
59: */
60: sum += *(u_char *)w; /* Big-Endian, else << 8 */
61: sum += sum;
62: w = (u_short *)(1 + (char *)w);
63: mlen = m->m_len - 1;
64: len--;
65: FOLD(sum);
66: } else
67: mlen = m->m_len;
68: if (len < mlen)
69: mlen = len;
70: len -= mlen;
71: /*
72: * We can do a 16 bit ones complement sum using
73: * 32 bit arithmetic registers for adding,
74: * with carries from the low added
75: * into the high (by normal carry-chaining)
76: * so long as we fold back before 16 carries have occured.
77: */
78: if (1 & (int) w)
79: goto uuuuglyy;
80: #ifndef TINY
81: /* -DTINY reduces the size from 1250 to 550, but slows it down by 22% */
82: while ((mlen -= 32) >= 0) {
83: sum += w[0]; sum += sum; sum += w[1]; sum += sum;
84: sum += w[2]; sum += sum; sum += w[3]; sum += sum;
85: sum += w[4]; sum += sum; sum += w[5]; sum += sum;
86: sum += w[6]; sum += sum; sum += w[7]; sum += sum;
87: FOLD(sum);
88: sum += w[8]; sum += sum; sum += w[9]; sum += sum;
89: sum += w[10]; sum += sum; sum += w[11]; sum += sum;
90: sum += w[12]; sum += sum; sum += w[13]; sum += sum;
91: sum += w[14]; sum += sum; sum += w[15]; sum += sum;
92: FOLD(sum);
93: w += 16;
94: }
95: mlen += 32;
96: #endif
97: while ((mlen -= 8) >= 0) {
98: sum += w[0]; sum += sum; sum += w[1]; sum += sum;
99: sum += w[2]; sum += sum; sum += w[3]; sum += sum;
100: FOLD(sum);
101: w += 4;
102: }
103: mlen += 8;
104: while ((mlen -= 2) >= 0) {
105: sum += *w++; sum += sum;
106: }
107: goto commoncase;
108: uuuuglyy:
109: /* Big-Endian; else reverse ww and vv */
110: #define ww(n) (((u_char *)w)[n + n + 1])
111: #define vv(n) (((u_char *)w)[n + n])
112: sum2 = 0;
113: #ifndef TINY
114: while ((mlen -= 32) >= 0) {
115: sum += ww(0); sum += sum; sum += ww(1); sum += sum;
116: sum += ww(2); sum += sum; sum += ww(3); sum += sum;
117: sum += ww(4); sum += sum; sum += ww(5); sum += sum;
118: sum += ww(6); sum += sum; sum += ww(7); sum += sum;
119: FOLD(sum);
120: sum += ww(8); sum += sum; sum += ww(9); sum += sum;
121: sum += ww(10); sum += sum; sum += ww(11); sum += sum;
122: sum += ww(12); sum += sum; sum += ww(13); sum += sum;
123: sum += ww(14); sum += sum; sum += ww(15); sum += sum;
124: FOLD(sum);
125: sum2 += vv(0); sum2 += sum2; sum2 += vv(1); sum2 += sum2;
126: sum2 += vv(2); sum2 += sum2; sum2 += vv(3); sum2 += sum2;
127: sum2 += vv(4); sum2 += sum2; sum2 += vv(5); sum2 += sum2;
128: sum2 += vv(6); sum2 += sum2; sum2 += vv(7); sum2 += sum2;
129: FOLD(sum2);
130: sum2 += vv(8); sum2 += sum2; sum2 += vv(9); sum2 += sum2;
131: sum2 += vv(10); sum2 += sum2; sum2 += vv(11); sum2 += sum2;
132: sum2 += vv(12); sum2 += sum2; sum2 += vv(13); sum2 += sum2;
133: sum2 += vv(14); sum2 += sum2; sum2 += vv(15); sum2 += sum2;
134: FOLD(sum2);
135: w += 16;
136: }
137: mlen += 32;
138: #endif
139: while ((mlen -= 8) >= 0) {
140: sum += ww(0); sum += sum; sum += ww(1); sum += sum;
141: sum += ww(2); sum += sum; sum += ww(3); sum += sum;
142: FOLD(sum);
143: sum2 += vv(0); sum2 += sum2; sum2 += vv(1); sum2 += sum2;
144: sum2 += vv(2); sum2 += sum2; sum2 += vv(3); sum2 += sum2;
145: FOLD(sum2);
146: w += 4;
147: }
148: mlen += 8;
149: while ((mlen -= 2) >= 0) {
150: sum += ww(0); sum += sum;
151: sum2 += vv(0); sum2 += sum2;
152: w++;
153: }
154: sum += (sum2 << 8);
155: commoncase:
156: if (mlen == -1) {
157: sum += *(u_char *)w << 8; /* Big-Endian, else no << 8 */
158: }
159: FOLD(sum);
160: }
161: if (mlen == -1) {
162: /* We had an odd number of bytes to sum; assume a garbage
163: byte of zero and clean up */
164: sum += sum;
165: FOLD(sum);
166: }
167: /*
168: * sum has already been kept to low sixteen bits.
169: * just examine result and exit.
170: */
171: if(sum==0xffff) sum = 0;
172: return (sum);
173: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.