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