Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / tools / rxperf / rxperf.c
1 /*
2 * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution
16 * at such time that OpenAFS documentation is written.
17 *
18 * 3. Neither the name of the Institute nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include <afsconfig.h>
36
37 /*
38 nn * We are using getopt since we want it to be possible to link to
39 * transarc libs.
40 */
41
42 #include <afsconfig.h>
43 #include <afs/param.h>
44 #include <roken.h>
45
46 #ifdef HAVE_SYS_FILE_H
47 #include <sys/file.h>
48 #endif
49
50 #include <assert.h>
51
52 #include <rx/rx.h>
53 #include <rx/rx_null.h>
54 #include <rx/rx_globals.h>
55 #include <rx/rx_packet.h>
56
57 #ifdef AFS_PTHREAD_ENV
58 #include <pthread.h>
59 #define MAX_THREADS 128
60 #endif
61
62 #define DEFAULT_PORT 7009 /* To match tcpdump */
63 #define DEFAULT_HOST "127.0.0.1"
64 #define DEFAULT_BYTES 1024 * 1024
65 #define RXPERF_BUFSIZE 512 * 1024
66
67 enum { RX_PERF_VERSION = 3 };
68 enum { RX_SERVER_ID = 147 };
69 enum { RX_PERF_UNKNOWN = -1,
70 RX_PERF_SEND = 0,
71 RX_PERF_RECV = 1,
72 RX_PERF_RPC = 3,
73 RX_PERF_FILE = 4
74 };
75
76 enum { RXPERF_MAGIC_COOKIE = 0x4711 };
77
78 /*
79 *
80 */
81
82 #if RXPERF_DEBUG
83 #define DBFPRINT(x) do { printf x ; } while(0)
84 #else
85 #define DBFPRINT(x)
86 #endif
87
88 static void
89 sigusr1(int foo)
90 {
91 exit(2); /* XXX profiler */
92 }
93
94 static void
95 sigint(int foo)
96 {
97 rx_Finalize();
98 exit(2); /* XXX profiler */
99 }
100
101 /*
102 *
103 */
104
105 static struct timeval timer_start;
106 static struct timeval timer_stop;
107 static int timer_check = 0;
108
109 static void
110 start_timer(void)
111 {
112 timer_check++;
113 gettimeofday(&timer_start, NULL);
114 }
115
116 /*
117 *
118 */
119
120 static void
121 end_and_print_timer(char *str, long long bytes)
122 {
123 long long start_l, stop_l;
124 double kbps;
125
126 timer_check--;
127 assert(timer_check == 0);
128 gettimeofday(&timer_stop, NULL);
129 start_l = timer_start.tv_sec * 1000000 + timer_start.tv_usec;
130 stop_l = timer_stop.tv_sec * 1000000 + timer_stop.tv_usec;
131 printf("%s:\t%8llu msec", str, (stop_l - start_l) / 1000);
132
133 kbps = bytes * 8000.0 / (stop_l - start_l);
134 if (kbps > 1000000.0)
135 printf("\t[%.4g Gbit/s]\n", kbps/1000000.0);
136 else if (kbps > 1000.0)
137 printf("\t[%.4g Mbit/s]\n", kbps/1000.0);
138 else
139 printf("\t[%.4g kbit/s]\n", kbps);
140 }
141
142 /*
143 *
144 */
145
146 static u_long
147 str2addr(const char *s)
148 {
149 struct in_addr server;
150 struct hostent *h;
151
152 #ifndef INADDR_NONE
153 #define INADDR_NONE 0xffffffff
154 #endif
155 if (inet_addr(s) != INADDR_NONE)
156 return inet_addr(s);
157 h = gethostbyname(s);
158 if (h != NULL) {
159 memcpy(&server, h->h_addr_list[0], sizeof(server));
160 return server.s_addr;
161 }
162 return 0;
163 }
164
165
166 /*
167 *
168 */
169
170 static void
171 get_sec(int serverp, struct rx_securityClass **sec, int *secureindex)
172 {
173 if (serverp) {
174 *sec = rxnull_NewServerSecurityObject();
175 *secureindex = 1;
176 } else {
177 *sec = rxnull_NewClientSecurityObject();
178 *secureindex = 0;
179 }
180 }
181
182 /*
183 * process the "RPC" and return the results
184 */
185
186 char somebuf[RXPERF_BUFSIZE];
187
188 afs_int32 rxwrite_size = sizeof(somebuf);
189 afs_int32 rxread_size = sizeof(somebuf);
190 afs_int32 use_rx_readv = 0;
191
192 static int
193 do_readbytes(struct rx_call *call, afs_int32 bytes)
194 {
195 struct iovec tiov[RX_MAXIOVECS];
196 afs_int32 size;
197 int tnio;
198 int code;
199
200 while (bytes > 0) {
201 size = rxread_size;
202
203 if (size > bytes)
204 size = bytes;
205 if (use_rx_readv) {
206 if (size > RX_MAX_PACKET_DATA_SIZE)
207 size = RX_MAX_PACKET_DATA_SIZE;
208 code = rx_Readv(call, tiov, &tnio, RX_MAXIOVECS, size);
209 } else
210 code = rx_Read(call, somebuf, size);
211 if (code != size)
212 return 1;
213
214 bytes -= size;
215 }
216 return 0;
217 }
218
219 static int
220 do_sendbytes(struct rx_call *call, afs_int32 bytes)
221 {
222 afs_int32 size;
223
224 while (bytes > 0) {
225 size = rxwrite_size;
226 if (size > bytes)
227 size = bytes;
228 if (rx_Write(call, somebuf, size) != size)
229 return 1;
230 bytes -= size;
231 }
232 return 0;
233 }
234
235
236 static afs_int32
237 rxperf_ExecuteRequest(struct rx_call *call)
238 {
239 afs_int32 version;
240 afs_int32 command;
241 afs_int32 bytes;
242 afs_int32 recvb;
243 afs_int32 sendb;
244 afs_int32 data;
245 afs_uint32 num;
246 afs_uint32 *readwrite;
247 afs_uint32 i;
248 int readp = TRUE;
249
250 DBFPRINT(("got a request\n"));
251
252 if (rx_Read32(call, &version) != 4) {
253 warn("rx_Read failed to read version");
254 return -1;
255 }
256
257 if (htonl(RX_PERF_VERSION) != version) {
258 warnx("client has wrong version");
259 return -1;
260 }
261
262 if (rx_Read32(call, &command) != 4) {
263 warnx("rx_Read failed to read command");
264 return -1;
265 }
266 command = ntohl(command);
267
268 if (rx_Read32(call, &data) != 4) {
269 warnx("rx_Read failed to read size");
270 return -1;
271 }
272 rxread_size = ntohl(data);
273 if (rxread_size > sizeof(somebuf)) {
274 warnx("rxread_size too large %d", rxread_size);
275 return -1;
276 }
277
278 if (rx_Read32(call, &data) != 4) {
279 warnx("rx_Read failed to write size");
280 return -1;
281 }
282 rxwrite_size = ntohl(data);
283 if (rxwrite_size > sizeof(somebuf)) {
284 warnx("rxwrite_size too large %d", rxwrite_size);
285 return -1;
286 }
287
288 switch (command) {
289 case RX_PERF_SEND:
290 DBFPRINT(("got a send request\n"));
291
292 if (rx_Read32(call, &bytes) != 4) {
293 warnx("rx_Read failed to read bytes");
294 return -1;
295 }
296 bytes = ntohl(bytes);
297
298 DBFPRINT(("reading(%d) ", bytes));
299 do_readbytes(call, bytes);
300
301 data = htonl(RXPERF_MAGIC_COOKIE);
302 if (rx_Write32(call, &data) != 4) {
303 warnx("rx_Write failed when sending back result");
304 return -1;
305 }
306 DBFPRINT(("done\n"));
307
308 break;
309 case RX_PERF_RPC:
310 DBFPRINT(("got a rpc request, reading commands\n"));
311
312 if (rx_Read32(call, &recvb) != 4) {
313 warnx("rx_Read failed to read recvbytes");
314 return -1;
315 }
316 recvb = ntohl(recvb);
317 if (rx_Read32(call, &sendb) != 4) {
318 warnx("rx_Read failed to read sendbytes");
319 return -1;
320 }
321 sendb = ntohl(sendb);
322
323 DBFPRINT(("read(%d) ", recvb));
324 if (do_readbytes(call, recvb)) {
325 warnx("do_readbytes failed");
326 return -1;
327 }
328 DBFPRINT(("send(%d) ", sendb));
329 if (do_sendbytes(call, sendb)) {
330 warnx("sendbytes failed");
331 return -1;
332 }
333
334 DBFPRINT(("done\n"));
335
336 data = htonl(RXPERF_MAGIC_COOKIE);
337 if (rx_Write32(call, &data) != 4) {
338 warnx("rx_Write failed when sending back magic cookie");
339 return -1;
340 }
341
342 break;
343 case RX_PERF_FILE:
344 if (rx_Read32(call, &data) != 4)
345 errx(1, "failed to read num from client");
346 num = ntohl(data);
347
348 readwrite = malloc(num * sizeof(afs_uint32));
349 if (readwrite == NULL)
350 err(1, "malloc");
351
352 if (rx_Read(call, (char*)readwrite, num * sizeof(afs_uint32)) !=
353 num * sizeof(afs_uint32))
354 errx(1, "failed to read recvlist from client");
355
356 for (i = 0; i < num; i++) {
357 if (readwrite[i] == 0) {
358 DBFPRINT(("readp %d", readwrite[i]));
359 readp = !readp;
360 }
361
362 bytes = ntohl(readwrite[i]) * sizeof(afs_uint32);
363
364 if (readp) {
365 DBFPRINT(("read\n"));
366 do_readbytes(call, bytes);
367 } else {
368 do_sendbytes(call, bytes);
369 DBFPRINT(("send\n"));
370 }
371 }
372
373 break;
374 case RX_PERF_RECV:
375 DBFPRINT(("got a recv request\n"));
376
377 if (rx_Read32(call, &bytes) != 4) {
378 warnx("rx_Read failed to read bytes");
379 return -1;
380 }
381 bytes = ntohl(bytes);
382
383 DBFPRINT(("sending(%d) ", bytes));
384 do_sendbytes(call, bytes);
385
386 data = htonl(RXPERF_MAGIC_COOKIE);
387 if (rx_Write32(call, &data) != 4) {
388 warnx("rx_Write failed when sending back result");
389 return -1;
390 }
391 DBFPRINT(("done\n"));
392
393 break;
394 default:
395 warnx("client sent a unsupported command");
396 return -1;
397 }
398 DBFPRINT(("done with command\n"));
399
400 return 0;
401 }
402
403 /*
404 *
405 */
406
407 static void
408 do_server(short port, int nojumbo, int maxmtu, int maxwsize, int minpeertimeout,
409 int udpbufsz, int nostats, int hotthread,
410 int minprocs, int maxprocs)
411 {
412 struct rx_service *service;
413 struct rx_securityClass *secureobj;
414 int secureindex;
415 int ret;
416
417 #ifdef AFS_NT40_ENV
418 if (afs_winsockInit() < 0) {
419 printf("Can't initialize winsock.\n");
420 exit(1);
421 }
422 #endif
423
424 if (hotthread)
425 rx_EnableHotThread();
426
427 if (nostats)
428 rx_enable_stats = 0;
429
430 rx_SetUdpBufSize(udpbufsz);
431
432 ret = rx_Init(htons(port));
433 if (ret)
434 errx(1, "rx_Init failed");
435
436 if (nojumbo)
437 rx_SetNoJumbo();
438
439 if (maxmtu)
440 rx_SetMaxMTU(maxmtu);
441
442 if (maxwsize) {
443 rx_SetMaxReceiveWindow(maxwsize);
444 rx_SetMaxSendWindow(maxwsize);
445 }
446
447 if (minpeertimeout)
448 rx_SetMinPeerTimeout(minpeertimeout);
449
450
451 get_sec(1, &secureobj, &secureindex);
452
453 service =
454 rx_NewService(0, RX_SERVER_ID, "rxperf", &secureobj, secureindex,
455 rxperf_ExecuteRequest);
456 if (service == NULL)
457 errx(1, "Cant create server");
458
459 rx_SetMinProcs(service, minprocs);
460 rx_SetMaxProcs(service, maxprocs);
461
462 rx_SetCheckReach(service, 1);
463
464 rx_StartServer(1);
465
466 abort();
467 }
468
469 /*
470 *
471 */
472
473 static void
474 readfile(const char *filename, afs_uint32 ** readwrite, afs_uint32 * size)
475 {
476 FILE *f;
477 afs_uint32 len = 16;
478 afs_uint32 num = 0;
479 afs_uint32 data;
480 char *ptr;
481 char *buf;
482
483 *readwrite = malloc(sizeof(afs_uint32) * len);
484 buf = malloc(RXPERF_BUFSIZE);
485
486 if (*readwrite == NULL)
487 err(1, "malloc");
488
489 f = fopen(filename, "r");
490 if (f == NULL)
491 err(1, "fopen");
492
493 while (fgets(buf, sizeof(buf), f) != NULL) {
494 if (num >= len) {
495 len = len * 2;
496 *readwrite = realloc(*readwrite, len * sizeof(afs_uint32));
497 if (*readwrite == NULL)
498 err(1, "realloc");
499 }
500
501 if (*buf != '\n') {
502 data = htonl(strtol(buf, &ptr, 0));
503 if (ptr && ptr == buf)
504 errx(1, "can't resolve number of bytes to transfer");
505 } else {
506 data = 0;
507 }
508
509 (*readwrite)[num] = data;
510 num++;
511 }
512
513 *size = num;
514
515
516 if (fclose(f) == -1)
517 err(1, "fclose");
518 free(buf);
519 }
520
521 struct client_data {
522 struct rx_connection *conn;
523 char *filename;
524 int command;
525 afs_int32 times;
526 afs_int32 bytes;
527 afs_int32 sendbytes;
528 afs_int32 readbytes;
529 };
530
531 static void *
532 client_thread( void *vparams)
533 {
534 struct client_data *params = (struct client_data *)vparams;
535 struct rx_call *call;
536 afs_int32 data;
537 int i, j;
538 afs_uint32 *readwrite;
539 int readp = FALSE;
540 afs_uint32 size;
541 afs_uint32 num;
542
543 for (i = 0; i < params->times; i++) {
544
545 DBFPRINT(("starting command "));
546
547 call = rx_NewCall(params->conn);
548 if (call == NULL)
549 errx(1, "rx_NewCall failed");
550
551 data = htonl(RX_PERF_VERSION);
552 if (rx_Write32(call, &data) != 4)
553 errx(1, "rx_Write failed to send version (err %d)", rx_Error(call));
554
555 data = htonl(params->command);
556 if (rx_Write32(call, &data) != 4)
557 errx(1, "rx_Write failed to send command (err %d)", rx_Error(call));
558
559 data = htonl(rxread_size);
560 if (rx_Write32(call, &data) != 4)
561 errx(1, "rx_Write failed to send read size (err %d)", rx_Error(call));
562 data = htonl(rxwrite_size);
563 if (rx_Write32(call, &data) != 4)
564 errx(1, "rx_Write failed to send write read (err %d)", rx_Error(call));
565
566
567 switch (params->command) {
568 case RX_PERF_RECV:
569 DBFPRINT(("command "));
570
571 data = htonl(params->bytes);
572 if (rx_Write32(call, &data) != 4)
573 errx(1, "rx_Write failed to send size (err %d)", rx_Error(call));
574
575 DBFPRINT(("sending(%d) ", params->bytes));
576 if (do_readbytes(call, params->bytes))
577 errx(1, "sendbytes (err %d)", rx_Error(call));
578
579 if (rx_Read32(call, &data) != 4)
580 errx(1, "failed to read result from server (err %d)", rx_Error(call));
581
582 if (data != htonl(RXPERF_MAGIC_COOKIE))
583 warn("server send wrong magic cookie in responce");
584
585 DBFPRINT(("done\n"));
586
587 break;
588 case RX_PERF_SEND:
589 DBFPRINT(("command "));
590
591 data = htonl(params->bytes);
592 if (rx_Write32(call, &data) != 4)
593 errx(1, "rx_Write failed to send size (err %d)", rx_Error(call));
594
595 DBFPRINT(("sending(%d) ", params->bytes));
596 if (do_sendbytes(call, params->bytes))
597 errx(1, "sendbytes (err %d)", rx_Error(call));
598
599 if (rx_Read32(call, &data) != 4)
600 errx(1, "failed to read result from server (err %d)", rx_Error(call));
601
602 if (data != htonl(RXPERF_MAGIC_COOKIE))
603 warn("server send wrong magic cookie in responce");
604
605 DBFPRINT(("done\n"));
606
607 break;
608 case RX_PERF_RPC:
609 DBFPRINT(("commands "));
610
611 data = htonl(params->sendbytes);
612 if (rx_Write32(call, &data) != 4)
613 errx(1, "rx_Write failed to send command (err %d)", rx_Error(call));
614
615 data = htonl(params->readbytes);
616 if (rx_Write32(call, &data) != 4)
617 errx(1, "rx_Write failed to send command (err %d)", rx_Error(call));
618
619 DBFPRINT(("send(%d) ", params->sendbytes));
620 if (do_sendbytes(call, params->sendbytes))
621 errx(1, "sendbytes (err %d)", rx_Error(call));
622
623 DBFPRINT(("recv(%d) ", params->readbytes));
624 if (do_readbytes(call, params->readbytes))
625 errx(1, "sendbytes (err %d)", rx_Error(call));
626
627 if (rx_Read32(call, &data) != 4)
628 errx(1, "failed to read result from server (err %d)", rx_Error(call));
629
630 if (data != htonl(RXPERF_MAGIC_COOKIE))
631 warn("server send wrong magic cookie in responce");
632
633 DBFPRINT(("done\n"));
634
635 break;
636
637 case RX_PERF_FILE:
638 readfile(params->filename, &readwrite, &num);
639
640 data = htonl(num);
641 if (rx_Write32(call, &data) != 4)
642 errx(1, "rx_Write failed to send size (err %d)", rx_Error(call));
643
644 if (rx_Write(call, (char *)readwrite, num * sizeof(afs_uint32))
645 != num * sizeof(afs_uint32))
646 errx(1, "rx_Write failed to send list (err %d)", rx_Error(call));
647
648 for (j = 0; j < num; j++) {
649 if (readwrite[j] == 0)
650 readp = !readp;
651
652 size = ntohl(readwrite[j]) * sizeof(afs_uint32);
653
654 if (readp) {
655 if (do_readbytes(call, size))
656 errx(1, "sendbytes (err %d)", rx_Error(call));
657 DBFPRINT(("read\n"));
658 } else {
659 if (do_sendbytes(call, size))
660 errx(1, "sendbytes (err %d)", rx_Error(call));
661 DBFPRINT(("send\n"));
662 }
663 }
664 break;
665 default:
666 abort();
667 }
668
669 rx_EndCall(call, 0);
670 }
671
672 #ifdef AFS_PTHREAD_ENV
673 pthread_exit(NULL);
674 #endif
675
676 return NULL;
677 }
678
679 /*
680 *
681 */
682
683 static void
684 do_client(const char *server, short port, char *filename, afs_int32 command,
685 afs_int32 times, afs_int32 bytes, afs_int32 sendbytes, afs_int32 readbytes,
686 int dumpstats, int nojumbo, int maxmtu, int maxwsize, int minpeertimeout,
687 int udpbufsz, int nostats, int hotthread, int threads)
688 {
689 struct rx_connection *conn;
690 afs_uint32 addr;
691 struct rx_securityClass *secureobj;
692 int secureindex;
693 int ret;
694 char stamp[2048];
695 struct client_data *params;
696
697 #ifdef AFS_PTHREAD_ENV
698 int i;
699 pthread_t thread[MAX_THREADS];
700 pthread_attr_t tattr;
701 void *status;
702 #endif
703
704 params = calloc(1, sizeof(struct client_data));
705
706 #ifdef AFS_NT40_ENV
707 if (afs_winsockInit() < 0) {
708 printf("Can't initialize winsock.\n");
709 exit(1);
710 }
711 #endif
712
713 if (hotthread)
714 rx_EnableHotThread();
715
716 if (nostats)
717 rx_enable_stats = 0;
718
719 addr = str2addr(server);
720
721 rx_SetUdpBufSize(udpbufsz);
722
723 ret = rx_Init(0);
724 if (ret)
725 errx(1, "rx_Init failed");
726
727 if (nojumbo)
728 rx_SetNoJumbo();
729
730 if (maxmtu)
731 rx_SetMaxMTU(maxmtu);
732
733 if (maxwsize) {
734 rx_SetMaxReceiveWindow(maxwsize);
735 rx_SetMaxSendWindow(maxwsize);
736 }
737
738 if (minpeertimeout)
739 rx_SetMinPeerTimeout(minpeertimeout);
740
741
742 get_sec(0, &secureobj, &secureindex);
743
744 switch (command) {
745 case RX_PERF_RPC:
746 sprintf(stamp, "RPC: threads\t%d, times\t%d, write bytes\t%d, read bytes\t%d",
747 threads, times, sendbytes, readbytes);
748 break;
749 case RX_PERF_RECV:
750 sprintf(stamp, "RECV: threads\t%d, times\t%d, bytes\t%d",
751 threads, times, bytes);
752 break;
753 case RX_PERF_SEND:
754 sprintf(stamp, "SEND: threads\t%d, times\t%d, bytes\t%d",
755 threads, times, bytes);
756 break;
757 case RX_PERF_FILE:
758 sprintf(stamp, "FILE %s: threads\t%d, times\t%d, bytes\t%d",
759 filename, threads, times, bytes);
760 break;
761 }
762
763 conn = rx_NewConnection(addr, htons(port), RX_SERVER_ID, secureobj, secureindex);
764 if (conn == NULL)
765 errx(1, "failed to contact server");
766
767 #ifdef AFS_PTHREAD_ENV
768 pthread_attr_init(&tattr);
769 pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE);
770 #endif
771
772 params->conn = conn;
773 params->filename = filename;
774 params->command = command;
775 params->times = times;
776 params->bytes = bytes;
777 params->sendbytes = sendbytes;
778 params->readbytes = readbytes;
779
780 start_timer();
781
782 #ifdef AFS_PTHREAD_ENV
783 for ( i=0; i<threads; i++) {
784 pthread_create(&thread[i], &tattr, client_thread, params);
785 if ( (i + 1) % RX_MAXCALLS == 0 ) {
786 conn = rx_NewConnection(addr, htons(port), RX_SERVER_ID, secureobj, secureindex);
787 if (conn != NULL) {
788 struct client_data *new_params = malloc(sizeof(struct client_data));
789 memcpy(new_params, params, sizeof(struct client_data));
790 new_params->conn = conn;
791 params = new_params;
792 }
793 }
794 }
795 #else
796 client_thread(params);
797 #endif
798
799 #ifdef AFS_PTHREAD_ENV
800 for ( i=0; i<threads; i++)
801 pthread_join(thread[i], &status);
802 #endif
803
804 switch (command) {
805 case RX_PERF_RPC:
806 end_and_print_timer(stamp, (long long)threads*times*(sendbytes+readbytes));
807 break;
808 case RX_PERF_RECV:
809 case RX_PERF_SEND:
810 case RX_PERF_FILE:
811 end_and_print_timer(stamp, (long long)threads*times*bytes);
812 break;
813 }
814
815 DBFPRINT(("done for good\n"));
816
817 if (dumpstats) {
818 rx_PrintStats(stdout);
819 rx_PrintPeerStats(stdout, rx_PeerOf(conn));
820 }
821 rx_Finalize();
822
823 #ifdef AFS_PTHREAD_ENV
824 pthread_attr_destroy(&tattr);
825 #endif
826
827 free(params);
828 }
829
830 static void
831 usage(void)
832 {
833 #define COMMON ""
834
835 fprintf(stderr, "usage: %s client -c send -b <bytes>\n", getprogname());
836 fprintf(stderr, "usage: %s client -c recv -b <bytes>\n", getprogname());
837 fprintf(stderr,
838 "usage: %s client -c rpc -S <sendbytes> -R <recvbytes>\n",
839 getprogname());
840 fprintf(stderr, "usage: %s client -c file -f filename\n", getprogname());
841 fprintf(stderr,
842 "%s: usage: common option to the client "
843 "-w <write-bytes> -r <read-bytes> -T times -p port -s server -D\n",
844 getprogname());
845 fprintf(stderr, "usage: %s server -p port\n", getprogname());
846 #undef COMMMON
847 exit(1);
848 }
849
850
851
852 /*
853 * do argument processing and call networking functions
854 */
855
856 static int
857 rxperf_server(int argc, char **argv)
858 {
859 short port = DEFAULT_PORT;
860 int nojumbo = 0;
861 int maxmtu = 0;
862 int nostats = 0;
863 int udpbufsz = 64 * 1024;
864 int hotthreads = 0;
865 int minprocs = 2;
866 int maxprocs = 20;
867 int maxwsize = 0;
868 int minpeertimeout = 0;
869 char *ptr;
870 int ch;
871
872 while ((ch = getopt(argc, argv, "r:d:p:P:w:W:HNjm:u:4:s:S:V")) != -1) {
873 switch (ch) {
874 case 'd':
875 #ifdef RXDEBUG
876 rx_debugFile = fopen(optarg, "w");
877 if (rx_debugFile == NULL)
878 err(1, "fopen %s", optarg);
879 #else
880 errx(1, "compiled without RXDEBUG");
881 #endif
882 break;
883 case 'r':
884 rxread_size = strtol(optarg, &ptr, 0);
885 if (ptr != 0 && ptr[0] != '\0')
886 errx(1, "can't resolve readsize");
887 if (rxread_size > sizeof(somebuf))
888 errx(1, "%d > sizeof(somebuf) (%"AFS_SIZET_FMT")", rxread_size,
889 sizeof(somebuf));
890 break;
891 case 's':
892 minprocs = strtol(optarg, &ptr, 0);
893 if (ptr != 0 && ptr[0] != '\0')
894 errx(1, "can't resolve minprocs");
895 break;
896 case 'S':
897 maxprocs = strtol(optarg, &ptr, 0);
898 if (ptr != 0 && ptr[0] != '\0')
899 errx(1, "can't resolve maxprocs");
900 break;
901 case 'P':
902 minpeertimeout = strtol(optarg, &ptr, 0);
903 if (ptr != 0 && ptr[0] != '\0')
904 errx(1, "can't resolve min peer timeout");
905 break;
906 case 'p':
907 port = (short) strtol(optarg, &ptr, 0);
908 if (ptr != 0 && ptr[0] != '\0')
909 errx(1, "can't resolve portname");
910 break;
911 case 'w':
912 rxwrite_size = strtol(optarg, &ptr, 0);
913 if (ptr != 0 && ptr[0] != '\0')
914 errx(1, "can't resolve writesize");
915 if (rxwrite_size > sizeof(somebuf))
916 errx(1, "%d > sizeof(somebuf) (%"AFS_SIZET_FMT")", rxwrite_size,
917 sizeof(somebuf));
918 break;
919 case 'j':
920 nojumbo=1;
921 break;
922 case 'N':
923 nostats=1;
924 break;
925 case 'H':
926 hotthreads = 1;
927 break;
928 case 'm':
929 maxmtu = strtol(optarg, &ptr, 0);
930 if (ptr && *ptr != '\0')
931 errx(1, "can't resolve rx maxmtu to use");
932 break;
933 case 'u':
934 udpbufsz = strtol(optarg, &ptr, 0) * 1024;
935 if (ptr && *ptr != '\0')
936 errx(1, "can't resolve upd buffer size (Kbytes)");
937 break;
938 case 'V':
939 use_rx_readv = 1;
940 break;
941 case 'W':
942 maxwsize = strtol(optarg, &ptr, 0);
943 if (ptr && *ptr != '\0')
944 errx(1, "can't resolve max send/recv window size (packets)");
945 break;
946 case '4':
947 RX_IPUDP_SIZE = 28;
948 break;
949 default:
950 usage();
951 }
952 }
953
954 if (optind != argc)
955 usage();
956
957 do_server(port, nojumbo, maxmtu, maxwsize, minpeertimeout, udpbufsz,
958 nostats, hotthreads, minprocs, maxprocs);
959
960 return 0;
961 }
962
963 /*
964 * do argument processing and call networking functions
965 */
966
967 static int
968 rxperf_client(int argc, char **argv)
969 {
970 char *host = DEFAULT_HOST;
971 int bytes = DEFAULT_BYTES;
972 short port = DEFAULT_PORT;
973 char *filename = NULL;
974 afs_int32 cmd;
975 int sendbytes = 3;
976 int readbytes = 30;
977 int times = 100;
978 int dumpstats = 0;
979 int nojumbo = 0;
980 int nostats = 0;
981 int maxmtu = 0;
982 int hotthreads = 0;
983 int threads = 1;
984 int udpbufsz = 64 * 1024;
985 int maxwsize = 0;
986 int minpeertimeout = 0;
987 char *ptr;
988 int ch;
989
990 cmd = RX_PERF_UNKNOWN;
991
992 while ((ch = getopt(argc, argv, "T:S:R:b:c:d:p:P:r:s:w:W:f:HDNjm:u:4:t:V")) != -1) {
993 switch (ch) {
994 case 'b':
995 bytes = strtol(optarg, &ptr, 0);
996 if (ptr && *ptr != '\0')
997 errx(1, "can't resolve number of bytes to transfer");
998 break;
999 case 'c':
1000 if (strcasecmp(optarg, "send") == 0)
1001 cmd = RX_PERF_SEND;
1002 else if (strcasecmp(optarg, "recv") == 0)
1003 cmd = RX_PERF_RECV;
1004 else if (strcasecmp(optarg, "rpc") == 0)
1005 cmd = RX_PERF_RPC;
1006 else if (strcasecmp(optarg, "file") == 0)
1007 cmd = RX_PERF_FILE;
1008 else
1009 errx(1, "unknown command %s", optarg);
1010 break;
1011 case 'd':
1012 #ifdef RXDEBUG
1013 rx_debugFile = fopen(optarg, "w");
1014 if (rx_debugFile == NULL)
1015 err(1, "fopen %s", optarg);
1016 #else
1017 errx(1, "compiled without RXDEBUG");
1018 #endif
1019 break;
1020 case 'P':
1021 minpeertimeout = strtol(optarg, &ptr, 0);
1022 if (ptr != 0 && ptr[0] != '\0')
1023 errx(1, "can't resolve min peer timeout");
1024 break;
1025 case 'p':
1026 port = (short) strtol(optarg, &ptr, 0);
1027 if (ptr != 0 && ptr[0] != '\0')
1028 errx(1, "can't resolve portname");
1029 break;
1030 case 'r':
1031 rxread_size = strtol(optarg, &ptr, 0);
1032 if (ptr != 0 && ptr[0] != '\0')
1033 errx(1, "can't resolve readsize");
1034 if (rxread_size > sizeof(somebuf))
1035 errx(1, "%d > sizeof(somebuf) (%"AFS_SIZET_FMT")", rxread_size,
1036 sizeof(somebuf));
1037 break;
1038 case 's':
1039 host = strdup(optarg);
1040 if (host == NULL)
1041 err(1, "strdup");
1042 break;
1043 case 'V':
1044 use_rx_readv = 1;
1045 break;
1046 case 'w':
1047 rxwrite_size = strtol(optarg, &ptr, 0);
1048 if (ptr != 0 && ptr[0] != '\0')
1049 errx(1, "can't resolve writesize");
1050 if (rxwrite_size > sizeof(somebuf))
1051 errx(1, "%d > sizeof(somebuf) (%"AFS_SIZET_FMT")", rxwrite_size,
1052 sizeof(somebuf));
1053 break;
1054 case 'W':
1055 maxwsize = strtol(optarg, &ptr, 0);
1056 if (ptr && *ptr != '\0')
1057 errx(1, "can't resolve max send/recv window size (packets)");
1058 break;
1059 case 'T':
1060 times = strtol(optarg, &ptr, 0);
1061 if (ptr && *ptr != '\0')
1062 errx(1, "can't resolve number of times to execute rpc");
1063 break;
1064 case 'S':
1065 sendbytes = strtol(optarg, &ptr, 0);
1066 if (ptr && *ptr != '\0')
1067 errx(1, "can't resolve number of bytes to send");
1068 break;
1069 case 'R':
1070 readbytes = strtol(optarg, &ptr, 0);
1071 if (ptr && *ptr != '\0')
1072 errx(1, "can't resolve number of bytes to receive");
1073 break;
1074 case 't':
1075 #ifdef AFS_PTHREAD_ENV
1076 threads = strtol(optarg, &ptr, 0);
1077 if (ptr && *ptr != '\0')
1078 errx(1, "can't resolve number of threads to execute");
1079 if (threads > MAX_THREADS)
1080 errx(1, "too many threads");
1081 #else
1082 errx(1, "Not built for pthreads");
1083 #endif
1084 break;
1085 case 'f':
1086 filename = optarg;
1087 break;
1088 case 'D':
1089 dumpstats = 1;
1090 break;
1091 case 'N':
1092 nostats = 1;
1093 break;
1094 case 'H':
1095 hotthreads = 1;
1096 break;
1097 case 'j':
1098 nojumbo=1;
1099 break;
1100 case 'm':
1101 maxmtu = strtol(optarg, &ptr, 0);
1102 if (ptr && *ptr != '\0')
1103 errx(1, "can't resolve rx maxmtu to use");
1104 break;
1105 case 'u':
1106 udpbufsz = strtol(optarg, &ptr, 0) * 1024;
1107 if (ptr && *ptr != '\0')
1108 errx(1, "can't resolve upd buffer size (Kbytes)");
1109 break;
1110 case '4':
1111 RX_IPUDP_SIZE = 28;
1112 break;
1113 default:
1114 usage();
1115 }
1116 }
1117
1118 if (nostats && dumpstats)
1119 errx(1, "cannot set both -N and -D");
1120
1121 if (threads > 1 && cmd == RX_PERF_FILE)
1122 errx(1, "cannot use multiple threads with file command");
1123
1124 if (optind != argc)
1125 usage();
1126
1127 if (cmd == RX_PERF_UNKNOWN)
1128 errx(1, "no command given to the client");
1129
1130 do_client(host, port, filename, cmd, times, bytes, sendbytes,
1131 readbytes, dumpstats, nojumbo, maxmtu, maxwsize, minpeertimeout,
1132 udpbufsz, nostats, hotthreads, threads);
1133
1134 return 0;
1135 }
1136
1137 /*
1138 * setup world and call cmd
1139 */
1140
1141 int
1142 main(int argc, char **argv)
1143 {
1144 #ifndef AFS_PTHREAD_ENV
1145 PROCESS pid;
1146 #endif
1147
1148 setprogname(argv[0]);
1149
1150 #ifndef AFS_NT40_ENV
1151 signal(SIGUSR1, sigusr1);
1152 signal(SIGINT, sigint);
1153 #endif
1154
1155 #ifndef AFS_PTHREAD_ENV
1156 LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY, &pid);
1157 #endif
1158
1159 memset(somebuf, 0, sizeof(somebuf));
1160
1161 if (argc >= 2 && strcmp(argv[1], "server") == 0)
1162 rxperf_server(argc - 1, argv + 1);
1163 else if (argc >= 2 && strcmp(argv[1], "client") == 0)
1164 rxperf_client(argc - 1, argv + 1);
1165 else
1166 usage();
1167 return 0;
1168 }