|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.