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