ipx_cksum.c revision 11991
111819Sjulian/* 211819Sjulian * Copyright (c) 1995, Mike Mitchell 311819Sjulian * Copyright (c) 1982, 1992, 1993 411819Sjulian * The Regents of the University of California. All rights reserved. 511819Sjulian * 611819Sjulian * Redistribution and use in source and binary forms, with or without 711819Sjulian * modification, are permitted provided that the following conditions 811819Sjulian * are met: 911819Sjulian * 1. Redistributions of source code must retain the above copyright 1011819Sjulian * notice, this list of conditions and the following disclaimer. 1111819Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1211819Sjulian * notice, this list of conditions and the following disclaimer in the 1311819Sjulian * documentation and/or other materials provided with the distribution. 1411819Sjulian * 3. All advertising materials mentioning features or use of this software 1511819Sjulian * must display the following acknowledgement: 1611819Sjulian * This product includes software developed by the University of 1711819Sjulian * California, Berkeley and its contributors. 1811819Sjulian * 4. Neither the name of the University nor the names of its contributors 1911819Sjulian * may be used to endorse or promote products derived from this software 2011819Sjulian * without specific prior written permission. 2111819Sjulian * 2211819Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2311819Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2411819Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2511819Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2611819Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2711819Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2811819Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2911819Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3011819Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3111819Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3211819Sjulian * SUCH DAMAGE. 3311819Sjulian * 3411991Sjulian * @(#)$Id$ 3511819Sjulian */ 3611819Sjulian 3711819Sjulian#include <sys/param.h> 3811819Sjulian#include <sys/mbuf.h> 3911819Sjulian 4011991Sjulian#include <netipx/ipx.h> 4111991Sjulian 4211819Sjulian/* 4311819Sjulian * Checksum routine for Network Systems Protocol Packets (Big-Endian). 4411819Sjulian * 4511819Sjulian * This routine is very heavily used in the network 4611819Sjulian * code and should be modified for each CPU to be as fast as possible. 4711819Sjulian */ 4811819Sjulian 4911819Sjulian#define ADDCARRY(x) { if ((x) > 65535) (x) -= 65535; } 5011819Sjulian#define FOLD(x) {l_util.l = (x); (x) = l_util.s[0] + l_util.s[1]; ADDCARRY(x);} 5111819Sjulian 5211819Sjulianu_short 5311819Sjulianipx_cksum(m, len) 5411991Sjulian struct mbuf *m; 5511991Sjulian int len; 5611819Sjulian{ 5711819Sjulian register u_short *w; 5811819Sjulian register int sum = 0; 5911819Sjulian register int mlen = 0; 6011819Sjulian register int sum2; 6111819Sjulian 6211819Sjulian union { 6311819Sjulian u_short s[2]; 6411819Sjulian long l; 6511819Sjulian } l_util; 6611819Sjulian 6711819Sjulian for (;m && len; m = m->m_next) { 6811819Sjulian if (m->m_len == 0) 6911819Sjulian continue; 7011819Sjulian /* 7111819Sjulian * Each trip around loop adds in 7211819Sjulian * word from one mbuf segment. 7311819Sjulian */ 7411819Sjulian w = mtod(m, u_short *); 7511819Sjulian if (mlen == -1) { 7611819Sjulian /* 7711819Sjulian * There is a byte left from the last segment; 7811819Sjulian * ones-complement add it into the checksum. 7911819Sjulian */ 8011819Sjulian#if BYTE_ORDER == BIG_ENDIAN 8111819Sjulian sum += *(u_char *)w; 8211819Sjulian#else 8311819Sjulian sum += *(u_char *)w << 8; 8411819Sjulian#endif 8511819Sjulian sum += sum; 8611819Sjulian w = (u_short *)(1 + (char *)w); 8711819Sjulian mlen = m->m_len - 1; 8811819Sjulian len--; 8911819Sjulian FOLD(sum); 9011819Sjulian } else 9111819Sjulian mlen = m->m_len; 9211819Sjulian if (len < mlen) 9311819Sjulian mlen = len; 9411819Sjulian len -= mlen; 9511819Sjulian /* 9611819Sjulian * We can do a 16 bit ones complement sum using 9711819Sjulian * 32 bit arithmetic registers for adding, 9811819Sjulian * with carries from the low added 9911819Sjulian * into the high (by normal carry-chaining) 10011819Sjulian * so long as we fold back before 16 carries have occured. 10111819Sjulian */ 10211819Sjulian if (1 & (int) w) 10311819Sjulian goto uuuuglyy; 10411819Sjulian#ifndef TINY 10511819Sjulian/* -DTINY reduces the size from 1250 to 550, but slows it down by 22% */ 10611819Sjulian while ((mlen -= 32) >= 0) { 10711819Sjulian sum += w[0]; sum += sum; sum += w[1]; sum += sum; 10811819Sjulian sum += w[2]; sum += sum; sum += w[3]; sum += sum; 10911819Sjulian sum += w[4]; sum += sum; sum += w[5]; sum += sum; 11011819Sjulian sum += w[6]; sum += sum; sum += w[7]; sum += sum; 11111819Sjulian FOLD(sum); 11211819Sjulian sum += w[8]; sum += sum; sum += w[9]; sum += sum; 11311819Sjulian sum += w[10]; sum += sum; sum += w[11]; sum += sum; 11411819Sjulian sum += w[12]; sum += sum; sum += w[13]; sum += sum; 11511819Sjulian sum += w[14]; sum += sum; sum += w[15]; sum += sum; 11611819Sjulian FOLD(sum); 11711819Sjulian w += 16; 11811819Sjulian } 11911819Sjulian mlen += 32; 12011819Sjulian#endif 12111819Sjulian while ((mlen -= 8) >= 0) { 12211819Sjulian sum += w[0]; sum += sum; sum += w[1]; sum += sum; 12311819Sjulian sum += w[2]; sum += sum; sum += w[3]; sum += sum; 12411819Sjulian FOLD(sum); 12511819Sjulian w += 4; 12611819Sjulian } 12711819Sjulian mlen += 8; 12811819Sjulian while ((mlen -= 2) >= 0) { 12911819Sjulian sum += *w++; sum += sum; 13011819Sjulian } 13111819Sjulian goto commoncase; 13211819Sjulianuuuuglyy: 13311819Sjulian#if BYTE_ORDER == BIG_ENDIAN 13411819Sjulian#define ww(n) (((u_char *)w)[n + n + 1]) 13511819Sjulian#define vv(n) (((u_char *)w)[n + n]) 13611819Sjulian#else 13711819Sjulian#if BYTE_ORDER == LITTLE_ENDIAN 13811819Sjulian#define vv(n) (((u_char *)w)[n + n + 1]) 13911819Sjulian#define ww(n) (((u_char *)w)[n + n]) 14011819Sjulian#endif 14111819Sjulian#endif 14211819Sjulian sum2 = 0; 14311819Sjulian#ifndef TINY 14411819Sjulian while ((mlen -= 32) >= 0) { 14511819Sjulian sum += ww(0); sum += sum; sum += ww(1); sum += sum; 14611819Sjulian sum += ww(2); sum += sum; sum += ww(3); sum += sum; 14711819Sjulian sum += ww(4); sum += sum; sum += ww(5); sum += sum; 14811819Sjulian sum += ww(6); sum += sum; sum += ww(7); sum += sum; 14911819Sjulian FOLD(sum); 15011819Sjulian sum += ww(8); sum += sum; sum += ww(9); sum += sum; 15111819Sjulian sum += ww(10); sum += sum; sum += ww(11); sum += sum; 15211819Sjulian sum += ww(12); sum += sum; sum += ww(13); sum += sum; 15311819Sjulian sum += ww(14); sum += sum; sum += ww(15); sum += sum; 15411819Sjulian FOLD(sum); 15511819Sjulian sum2 += vv(0); sum2 += sum2; sum2 += vv(1); sum2 += sum2; 15611819Sjulian sum2 += vv(2); sum2 += sum2; sum2 += vv(3); sum2 += sum2; 15711819Sjulian sum2 += vv(4); sum2 += sum2; sum2 += vv(5); sum2 += sum2; 15811819Sjulian sum2 += vv(6); sum2 += sum2; sum2 += vv(7); sum2 += sum2; 15911819Sjulian FOLD(sum2); 16011819Sjulian sum2 += vv(8); sum2 += sum2; sum2 += vv(9); sum2 += sum2; 16111819Sjulian sum2 += vv(10); sum2 += sum2; sum2 += vv(11); sum2 += sum2; 16211819Sjulian sum2 += vv(12); sum2 += sum2; sum2 += vv(13); sum2 += sum2; 16311819Sjulian sum2 += vv(14); sum2 += sum2; sum2 += vv(15); sum2 += sum2; 16411819Sjulian FOLD(sum2); 16511819Sjulian w += 16; 16611819Sjulian } 16711819Sjulian mlen += 32; 16811819Sjulian#endif 16911819Sjulian while ((mlen -= 8) >= 0) { 17011819Sjulian sum += ww(0); sum += sum; sum += ww(1); sum += sum; 17111819Sjulian sum += ww(2); sum += sum; sum += ww(3); sum += sum; 17211819Sjulian FOLD(sum); 17311819Sjulian sum2 += vv(0); sum2 += sum2; sum2 += vv(1); sum2 += sum2; 17411819Sjulian sum2 += vv(2); sum2 += sum2; sum2 += vv(3); sum2 += sum2; 17511819Sjulian FOLD(sum2); 17611819Sjulian w += 4; 17711819Sjulian } 17811819Sjulian mlen += 8; 17911819Sjulian while ((mlen -= 2) >= 0) { 18011819Sjulian sum += ww(0); sum += sum; 18111819Sjulian sum2 += vv(0); sum2 += sum2; 18211819Sjulian w++; 18311819Sjulian } 18411819Sjulian sum += (sum2 << 8); 18511819Sjuliancommoncase: 18611819Sjulian if (mlen == -1) { 18711819Sjulian#if BYTE_ORDER == BIG_ENDIAN 18811819Sjulian sum += *(u_char *)w << 8; 18911819Sjulian#else 19011819Sjulian sum += *(u_char *)w; 19111819Sjulian#endif 19211819Sjulian } 19311819Sjulian FOLD(sum); 19411819Sjulian } 19511819Sjulian if (mlen == -1) { 19611819Sjulian /* We had an odd number of bytes to sum; assume a garbage 19711819Sjulian byte of zero and clean up */ 19811819Sjulian sum += sum; 19911819Sjulian FOLD(sum); 20011819Sjulian } 20111819Sjulian /* 20211819Sjulian * sum has already been kept to low sixteen bits. 20311819Sjulian * just examine result and exit. 20411819Sjulian */ 20511819Sjulian if(sum==0xffff) sum = 0; 20611819Sjulian return (sum); 20711819Sjulian} 208