Rx: Permit udp buffer size to be set in rxperf
[openafs.git] / src / rx / test / 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
45 #include <stdarg.h>
46 #include <sys/types.h>
47 #ifdef AFS_NT40_ENV
48 #include <io.h>
49 #include <winsock2.h>
50 #include <fcntl.h>
51 #include <stdlib.h>
52 #include <time.h>
53 #else
54 #include <sys/time.h>
55 #include <sys/socket.h>
56 #include <sys/file.h>
57 #include <sys/stat.h>
58 #include <netinet/in.h>
59 #include <arpa/inet.h>
60 #include <netdb.h>
61 #endif
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <errno.h>
65 #ifdef HAVE_STRING_H
66 #include <string.h>
67 #else
68 #ifdef HAVE_STRINGS_H
69 #include <strings.h>
70 #endif
71 #endif
72 #include <assert.h>
73 #ifdef HAVE_UNISTD_H
74 #include <unistd.h>
75 #endif
76 #include <signal.h>
77 #ifdef HAVE_ERRX
78 #include <err.h>                /* not stricly right, but if we have a errx() there
79                                  * is hopefully a err.h */
80 #endif
81 #include <getopt.h>
82 #include "rx.h"
83 #include "rx_null.h"
84 #include "rx_globals.h"
85
86 static const char *__progname;
87
88 #ifndef HAVE_WARNX
89 static void
90 warnx(const char *fmt, ...)
91 {
92     va_list args;
93
94     va_start(args, fmt);
95     fprintf(stderr, "%s: ", __progname);
96     vfprintf(stderr, fmt, args);
97     fprintf(stderr, "\n");
98     va_end(args);
99 }
100 #endif /* !HAVE_WARNX */
101
102 #ifndef HAVE_ERRX
103 static void
104 errx(int eval, const char *fmt, ...)
105 {
106     va_list args;
107
108     va_start(args, fmt);
109     fprintf(stderr, "%s: ", __progname);
110     vfprintf(stderr, fmt, args);
111     fprintf(stderr, "\n");
112     va_end(args);
113
114     exit(eval);
115 }
116 #endif /* !HAVE_ERRX */
117
118 #ifndef HAVE_WARN
119 static void
120 warn(const char *fmt, ...)
121 {
122     va_list args;
123     char *errstr;
124
125     va_start(args, fmt);
126     fprintf(stderr, "%s: ", __progname);
127     vfprintf(stderr, fmt, args);
128
129     errstr = strerror(errno);
130
131     fprintf(stderr, ": %s\n", errstr ? errstr : "unknown error");
132     va_end(args);
133 }
134 #endif /* !HAVE_WARN */
135
136 #ifndef HAVE_ERR
137 static void
138 err(int eval, const char *fmt, ...)
139 {
140     va_list args;
141     char *errstr;
142
143     va_start(args, fmt);
144     fprintf(stderr, "%s: ", __progname);
145     vfprintf(stderr, fmt, args);
146
147     errstr = strerror(errno);
148
149     fprintf(stderr, ": %s\n", errstr ? errstr : "unknown error");
150     va_end(args);
151
152     exit(eval);
153 }
154 #endif /* !HAVE_ERR */
155
156 #define DEFAULT_PORT 7009       /* To match tcpdump */
157 #define DEFAULT_HOST "127.0.0.1"
158 #define DEFAULT_BYTES 1000000
159 #define RXPERF_BUFSIZE 512 * 1024
160
161 enum { RX_PERF_VERSION = 3 };
162 enum { RX_SERVER_ID = 147 };
163 enum { RX_PERF_UNKNOWN = -1,
164        RX_PERF_SEND = 0,
165        RX_PERF_RECV = 1,
166        RX_PERF_RPC = 3,
167        RX_PERF_FILE = 4
168 };
169
170 enum { RXPERF_MAGIC_COOKIE = 0x4711 };
171
172 /*
173  *
174  */
175
176 #if RXPERF_DEBUG
177 #define DBFPRINT(x) do { printf x ; } while(0)
178 #else
179 #define DBFPRINT(x)
180 #endif
181
182 static void
183 sigusr1(int foo)
184 {
185     exit(2);                    /* XXX profiler */
186 }
187
188 static void
189 sigint(int foo)
190 {
191     rx_Finalize();
192     exit(2);                    /* XXX profiler */
193 }
194
195 /*
196  *
197  */
198
199 static struct timeval timer_start;
200 static struct timeval timer_stop;
201 static int timer_check = 0;
202
203 static void
204 start_timer(void)
205 {
206     timer_check++;
207     gettimeofday(&timer_start, NULL);
208 }
209
210 /*
211  *
212  */
213
214 static void
215 end_and_print_timer(char *str)
216 {
217     long long start_l, stop_l;
218
219     timer_check--;
220     assert(timer_check == 0);
221     gettimeofday(&timer_stop, NULL);
222     start_l = timer_start.tv_sec * 1000000 + timer_start.tv_usec;
223     stop_l = timer_stop.tv_sec * 1000000 + timer_stop.tv_usec;
224     printf("%s:\t%8llu msec\n", str, (stop_l - start_l) / 1000);
225 }
226
227 /*
228  *
229  */
230
231 static u_long
232 str2addr(const char *s)
233 {
234     struct in_addr server;
235     struct hostent *h;
236
237 #ifndef INADDR_NONE
238 #define INADDR_NONE 0xffffffff
239 #endif
240     if (inet_addr(s) != INADDR_NONE)
241         return inet_addr(s);
242     h = gethostbyname(s);
243     if (h != NULL) {
244         memcpy(&server, h->h_addr_list[0], sizeof(server));
245         return server.s_addr;
246     }
247     return 0;
248 }
249
250
251 /*
252  *
253  */
254
255 static void
256 get_sec(int serverp, struct rx_securityClass **sec, int *secureindex)
257 {
258     if (serverp) {
259         *sec = rxnull_NewServerSecurityObject();
260         *secureindex = 1;
261     } else {
262         *sec = rxnull_NewClientSecurityObject();
263         *secureindex = 0;
264     }
265 }
266
267 /*
268  * process the "RPC" and return the results
269  */
270
271 char somebuf[RXPERF_BUFSIZE];
272
273 afs_int32 rxwrite_size = sizeof(somebuf);
274 afs_int32 rxread_size = sizeof(somebuf);
275
276 static int
277 readbytes(struct rx_call *call, afs_int32 bytes)
278 {
279     afs_int32 size;
280
281     while (bytes > 0) {
282         size = rxread_size;
283         if (size > bytes)
284             size = bytes;
285         if (rx_Read(call, somebuf, size) != size)
286             return 1;
287         bytes -= size;
288     }
289     return 0;
290 }
291
292 static int
293 sendbytes(struct rx_call *call, afs_int32 bytes)
294 {
295     afs_int32 size;
296
297     while (bytes > 0) {
298         size = rxwrite_size;
299         if (size > bytes)
300             size = bytes;
301         if (rx_Write(call, somebuf, size) != size)
302             return 1;
303         bytes -= size;
304     }
305     return 0;
306 }
307
308
309 static afs_int32
310 rxperf_ExecuteRequest(struct rx_call *call)
311 {
312     afs_int32 version;
313     afs_int32 command;
314     afs_uint32 bytes;
315     afs_uint32 recvb;
316     afs_uint32 sendb;
317     afs_uint32 data;
318     afs_uint32 num;
319     afs_uint32 *readwrite;
320     afs_uint32 i;
321     int readp = TRUE;
322
323     DBFPRINT(("got a request\n"));
324
325     if (rx_Read32(call, &version) != 4) {
326         warn("rx_Read failed to read version");
327         return -1;
328     }
329
330     if (htonl(RX_PERF_VERSION) != version) {
331         warnx("client has wrong version");
332         return -1;
333     }
334
335     if (rx_Read32(call, &command) != 4) {
336         warnx("rx_Read failed to read command");
337         return -1;
338     }
339     command = ntohl(command);
340
341     if (rx_Read32(call, &data) != 4) {
342         warnx("rx_Read failed to read size");
343         return -1;
344     }
345     rxread_size = ntohl(data);
346     if (rxread_size > sizeof(somebuf)) {
347         warnx("rxread_size too large %d", rxread_size);
348         return -1;
349     }
350
351     if (rx_Read32(call, &data) != 4) {
352         warnx("rx_Read failed to write size");
353         return -1;
354     }
355     rxwrite_size = ntohl(data);
356     if (rxwrite_size > sizeof(somebuf)) {
357         warnx("rxwrite_size too large %d", rxwrite_size);
358         return -1;
359     }
360
361     switch (command) {
362     case RX_PERF_SEND:
363         DBFPRINT(("got a send request\n"));
364
365         if (rx_Read32(call, &bytes) != 4) {
366             warnx("rx_Read failed to read bytes");
367             return -1;
368         }
369         bytes = ntohl(bytes);
370
371         DBFPRINT(("reading(%d) ", bytes));
372         readbytes(call, bytes);
373
374         data = htonl(RXPERF_MAGIC_COOKIE);
375         if (rx_Write32(call, &data) != 4) {
376             warnx("rx_Write failed when sending back result");
377             return -1;
378         }
379         DBFPRINT(("done\n"));
380
381         break;
382     case RX_PERF_RPC:
383         DBFPRINT(("got a rpc request, reading commands\n"));
384
385         if (rx_Read32(call, &recvb) != 4) {
386             warnx("rx_Read failed to read recvbytes");
387             return -1;
388         }
389         recvb = ntohl(recvb);
390         if (rx_Read32(call, &sendb) != 4) {
391             warnx("rx_Read failed to read sendbytes");
392             return -1;
393         }
394         sendb = ntohl(sendb);
395
396         DBFPRINT(("read(%d) ", recvb));
397         if (readbytes(call, recvb)) {
398             warnx("readbytes failed");
399             return -1;
400         }
401         DBFPRINT(("send(%d) ", sendb));
402         if (sendbytes(call, sendb)) {
403             warnx("sendbytes failed");
404             return -1;
405         }
406
407         DBFPRINT(("done\n"));
408
409         data = htonl(RXPERF_MAGIC_COOKIE);
410         if (rx_Write32(call, &data) != 4) {
411             warnx("rx_Write failed when sending back magic cookie");
412             return -1;
413         }
414
415         break;
416     case RX_PERF_FILE:
417         if (rx_Read32(call, &data) != 4)
418             errx(1, "failed to read num from client");
419         num = ntohl(data);
420
421         readwrite = malloc(num * sizeof(afs_uint32));
422         if (readwrite == NULL)
423             err(1, "malloc");
424
425         if (rx_Read(call, (char*)readwrite, num * sizeof(afs_uint32)) !=
426             num * sizeof(afs_uint32))
427             errx(1, "failed to read recvlist from client");
428
429         for (i = 0; i < num; i++) {
430             if (readwrite[i] == 0) {
431                 DBFPRINT(("readp %d", readwrite[i]));
432                 readp = !readp;
433             }
434
435             bytes = ntohl(readwrite[i]) * sizeof(afs_uint32);
436
437             if (readp) {
438                 DBFPRINT(("read\n"));
439                 readbytes(call, bytes);
440             } else {
441                 sendbytes(call, bytes);
442                 DBFPRINT(("send\n"));
443             }
444         }
445
446         break;
447     case RX_PERF_RECV:
448         DBFPRINT(("got a recv request\n"));
449
450         if (rx_Read32(call, &bytes) != 4) {
451             warnx("rx_Read failed to read bytes");
452             return -1;
453         }
454         bytes = ntohl(bytes);
455
456         DBFPRINT(("sending(%d) ", bytes));
457         sendbytes(call, bytes);
458
459         data = htonl(RXPERF_MAGIC_COOKIE);
460         if (rx_Write32(call, &data) != 4) {
461             warnx("rx_Write failed when sending back result");
462             return -1;
463         }
464         DBFPRINT(("done\n"));
465
466         break;
467     default:
468         warnx("client sent a unsupported command");
469         return -1;
470     }
471     DBFPRINT(("done with command\n"));
472
473     return 0;
474 }
475
476 /*
477  *
478  */
479
480 static void
481 do_server(short port, int nojumbo, int maxmtu, int udpbufsz)
482 {
483     struct rx_service *service;
484     struct rx_securityClass *secureobj;
485     int secureindex;
486     int ret;
487
488 #ifdef AFS_NT40_ENV
489     if (afs_winsockInit() < 0) {
490         printf("Can't initialize winsock.\n");
491         exit(1);
492     }
493     rx_EnableHotThread();
494 #endif
495
496     ret = rx_Init(htons(port));
497     if (ret)
498         errx(1, "rx_Init failed");
499
500     if (nojumbo)
501       rx_SetNoJumbo();
502
503     if (maxmtu)
504       rx_SetMaxMTU(maxmtu);
505
506     rx_SetUdpBufSize(udpbufsz);
507
508     get_sec(1, &secureobj, &secureindex);
509
510     service =
511         rx_NewService(0, RX_SERVER_ID, "rxperf", &secureobj, secureindex,
512                       rxperf_ExecuteRequest);
513     if (service == NULL)
514         errx(1, "Cant create server");
515
516     rx_SetMinProcs(service, 2);
517     rx_SetMaxProcs(service, 100);
518     rx_SetCheckReach(service, 1);
519
520     rx_StartServer(1);
521     abort();
522 }
523
524 /*
525  *
526  */
527
528 static void
529 readfile(const char *filename, afs_uint32 ** readwrite, afs_uint32 * size)
530 {
531     FILE *f;
532     afs_uint32 len = 16;
533     afs_uint32 num = 0;
534     afs_uint32 data;
535     char *ptr;
536     char buf[RXPERF_BUFSIZE];
537
538     *readwrite = malloc(sizeof(afs_uint32) * len);
539
540     if (*readwrite == NULL)
541         err(1, "malloc");
542
543     f = fopen(filename, "r");
544     if (f == NULL)
545         err(1, "fopen");
546
547     while (fgets(buf, sizeof(buf), f) != NULL) {
548         if (num >= len) {
549             len = len * 2;
550             *readwrite = realloc(*readwrite, len * sizeof(afs_uint32));
551             if (*readwrite == NULL)
552                 err(1, "realloc");
553         }
554
555         if (*buf != '\n') {
556             data = htonl(strtol(buf, &ptr, 0));
557             if (ptr && ptr == buf)
558                 errx(1, "can't resolve number of bytes to transfer");
559         } else {
560             data = 0;
561         }
562
563         (*readwrite)[num] = data;
564         num++;
565     }
566
567     *size = num;
568
569
570     if (fclose(f) == -1)
571         err(1, "fclose");
572 }
573
574
575 /*
576  *
577  */
578
579 static void
580 do_client(const char *server, short port, char *filename, afs_int32 command,
581           afs_int32 times, afs_int32 bytes, afs_int32 sendtimes, afs_int32 recvtimes,
582           int dumpstats, int nojumbo, int maxmtu, int udpbufsz)
583 {
584     struct rx_connection *conn;
585     struct rx_call *call;
586     afs_uint32 addr;
587     struct rx_securityClass *secureobj;
588     int secureindex;
589     afs_int32 data;
590     afs_int32 num;
591     int ret;
592     int i;
593     int readp = FALSE;
594     char stamp[1024];
595     afs_uint32 size;
596
597     afs_uint32 *readwrite;
598
599 #ifdef AFS_NT40_ENV
600     if (afs_winsockInit() < 0) {
601         printf("Can't initialize winsock.\n");
602         exit(1);
603     }
604     rx_EnableHotThread();
605 #endif
606
607     addr = str2addr(server);
608
609     ret = rx_Init(0);
610     if (ret)
611         errx(1, "rx_Init failed");
612
613     if (nojumbo)
614       rx_SetNoJumbo();
615
616     if (maxmtu)
617       rx_SetMaxMTU(maxmtu);
618
619     rx_SetUdpBufSize(udpbufsz);
620
621     get_sec(0, &secureobj, &secureindex);
622
623     conn = rx_NewConnection(addr, htons(port), RX_SERVER_ID, secureobj, secureindex);
624     if (conn == NULL)
625         errx(1, "failed to contact server");
626
627     sprintf(stamp, "send\t%d times\t%d writes\t%d reads", times, sendtimes,
628             recvtimes);
629     start_timer();
630
631     for (i = 0; i < times; i++) {
632
633         DBFPRINT(("starting command "));
634
635         call = rx_NewCall(conn);
636         if (call == NULL)
637             errx(1, "rx_NewCall failed");
638
639         data = htonl(RX_PERF_VERSION);
640         if (rx_Write32(call, &data) != 4)
641             errx(1, "rx_Write failed to send version (err %d)", rx_Error(call));
642
643         data = htonl(command);
644         if (rx_Write32(call, &data) != 4)
645             errx(1, "rx_Write failed to send command (err %d)", rx_Error(call));
646
647         data = htonl(rxread_size);
648         if (rx_Write32(call, &data) != 4)
649             errx(1, "rx_Write failed to send read size (err %d)", rx_Error(call));
650         data = htonl(rxwrite_size);
651         if (rx_Write32(call, &data) != 4)
652             errx(1, "rx_Write failed to send write read (err %d)", rx_Error(call));
653
654
655         switch (command) {
656         case RX_PERF_RECV:
657             DBFPRINT(("command "));
658
659             data = htonl(bytes);
660             if (rx_Write32(call, &data) != 4)
661                 errx(1, "rx_Write failed to send size (err %d)", rx_Error(call));
662
663             DBFPRINT(("sending(%d) ", bytes));
664             if (readbytes(call, bytes))
665                 errx(1, "sendbytes (err %d)", rx_Error(call));
666
667             if (rx_Read32(call, &data) != 4)
668                 errx(1, "failed to read result from server (err %d)", rx_Error(call));
669
670             if (data != htonl(RXPERF_MAGIC_COOKIE))
671                 warn("server send wrong magic cookie in responce");
672
673             DBFPRINT(("done\n"));
674
675             break;
676         case RX_PERF_SEND:
677             DBFPRINT(("command "));
678
679             data = htonl(bytes);
680             if (rx_Write32(call, &data) != 4)
681                 errx(1, "rx_Write failed to send size (err %d)", rx_Error(call));
682
683             DBFPRINT(("sending(%d) ", bytes));
684             if (sendbytes(call, bytes))
685                 errx(1, "sendbytes (err %d)", rx_Error(call));
686
687             if (rx_Read32(call, &data) != 4)
688                 errx(1, "failed to read result from server (err %d)", rx_Error(call));
689
690             if (data != htonl(RXPERF_MAGIC_COOKIE))
691                 warn("server send wrong magic cookie in responce");
692
693             DBFPRINT(("done\n"));
694
695             break;
696         case RX_PERF_RPC:
697             DBFPRINT(("commands "));
698
699             data = htonl(sendtimes);
700             if (rx_Write32(call, &data) != 4)
701                 errx(1, "rx_Write failed to send command (err %d)", rx_Error(call));
702
703             data = htonl(recvtimes);
704             if (rx_Write32(call, &data) != 4)
705                 errx(1, "rx_Write failed to send command (err %d)", rx_Error(call));
706
707             DBFPRINT(("send(%d) ", sendtimes));
708             if (sendbytes(call, sendtimes))
709                 errx(1, "sendbytes (err %d)", rx_Error(call));
710
711             DBFPRINT(("recv(%d) ", recvtimes));
712             if (readbytes(call, recvtimes))
713                 errx(1, "sendbytes (err %d)", rx_Error(call));
714
715             if (rx_Read32(call, &bytes) != 4)
716                 errx(1, "failed to read result from server (err %d)", rx_Error(call));
717
718             if (bytes != htonl(RXPERF_MAGIC_COOKIE))
719                 warn("server send wrong magic cookie in responce");
720
721             DBFPRINT(("done\n"));
722
723             break;
724         case RX_PERF_FILE:
725             readfile(filename, &readwrite, &num);
726
727             data = htonl(num);
728             if (rx_Write32(call, &data) != 4)
729                 errx(1, "rx_Write failed to send size (err %d)", rx_Error(call));
730
731             if (rx_Write(call, (char *)readwrite, num * sizeof(afs_uint32))
732                 != num * sizeof(afs_uint32))
733                 errx(1, "rx_Write failed to send list (err %d)", rx_Error(call));
734
735             for (i = 0; i < num; i++) {
736                 if (readwrite[i] == 0)
737                     readp = !readp;
738
739                 size = ntohl(readwrite[i]) * sizeof(afs_uint32);
740
741                 if (readp) {
742                     if (readbytes(call, size))
743                         errx(1, "sendbytes (err %d)", rx_Error(call));
744                     DBFPRINT(("read\n"));
745                 } else {
746                     if (sendbytes(call, size))
747                         errx(1, "sendbytes (err %d)", rx_Error(call));
748                     DBFPRINT(("send\n"));
749                 }
750             }
751             break;
752         default:
753             abort();
754         }
755
756         rx_EndCall(call, 0);
757     }
758
759     end_and_print_timer(stamp);
760     DBFPRINT(("done for good\n"));
761
762     if (dumpstats) {
763         rx_PrintStats(stdout);
764         rx_PrintPeerStats(stdout, conn->peer);
765     }
766     rx_Finalize();
767 }
768
769 static void
770 usage()
771 {
772 #define COMMON ""
773
774     fprintf(stderr, "usage: %s client -c send -b <bytes>\n", __progname);
775     fprintf(stderr, "usage: %s client -c recv -b <bytes>\n", __progname);
776     fprintf(stderr,
777             "usage: %s client -c rpc  -S <sendbytes> -R <recvbytes>\n",
778             __progname);
779     fprintf(stderr, "usage: %s client -c file -f filename\n", __progname);
780     fprintf(stderr,
781             "%s: usage: common option to the client "
782             "-w <write-bytes> -r <read-bytes> -T times -p port -s server -D\n",
783             __progname);
784     fprintf(stderr, "usage: %s server -p port\n", __progname);
785 #undef COMMMON
786     exit(1);
787 }
788
789 /*
790  * do argument processing and call networking functions
791  */
792
793 static int
794 rxperf_server(int argc, char **argv)
795 {
796     short port = DEFAULT_PORT;
797     int nojumbo = 0;
798     int maxmtu = 0;
799     int udpbufsz = 64 * 1024;
800     char *ptr;
801     int ch;
802
803     while ((ch = getopt(argc, argv, "r:d:p:w:jm:u:4")) != -1) {
804         switch (ch) {
805         case 'd':
806 #ifdef RXDEBUG
807             rx_debugFile = fopen(optarg, "w");
808             if (rx_debugFile == NULL)
809                 err(1, "fopen %s", optarg);
810 #else
811             errx(1, "compiled without RXDEBUG");
812 #endif
813             break;
814         case 'r':
815             rxread_size = strtol(optarg, &ptr, 0);
816             if (ptr != 0 && ptr[0] != '\0')
817                 errx(1, "can't resolve readsize");
818             if (rxread_size > sizeof(somebuf))
819                 errx(1, "%d > sizeof(somebuf) (%d)", rxread_size,
820                      sizeof(somebuf));
821             break;
822         case 'p':
823             port = strtol(optarg, &ptr, 0);
824             if (ptr != 0 && ptr[0] != '\0')
825                 errx(1, "can't resolve portname");
826             break;
827         case 'w':
828             rxwrite_size = strtol(optarg, &ptr, 0);
829             if (ptr != 0 && ptr[0] != '\0')
830                 errx(1, "can't resolve writesize");
831             if (rxwrite_size > sizeof(somebuf))
832                 errx(1, "%d > sizeof(somebuf) (%d)", rxwrite_size,
833                      sizeof(somebuf));
834             break;
835         case 'j':
836           nojumbo=1;
837           break;
838         case 'm':
839           maxmtu = strtol(optarg, &ptr, 0);
840           if (ptr && *ptr != '\0')
841             errx(1, "can't resolve rx maxmtu to use");
842             break;
843         case 'u':
844             udpbufsz = strtol(optarg, &ptr, 0) * 1024;
845             if (ptr && *ptr != '\0')
846                 errx(1, "can't resolve upd buffer size (Kbytes)");
847             break;
848         case '4':
849           RX_IPUDP_SIZE = 28;
850           break;
851         default:
852             usage();
853         }
854     }
855
856     if (optind != argc)
857         usage();
858
859     do_server(port, nojumbo, maxmtu, udpbufsz);
860
861     return 0;
862 }
863
864 /*
865  * do argument processing and call networking functions
866  */
867
868 static int
869 rxperf_client(int argc, char **argv)
870 {
871     char *host = DEFAULT_HOST;
872     int bytes = DEFAULT_BYTES;
873     short port = DEFAULT_PORT;
874     char *filename = NULL;
875     afs_int32 cmd;
876     int sendtimes = 3;
877     int recvtimes = 30;
878     int times = 100;
879     int dumpstats = 0;
880     int nojumbo = 0;
881     int maxmtu = 0;
882     int udpbufsz = 64 * 1024;
883     char *ptr;
884     int ch;
885
886     cmd = RX_PERF_UNKNOWN;
887
888     while ((ch = getopt(argc, argv, "T:S:R:b:c:d:p:r:s:w:f:Djm:u:4")) != -1) {
889         switch (ch) {
890         case 'b':
891             bytes = strtol(optarg, &ptr, 0);
892             if (ptr && *ptr != '\0')
893                 errx(1, "can't resolve number of bytes to transfer");
894             break;
895         case 'c':
896             if (strcasecmp(optarg, "send") == 0)
897                 cmd = RX_PERF_SEND;
898             else if (strcasecmp(optarg, "recv") == 0)
899                 cmd = RX_PERF_RECV;
900             else if (strcasecmp(optarg, "rpc") == 0)
901                 cmd = RX_PERF_RPC;
902             else if (strcasecmp(optarg, "file") == 0)
903                 cmd = RX_PERF_FILE;
904             else
905                 errx(1, "unknown command %s", optarg);
906             break;
907         case 'd':
908 #ifdef RXDEBUG
909             rx_debugFile = fopen(optarg, "w");
910             if (rx_debugFile == NULL)
911                 err(1, "fopen %s", optarg);
912 #else
913             errx(1, "compiled without RXDEBUG");
914 #endif
915             break;
916         case 'p':
917             port = strtol(optarg, &ptr, 0);
918             if (ptr != 0 && ptr[0] != '\0')
919                 errx(1, "can't resolve portname");
920             break;
921         case 'r':
922             rxread_size = strtol(optarg, &ptr, 0);
923             if (ptr != 0 && ptr[0] != '\0')
924                 errx(1, "can't resolve readsize");
925             if (rxread_size > sizeof(somebuf))
926                 errx(1, "%d > sizeof(somebuf) (%d)", rxread_size,
927                      sizeof(somebuf));
928             break;
929         case 's':
930             host = strdup(optarg);
931             if (host == NULL)
932                 err(1, "strdup");
933             break;
934         case 'w':
935             rxwrite_size = strtol(optarg, &ptr, 0);
936             if (ptr != 0 && ptr[0] != '\0')
937                 errx(1, "can't resolve writesize");
938             if (rxwrite_size > sizeof(somebuf))
939                 errx(1, "%d > sizeof(somebuf) (%d)", rxwrite_size,
940                      sizeof(somebuf));
941             break;
942         case 'T':
943             times = strtol(optarg, &ptr, 0);
944             if (ptr && *ptr != '\0')
945                 errx(1, "can't resolve number of times to execute rpc");
946             break;
947         case 'S':
948             sendtimes = strtol(optarg, &ptr, 0);
949             if (ptr && *ptr != '\0')
950                 errx(1, "can't resolve number of bytes to send");
951             break;
952         case 'R':
953             recvtimes = strtol(optarg, &ptr, 0);
954             if (ptr && *ptr != '\0')
955                 errx(1, "can't resolve number of bytes to receive");
956             break;
957         case 'f':
958             filename = optarg;
959             break;
960         case 'D':
961             dumpstats = 1;
962             break;
963         case 'j':
964           nojumbo=1;
965           break;
966         case 'm':
967           maxmtu = strtol(optarg, &ptr, 0);
968           if (ptr && *ptr != '\0')
969             errx(1, "can't resolve rx maxmtu to use");
970             break;
971         case 'u':
972             udpbufsz = strtol(optarg, &ptr, 0) * 1024;
973             if (ptr && *ptr != '\0')
974                 errx(1, "can't resolve upd buffer size (Kbytes)");
975             break;
976         case '4':
977           RX_IPUDP_SIZE = 28;
978           break;
979         default:
980             usage();
981         }
982     }
983
984     if (optind != argc)
985         usage();
986
987     if (cmd == RX_PERF_UNKNOWN)
988         errx(1, "no command given to the client");
989
990     do_client(host, port, filename, cmd, times, bytes, sendtimes,
991               recvtimes, dumpstats, nojumbo, maxmtu, udpbufsz);
992
993     return 0;
994 }
995
996 /*
997  * setup world and call cmd
998  */
999
1000 int
1001 main(int argc, char **argv)
1002 {
1003 #ifndef AFS_PTHREAD_ENV
1004     PROCESS pid;
1005 #endif
1006
1007     __progname = strrchr(argv[0], '/');
1008     if (__progname == 0)
1009         __progname = argv[0];
1010
1011 #ifndef AFS_NT40_ENV
1012     signal(SIGUSR1, sigusr1);
1013     signal(SIGINT, sigint);
1014 #endif
1015
1016 #ifndef AFS_PTHREAD_ENV
1017     LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY, &pid);
1018 #endif
1019
1020     memset(somebuf, 0, sizeof(somebuf));
1021
1022     if (argc >= 2 && strcmp(argv[1], "server") == 0)
1023         rxperf_server(argc - 1, argv + 1);
1024     else if (argc >= 2 && strcmp(argv[1], "client") == 0)
1025         rxperf_client(argc - 1, argv + 1);
1026     else
1027         usage();
1028     return 0;
1029 }