Annotation of sys/netinet/in_cksum.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: in_cksum.c,v 1.6 2003/12/10 07:22:43 itojun Exp $ */
! 2: /* $NetBSD: in_cksum.c,v 1.11 1996/04/08 19:55:37 jonathan Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1988, 1992, 1993
! 6: * The Regents of the University of California. All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: * 3. Neither the name of the University nor the names of its contributors
! 17: * may be used to endorse or promote products derived from this software
! 18: * without specific prior written permission.
! 19: *
! 20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 30: * SUCH DAMAGE.
! 31: *
! 32: * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
! 33: */
! 34:
! 35: #include <sys/param.h>
! 36: #include <sys/mbuf.h>
! 37: #include <sys/systm.h>
! 38: #include <netinet/in.h>
! 39:
! 40: /*
! 41: * Checksum routine for Internet Protocol family headers (Portable Version).
! 42: *
! 43: * This routine is very heavily used in the network
! 44: * code and should be modified for each CPU to be as fast as possible.
! 45: */
! 46:
! 47: #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
! 48: #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
! 49:
! 50: int
! 51: in_cksum(m, len)
! 52: struct mbuf *m;
! 53: int len;
! 54: {
! 55: u_int16_t *w;
! 56: int sum = 0;
! 57: int mlen = 0;
! 58: int byte_swapped = 0;
! 59:
! 60: union {
! 61: u_int8_t c[2];
! 62: u_int16_t s;
! 63: } s_util;
! 64: union {
! 65: u_int16_t s[2];
! 66: u_int32_t l;
! 67: } l_util;
! 68:
! 69: for (;m && len; m = m->m_next) {
! 70: if (m->m_len == 0)
! 71: continue;
! 72: w = mtod(m, u_int16_t *);
! 73: if (mlen == -1) {
! 74: /*
! 75: * The first byte of this mbuf is the continuation
! 76: * of a word spanning between this mbuf and the
! 77: * last mbuf.
! 78: *
! 79: * s_util.c[0] is already saved when scanning previous
! 80: * mbuf.
! 81: */
! 82: s_util.c[1] = *(u_int8_t *)w;
! 83: sum += s_util.s;
! 84: w = (u_int16_t *)((u_int8_t *)w + 1);
! 85: mlen = m->m_len - 1;
! 86: len--;
! 87: } else
! 88: mlen = m->m_len;
! 89: if (len < mlen)
! 90: mlen = len;
! 91: len -= mlen;
! 92: /*
! 93: * Force to even boundary.
! 94: */
! 95: if ((1 & (long) w) && (mlen > 0)) {
! 96: REDUCE;
! 97: sum <<= 8;
! 98: s_util.c[0] = *(u_int8_t *)w;
! 99: w = (u_int16_t *)((int8_t *)w + 1);
! 100: mlen--;
! 101: byte_swapped = 1;
! 102: }
! 103: /*
! 104: * Unroll the loop to make overhead from
! 105: * branches &c small.
! 106: */
! 107: while ((mlen -= 32) >= 0) {
! 108: sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
! 109: sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
! 110: sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
! 111: sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
! 112: w += 16;
! 113: }
! 114: mlen += 32;
! 115: while ((mlen -= 8) >= 0) {
! 116: sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
! 117: w += 4;
! 118: }
! 119: mlen += 8;
! 120: if (mlen == 0 && byte_swapped == 0)
! 121: continue;
! 122: REDUCE;
! 123: while ((mlen -= 2) >= 0) {
! 124: sum += *w++;
! 125: }
! 126: if (byte_swapped) {
! 127: REDUCE;
! 128: sum <<= 8;
! 129: byte_swapped = 0;
! 130: if (mlen == -1) {
! 131: s_util.c[1] = *(u_int8_t *)w;
! 132: sum += s_util.s;
! 133: mlen = 0;
! 134: } else
! 135: mlen = -1;
! 136: } else if (mlen == -1)
! 137: s_util.c[0] = *(u_int8_t *)w;
! 138: }
! 139: if (len)
! 140: printf("cksum: out of data\n");
! 141: if (mlen == -1) {
! 142: /* The last mbuf has odd # of bytes. Follow the
! 143: standard (the odd byte may be shifted left by 8 bits
! 144: or not as determined by endian-ness of the machine) */
! 145: s_util.c[1] = 0;
! 146: sum += s_util.s;
! 147: }
! 148: REDUCE;
! 149: return (~sum & 0xffff);
! 150: }
CVSweb