VROOT flag is set in union_allocvp
[unix-history] / usr / src / sys / netns / ns_cksum.c
CommitLineData
93a804a7 1/*
99315dca
KB
2 * Copyright (c) 1982, 1992, 1993
3 * The Regents of the University of California. All rights reserved.
250fdfd7 4 *
a2458a1b 5 * %sccs.include.redist.c%
250fdfd7 6 *
99315dca 7 * @(#)ns_cksum.c 8.1 (Berkeley) %G%
93a804a7 8 */
616d42db 9
5548a02f
KB
10#include <sys/param.h>
11#include <sys/mbuf.h>
b28b3a13 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 */
613ea68b
KS
51#if BYTE_ORDER == BIG_ENDIAN
52 sum += *(u_char *)w;
53#else
54 sum += *(u_char *)w << 8;
55#endif
250fdfd7
KS
56 sum += sum;
57 w = (u_short *)(1 + (char *)w);
58 mlen = m->m_len - 1;
59 len--;
60 FOLD(sum);
61 } else
62 mlen = m->m_len;
63 if (len < mlen)
64 mlen = len;
65 len -= mlen;
66 /*
67 * We can do a 16 bit ones complement sum using
68 * 32 bit arithmetic registers for adding,
69 * with carries from the low added
70 * into the high (by normal carry-chaining)
71 * so long as we fold back before 16 carries have occured.
72 */
73 if (1 & (int) w)
74 goto uuuuglyy;
75#ifndef TINY
76/* -DTINY reduces the size from 1250 to 550, but slows it down by 22% */
77 while ((mlen -= 32) >= 0) {
78 sum += w[0]; sum += sum; sum += w[1]; sum += sum;
79 sum += w[2]; sum += sum; sum += w[3]; sum += sum;
80 sum += w[4]; sum += sum; sum += w[5]; sum += sum;
81 sum += w[6]; sum += sum; sum += w[7]; sum += sum;
82 FOLD(sum);
83 sum += w[8]; sum += sum; sum += w[9]; sum += sum;
84 sum += w[10]; sum += sum; sum += w[11]; sum += sum;
85 sum += w[12]; sum += sum; sum += w[13]; sum += sum;
86 sum += w[14]; sum += sum; sum += w[15]; sum += sum;
87 FOLD(sum);
88 w += 16;
93a804a7 89 }
250fdfd7
KS
90 mlen += 32;
91#endif
92 while ((mlen -= 8) >= 0) {
93 sum += w[0]; sum += sum; sum += w[1]; sum += sum;
94 sum += w[2]; sum += sum; sum += w[3]; sum += sum;
95 FOLD(sum);
96 w += 4;
97 }
98 mlen += 8;
99 while ((mlen -= 2) >= 0) {
100 sum += *w++; sum += sum;
101 }
102 goto commoncase;
103uuuuglyy:
613ea68b 104#if BYTE_ORDER == BIG_ENDIAN
8f7cbd44
KS
105#define ww(n) (((u_char *)w)[n + n + 1])
106#define vv(n) (((u_char *)w)[n + n])
613ea68b
KS
107#else
108#if BYTE_ORDER == LITTLE_ENDIAN
109#define vv(n) (((u_char *)w)[n + n + 1])
110#define ww(n) (((u_char *)w)[n + n])
111#endif
112#endif
250fdfd7
KS
113 sum2 = 0;
114#ifndef TINY
115 while ((mlen -= 32) >= 0) {
116 sum += ww(0); sum += sum; sum += ww(1); sum += sum;
117 sum += ww(2); sum += sum; sum += ww(3); sum += sum;
118 sum += ww(4); sum += sum; sum += ww(5); sum += sum;
119 sum += ww(6); sum += sum; sum += ww(7); sum += sum;
120 FOLD(sum);
121 sum += ww(8); sum += sum; sum += ww(9); sum += sum;
122 sum += ww(10); sum += sum; sum += ww(11); sum += sum;
123 sum += ww(12); sum += sum; sum += ww(13); sum += sum;
124 sum += ww(14); sum += sum; sum += ww(15); sum += sum;
125 FOLD(sum);
126 sum2 += vv(0); sum2 += sum2; sum2 += vv(1); sum2 += sum2;
127 sum2 += vv(2); sum2 += sum2; sum2 += vv(3); sum2 += sum2;
128 sum2 += vv(4); sum2 += sum2; sum2 += vv(5); sum2 += sum2;
129 sum2 += vv(6); sum2 += sum2; sum2 += vv(7); sum2 += sum2;
130 FOLD(sum2);
131 sum2 += vv(8); sum2 += sum2; sum2 += vv(9); sum2 += sum2;
132 sum2 += vv(10); sum2 += sum2; sum2 += vv(11); sum2 += sum2;
133 sum2 += vv(12); sum2 += sum2; sum2 += vv(13); sum2 += sum2;
134 sum2 += vv(14); sum2 += sum2; sum2 += vv(15); sum2 += sum2;
135 FOLD(sum2);
136 w += 16;
137 }
138 mlen += 32;
93a804a7 139#endif
250fdfd7
KS
140 while ((mlen -= 8) >= 0) {
141 sum += ww(0); sum += sum; sum += ww(1); sum += sum;
142 sum += ww(2); sum += sum; sum += ww(3); sum += sum;
143 FOLD(sum);
144 sum2 += vv(0); sum2 += sum2; sum2 += vv(1); sum2 += sum2;
145 sum2 += vv(2); sum2 += sum2; sum2 += vv(3); sum2 += sum2;
146 FOLD(sum2);
147 w += 4;
148 }
149 mlen += 8;
150 while ((mlen -= 2) >= 0) {
151 sum += ww(0); sum += sum;
152 sum2 += vv(0); sum2 += sum2;
153 w++;
154 }
155 sum += (sum2 << 8);
156commoncase:
157 if (mlen == -1) {
613ea68b
KS
158#if BYTE_ORDER == BIG_ENDIAN
159 sum += *(u_char *)w << 8;
160#else
161 sum += *(u_char *)w;
162#endif
250fdfd7
KS
163 }
164 FOLD(sum);
165 }
166 if (mlen == -1) {
167 /* We had an odd number of bytes to sum; assume a garbage
168 byte of zero and clean up */
169 sum += sum;
170 FOLD(sum);
171 }
172 /*
173 * sum has already been kept to low sixteen bits.
174 * just examine result and exit.
175 */
176 if(sum==0xffff) sum = 0;
177 return (sum);
93a804a7 178}