|
|
1.1 root 1: /* in_cksum.c 6.1 83/07/29 */
2:
3: #include "../h/types.h"
4: #include "../h/mbuf.h"
5: #include "../netinet/in.h"
6: #include "../netinet/in_systm.h"
7:
8: #if defined(tahoe)
9: /*
10: * Checksum routine for Internet Protocol family headers.
11: *
12: * This routine is very heavily used in the network
13: * code and should be modified for each CPU to be as fast as possible.
14: *
15: * This implementation is TAHOE version.
16: */
17:
18: #undef ADDCARRY
19: #define ADDCARRY(sum) { \
20: if (sum & 0xffff0000) { \
21: sum &= 0xffff; \
22: sum++; \
23: } \
24: }
25: in_cksum(m, len)
26: register struct mbuf *m;
27: register int len;
28: {
29: union word {
30: char c[2];
31: u_short s;
32: } u;
33: register u_short *w;
34: register int sum = 0;
35: register int mlen = 0;
36:
37: for (;m && len; m = m->m_next) {
38:
39: if (m->m_len == 0) {
40: continue;
41: }
42:
43: w = mtod(m, u_short *);
44: if (mlen == -1) {
45: /*
46: * The first byte of this mbuf is the continuation
47: * of a word spanning between this mbuf and the
48: * last mbuf.
49: */
50:
51: /* u.c[0] is already saved when scanning previous
52: * mbuf.
53: */
54: u.c[1] = *(u_char *)w;
55: sum += u.s;
56: ADDCARRY(sum);
57:
58: w = (u_short *)((char *)w + 1);
59: mlen = m->m_len - 1;
60: len--;
61: } else
62: mlen = m->m_len;
63:
64: if (len < mlen)
65: mlen = len;
66: len -= mlen;
67:
68: /*
69: * add by words.
70: */
71: while ((mlen -= 2) >= 0) {
72:
73: if ((int)w & 0x1) {
74: /* word is not aligned */
75: u.c[0] = *(char *)w;
76: u.c[1] = *((char *)w+1);
77: sum += u.s;
78: w++;
79: }
80: else {
81: sum += *w++;
82: }
83: ADDCARRY(sum);
84: }
85: if (mlen == -1) {
86: /*
87: * This mbuf has odd number of bytes.
88: * There could be a word split betwen
89: * this mbuf and the next mbuf.
90: * Save the last byte (to prepend to next mbuf).
91: */
92: u.c[0] = *(u_char *)w;
93: }
94: }
95: if (len)
96: printf("cksum: out of data\n");
97: if (mlen == -1) {
98: /* The last mbuf has odd # of bytes. Follow the
99: standard (the odd byte is shifted left by 8 bits) */
100: u.c[1] = 0;
101: sum += u.s;
102: ADDCARRY(sum);
103: }
104: done:
105: return (~sum & 0xffff);
106: }
107: #endif
108:
109: #if defined(vax)
110:
111: /*
112: * Checksum routine for Internet Protocol family headers (VAX Version).
113: *
114: * This routine is very heavily used in the network
115: * code and should be modified for each CPU to be as fast as possible.
116: */
117:
118: in_cksum(m, len)
119: register struct mbuf *m;
120: register int len;
121: {
122: register u_short *w; /* on Tahoe, known to be r10 */
123: register int sum = 0; /* on Tahoe, known to be r9 */
124: register int mlen = 0;
125:
126: for (;;) {
127: /*
128: * Each trip around loop adds in
129: * word from one mbuf segment.
130: */
131: w = mtod(m, u_short *);
132: if (mlen == -1) {
133: /*
134: * There is a byte left from the last segment;
135: * add it into the checksum. Don't have to worry
136: * about a carry-out here because we make sure
137: * that high part of (32 bit) sum is small below.
138: */
139: sum += *(u_char *)w << 8;
140: w = (u_short *)((char *)w + 1);
141: mlen = m->m_len - 1;
142: len--;
143: } else
144: mlen = m->m_len;
145: m = m->m_next;
146: if (len < mlen)
147: mlen = len;
148: len -= mlen;
149: /*
150: * Force to long boundary so we do longword aligned
151: * memory operations.
152: */
153: if (((int)w&0x1) && mlen >= 1) {
154: sum += *(u_char *)w++;
155: mlen -= 1;
156: }
157: if (((int)w&0x2) && mlen >= 2) {
158: sum += *w++;
159: mlen -= 2;
160: }
161: /*
162: * Do as much of the checksum as possible 32 bits at at time.
163: * In fact, this loop is unrolled to make overhead from
164: * branches &c small.
165: *
166: * We can do a 16 bit ones complement sum 32 bits at a time
167: * because the 32 bit register is acting as two 16 bit
168: * registers for adding, with carries from the low added
169: * into the high (by normal carry-chaining) and carries
170: * from the high carried into the low on the next word
171: * by use of the adwc instruction. This lets us run
172: * this loop at almost memory speed.
173: *
174: * Here there is the danger of high order carry out, and
175: * we carefully use adwc.
176: */
177: while ((mlen -= 32) >= 0) {
178: #undef ADD
179: asm("clrl r0"); /* clears carry */
180: #define ADD asm("adwc (r10),r9;addl2 $4,r10; ");
181: ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD;
182: asm("adwc $0,r9");
183: }
184: mlen += 32;
185: while ((mlen -= 8) >= 0) {
186: asm("clrl r0");
187: ADD; ADD;
188: asm("adwc $0,r9");
189: }
190: mlen += 8;
191: /*
192: * Now eliminate the possibility of carry-out's by
193: * folding back to a 16 bit number (adding high and
194: * low parts together.) Then mop up trailing words
195: * and maybe an odd byte.
196: */
197: { asm("shal $-16,r9,r0; addw2 r0,r9");
198: asm("adwc $0,r9; movzwl r9,r9"); }
199: while ((mlen -= 2) >= 0) {
200: asm("movzwl (r10),r0;addl2 $4,r10; addl2 r0,r9");
201: }
202: if (mlen == -1) {
203: sum += *(u_char *)w;
204: }
205: if (len == 0)
206: break;
207: /*
208: * Locate the next block with some data.
209: * If there is a word split across a boundary we
210: * will wrap to the top with mlen == -1 and
211: * then add it in shifted appropriately.
212: */
213: for (;;) {
214: if (m == 0) {
215: printf("cksum: out of data\n");
216: goto done;
217: }
218: if (m->m_len)
219: break;
220: m = m->m_next;
221: }
222: }
223: done:
224: /*
225: * Add together high and low parts of sum
226: * and carry to get cksum.
227: * Have to be careful to not drop the last
228: * carry here.
229: */
230: { asm("shal $-16,r9,r0; addw2 r0,r9; adwc $0,r9");
231: asm("mcoml r9,r9; movzwl r9,r9"); }
232: return (sum);
233: }
234: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.