|
|
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.