New-style prototype declarations.
[unix-history] / usr / src / sys / netns / ns_cksum.c
CommitLineData
93a804a7 1/*
250fdfd7
KS
2 * Copyright (c) 1982, 1988 Regents of the University of California.
3 * All rights reserved.
4 *
a2458a1b 5 * %sccs.include.redist.c%
250fdfd7 6 *
b28b3a13 7 * @(#)ns_cksum.c 7.6 (Berkeley) %G%
93a804a7 8 */
616d42db 9
b28b3a13
KB
10#include "sys/param.h"
11#include "sys/mbuf.h"
12
93a804a7 13/*
8f7cbd44 14 * Checksum routine for Network Systems Protocol Packets (Big-Endian).
93a804a7 15 *
250fdfd7
KS
16 * This routine is very heavily used in the network
17 * code and should be modified for each CPU to be as fast as possible.
93a804a7 18 */
250fdfd7 19
1c1b22c0
MK
20#define ADDCARRY(x) { if ((x) > 65535) (x) -= 65535; }
21#define FOLD(x) {l_util.l = (x); (x) = l_util.s[0] + l_util.s[1]; ADDCARRY(x);}
250fdfd7 22
93a804a7
SL
23u_short
24ns_cksum(m, len)
25 register struct mbuf *m;
26 register int len;
27{
250fdfd7
KS
28 register u_short *w;
29 register int sum = 0;
30 register int mlen = 0;
31 register int sum2;
32
33 union {
34 u_short s[2];
35 long l;
36 } l_util;
93a804a7 37
250fdfd7
KS
38 for (;m && len; m = m->m_next) {
39 if (m->m_len == 0)
40 continue;
41 /*
42 * Each trip around loop adds in
43 * word from one mbuf segment.
44 */
45 w = mtod(m, u_short *);
46 if (mlen == -1) {
47 /*
48 * There is a byte left from the last segment;
49 * ones-complement add it into the checksum.
50 */
51 sum += *(u_char *)w; /* Big-Endian, else << 8 */
52 sum += sum;
53 w = (u_short *)(1 + (char *)w);
54 mlen = m->m_len - 1;
55 len--;
56 FOLD(sum);
57 } else
58 mlen = m->m_len;
59 if (len < mlen)
60 mlen = len;
61 len -= mlen;
62 /*
63 * We can do a 16 bit ones complement sum using
64 * 32 bit arithmetic registers for adding,
65 * with carries from the low added
66 * into the high (by normal carry-chaining)
67 * so long as we fold back before 16 carries have occured.
68 */
69 if (1 & (int) w)
70 goto uuuuglyy;
71#ifndef TINY
72/* -DTINY reduces the size from 1250 to 550, but slows it down by 22% */
73 while ((mlen -= 32) >= 0) {
74 sum += w[0]; sum += sum; sum += w[1]; sum += sum;
75 sum += w[2]; sum += sum; sum += w[3]; sum += sum;
76 sum += w[4]; sum += sum; sum += w[5]; sum += sum;
77 sum += w[6]; sum += sum; sum += w[7]; sum += sum;
78 FOLD(sum);
79 sum += w[8]; sum += sum; sum += w[9]; sum += sum;
80 sum += w[10]; sum += sum; sum += w[11]; sum += sum;
81 sum += w[12]; sum += sum; sum += w[13]; sum += sum;
82 sum += w[14]; sum += sum; sum += w[15]; sum += sum;
83 FOLD(sum);
84 w += 16;
93a804a7 85 }
250fdfd7
KS
86 mlen += 32;
87#endif
88 while ((mlen -= 8) >= 0) {
89 sum += w[0]; sum += sum; sum += w[1]; sum += sum;
90 sum += w[2]; sum += sum; sum += w[3]; sum += sum;
91 FOLD(sum);
92 w += 4;
93 }
94 mlen += 8;
95 while ((mlen -= 2) >= 0) {
96 sum += *w++; sum += sum;
97 }
98 goto commoncase;
99uuuuglyy:
250fdfd7 100/* Big-Endian; else reverse ww and vv */
8f7cbd44
KS
101#define ww(n) (((u_char *)w)[n + n + 1])
102#define vv(n) (((u_char *)w)[n + n])
250fdfd7
KS
103 sum2 = 0;
104#ifndef TINY
105 while ((mlen -= 32) >= 0) {
106 sum += ww(0); sum += sum; sum += ww(1); sum += sum;
107 sum += ww(2); sum += sum; sum += ww(3); sum += sum;
108 sum += ww(4); sum += sum; sum += ww(5); sum += sum;
109 sum += ww(6); sum += sum; sum += ww(7); sum += sum;
110 FOLD(sum);
111 sum += ww(8); sum += sum; sum += ww(9); sum += sum;
112 sum += ww(10); sum += sum; sum += ww(11); sum += sum;
113 sum += ww(12); sum += sum; sum += ww(13); sum += sum;
114 sum += ww(14); sum += sum; sum += ww(15); sum += sum;
115 FOLD(sum);
116 sum2 += vv(0); sum2 += sum2; sum2 += vv(1); sum2 += sum2;
117 sum2 += vv(2); sum2 += sum2; sum2 += vv(3); sum2 += sum2;
118 sum2 += vv(4); sum2 += sum2; sum2 += vv(5); sum2 += sum2;
119 sum2 += vv(6); sum2 += sum2; sum2 += vv(7); sum2 += sum2;
120 FOLD(sum2);
121 sum2 += vv(8); sum2 += sum2; sum2 += vv(9); sum2 += sum2;
122 sum2 += vv(10); sum2 += sum2; sum2 += vv(11); sum2 += sum2;
123 sum2 += vv(12); sum2 += sum2; sum2 += vv(13); sum2 += sum2;
124 sum2 += vv(14); sum2 += sum2; sum2 += vv(15); sum2 += sum2;
125 FOLD(sum2);
126 w += 16;
127 }
128 mlen += 32;
93a804a7 129#endif
250fdfd7
KS
130 while ((mlen -= 8) >= 0) {
131 sum += ww(0); sum += sum; sum += ww(1); sum += sum;
132 sum += ww(2); sum += sum; sum += ww(3); sum += sum;
133 FOLD(sum);
134 sum2 += vv(0); sum2 += sum2; sum2 += vv(1); sum2 += sum2;
135 sum2 += vv(2); sum2 += sum2; sum2 += vv(3); sum2 += sum2;
136 FOLD(sum2);
137 w += 4;
138 }
139 mlen += 8;
140 while ((mlen -= 2) >= 0) {
141 sum += ww(0); sum += sum;
142 sum2 += vv(0); sum2 += sum2;
143 w++;
144 }
145 sum += (sum2 << 8);
146commoncase:
147 if (mlen == -1) {
148 sum += *(u_char *)w << 8; /* Big-Endian, else no << 8 */
149 }
150 FOLD(sum);
151 }
152 if (mlen == -1) {
153 /* We had an odd number of bytes to sum; assume a garbage
154 byte of zero and clean up */
155 sum += sum;
156 FOLD(sum);
157 }
158 /*
159 * sum has already been kept to low sixteen bits.
160 * just examine result and exit.
161 */
162 if(sum==0xffff) sum = 0;
163 return (sum);
93a804a7 164}