Annotation of kernel/machdep/i386/in_cksum.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.