Annotation of driverkit/tests/ether.m, revision 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:  * Ethernet object exerciser.
        !            26:  */
        !            27:  
        !            28: #define dbg_prn(a,b,c,d,e,f)           \
        !            29: {                                      \
        !            30:        if(verbose) {                   \
        !            31:                printf(a,b,c,d,e,f);    \
        !            32:        }                               \
        !            33: }
        !            34: 
        !            35: /*
        !            36:  * Hmmm...we need KERNEL defined to get netif.h...
        !            37:  * ...and if.h really should import sys/socket.h.
        !            38:  */
        !            39: #import <bsd/sys/socket.h>             
        !            40: #define KERNEL 1
        !            41: #import <net/netif.h>
        !            42: #undef KERNEL
        !            43: #import <Enet/Ethernet.h>
        !            44: #import <driverkit/KernDevUxpr.h>
        !            45: #import <driverkit/generalFuncs.h>
        !            46: #import <kernserv/queue.h>
        !            47: #import <machkit/NXLock.h>
        !            48: #import <libc.h>
        !            49: 
        !            50: #define MIN_SIZE       100             // minimum packet size
        !            51: #define MAX_SIZE       500             // maximum packet size
        !            52: #define INCREMENT      20              // delta packet size
        !            53: #define THROTTLE       10              // max # packets outstanding
        !            54: #define LOOP_COUNT     1
        !            55: 
        !            56: /*
        !            57:  * This is how we enqueue incoming buffers.
        !            58:  */
        !            59: typedef struct in_buf in_buf_t;
        !            60: struct in_buf {
        !            61:        netbuf_t nb;
        !            62:        in_buf_t *next;
        !            63: };
        !            64: 
        !            65: /*
        !            66:  * Static functions.
        !            67:  */
        !            68: static void usage(char **argv);
        !            69: static int runTest(netif_t nif,
        !            70:        int min_packet_size,
        !            71:        int max_packet_size,
        !            72:        int increment,
        !            73:        int throttle);
        !            74: static int check_new_bufs(int min_size, int increment, int packets_recd);
        !            75: static void etherTimeout(void *flag);
        !            76: static netbuf_t wait_for_packets(netif_t nif);
        !            77: 
        !            78: /*
        !            79:  * Static variables.
        !            80:  */
        !            81: in_buf_t       *in_buf_next, *in_buf_last;
        !            82: id             in_buf_lock;                    // NXLock - protects
        !            83:                                                //   in_buf
        !            84: enetAddress_t  destAdrs = { {0,1,2,3,4,5} };
        !            85: #ifdef notdef
        !            86: id             buf_wait_lock;                  // NXConditionLock - used to 
        !            87:                                                //   wait for incoming buf
        !            88: #endif notdef
        !            89: 
        !            90: /*
        !            91:  * User-specified parameters.
        !            92:  */
        !            93: int min_size  = MIN_SIZE;
        !            94: int max_size  = MAX_SIZE;
        !            95: int increment = INCREMENT;
        !            96: int throttle  = THROTTLE;
        !            97: int verbose = 0;
        !            98: int loop_count = LOOP_COUNT;
        !            99:                                                
        !           100: int main(int argc, char **argv)
        !           101: {
        !           102:        id      etherId;
        !           103:        netif_t nif;
        !           104:        char    s[100];
        !           105:        int     arg;
        !           106:        int     loop_num;
        !           107:        
        !           108:        for(arg=1; arg<argc; arg++) {
        !           109:                switch(argv[arg][0]) {
        !           110:                    case 'v':
        !           111:                        verbose++;
        !           112:                        break;
        !           113:                    case 'n':
        !           114:                        min_size = atoi(&argv[arg][2]);
        !           115:                        break;
        !           116:                    case 'x':
        !           117:                        max_size = atoi(&argv[arg][2]);
        !           118:                        break;
        !           119:                    case 'i':
        !           120:                        increment = atoi(&argv[arg][2]);
        !           121:                        break;
        !           122:                    case 't':
        !           123:                        throttle = atoi(&argv[arg][2]);
        !           124:                        break;
        !           125:                    case 'l':
        !           126:                        loop_count = atoi(&argv[arg][2]);
        !           127:                        break;
        !           128:                    default:
        !           129:                        usage(argv);
        !           130:                }
        !           131:        }
        !           132: 
        !           133: #ifdef DDM_DEBUG
        !           134:        IOInitDDM(1000, "EnetXpr");
        !           135:        IOSetDDMMask(XPR_IODEVICE_INDEX,
        !           136:                 XPR_NET | XPR_ENTX | XPR_ENRX | XPR_ENCOM | XPR_NDMA);
        !           137: #endif DDM_DEBUG
        !           138:        IOInitGeneralFuncs();
        !           139:        etherId = [Ethernet probe:0 deviceMaster:PORT_NULL];
        !           140:        if(etherId == nil) {
        !           141:                printf("Driver Probe failed; exiting.\n");
        !           142:                exit(1);
        !           143:        }
        !           144:        nif = [etherId getNetif];
        !           145: #ifdef notdef
        !           146:        buf_wait_lock = [NXConditionLock new];
        !           147: #endif notdef
        !           148:        in_buf_lock   = [NXLock new];
        !           149:        loop_num = 0;
        !           150:        do {
        !           151:                printf("...Loop %d\n", loop_num);
        !           152:                if(runTest(nif, min_size, max_size, increment, throttle))
        !           153:                        break;
        !           154:                loop_num++;
        !           155:        } while ((loop_count == 0) || (loop_num < loop_count));
        !           156:        printf("Hit <CR> to quit: ");
        !           157:        gets(s);
        !           158:        exit(0);
        !           159: }
        !           160: 
        !           161: static void usage(char **argv)
        !           162: {
        !           163:        printf("Usage: %s [options]\n");
        !           164:        printf("   Options:\n");
        !           165:        printf("\tn=min_size   (default = %d)\n", MIN_SIZE);
        !           166:        printf("\tx=max_size   (default = %d)\n", MAX_SIZE);
        !           167:        printf("\ti=increment  (default = %d)\n", INCREMENT);
        !           168:        printf("\tt=throttle   (default = %d)\n", THROTTLE);
        !           169:        printf("\tl=loop count (default = %d; 0 means forever)\n", LOOP_COUNT); 
        !           170:        printf("\tv=verbose mode\n");
        !           171:        exit(1);
        !           172: }
        !           173: /*
        !           174:  * Main test loop. Returns non-zero on error.
        !           175:  */
        !           176: static int runTest(netif_t nif,
        !           177:        int min_size,
        !           178:        int max_size,
        !           179:        int increment,
        !           180:        int throttle)
        !           181: {
        !           182: /*
        !           183:  *     packets_recd = 0;
        !           184:  *     for(size=min to max) {
        !           185:  *             getbuf a netbuf from driver;
        !           186:  *             if(no bufs available or throttle exceeded) {
        !           187:  *                     wait for some rx buffers to arrive;
        !           188:  *             }
        !           189:  *             else {
        !           190:  *                     fill with some data pattern;
        !           191:  *                     if_output() the netbuf to the driver;
        !           192:  *                     packets_sent++;
        !           193:  *             }
        !           194:  *             if any new netbufs on in_buf queue {
        !           195:  *                     for each one {
        !           196:  *                             verify proper data;
        !           197:  *                             packets_recd++;
        !           198:  *                             nb_free() it;
        !           199:  *                     }
        !           200:  *             }
        !           201:  *      }
        !           202:  *     wait a reasonable time for packets_sent == packets_recd, checking 
        !           203:  *             all incoming data;
        !           204:  */
        !           205:  
        !           206:        int size;
        !           207:        int packets_sent = 0;
        !           208:        int packets_recd = 0;
        !           209:        netbuf_t nb;
        !           210:        int rtn;
        !           211:        int current_size;
        !           212:        int timeout_flag;
        !           213:        int packets_out = 0;
        !           214:        
        !           215:        packets_recd = 0;
        !           216:        size = min_size;
        !           217:        do {
        !           218:                nb = if_getbuf(nif);
        !           219:                if((nb == NULL) || (packets_out >= throttle)) {
        !           220:                        
        !           221:                        /*
        !           222:                         * nb == NULL means that the driver has no more 
        !           223:                         * buffers; exceeding the throttle means we should
        !           224:                         * back off and let 'DMA' complete.
        !           225:                         *
        !           226:                         * We'll just have to wait for some network activity.
        !           227:                         */
        !           228:                        nb = wait_for_packets(nif);
        !           229:                        if(nb == NULL) {
        !           230:                                
        !           231:                                /*
        !           232:                                 * Still no Tx bufs available, but some 
        !           233:                                 * Rx bufs showed up.
        !           234:                                 */
        !           235:                                goto handle_input;
        !           236:                        }
        !           237:                        /* 
        !           238:                         * Else drop thru and send using nb.
        !           239:                         */
        !           240:                }
        !           241: 
        !           242:                /*
        !           243:                 * nb_write() some data here eventually. For now, 
        !           244:                 * just set the size to min_size + 
        !           245:                 * (increment * packet_num).
        !           246:                 */
        !           247:                dbg_prn("sending  packet num %d size %d\n", 
        !           248:                        packets_sent, size, 3,4,5);
        !           249:                current_size = min_size + (increment * packets_sent); 
        !           250:                nb_shrink_bot(nb, nb_size(nb) - current_size);
        !           251:                rtn = if_output(nif, nb, &destAdrs);
        !           252:                if(rtn) {
        !           253:                        printf("Error on if_output (rtn = %d)\n", rtn);
        !           254:                        return -1;
        !           255:                }
        !           256:                packets_sent++;
        !           257:                packets_out++;
        !           258:                size += increment;
        !           259:                
        !           260:                /*
        !           261:                 * Check for incoming packets.
        !           262:                 */
        !           263: handle_input:
        !           264:                rtn = check_new_bufs(min_size, increment, packets_recd);
        !           265:                if(rtn < 0) 
        !           266:                        return rtn;
        !           267:                packets_recd += rtn;
        !           268:                packets_out -= rtn;
        !           269:                
        !           270:        } while (size <= max_size);
        !           271:        
        !           272:        /*
        !           273:         * In a reasonable time, we should see all of the packets. 
        !           274:         */
        !           275:        if(packets_recd != packets_sent) {
        !           276:                dbg_prn("Exit main loop; waiting for incoming packets\n",
        !           277:                        1,2,3,4,5);
        !           278:                timeout_flag = 0;
        !           279:                IOScheduleFunc((IOThreadFunc)etherTimeout, &timeout_flag, 2);
        !           280:                do {
        !           281:                        rtn = check_new_bufs(min_size, increment,
        !           282:                                packets_recd);
        !           283:                        if(rtn < 0) 
        !           284:                                return rtn;
        !           285:                        packets_recd += rtn;
        !           286:                } while (!timeout_flag && (packets_recd != packets_sent));
        !           287:                if(timeout_flag) {
        !           288:                        printf("%d packets sent, %d received: FATAL\n",
        !           289:                                packets_sent, packets_recd);
        !           290:                        return -1;
        !           291:                }
        !           292:                else {
        !           293:                        IOUnscheduleFunc((IOThreadFunc)etherTimeout,
        !           294:                                &timeout_flag);
        !           295:                }
        !           296:        }
        !           297:        return 0;
        !           298: }
        !           299: 
        !           300: /*
        !           301:  * Timeout function, called out via IOScheduleFunc. Sets the specified flag to 1. 
        !           302:  */
        !           303: static void etherTimeout(void *flag)
        !           304: {
        !           305:        *((int *)flag) = 1;
        !           306: #ifdef notdef
        !           307:        [buf_wait_lock lock];
        !           308:        [buf_wait_lock unlockWith:TRUE];
        !           309: #endif notdef
        !           310: }
        !           311: 
        !           312: /*
        !           313:  * Wait for some packets to arrive or for if_getbuf() to succeed.
        !           314:  * if_getbuf() is attempted every 50 ms (actually, with current libIO, 
        !           315:  * every 1 second...). 
        !           316:  *
        !           317:  * If if_getbuf() succeeds, this returns a netbuf_t; else (in_buf non-empty)
        !           318:  * returns NULL.
        !           319:  */
        !           320: static netbuf_t wait_for_packets(netif_t nif)
        !           321: {
        !           322:        netbuf_t nb;
        !           323:        
        !           324:        dbg_prn("...waiting for available packets\n", 1,2,3,4,5);
        !           325:        while(1) {
        !           326:        
        !           327:                /*
        !           328:                 * Any incoming bufs?
        !           329:                 */
        !           330:                [in_buf_lock lock];
        !           331:                if(in_buf_next != NULL) {
        !           332:                        [in_buf_lock unlock];
        !           333:                        return NULL;
        !           334:                }
        !           335:                [in_buf_lock unlock];
        !           336:                
        !           337:                /*
        !           338:                 * Any outgoing bufs?
        !           339:                 */
        !           340:                nb = if_getbuf(nif);
        !           341:                if(nb) {
        !           342:                        return(nb);
        !           343:                }         
        !           344:                
        !           345:                /*
        !           346:                 * Go to sleep. 
        !           347:                 */
        !           348:                /* IOSleep(50); */
        !           349:                cthread_yield();
        !           350:        }
        !           351: }
        !           352: 
        !           353: /*
        !           354:  * Check out any new netbufs in in_buf queue. Returns -1 on error, else 
        !           355:  * return the number of new packets received and checked.
        !           356:  *
        !           357:  * One entry, packets_recd is the number of packets already seen.
        !           358:  */
        !           359: static int check_new_bufs(int min_size, int increment, int packets_recd)
        !           360: {
        !           361:        in_buf_t *ib;
        !           362:        int new_packets = 0;
        !           363:        int current_size;
        !           364:        int error = 0;
        !           365:        int current_packet = packets_recd;
        !           366:        int recd_size;
        !           367:        
        !           368:        [in_buf_lock lock];
        !           369:        ib = in_buf_next;
        !           370:        if(ib) {
        !           371:                in_buf_next = ib->next;
        !           372:        }
        !           373:        [in_buf_lock unlock];
        !           374:        while(ib) {
        !           375:                        
        !           376:                /*
        !           377:                 * eventually check out data here...For now, just check size.
        !           378:                 */
        !           379:                current_size = min_size + (increment * (current_packet));
        !           380:                recd_size = nb_size(ib->nb);
        !           381:                dbg_prn("received packet num %d size %d\n", 
        !           382:                        current_packet, recd_size,3,4,5);
        !           383:                if(recd_size != current_size) {
        !           384:                        printf("***bad size for in_packet %d\n", 
        !           385:                                current_packet);
        !           386:                        printf("   Expected %d   actual %d\n",
        !           387:                                current_size, recd_size);
        !           388:                        error++;
        !           389:                }
        !           390:                current_packet++;
        !           391:                new_packets++;          
        !           392:                
        !           393:                /*
        !           394:                 * Free both the netbuf and the in_buf.
        !           395:                 */
        !           396:                nb_free(ib->nb);
        !           397:                IOFree(ib, sizeof(*ib));
        !           398:                
        !           399:                /*
        !           400:                 * Get next in_buf.
        !           401:                 */
        !           402:                [in_buf_lock lock];
        !           403:                ib = in_buf_next;
        !           404:                if(ib) {
        !           405:                        in_buf_next = ib->next;
        !           406:                }
        !           407:                [in_buf_lock unlock];
        !           408: 
        !           409:        }
        !           410:        if(error)
        !           411:                return -1;
        !           412:        else
        !           413:                return new_packets;
        !           414: }
        !           415: 
        !           416: /*
        !           417:  * Provided for handling incoming packets. These should map one-to-one with the
        !           418:  * packets we send via if_output(). This will actually be called from the 
        !           419:  * driver's enetThread.
        !           420:  *
        !           421:  * All we do is save the incoming netbuf in in_buf. The main thread
        !           422:  * does data and sequence checking.
        !           423:  */
        !           424: int if_handle_input(netif_t netif, 
        !           425:        netbuf_t nb, 
        !           426:        void *extra)
        !           427: {
        !           428:        in_buf_t *ib = IOMalloc(sizeof(in_buf_t));
        !           429: 
        !           430:        ib->nb = nb;
        !           431:        ib->next = NULL;
        !           432:        [in_buf_lock lock];
        !           433:        if(in_buf_next == NULL) {
        !           434:                in_buf_next = in_buf_last = ib;
        !           435:        }
        !           436:        else {
        !           437:                in_buf_last->next = ib;
        !           438:                in_buf_last = ib;
        !           439:        }
        !           440:        [in_buf_lock unlock];
        !           441: #ifdef notdef
        !           442:        [buf_wait_lock lock];
        !           443:        [buf_wait_lock unlockWith:TRUE];
        !           444: #endif notdef
        !           445:        return 0;
        !           446: }
        !           447: 

unix.superglobalmegacorp.com

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