|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* ! 26: * Copyright (c) 1988 Regents of the University of California. ! 27: * All rights reserved. ! 28: * ! 29: * Redistribution and use in source and binary forms are permitted ! 30: * provided that this notice is preserved and that due credit is given ! 31: * to the University of California at Berkeley. The name of the University ! 32: * may not be used to endorse or promote products derived from this ! 33: * software without specific prior written permission. This software ! 34: * is provided ``as is'' without express or implied warranty. ! 35: * ! 36: * @(#)in_cksum.c 7.1 (Berkeley) 3/29/88 ! 37: */ ! 38: ! 39: /* HISTORY ! 40: * 26-May-94 Curtis Galloway at NeXT ! 41: * Grabbed the m68k code and added a Pentium-optimized checksummer. ! 42: * (See RFC 1107 for the checksum algorithm.) ! 43: * ! 44: * 06-Dec-92 Mac Gillon (mgillon) at NeXT ! 45: * Lifted the '020 code from 4.4. The compiler generates crummy ! 46: * code for the portable version. ! 47: */ ! 48: ! 49: #include <sys/param.h> ! 50: #include <sys/mbuf.h> ! 51: #include <netinet/in.h> ! 52: #include <netinet/in_systm.h> ! 53: ! 54: #if defined(NX_CURRENT_COMPILER_RELEASE) && (NX_CURRENT_COMPILER_RELEASE < 320) ! 55: #define SIREG "e" ! 56: #else ! 57: #define SIREG "S" ! 58: #endif ! 59: ! 60: ! 61: #if DEBUG_OC ! 62: ! 63: static inline int ! 64: oc_cksum( ! 65: unsigned char *buf, ! 66: int len, ! 67: unsigned long oldsum ! 68: ) ! 69: { ! 70: unsigned short *p = (unsigned short *)buf; ! 71: ! 72: for (; len>1; len -=2) ! 73: oldsum += *p++; ! 74: #if __BIG_ENDIAN__ ! 75: if (len > 0) ! 76: oldsum += (*(unsigned char *)p) << 8; ! 77: #else ! 78: if (len > 0) ! 79: oldsum += *(unsigned char *)p; ! 80: #endif ! 81: oldsum = (oldsum >> 16) + (oldsum & 0xffff); ! 82: oldsum = (oldsum >> 16) + (oldsum & 0xffff); ! 83: return oldsum; ! 84: } ! 85: ! 86: #else DEBUG_OC ! 87: ! 88: static inline int ! 89: oc_cksum( ! 90: unsigned char *buf, ! 91: int len, ! 92: unsigned long oldsum ! 93: ) ! 94: { ! 95: unsigned short sum; ! 96: ! 97: asm(" ! 98: testb $1, %%ecx ! 99: jne 5f // one or three extra bytes ! 100: testb $2, %%ecx ! 101: jne 7f // two extra bytes ! 102: 0: ! 103: adc $0,%%eax //add carry if extra bytes ! 104: shr $3,%%ecx //we'll do two dwords per loop ! 105: jnc 1f //is there an odd dword in buffer? ! 106: add (%%esi),%%eax //checksum the odd dword ! 107: adc $0,%%eax //add carry if needed ! 108: add $4,%%esi //point to the next dword ! 109: 1: ! 110: test %%ecx, %%ecx ! 111: jz 4f ! 112: mov (%%esi),%%edx //preload the first dword ! 113: mov 4(%%esi),%%ebx //preload the second dword ! 114: dec %%ecx //we'll do 1 checksum outside the loop ! 115: jz 3f //only 1 checksum to do ! 116: add $8, %%esi //point to the next dword ! 117: ! 118: 2: ! 119: add %%edx,%%eax //cycle 1 U-pipe ! 120: mov (%%esi),%%edx //cycle 1 V-pipe ! 121: adc %%ebx,%%eax //cycle 2 U-pipe ! 122: mov 4(%%esi),%%ebx //cycle 2 V-pipe ! 123: adc $0,%%eax //cycle 3 U-pipe ! 124: add $8,%%esi //cycle 3 V-pipe ! 125: dec %%ecx //cycle 4 U-pipe ! 126: jnz 2b //cycle 4 V-pipe ! 127: ! 128: 3: ! 129: add %%edx,%%eax //checksum the last two dwords ! 130: adc %%ebx,%%eax ! 131: adc $0,%%eax ! 132: 4: ! 133: mov %%eax,%%edx //compress the 32-bit checksum ! 134: shr $16,%%edx //into a 16-bit checksum ! 135: add %%dx,%%ax ! 136: adc $0,%%eax ! 137: jmp 8f ! 138: ! 139: 5: ! 140: testb $2, %%ecx ! 141: je 6f // do one byte ! 142: ! 143: movzwl -3(%%esi,%%ecx),%%ebx ! 144: add %%ebx,%%eax // pick up two bytes and fall through ! 145: ! 146: 6: ! 147: movzbl -1(%%esi,%%ecx),%%ebx ! 148: adc %%ebx,%%eax ! 149: jmp 0b ! 150: ! 151: 7: ! 152: movzwl -2(%%esi,%%ecx),%%ebx ! 153: add %%ebx, %%eax ! 154: jmp 0b ! 155: ! 156: 8: ! 157: " : "=a" (sum) : "c" (len), SIREG (buf), "a" (oldsum) : ! 158: "eax", "ebx", "ecx", "edx", "esi"); ! 159: ! 160: return sum; ! 161: } ! 162: ! 163: #endif DEBUG_OC ! 164: ! 165: ! 166: ! 167: /* ! 168: * Checksum routine for the Internet Protocol family. ! 169: * ! 170: * This isn't as bad as it looks. For ip headers the "while" isn't ! 171: * executed and we just drop through to the return statement at the ! 172: * end. For the usual tcp or udp packet (a single header mbuf ! 173: * chained onto a cluster of data, we make exactly one trip through ! 174: * the while (for the header mbuf) and never do the hairy code ! 175: * inside the "if". If fact, if m_copydata & sb_compact are doing ! 176: * their job, we should never do the hairy code inside the "if". ! 177: */ ! 178: in_cksum(m, len) ! 179: register struct mbuf *m; ! 180: register int len; ! 181: { ! 182: register int sum = 0; ! 183: register int i; ! 184: ! 185: while (len > m->m_len) { ! 186: sum = oc_cksum(mtod(m, u_char *), i = m->m_len, sum); ! 187: m = m->m_next; ! 188: len -= i; ! 189: if (i & 1) { ! 190: /* ! 191: * ouch - we ended on an odd byte with more ! 192: * to do. This xfer is obviously not interested ! 193: * in performance so finish things slowly. ! 194: */ ! 195: register u_char *cp; ! 196: ! 197: while (len > m->m_len) { ! 198: cp = mtod(m, u_char *); ! 199: if (i & 1) { ! 200: i = m->m_len - 1; ! 201: --len; ! 202: #if __BIG_ENDIAN__ ! 203: sum += *cp++; ! 204: #else ! 205: sum += (*cp++) << 8; ! 206: #endif ! 207: } else ! 208: i = m->m_len; ! 209: ! 210: sum = oc_cksum(cp, i, sum); ! 211: m = m->m_next; ! 212: len -= i; ! 213: } ! 214: if (i & 1) { ! 215: cp = mtod(m, u_char *); ! 216: #if __BIG_ENDIAN__ ! 217: sum += *cp++; ! 218: #else ! 219: sum += (*cp++) << 8; ! 220: #endif ! 221: return (0xffff & ~oc_cksum(cp, len - 1, sum)); ! 222: } ! 223: } ! 224: } ! 225: return (0xffff & ~oc_cksum(mtod(m, u_char *), len, sum)); ! 226: } ! 227: ! 228: ! 229: /* ! 230: * Checksum routine for Internet Protocol family headers (Portable Version). ! 231: * ! 232: * This routine is very heavily used in the network ! 233: * code and should be modified for each CPU to be as fast as possible. ! 234: */ ! 235: ! 236: #ifdef notdef ! 237: ! 238: #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) ! 239: #define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);} ! 240: ! 241: in_cksum(m, len) ! 242: register struct mbuf *m; ! 243: register int len; ! 244: { ! 245: register u_short *w; ! 246: register int sum = 0; ! 247: register int mlen = 0; ! 248: int byte_swapped = 0; ! 249: ! 250: union { ! 251: char c[2]; ! 252: u_short s; ! 253: } s_util; ! 254: union { ! 255: u_short s[2]; ! 256: long l; ! 257: } l_util; ! 258: ! 259: for (;m && len; m = m->m_next) { ! 260: if (m->m_len == 0) ! 261: continue; ! 262: w = mtod(m, u_short *); ! 263: if (mlen == -1) { ! 264: /* ! 265: * The first byte of this mbuf is the continuation ! 266: * of a word spanning between this mbuf and the ! 267: * last mbuf. ! 268: * ! 269: * s_util.c[0] is already saved when scanning previous ! 270: * mbuf. ! 271: */ ! 272: s_util.c[1] = *(char *)w; ! 273: sum += s_util.s; ! 274: w = (u_short *)((char *)w + 1); ! 275: mlen = m->m_len - 1; ! 276: len--; ! 277: } else ! 278: mlen = m->m_len; ! 279: if (len < mlen) ! 280: mlen = len; ! 281: len -= mlen; ! 282: /* ! 283: * Force to even boundary. ! 284: */ ! 285: if ((1 & (int) w) && (mlen > 0)) { ! 286: REDUCE; ! 287: sum <<= 8; ! 288: s_util.c[0] = *(u_char *)w; ! 289: w = (u_short *)((char *)w + 1); ! 290: mlen--; ! 291: byte_swapped = 1; ! 292: } ! 293: /* ! 294: * Unroll the loop to make overhead from ! 295: * branches &c small. ! 296: */ ! 297: while ((mlen -= 32) >= 0) { ! 298: sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; ! 299: sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; ! 300: sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; ! 301: sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; ! 302: w += 16; ! 303: } ! 304: mlen += 32; ! 305: while ((mlen -= 8) >= 0) { ! 306: sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; ! 307: w += 4; ! 308: } ! 309: mlen += 8; ! 310: if (mlen == 0 && byte_swapped == 0) ! 311: continue; ! 312: REDUCE; ! 313: while ((mlen -= 2) >= 0) { ! 314: sum += *w++; ! 315: } ! 316: if (byte_swapped) { ! 317: REDUCE; ! 318: sum <<= 8; ! 319: byte_swapped = 0; ! 320: if (mlen == -1) { ! 321: s_util.c[1] = *(char *)w; ! 322: sum += s_util.s; ! 323: mlen = 0; ! 324: } else ! 325: mlen = -1; ! 326: } else if (mlen == -1) ! 327: s_util.c[0] = *(char *)w; ! 328: } ! 329: if (len) ! 330: printf("cksum: out of data\n"); ! 331: if (mlen == -1) { ! 332: /* The last mbuf has odd # of bytes. Follow the ! 333: standard (the odd byte may be shifted left by 8 bits ! 334: or not as determined by endian-ness of the machine) */ ! 335: s_util.c[1] = 0; ! 336: sum += s_util.s; ! 337: } ! 338: REDUCE; ! 339: return (~sum & 0xffff); ! 340: } ! 341: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.