1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1992,1997 by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All rights reserved. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1990 Mentat Inc. */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/stream.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h> 35*7c478bd9Sstevel@tonic-gate #include <inet/common.h> 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #define FOLD_SUM(sum) \ 38*7c478bd9Sstevel@tonic-gate { sum = (sum >> 16) + (sum & 0xFFFF); sum = (sum >> 16) + (sum & 0xFFFF); } 39*7c478bd9Sstevel@tonic-gate #define U16AM(p, i, m) ((((uint16_t *)(p))[i]) & (uint32_t)(m)) 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate /* 42*7c478bd9Sstevel@tonic-gate * For maximum efficiency, these access macros should be redone for 43*7c478bd9Sstevel@tonic-gate * machines that can access unaligned data. NOTE: these assume 44*7c478bd9Sstevel@tonic-gate * ability to fetch from a zero extended 'uint8_t' and 'uint16_t'. Add explicit 45*7c478bd9Sstevel@tonic-gate * masks in the U8_FETCH, U16_FETCH, PREV_TWO and NEXT_TWO as needed. 46*7c478bd9Sstevel@tonic-gate */ 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN 49*7c478bd9Sstevel@tonic-gate #define U8_FETCH_FIRST(p) ((p)[0]) 50*7c478bd9Sstevel@tonic-gate #define U8_FETCH_SECOND(p) (((uint32_t)(p)[0]) << 8) 51*7c478bd9Sstevel@tonic-gate #define PREV_ONE(p) U16AM(p, -1, 0xFF00) 52*7c478bd9Sstevel@tonic-gate #define NEXT_ONE(p) U16AM(p, 0, 0xFF) 53*7c478bd9Sstevel@tonic-gate #else 54*7c478bd9Sstevel@tonic-gate #define U8_FETCH_FIRST(p) ((uint32_t)((p)[0]) << 8) 55*7c478bd9Sstevel@tonic-gate #define U8_FETCH_SECOND(p) ((p)[0]) 56*7c478bd9Sstevel@tonic-gate #define PREV_ONE(p) U16AM(p, -1, 0xFF) 57*7c478bd9Sstevel@tonic-gate #define NEXT_ONE(p) U16AM(p, 0, 0xFF00) 58*7c478bd9Sstevel@tonic-gate #endif 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate #define U16_FETCH(p) U8_FETCH_FIRST(p) + U8_FETCH_SECOND(p+1) 61*7c478bd9Sstevel@tonic-gate #define PREV_TWO(p) ((uint32_t)(((uint16_t *)(p))[-1])) 62*7c478bd9Sstevel@tonic-gate #define NEXT_TWO(p) ((uint32_t)(((uint16_t *)(p))[0])) 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate /* 65*7c478bd9Sstevel@tonic-gate * Return the ones complement checksum from the mblk chain at mp, 66*7c478bd9Sstevel@tonic-gate * after skipping offset bytes, and adding in the supplied partial 67*7c478bd9Sstevel@tonic-gate * sum. Note that a final complement of the return value is needed 68*7c478bd9Sstevel@tonic-gate * if no further contributions to the checksum are forthcoming. 69*7c478bd9Sstevel@tonic-gate */ 70*7c478bd9Sstevel@tonic-gate uint16_t 71*7c478bd9Sstevel@tonic-gate ip_csum(mp, offset, sum) 72*7c478bd9Sstevel@tonic-gate mblk_t *mp; 73*7c478bd9Sstevel@tonic-gate int offset; 74*7c478bd9Sstevel@tonic-gate uint32_t sum; 75*7c478bd9Sstevel@tonic-gate { 76*7c478bd9Sstevel@tonic-gate uint8_t *startp = mp->b_rptr + offset; 77*7c478bd9Sstevel@tonic-gate uint8_t *endp = mp->b_wptr; 78*7c478bd9Sstevel@tonic-gate /* >= 0x2 means flipped for memory align, 0x1 means last count was odd */ 79*7c478bd9Sstevel@tonic-gate int odd_total = 0; 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate #ifdef TEST_COVERAGE 82*7c478bd9Sstevel@tonic-gate mblk_t *safe_mp; 83*7c478bd9Sstevel@tonic-gate #define INIT_COVERAGE() (safe_mp = mp, safe_mp->b_next = NULL) 84*7c478bd9Sstevel@tonic-gate #define MARK_COVERAGE(flag) (safe_mp->b_next = \ 85*7c478bd9Sstevel@tonic-gate (mblk_t *)((uint32_t)safe_mp->b_next | flag)) 86*7c478bd9Sstevel@tonic-gate #else 87*7c478bd9Sstevel@tonic-gate #define INIT_COVERAGE() /* */ 88*7c478bd9Sstevel@tonic-gate #define MARK_COVERAGE(flag) /* */ 89*7c478bd9Sstevel@tonic-gate #endif 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate for (;;) { 92*7c478bd9Sstevel@tonic-gate INIT_COVERAGE(); 93*7c478bd9Sstevel@tonic-gate if ((endp - startp) < 10) { 94*7c478bd9Sstevel@tonic-gate MARK_COVERAGE(0x1); 95*7c478bd9Sstevel@tonic-gate while ((endp - startp) >= 2) { 96*7c478bd9Sstevel@tonic-gate MARK_COVERAGE(0x2); 97*7c478bd9Sstevel@tonic-gate sum += U16_FETCH(startp); 98*7c478bd9Sstevel@tonic-gate startp += 2; 99*7c478bd9Sstevel@tonic-gate } 100*7c478bd9Sstevel@tonic-gate if ((endp - startp) >= 1) { 101*7c478bd9Sstevel@tonic-gate MARK_COVERAGE(0x4); 102*7c478bd9Sstevel@tonic-gate odd_total = 1; 103*7c478bd9Sstevel@tonic-gate sum += U8_FETCH_FIRST(startp); 104*7c478bd9Sstevel@tonic-gate } 105*7c478bd9Sstevel@tonic-gate MARK_COVERAGE(0x8); 106*7c478bd9Sstevel@tonic-gate FOLD_SUM(sum); 107*7c478bd9Sstevel@tonic-gate goto next_frag; 108*7c478bd9Sstevel@tonic-gate } 109*7c478bd9Sstevel@tonic-gate if ((uint32_t)startp & 0x1) { 110*7c478bd9Sstevel@tonic-gate MARK_COVERAGE(0x10); 111*7c478bd9Sstevel@tonic-gate odd_total = 3; 112*7c478bd9Sstevel@tonic-gate startp++; 113*7c478bd9Sstevel@tonic-gate sum = (sum << 8) + PREV_ONE(startp); 114*7c478bd9Sstevel@tonic-gate } 115*7c478bd9Sstevel@tonic-gate if ((uint32_t)startp & 0x2) { 116*7c478bd9Sstevel@tonic-gate MARK_COVERAGE(0x20); 117*7c478bd9Sstevel@tonic-gate startp += 2; 118*7c478bd9Sstevel@tonic-gate sum += PREV_TWO(startp); 119*7c478bd9Sstevel@tonic-gate } 120*7c478bd9Sstevel@tonic-gate if ((uint32_t)endp & 0x1) { 121*7c478bd9Sstevel@tonic-gate MARK_COVERAGE(0x40); 122*7c478bd9Sstevel@tonic-gate odd_total ^= 0x1; 123*7c478bd9Sstevel@tonic-gate endp--; 124*7c478bd9Sstevel@tonic-gate sum += NEXT_ONE(endp); 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate if ((uint32_t)endp & 0x2) { 127*7c478bd9Sstevel@tonic-gate MARK_COVERAGE(0x80); 128*7c478bd9Sstevel@tonic-gate endp -= 2; 129*7c478bd9Sstevel@tonic-gate sum += NEXT_TWO(endp); 130*7c478bd9Sstevel@tonic-gate } 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate { 133*7c478bd9Sstevel@tonic-gate #ifdef NOT_ALL_PTRS_EQUAL 134*7c478bd9Sstevel@tonic-gate #define INC_PTR(cnt) ptr += cnt 135*7c478bd9Sstevel@tonic-gate #define INC_ENDPTR(cnt) endptr += cnt 136*7c478bd9Sstevel@tonic-gate uint32_t *ptr = (uint32_t *)startp; 137*7c478bd9Sstevel@tonic-gate uint32_t *endptr = (uint32_t *)endp; 138*7c478bd9Sstevel@tonic-gate #else 139*7c478bd9Sstevel@tonic-gate #define INC_PTR(cnt) startp += (cnt * sizeof (uint32_t)) 140*7c478bd9Sstevel@tonic-gate #define INC_ENDPTR(cnt) endp += (cnt * sizeof (uint32_t)) 141*7c478bd9Sstevel@tonic-gate #define ptr ((uint32_t *)startp) 142*7c478bd9Sstevel@tonic-gate #define endptr ((uint32_t *)endp) 143*7c478bd9Sstevel@tonic-gate #endif 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate #ifdef USE_FETCH_AND_SHIFT 147*7c478bd9Sstevel@tonic-gate uint32_t u1, u2; 148*7c478bd9Sstevel@tonic-gate uint32_t mask = 0xFFFF; 149*7c478bd9Sstevel@tonic-gate #define LOAD1(i) u1 = ptr[i] 150*7c478bd9Sstevel@tonic-gate #define LOAD2(i) u2 = ptr[i] 151*7c478bd9Sstevel@tonic-gate #define SUM1(i) sum += (u1 & mask) + (u1 >> 16) 152*7c478bd9Sstevel@tonic-gate #define SUM2(i) sum += (u2 & mask) + (u2 >> 16) 153*7c478bd9Sstevel@tonic-gate #endif 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate #ifdef USE_FETCH_AND_ADDC 156*7c478bd9Sstevel@tonic-gate uint32_t u1, u2; 157*7c478bd9Sstevel@tonic-gate #define LOAD1(i) u1 = ptr[i] 158*7c478bd9Sstevel@tonic-gate #define LOAD2(i) u2 = ptr[i] 159*7c478bd9Sstevel@tonic-gate #define SUM1(i) sum += u1 160*7c478bd9Sstevel@tonic-gate #define SUM2(i) sum += u2 161*7c478bd9Sstevel@tonic-gate #endif 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate #ifdef USE_ADDC 164*7c478bd9Sstevel@tonic-gate #define SUM1(i) sum += ptr[i] 165*7c478bd9Sstevel@tonic-gate #endif 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate #ifdef USE_POSTINC 168*7c478bd9Sstevel@tonic-gate #define SUM1(i) sum += *((uint16_t *)ptr)++; sum += *((uint16_t *)ptr)++ 169*7c478bd9Sstevel@tonic-gate #undef INC_PTR 170*7c478bd9Sstevel@tonic-gate #define INC_PTR(i) /* */ 171*7c478bd9Sstevel@tonic-gate #endif 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate #ifndef LOAD1 174*7c478bd9Sstevel@tonic-gate #define LOAD1(i) /* */ 175*7c478bd9Sstevel@tonic-gate #endif 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate #ifndef LOAD2 178*7c478bd9Sstevel@tonic-gate #define LOAD2(i) /* */ 179*7c478bd9Sstevel@tonic-gate #endif 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate #ifndef SUM2 182*7c478bd9Sstevel@tonic-gate #define SUM2(i) SUM1(i) 183*7c478bd9Sstevel@tonic-gate #endif 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* USE_INDEXING is the default */ 186*7c478bd9Sstevel@tonic-gate #ifndef SUM1 187*7c478bd9Sstevel@tonic-gate #define SUM1(i) 188*7c478bd9Sstevel@tonic-gate sum += ((uint16_t *)ptr)[i * 2]; sum += ((uint16_t *)ptr)[(i * 2) + 1] 189*7c478bd9Sstevel@tonic-gate #endif 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate LOAD1(0); 192*7c478bd9Sstevel@tonic-gate INC_ENDPTR(-8); 193*7c478bd9Sstevel@tonic-gate if (ptr <= endptr) { 194*7c478bd9Sstevel@tonic-gate MARK_COVERAGE(0x100); 195*7c478bd9Sstevel@tonic-gate do { 196*7c478bd9Sstevel@tonic-gate LOAD2(1); SUM1(0); 197*7c478bd9Sstevel@tonic-gate LOAD1(2); SUM2(1); 198*7c478bd9Sstevel@tonic-gate LOAD2(3); SUM1(2); 199*7c478bd9Sstevel@tonic-gate LOAD1(4); SUM2(3); 200*7c478bd9Sstevel@tonic-gate LOAD2(5); SUM1(4); 201*7c478bd9Sstevel@tonic-gate LOAD1(6); SUM2(5); 202*7c478bd9Sstevel@tonic-gate LOAD2(7); SUM1(6); 203*7c478bd9Sstevel@tonic-gate LOAD1(8); SUM2(7); 204*7c478bd9Sstevel@tonic-gate INC_PTR(8); 205*7c478bd9Sstevel@tonic-gate } while (ptr <= endptr); 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate #ifdef USE_TAIL_SWITCH 208*7c478bd9Sstevel@tonic-gate switch ((endptr + 8) - ptr) { 209*7c478bd9Sstevel@tonic-gate case 7: LOAD2(6); SUM2(6); 210*7c478bd9Sstevel@tonic-gate case 6: LOAD2(5); SUM2(5); 211*7c478bd9Sstevel@tonic-gate case 5: LOAD2(4); SUM2(4); 212*7c478bd9Sstevel@tonic-gate case 4: LOAD2(3); SUM2(3); 213*7c478bd9Sstevel@tonic-gate case 3: LOAD2(2); SUM2(2); 214*7c478bd9Sstevel@tonic-gate case 2: LOAD2(1); SUM2(1); 215*7c478bd9Sstevel@tonic-gate case 1: SUM1(0); 216*7c478bd9Sstevel@tonic-gate case 0: break; 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate #else 219*7c478bd9Sstevel@tonic-gate INC_ENDPTR(4); 220*7c478bd9Sstevel@tonic-gate if (ptr <= endptr) { 221*7c478bd9Sstevel@tonic-gate MARK_COVERAGE(0x200); 222*7c478bd9Sstevel@tonic-gate LOAD2(1); SUM1(0); 223*7c478bd9Sstevel@tonic-gate LOAD1(2); SUM2(1); 224*7c478bd9Sstevel@tonic-gate LOAD2(3); SUM1(2); 225*7c478bd9Sstevel@tonic-gate LOAD1(4); SUM2(3); 226*7c478bd9Sstevel@tonic-gate INC_PTR(4); 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate INC_ENDPTR(4); 229*7c478bd9Sstevel@tonic-gate if (ptr < endptr) { 230*7c478bd9Sstevel@tonic-gate MARK_COVERAGE(0x400); 231*7c478bd9Sstevel@tonic-gate do { 232*7c478bd9Sstevel@tonic-gate SUM1(0); LOAD1(1); 233*7c478bd9Sstevel@tonic-gate INC_PTR(1); 234*7c478bd9Sstevel@tonic-gate } while (ptr < endptr); 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate #endif 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate FOLD_SUM(sum); 240*7c478bd9Sstevel@tonic-gate if (odd_total > 1) { 241*7c478bd9Sstevel@tonic-gate MARK_COVERAGE(0x800); 242*7c478bd9Sstevel@tonic-gate sum = ((sum << 8) | (sum >> 8)) & 0xFFFF; 243*7c478bd9Sstevel@tonic-gate odd_total -= 2; 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate next_frag: 246*7c478bd9Sstevel@tonic-gate mp = mp->b_cont; 247*7c478bd9Sstevel@tonic-gate if (!mp) { 248*7c478bd9Sstevel@tonic-gate MARK_COVERAGE(0x1000); 249*7c478bd9Sstevel@tonic-gate { 250*7c478bd9Sstevel@tonic-gate uint32_t u1 = sum; 251*7c478bd9Sstevel@tonic-gate return ((uint16_t)u1); 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate MARK_COVERAGE(0x4000); 255*7c478bd9Sstevel@tonic-gate startp = mp->b_rptr; 256*7c478bd9Sstevel@tonic-gate endp = mp->b_wptr; 257*7c478bd9Sstevel@tonic-gate if (odd_total && (endp > startp)) { 258*7c478bd9Sstevel@tonic-gate MARK_COVERAGE(0x8000); 259*7c478bd9Sstevel@tonic-gate odd_total = 0; 260*7c478bd9Sstevel@tonic-gate sum += U8_FETCH_SECOND(startp); 261*7c478bd9Sstevel@tonic-gate startp++; 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate #undef endptr 266*7c478bd9Sstevel@tonic-gate #undef INIT_COVERAGE 267*7c478bd9Sstevel@tonic-gate #undef INC_PTR 268*7c478bd9Sstevel@tonic-gate #undef INC_ENDPTR 269*7c478bd9Sstevel@tonic-gate #undef LOAD1 270*7c478bd9Sstevel@tonic-gate #undef LOAD2 271*7c478bd9Sstevel@tonic-gate #undef MARK_COVERAGE 272*7c478bd9Sstevel@tonic-gate #undef ptr 273*7c478bd9Sstevel@tonic-gate #undef SUM1 274*7c478bd9Sstevel@tonic-gate #undef SUM2 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate #undef FOLD_SUM 279*7c478bd9Sstevel@tonic-gate #undef NEXT_ONE 280*7c478bd9Sstevel@tonic-gate #undef NEXT_TWO 281*7c478bd9Sstevel@tonic-gate #undef PREV_ONE 282*7c478bd9Sstevel@tonic-gate #undef PREV_TWO 283*7c478bd9Sstevel@tonic-gate #undef U8_FETCH_FIRST 284*7c478bd9Sstevel@tonic-gate #undef U8_FETCH_SECOND 285*7c478bd9Sstevel@tonic-gate #undef U16AM 286*7c478bd9Sstevel@tonic-gate #undef U16_FETCH 287