lint
[unix-history] / usr / src / sys / netinet / in_cksum.c
CommitLineData
7c060394
MK
1/*
2 * Copyright (c) 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 this notice is preserved and that due credit is given
7 * to the University of California at Berkeley. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
11 *
12 * @(#)in_cksum.c 7.1 (Berkeley) %G%
13 */
14
15#include "../h/types.h"
16#include "../h/mbuf.h"
17
18/*
19 * Checksum routine for Internet Protocol family headers (Portable Version).
20 *
21 * This routine is very heavily used in the network
22 * code and should be modified for each CPU to be as fast as possible.
23 */
24
25#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
26#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
27
28in_cksum_c(m, len)
29 register struct mbuf *m;
30 register int len;
31{
32 register u_short *w;
33 register int sum = 0;
34 register int mlen = 0;
35 int byte_swapped = 0;
36
37 union {
38 char c[2];
39 u_short s;
40 } s_util;
41 union {
42 u_short s[2];
43 long l;
44 } l_util;
45
46 for (;m && len; m = m->m_next) {
47 if (m->m_len == 0)
48 continue;
49 w = mtod(m, u_short *);
50 if (mlen == -1) {
51 /*
52 * The first byte of this mbuf is the continuation
53 * of a word spanning between this mbuf and the
54 * last mbuf.
55 *
56 * s_util.c[0] is already saved when scanning previous
57 * mbuf.
58 */
59 s_util.c[1] = *(char *)w;
60 sum += s_util.s;
61 w = (u_short *)((char *)w + 1);
62 mlen = m->m_len - 1;
63 len--;
64 } else
65 mlen = m->m_len;
66 if (len < mlen)
67 mlen = len;
68 len -= mlen;
69 /*
70 * Force to even boundary.
71 */
72 if ((1 & (int) w) && (mlen > 0)) {
73 REDUCE;
74 sum <<= 8;
75 s_util.c[0] = *(u_char *)w;
76 w = (u_short *)((char *)w + 1);
77 mlen--;
78 byte_swapped = 1;
79 }
80 /*
81 * Unroll the loop to make overhead from
82 * branches &c small.
83 */
84 while ((mlen -= 32) >= 0) {
85 sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
86 sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
87 sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
88 sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
89 w += 16;
90 }
91 mlen += 32;
92 while ((mlen -= 8) >= 0) {
93 sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
94 w += 4;
95 }
96 mlen += 8;
97 if (mlen == 0 && byte_swapped == 0)
98 continue;
99 REDUCE;
100 while ((mlen -= 2) >= 0) {
101 sum += *w++;
102 }
103 if (byte_swapped) {
104 REDUCE;
105 sum <<= 8;
106 byte_swapped = 0;
107 if (mlen == -1) {
108 s_util.c[1] = *(char *)w;
109 sum += s_util.s;
110 mlen = 0;
111 } else
112 mlen = -1;
113 } else if (mlen == -1)
114 s_util.c[0] = *(char *)w;
115 }
116 if (len)
117 printf("cksum: out of data\n");
118 if (mlen == -1) {
119 /* The last mbuf has odd # of bytes. Follow the
120 standard (the odd byte may be shifted left by 8 bits
121 or not as determined by endian-ness of the machine) */
122 s_util.c[1] = 0;
123 sum += s_util.s;
124 }
125 REDUCE;
126 return (~sum & 0xffff);
127}