Annotation of embedaddon/quagga/tests/test-checksum.c, revision 1.1

1.1     ! misho       1: #include <zebra.h>
        !             2: #include <stdlib.h>
        !             3: #include <time.h>
        !             4: 
        !             5: #include "checksum.h"
        !             6: 
        !             7: struct thread_master *master;
        !             8: 
        !             9: struct acc_vals {
        !            10:   int c0;
        !            11:   int c1;
        !            12: };
        !            13: 
        !            14: struct csum_vals {
        !            15:   struct acc_vals a;
        !            16:   int x; 
        !            17:   int y;
        !            18: };
        !            19: 
        !            20: static struct csum_vals ospfd_vals, isisd_vals;
        !            21: 
        !            22: typedef size_t testsz_t;
        !            23: typedef uint16_t testoff_t;
        !            24: 
        !            25: /* Fletcher Checksum -- Refer to RFC1008. */
        !            26: #define MODX                 4102
        !            27: 
        !            28: /* Accumulator phase of checksum */
        !            29: static 
        !            30: struct acc_vals
        !            31: accumulate (u_char *buffer, testsz_t len, testoff_t off)
        !            32: {
        !            33:   u_int8_t *p;
        !            34:   u_int16_t *csum;
        !            35:   int i, init_len, partial_len;
        !            36:   struct acc_vals ret;
        !            37:   
        !            38:   csum = (u_int16_t *) (buffer + off);
        !            39:   *(csum) = 0;
        !            40:   
        !            41:   p = buffer;
        !            42:   ret.c0 = 0;
        !            43:   ret.c1 = 0;
        !            44:   init_len = len;
        !            45:   
        !            46:   while (len != 0)
        !            47:     {
        !            48:       partial_len = MIN(len, MODX);
        !            49: 
        !            50:       for (i = 0; i < partial_len; i++)
        !            51:        {
        !            52:          ret.c0 = ret.c0 + *(p++);
        !            53:          ret.c1 += ret.c0;
        !            54:        }
        !            55: 
        !            56:       ret.c0 = ret.c0 % 255;
        !            57:       ret.c1 = ret.c1 % 255;
        !            58: 
        !            59:       len -= partial_len;
        !            60:     }
        !            61:   return ret;
        !            62: }
        !            63: 
        !            64: /* The final reduction phase.
        !            65:  * This one should be the original ospfd version 
        !            66:  */
        !            67: static u_int16_t 
        !            68: reduce_ospfd (struct csum_vals *vals, testsz_t len, testoff_t off)
        !            69: {
        !            70: #define x vals->x
        !            71: #define y vals->y
        !            72: #define c0 vals->a.c0
        !            73: #define c1 vals->a.c1
        !            74: 
        !            75:   x = ((len - off - 1) * c0 - c1) % 255;
        !            76:   
        !            77:   if (x <= 0)
        !            78:     x += 255;
        !            79:   y = 510 - c0 - x;
        !            80:   if (y > 255)
        !            81:     y -= 255;
        !            82: 
        !            83:    /* take care endian issue. */
        !            84:    return htons ((x << 8) + y); 
        !            85: #undef x
        !            86: #undef y
        !            87: #undef c0
        !            88: #undef c1
        !            89: }
        !            90: 
        !            91: /* slightly different concatenation */
        !            92: static u_int16_t 
        !            93: reduce_ospfd1 (struct csum_vals *vals, testsz_t len, testoff_t off)
        !            94: {
        !            95: #define x vals->x
        !            96: #define y vals->y
        !            97: #define c0 vals->a.c0
        !            98: #define c1 vals->a.c1
        !            99: 
        !           100:   x = ((len - off - 1) * c0 - c1) % 255;
        !           101:   if (x <= 0)
        !           102:     x += 255;
        !           103:   y = 510 - c0 - x;
        !           104:   if (y > 255)
        !           105:     y -= 255;
        !           106: 
        !           107:    /* take care endian issue. */
        !           108:    return htons ((x << 8) | (y & 0xff)); 
        !           109: #undef x
        !           110: #undef y
        !           111: #undef c0
        !           112: #undef c1
        !           113: }
        !           114: 
        !           115: /* original isisd version */
        !           116: static u_int16_t 
        !           117: reduce_isisd (struct csum_vals *vals, testsz_t len, testoff_t off)
        !           118: {
        !           119: #define x vals->x
        !           120: #define y vals->y
        !           121: #define c0 vals->a.c0
        !           122: #define c1 vals->a.c1
        !           123:   u_int32_t mul;
        !           124:   
        !           125:   mul = (len - off)*(c0);
        !           126:   x = mul - c0 - c1;
        !           127:   y = c1 - mul - 1;
        !           128: 
        !           129:   if (y > 0)
        !           130:     y++;
        !           131:   if (x < 0)
        !           132:     x--;
        !           133: 
        !           134:   x %= 255;
        !           135:   y %= 255;
        !           136: 
        !           137:   if (x == 0)
        !           138:     x = 255;
        !           139:   if (y == 0)
        !           140:     y = 1;
        !           141: 
        !           142:   return htons ((x << 8) | (y & 0xff));
        !           143: 
        !           144: #undef x
        !           145: #undef y
        !           146: #undef c0
        !           147: #undef c1
        !           148: }
        !           149: 
        !           150: /* Is the -1 in y wrong perhaps? */
        !           151: static u_int16_t 
        !           152: reduce_isisd_yfix (struct csum_vals *vals, testsz_t len, testoff_t off)
        !           153: {
        !           154: #define x vals->x
        !           155: #define y vals->y
        !           156: #define c0 vals->a.c0
        !           157: #define c1 vals->a.c1
        !           158:   u_int32_t mul;
        !           159:   
        !           160:   mul = (len - off)*(c0);
        !           161:   x = mul - c0 - c1;
        !           162:   y = c1 - mul;
        !           163: 
        !           164:   if (y > 0)
        !           165:     y++;
        !           166:   if (x < 0)
        !           167:     x--;
        !           168: 
        !           169:   x %= 255;
        !           170:   y %= 255;
        !           171: 
        !           172:   if (x == 0)
        !           173:     x = 255;
        !           174:   if (y == 0)
        !           175:     y = 1;
        !           176: 
        !           177:   return htons ((x << 8) | (y & 0xff));
        !           178: 
        !           179: #undef x
        !           180: #undef y
        !           181: #undef c0
        !           182: #undef c1
        !           183: }
        !           184: 
        !           185: /* Move the mods yp */
        !           186: static u_int16_t 
        !           187: reduce_isisd_mod (struct csum_vals *vals, testsz_t len, testoff_t off)
        !           188: {
        !           189: #define x vals->x
        !           190: #define y vals->y
        !           191: #define c0 vals->a.c0
        !           192: #define c1 vals->a.c1
        !           193:   u_int32_t mul;
        !           194:   
        !           195:   mul = (len - off)*(c0);
        !           196:   x = mul - c1 - c0;
        !           197:   y = c1 - mul - 1;
        !           198: 
        !           199:   x %= 255;
        !           200:   y %= 255;
        !           201: 
        !           202:   if (y > 0)
        !           203:     y++;
        !           204:   if (x < 0)
        !           205:     x--;
        !           206: 
        !           207:   if (x == 0)
        !           208:     x = 255;
        !           209:   if (y == 0)
        !           210:     y = 1;
        !           211: 
        !           212:   return htons ((x << 8) | (y & 0xff));
        !           213: 
        !           214: #undef x
        !           215: #undef y
        !           216: #undef c0
        !           217: #undef c1
        !           218: }
        !           219: 
        !           220: /* Move the mods up + fix y */
        !           221: static u_int16_t 
        !           222: reduce_isisd_mody (struct csum_vals *vals, testsz_t len, testoff_t off)
        !           223: {
        !           224: #define x vals->x
        !           225: #define y vals->y
        !           226: #define c0 vals->a.c0
        !           227: #define c1 vals->a.c1
        !           228:   u_int32_t mul;
        !           229:   
        !           230:   mul = (len - off)*(c0);
        !           231:   x = mul - c0 - c1;
        !           232:   y = c1 - mul;
        !           233: 
        !           234:   x %= 255;
        !           235:   y %= 255;
        !           236: 
        !           237:   if (y > 0)
        !           238:     y++;
        !           239:   if (x < 0)
        !           240:     x--;
        !           241: 
        !           242:   if (x == 0)
        !           243:     x = 255;
        !           244:   if (y == 0)
        !           245:     y = 1;
        !           246: 
        !           247:   return htons ((x << 8) | (y & 0xff));
        !           248: 
        !           249: #undef x
        !           250: #undef y
        !           251: #undef c0
        !           252: #undef c1
        !           253: }
        !           254: 
        !           255: struct reductions_t {
        !           256:   const char *name;
        !           257:   u_int16_t (*f) (struct csum_vals *, testsz_t, testoff_t);
        !           258: } reducts[] = {
        !           259:   { .name = "ospfd",           .f = reduce_ospfd },
        !           260:   { .name = "ospfd-1",         .f = reduce_ospfd1 },
        !           261:   { .name = "isisd",           .f = reduce_isisd },
        !           262:   { .name = "isisd-yfix",      .f = reduce_isisd_yfix },
        !           263:   { .name = "isisd-mod",       .f = reduce_isisd_mod },
        !           264:   { .name = "isisd-mody",      .f = reduce_isisd_mody },
        !           265:   { NULL, NULL },
        !           266: };
        !           267: 
        !           268: /* The original ospfd checksum */
        !           269: static u_int16_t
        !           270: ospfd_checksum (u_char *buffer, testsz_t len, testoff_t off)
        !           271: {
        !           272:   u_char *sp, *ep, *p, *q;
        !           273:   int c0 = 0, c1 = 0;
        !           274:   int x, y;
        !           275:   u_int16_t checksum, *csum;
        !           276: 
        !           277:   csum = (u_int16_t *) (buffer + off);
        !           278:   *(csum) = 0;
        !           279:   
        !           280:   sp = buffer;
        !           281: 
        !           282:   for (ep = sp + len; sp < ep; sp = q)
        !           283:     {
        !           284:       q = sp + MODX;
        !           285:       if (q > ep)
        !           286:         q = ep;
        !           287:       for (p = sp; p < q; p++)
        !           288:         {
        !           289:           c0 += *p;
        !           290:           c1 += c0;
        !           291:         }
        !           292:       c0 %= 255;
        !           293:       c1 %= 255;
        !           294:     }
        !           295:   
        !           296:   ospfd_vals.a.c0 = c0;
        !           297:   ospfd_vals.a.c1 = c1;
        !           298:   
        !           299:   //printf ("%s: len %u, off %u, c0 %d, c1 %d\n",
        !           300:   //        __func__, len, off, c0, c1);
        !           301: 
        !           302:   x = ((int)(len - off - 1) * (int)c0 - (int)c1) % 255;
        !           303:   
        !           304:   if (x <= 0)
        !           305:     x += 255;
        !           306:   y = 510 - c0 - x;
        !           307:   if (y > 255)
        !           308:     y -= 255;
        !           309:   
        !           310:   ospfd_vals.x = x;
        !           311:   ospfd_vals.y = y;
        !           312:   
        !           313:   buffer[off] = x;
        !           314:   buffer[off + 1] = y;
        !           315:   
        !           316:   /* take care endian issue. */
        !           317:   checksum = htons ((x << 8) | (y & 0xff));
        !           318: 
        !           319:   return (checksum);
        !           320: }
        !           321: 
        !           322: /* the original, broken isisd checksum */
        !           323: static u_int16_t
        !           324: iso_csum_create (u_char * buffer, testsz_t len, testoff_t off)
        !           325: {
        !           326: 
        !           327:   u_int8_t *p;
        !           328:   int x;
        !           329:   int y;
        !           330:   u_int32_t mul;
        !           331:   u_int32_t c0;
        !           332:   u_int32_t c1;
        !           333:   u_int16_t checksum, *csum;
        !           334:   int i, init_len, partial_len;
        !           335: 
        !           336:   checksum = 0;
        !           337:   
        !           338:   csum = (u_int16_t *) (buffer + off);
        !           339:   *(csum) = checksum;
        !           340:   
        !           341:   p = buffer;
        !           342:   c0 = 0;
        !           343:   c1 = 0;
        !           344:   init_len = len;
        !           345:   
        !           346:   while (len != 0)
        !           347:     {
        !           348:       partial_len = MIN(len, MODX);
        !           349: 
        !           350:       for (i = 0; i < partial_len; i++)
        !           351:        {
        !           352:          c0 = c0 + *(p++);
        !           353:          c1 += c0;
        !           354:        }
        !           355: 
        !           356:       c0 = c0 % 255;
        !           357:       c1 = c1 % 255;
        !           358: 
        !           359:       len -= partial_len;
        !           360:     }
        !           361: 
        !           362:   isisd_vals.a.c0 = c0;
        !           363:   isisd_vals.a.c1 = c1;
        !           364:   
        !           365:   mul = (init_len - off) * c0;
        !           366: 
        !           367:   x = mul - c1 - c0;
        !           368:   y = c1 - mul - 1;
        !           369: 
        !           370:   if (y > 0)
        !           371:     y++;
        !           372:   if (x < 0)
        !           373:     x--;
        !           374: 
        !           375:   x %= 255;
        !           376:   y %= 255;
        !           377: 
        !           378:   if (x == 0)
        !           379:     x = 255;
        !           380:   if (y == 0)
        !           381:     y = 1;
        !           382:   
        !           383:   isisd_vals.x = x;
        !           384:   isisd_vals.y = y;
        !           385:   
        !           386:   checksum = htons((x << 8) | (y & 0xFF));
        !           387:   
        !           388:   *(csum) = checksum;
        !           389:   
        !           390:   /* return the checksum for user usage */
        !           391:   return checksum;
        !           392: }
        !           393: 
        !           394: static int
        !           395: verify (u_char * buffer, testsz_t len)
        !           396: {
        !           397:   u_int8_t *p;
        !           398:   u_int32_t c0;
        !           399:   u_int32_t c1;
        !           400:   u_int16_t checksum;
        !           401:   int i, partial_len;
        !           402:  
        !           403:   p = buffer;
        !           404:   checksum = 0;
        !           405: 
        !           406:   c0 = 0;
        !           407:   c1 = 0;
        !           408: 
        !           409:   while (len)
        !           410:     {
        !           411:       partial_len = MIN(len, 5803);
        !           412: 
        !           413:       for (i = 0; i < partial_len; i++)
        !           414:         {
        !           415:           c0 = c0 + *(p++);
        !           416:           c1 += c0;
        !           417:         }
        !           418:       c0 = c0 % 255;
        !           419:       c1 = c1 % 255;
        !           420: 
        !           421:       len -= partial_len;
        !           422:     }
        !           423: 
        !           424:   if (c0 == 0 && c1 == 0)
        !           425:     return 0;
        !           426: 
        !           427:   return 1;
        !           428: }
        !           429: 
        !           430: int  /* return checksum in low-order 16 bits */
        !           431: in_cksum_optimized(void *parg, int nbytes)
        !           432: {
        !           433:        u_short *ptr = parg;
        !           434:        register long           sum;            /* assumes long == 32 bits */
        !           435:        register u_short        answer;         /* assumes u_short == 16 bits */
        !           436:        register int count;
        !           437:        /*
        !           438:         * Our algorithm is simple, using a 32-bit accumulator (sum),
        !           439:         * we add sequential 16-bit words to it, and at the end, fold back
        !           440:         * all the carry bits from the top 16 bits into the lower 16 bits.
        !           441:         */
        !           442: 
        !           443:        sum = 0;
        !           444:        count = nbytes >> 1; /* div by 2 */
        !           445:        for(ptr--; count; --count)
        !           446:          sum += *++ptr;
        !           447: 
        !           448:        if (nbytes & 1) /* Odd */
        !           449:          sum += *(u_char *)(++ptr);   /* one byte only */
        !           450: 
        !           451:        /*
        !           452:         * Add back carry outs from top 16 bits to low 16 bits.
        !           453:         */
        !           454: 
        !           455:        sum  = (sum >> 16) + (sum & 0xffff);    /* add high-16 to low-16 */
        !           456:        sum += (sum >> 16);                     /* add carry */
        !           457:        answer = ~sum;          /* ones-complement, then truncate to 16 bits */
        !           458:        return(answer);
        !           459: }
        !           460: 
        !           461: 
        !           462: int /* return checksum in low-order 16 bits */
        !           463: in_cksum_rfc(void *parg, int count)
        !           464: /* from RFC 1071 */
        !           465: {
        !           466:        u_short *addr = parg;
        !           467:        /* Compute Internet Checksum for "count" bytes
        !           468:         *         beginning at location "addr".
        !           469:         */
        !           470:        register long  sum = 0;
        !           471: 
        !           472:        while (count > 1)  {
        !           473:          /*  This is the inner loop */
        !           474:          sum += *addr++;
        !           475:          count -= 2;
        !           476:        }
        !           477:        /*  Add left-over byte, if any */
        !           478:        if (count > 0) {
        !           479:          sum += *(u_char *)addr;
        !           480:        }
        !           481: 
        !           482:        /*  Fold 32-bit sum to 16 bits */
        !           483:        while (sum>>16)
        !           484:            sum = (sum & 0xffff) + (sum >> 16);
        !           485:        return ~sum;
        !           486: }
        !           487: 
        !           488: 
        !           489: int
        !           490: main(int argc, char **argv)
        !           491: {
        !           492: /* 60017 65629 702179 */
        !           493: #define MAXDATALEN 60017
        !           494: #define BUFSIZE MAXDATALEN + sizeof(u_int16_t)
        !           495:   u_char buffer[BUFSIZE];
        !           496:   int exercise = 0;
        !           497: #define EXERCISESTEP 257
        !           498:   
        !           499:   srandom (time (NULL));
        !           500:   
        !           501:   while (1) {
        !           502:     u_int16_t ospfd, isisd, lib, in_csum, in_csum_res, in_csum_rfc;
        !           503:     int i,j;
        !           504: 
        !           505:     exercise += EXERCISESTEP;
        !           506:     exercise %= MAXDATALEN;
        !           507:     
        !           508:     for (i = 0; i < exercise; i += sizeof (long int)) {
        !           509:       long int rand = random ();
        !           510:       
        !           511:       for (j = sizeof (long int); j > 0; j--)
        !           512:         buffer[i + (sizeof (long int) - j)] = (rand >> (j * 8)) & 0xff;
        !           513:     }
        !           514:     
        !           515:     in_csum = in_cksum(buffer, exercise);
        !           516:     in_csum_res = in_cksum_optimized(buffer, exercise);
        !           517:     in_csum_rfc = in_cksum_rfc(buffer, exercise);
        !           518:     if (in_csum_res != in_csum || in_csum != in_csum_rfc)
        !           519:       printf ("verify: in_chksum failed in_csum:%x, in_csum_res:%x,"
        !           520:              "in_csum_rfc %x, len:%d\n", 
        !           521:              in_csum, in_csum_res, in_csum_rfc, exercise);
        !           522: 
        !           523:     ospfd = ospfd_checksum (buffer, exercise + sizeof(u_int16_t), exercise);
        !           524:     if (verify (buffer, exercise + sizeof(u_int16_t)))
        !           525:       printf ("verify: ospfd failed\n");
        !           526:     isisd = iso_csum_create (buffer, exercise + sizeof(u_int16_t), exercise);
        !           527:     if (verify (buffer, exercise + sizeof(u_int16_t)))
        !           528:       printf ("verify: isisd failed\n");
        !           529:     lib = fletcher_checksum (buffer, exercise + sizeof(u_int16_t), exercise);
        !           530:     if (verify (buffer, exercise + sizeof(u_int16_t)))
        !           531:       printf ("verify: lib failed\n");
        !           532:     
        !           533:     if (ospfd != lib) {
        !           534:       printf ("Mismatch in values at size %u\n"
        !           535:               "ospfd: 0x%04x\tc0: %d\tc1: %d\tx: %d\ty: %d\n"
        !           536:               "isisd: 0x%04x\tc0: %d\tc1: %d\tx: %d\ty: %d\n"
        !           537:               "lib: 0x%04x\n",
        !           538:               exercise,
        !           539:               ospfd, ospfd_vals.a.c0, ospfd_vals.a.c1, ospfd_vals.x, ospfd_vals.y,
        !           540:               isisd, isisd_vals.a.c0, isisd_vals.a.c1, isisd_vals.x, isisd_vals.y,
        !           541:               lib
        !           542:               );
        !           543:       
        !           544:       /* Investigate reduction phase discrepencies */
        !           545:       if (ospfd_vals.a.c0 == isisd_vals.a.c0
        !           546:           && ospfd_vals.a.c1 == isisd_vals.a.c1) {
        !           547:         printf ("\n");
        !           548:         for (i = 0; reducts[i].name != NULL; i++) {    
        !           549:           ospfd = reducts[i].f (&ospfd_vals,
        !           550:                                 exercise + sizeof (u_int16_t),
        !           551:                                 exercise);
        !           552:           printf ("%20s: x: %02x, y %02x, checksum 0x%04x\n",
        !           553:                   reducts[i].name, ospfd_vals.x & 0xff, ospfd_vals.y & 0xff, ospfd);
        !           554:         }
        !           555:       }
        !           556:               
        !           557:       printf ("\n  u_char testdata [] = {\n  ");
        !           558:       for (i = 0; i < exercise; i++) {
        !           559:         printf ("0x%02x,%s",
        !           560:                 buffer[i],
        !           561:                 (i + 1) % 8 ? " " : "\n  ");
        !           562:       }
        !           563:       printf ("\n}\n");
        !           564:       exit (1);
        !           565:     }
        !           566:   }
        !           567: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>