2 * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
35 #include <afsconfig.h>
38 nn * We are using getopt since we want it to be possible to link to
42 #include <afsconfig.h>
43 #include <afs/param.h>
46 #include <sys/types.h>
55 #include <sys/socket.h>
58 #include <netinet/in.h>
59 #include <arpa/inet.h>
78 #include <err.h> /* not stricly right, but if we have a errx() there
79 * is hopefully a err.h */
84 #include "rx_globals.h"
86 static const char *__progname;
90 warnx(const char *fmt, ...)
95 fprintf(stderr, "%s: ", __progname);
96 vfprintf(stderr, fmt, args);
97 fprintf(stderr, "\n");
100 #endif /* !HAVE_WARNX */
104 errx(int eval, const char *fmt, ...)
109 fprintf(stderr, "%s: ", __progname);
110 vfprintf(stderr, fmt, args);
111 fprintf(stderr, "\n");
116 #endif /* !HAVE_ERRX */
120 warn(const char *fmt, ...)
126 fprintf(stderr, "%s: ", __progname);
127 vfprintf(stderr, fmt, args);
129 errstr = strerror(errno);
131 fprintf(stderr, ": %s\n", errstr ? errstr : "unknown error");
134 #endif /* !HAVE_WARN */
138 err(int eval, const char *fmt, ...)
144 fprintf(stderr, "%s: ", __progname);
145 vfprintf(stderr, fmt, args);
147 errstr = strerror(errno);
149 fprintf(stderr, ": %s\n", errstr ? errstr : "unknown error");
154 #endif /* !HAVE_ERR */
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
161 enum { RX_PERF_VERSION = 3 };
162 enum { RX_SERVER_ID = 147 };
163 enum { RX_PERF_UNKNOWN = -1,
170 enum { RXPERF_MAGIC_COOKIE = 0x4711 };
177 #define DBFPRINT(x) do { printf x ; } while(0)
185 exit(2); /* XXX profiler */
192 exit(2); /* XXX profiler */
199 static struct timeval timer_start;
200 static struct timeval timer_stop;
201 static int timer_check = 0;
207 gettimeofday(&timer_start, NULL);
215 end_and_print_timer(char *str)
217 long long start_l, stop_l;
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);
232 str2addr(const char *s)
234 struct in_addr server;
238 #define INADDR_NONE 0xffffffff
240 if (inet_addr(s) != INADDR_NONE)
242 h = gethostbyname(s);
244 memcpy(&server, h->h_addr_list[0], sizeof(server));
245 return server.s_addr;
256 get_sec(int serverp, struct rx_securityClass **sec, int *secureindex)
259 *sec = rxnull_NewServerSecurityObject();
262 *sec = rxnull_NewClientSecurityObject();
268 * process the "RPC" and return the results
271 char somebuf[RXPERF_BUFSIZE];
273 afs_int32 rxwrite_size = sizeof(somebuf);
274 afs_int32 rxread_size = sizeof(somebuf);
277 readbytes(struct rx_call *call, afs_int32 bytes)
285 if (rx_Read(call, somebuf, size) != size)
293 sendbytes(struct rx_call *call, afs_int32 bytes)
301 if (rx_Write(call, somebuf, size) != size)
310 rxperf_ExecuteRequest(struct rx_call *call)
319 afs_uint32 *readwrite;
323 DBFPRINT(("got a request\n"));
325 if (rx_Read32(call, &version) != 4) {
326 warn("rx_Read failed to read version");
330 if (htonl(RX_PERF_VERSION) != version) {
331 warnx("client has wrong version");
335 if (rx_Read32(call, &command) != 4) {
336 warnx("rx_Read failed to read command");
339 command = ntohl(command);
341 if (rx_Read32(call, &data) != 4) {
342 warnx("rx_Read failed to read size");
345 rxread_size = ntohl(data);
346 if (rxread_size > sizeof(somebuf)) {
347 warnx("rxread_size too large %d", rxread_size);
351 if (rx_Read32(call, &data) != 4) {
352 warnx("rx_Read failed to write size");
355 rxwrite_size = ntohl(data);
356 if (rxwrite_size > sizeof(somebuf)) {
357 warnx("rxwrite_size too large %d", rxwrite_size);
363 DBFPRINT(("got a send request\n"));
365 if (rx_Read32(call, &bytes) != 4) {
366 warnx("rx_Read failed to read bytes");
369 bytes = ntohl(bytes);
371 DBFPRINT(("reading(%d) ", bytes));
372 readbytes(call, bytes);
374 data = htonl(RXPERF_MAGIC_COOKIE);
375 if (rx_Write32(call, &data) != 4) {
376 warnx("rx_Write failed when sending back result");
379 DBFPRINT(("done\n"));
383 DBFPRINT(("got a rpc request, reading commands\n"));
385 if (rx_Read32(call, &recvb) != 4) {
386 warnx("rx_Read failed to read recvbytes");
389 recvb = ntohl(recvb);
390 if (rx_Read32(call, &sendb) != 4) {
391 warnx("rx_Read failed to read sendbytes");
394 sendb = ntohl(sendb);
396 DBFPRINT(("read(%d) ", recvb));
397 if (readbytes(call, recvb)) {
398 warnx("readbytes failed");
401 DBFPRINT(("send(%d) ", sendb));
402 if (sendbytes(call, sendb)) {
403 warnx("sendbytes failed");
407 DBFPRINT(("done\n"));
409 data = htonl(RXPERF_MAGIC_COOKIE);
410 if (rx_Write32(call, &data) != 4) {
411 warnx("rx_Write failed when sending back magic cookie");
417 if (rx_Read32(call, &data) != 4)
418 errx(1, "failed to read num from client");
421 readwrite = malloc(num * sizeof(afs_uint32));
422 if (readwrite == NULL)
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");
429 for (i = 0; i < num; i++) {
430 if (readwrite[i] == 0) {
431 DBFPRINT(("readp %d", readwrite[i]));
435 bytes = ntohl(readwrite[i]) * sizeof(afs_uint32);
438 DBFPRINT(("read\n"));
439 readbytes(call, bytes);
441 sendbytes(call, bytes);
442 DBFPRINT(("send\n"));
448 DBFPRINT(("got a recv request\n"));
450 if (rx_Read32(call, &bytes) != 4) {
451 warnx("rx_Read failed to read bytes");
454 bytes = ntohl(bytes);
456 DBFPRINT(("sending(%d) ", bytes));
457 sendbytes(call, bytes);
459 data = htonl(RXPERF_MAGIC_COOKIE);
460 if (rx_Write32(call, &data) != 4) {
461 warnx("rx_Write failed when sending back result");
464 DBFPRINT(("done\n"));
468 warnx("client sent a unsupported command");
471 DBFPRINT(("done with command\n"));
481 do_server(short port, int nojumbo, int maxmtu, int udpbufsz)
483 struct rx_service *service;
484 struct rx_securityClass *secureobj;
489 if (afs_winsockInit() < 0) {
490 printf("Can't initialize winsock.\n");
493 rx_EnableHotThread();
496 ret = rx_Init(htons(port));
498 errx(1, "rx_Init failed");
504 rx_SetMaxMTU(maxmtu);
506 rx_SetUdpBufSize(udpbufsz);
508 get_sec(1, &secureobj, &secureindex);
511 rx_NewService(0, RX_SERVER_ID, "rxperf", &secureobj, secureindex,
512 rxperf_ExecuteRequest);
514 errx(1, "Cant create server");
516 rx_SetMinProcs(service, 2);
517 rx_SetMaxProcs(service, 100);
518 rx_SetCheckReach(service, 1);
529 readfile(const char *filename, afs_uint32 ** readwrite, afs_uint32 * size)
536 char buf[RXPERF_BUFSIZE];
538 *readwrite = malloc(sizeof(afs_uint32) * len);
540 if (*readwrite == NULL)
543 f = fopen(filename, "r");
547 while (fgets(buf, sizeof(buf), f) != NULL) {
550 *readwrite = realloc(*readwrite, len * sizeof(afs_uint32));
551 if (*readwrite == NULL)
556 data = htonl(strtol(buf, &ptr, 0));
557 if (ptr && ptr == buf)
558 errx(1, "can't resolve number of bytes to transfer");
563 (*readwrite)[num] = data;
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)
584 struct rx_connection *conn;
585 struct rx_call *call;
587 struct rx_securityClass *secureobj;
597 afs_uint32 *readwrite;
600 if (afs_winsockInit() < 0) {
601 printf("Can't initialize winsock.\n");
604 rx_EnableHotThread();
607 addr = str2addr(server);
611 errx(1, "rx_Init failed");
617 rx_SetMaxMTU(maxmtu);
619 rx_SetUdpBufSize(udpbufsz);
621 get_sec(0, &secureobj, &secureindex);
623 conn = rx_NewConnection(addr, htons(port), RX_SERVER_ID, secureobj, secureindex);
625 errx(1, "failed to contact server");
627 sprintf(stamp, "send\t%d times\t%d writes\t%d reads", times, sendtimes,
631 for (i = 0; i < times; i++) {
633 DBFPRINT(("starting command "));
635 call = rx_NewCall(conn);
637 errx(1, "rx_NewCall failed");
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));
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));
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));
657 DBFPRINT(("command "));
660 if (rx_Write32(call, &data) != 4)
661 errx(1, "rx_Write failed to send size (err %d)", rx_Error(call));
663 DBFPRINT(("sending(%d) ", bytes));
664 if (readbytes(call, bytes))
665 errx(1, "sendbytes (err %d)", rx_Error(call));
667 if (rx_Read32(call, &data) != 4)
668 errx(1, "failed to read result from server (err %d)", rx_Error(call));
670 if (data != htonl(RXPERF_MAGIC_COOKIE))
671 warn("server send wrong magic cookie in responce");
673 DBFPRINT(("done\n"));
677 DBFPRINT(("command "));
680 if (rx_Write32(call, &data) != 4)
681 errx(1, "rx_Write failed to send size (err %d)", rx_Error(call));
683 DBFPRINT(("sending(%d) ", bytes));
684 if (sendbytes(call, bytes))
685 errx(1, "sendbytes (err %d)", rx_Error(call));
687 if (rx_Read32(call, &data) != 4)
688 errx(1, "failed to read result from server (err %d)", rx_Error(call));
690 if (data != htonl(RXPERF_MAGIC_COOKIE))
691 warn("server send wrong magic cookie in responce");
693 DBFPRINT(("done\n"));
697 DBFPRINT(("commands "));
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));
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));
707 DBFPRINT(("send(%d) ", sendtimes));
708 if (sendbytes(call, sendtimes))
709 errx(1, "sendbytes (err %d)", rx_Error(call));
711 DBFPRINT(("recv(%d) ", recvtimes));
712 if (readbytes(call, recvtimes))
713 errx(1, "sendbytes (err %d)", rx_Error(call));
715 if (rx_Read32(call, &bytes) != 4)
716 errx(1, "failed to read result from server (err %d)", rx_Error(call));
718 if (bytes != htonl(RXPERF_MAGIC_COOKIE))
719 warn("server send wrong magic cookie in responce");
721 DBFPRINT(("done\n"));
725 readfile(filename, &readwrite, &num);
728 if (rx_Write32(call, &data) != 4)
729 errx(1, "rx_Write failed to send size (err %d)", rx_Error(call));
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));
735 for (i = 0; i < num; i++) {
736 if (readwrite[i] == 0)
739 size = ntohl(readwrite[i]) * sizeof(afs_uint32);
742 if (readbytes(call, size))
743 errx(1, "sendbytes (err %d)", rx_Error(call));
744 DBFPRINT(("read\n"));
746 if (sendbytes(call, size))
747 errx(1, "sendbytes (err %d)", rx_Error(call));
748 DBFPRINT(("send\n"));
759 end_and_print_timer(stamp);
760 DBFPRINT(("done for good\n"));
763 rx_PrintStats(stdout);
764 rx_PrintPeerStats(stdout, conn->peer);
774 fprintf(stderr, "usage: %s client -c send -b <bytes>\n", __progname);
775 fprintf(stderr, "usage: %s client -c recv -b <bytes>\n", __progname);
777 "usage: %s client -c rpc -S <sendbytes> -R <recvbytes>\n",
779 fprintf(stderr, "usage: %s client -c file -f filename\n", __progname);
781 "%s: usage: common option to the client "
782 "-w <write-bytes> -r <read-bytes> -T times -p port -s server -D\n",
784 fprintf(stderr, "usage: %s server -p port\n", __progname);
790 * do argument processing and call networking functions
794 rxperf_server(int argc, char **argv)
796 short port = DEFAULT_PORT;
799 int udpbufsz = 64 * 1024;
803 while ((ch = getopt(argc, argv, "r:d:p:w:jm:u:4")) != -1) {
807 rx_debugFile = fopen(optarg, "w");
808 if (rx_debugFile == NULL)
809 err(1, "fopen %s", optarg);
811 errx(1, "compiled without RXDEBUG");
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,
823 port = strtol(optarg, &ptr, 0);
824 if (ptr != 0 && ptr[0] != '\0')
825 errx(1, "can't resolve portname");
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,
839 maxmtu = strtol(optarg, &ptr, 0);
840 if (ptr && *ptr != '\0')
841 errx(1, "can't resolve rx maxmtu to use");
844 udpbufsz = strtol(optarg, &ptr, 0) * 1024;
845 if (ptr && *ptr != '\0')
846 errx(1, "can't resolve upd buffer size (Kbytes)");
859 do_server(port, nojumbo, maxmtu, udpbufsz);
865 * do argument processing and call networking functions
869 rxperf_client(int argc, char **argv)
871 char *host = DEFAULT_HOST;
872 int bytes = DEFAULT_BYTES;
873 short port = DEFAULT_PORT;
874 char *filename = NULL;
882 int udpbufsz = 64 * 1024;
886 cmd = RX_PERF_UNKNOWN;
888 while ((ch = getopt(argc, argv, "T:S:R:b:c:d:p:r:s:w:f:Djm:u:4")) != -1) {
891 bytes = strtol(optarg, &ptr, 0);
892 if (ptr && *ptr != '\0')
893 errx(1, "can't resolve number of bytes to transfer");
896 if (strcasecmp(optarg, "send") == 0)
898 else if (strcasecmp(optarg, "recv") == 0)
900 else if (strcasecmp(optarg, "rpc") == 0)
902 else if (strcasecmp(optarg, "file") == 0)
905 errx(1, "unknown command %s", optarg);
909 rx_debugFile = fopen(optarg, "w");
910 if (rx_debugFile == NULL)
911 err(1, "fopen %s", optarg);
913 errx(1, "compiled without RXDEBUG");
917 port = strtol(optarg, &ptr, 0);
918 if (ptr != 0 && ptr[0] != '\0')
919 errx(1, "can't resolve portname");
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,
930 host = strdup(optarg);
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,
943 times = strtol(optarg, &ptr, 0);
944 if (ptr && *ptr != '\0')
945 errx(1, "can't resolve number of times to execute rpc");
948 sendtimes = strtol(optarg, &ptr, 0);
949 if (ptr && *ptr != '\0')
950 errx(1, "can't resolve number of bytes to send");
953 recvtimes = strtol(optarg, &ptr, 0);
954 if (ptr && *ptr != '\0')
955 errx(1, "can't resolve number of bytes to receive");
967 maxmtu = strtol(optarg, &ptr, 0);
968 if (ptr && *ptr != '\0')
969 errx(1, "can't resolve rx maxmtu to use");
972 udpbufsz = strtol(optarg, &ptr, 0) * 1024;
973 if (ptr && *ptr != '\0')
974 errx(1, "can't resolve upd buffer size (Kbytes)");
987 if (cmd == RX_PERF_UNKNOWN)
988 errx(1, "no command given to the client");
990 do_client(host, port, filename, cmd, times, bytes, sendtimes,
991 recvtimes, dumpstats, nojumbo, maxmtu, udpbufsz);
997 * setup world and call cmd
1001 main(int argc, char **argv)
1003 #ifndef AFS_PTHREAD_ENV
1007 __progname = strrchr(argv[0], '/');
1008 if (__progname == 0)
1009 __progname = argv[0];
1011 #ifndef AFS_NT40_ENV
1012 signal(SIGUSR1, sigusr1);
1013 signal(SIGINT, sigint);
1016 #ifndef AFS_PTHREAD_ENV
1017 LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY, &pid);
1020 memset(somebuf, 0, sizeof(somebuf));
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);