Annotation of driverkit/tests/ether.m, 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:  * 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.