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
47 #include <sys/types.h>
49 #include <sys/socket.h>
52 #include <netinet/in.h>
53 #include <arpa/inet.h>
71 #include <err.h> /* not stricly right, but if we have a errx() there
72 * is hopefully a err.h */
76 #include "rx_globals.h"
79 #define u_int32_t u_int32
81 #define u_int32_t afs_uint32
84 static const char *__progname;
88 warnx(const char *fmt, ...)
93 fprintf(stderr, "%s: ", __progname);
94 vfprintf(stderr, fmt, args);
95 fprintf(stderr, "\n");
98 #endif /* !HAVE_WARNX */
102 errx(int eval, const char *fmt, ...)
107 fprintf(stderr, "%s: ", __progname);
108 vfprintf(stderr, fmt, args);
109 fprintf(stderr, "\n");
114 #endif /* !HAVE_ERRX */
118 warn(const char *fmt, ...)
124 fprintf(stderr, "%s: ", __progname);
125 vfprintf(stderr, fmt, args);
127 errstr = strerror(errno);
129 fprintf(stderr, ": %s\n", errstr ? errstr : "unknown error");
132 #endif /* !HAVE_WARN */
136 err(int eval, const char *fmt, ...)
142 fprintf(stderr, "%s: ", __progname);
143 vfprintf(stderr, fmt, args);
145 errstr = strerror(errno);
147 fprintf(stderr, ": %s\n", errstr ? errstr : "unknown error");
152 #endif /* !HAVE_ERR */
154 #define DEFAULT_PORT 7009 /* To match tcpdump */
155 #define DEFAULT_HOST "127.0.0.1"
156 #define DEFAULT_BYTES 1000000
157 #define RXPERF_BUFSIZE 10000
159 enum { RX_PERF_VERSION = 3 };
160 enum { RX_SERVER_ID = 147 };
161 enum { RX_PERF_UNKNOWN = -1, RX_PERF_SEND = 0, RX_PERF_RECV = 1,
162 RX_PERF_RPC = 3, RX_PERF_FILE = 4
165 enum { RXPERF_MAGIC_COOKIE = 0x4711 };
172 #define DBFPRINT(x) do { printf x ; } while(0)
180 exit(2); /* XXX profiler */
187 exit(2); /* XXX profiler */
194 static struct timeval timer_start;
195 static struct timeval timer_stop;
196 static int timer_check = 0;
202 gettimeofday(&timer_start, NULL);
210 end_and_print_timer(char *str)
212 long long start_l, stop_l;
215 assert(timer_check == 0);
216 gettimeofday(&timer_stop, NULL);
217 start_l = timer_start.tv_sec * 1000000 + timer_start.tv_usec;
218 stop_l = timer_stop.tv_sec * 1000000 + timer_stop.tv_usec;
219 printf("%s:\t%8llu msec\n", str, (stop_l - start_l) / 1000);
227 str2addr(const char *s)
229 struct in_addr server;
233 #define INADDR_NONE 0xffffffff
235 if (inet_addr(s) != INADDR_NONE)
237 h = gethostbyname(s);
239 memcpy(&server, h->h_addr_list[0], sizeof(server));
240 return server.s_addr;
251 get_sec(int serverp, struct rx_securityClass **sec, int *secureindex)
254 *sec = rxnull_NewServerSecurityObject();
257 *sec = rxnull_NewClientSecurityObject();
263 * process the "RPC" and return the results
266 char somebuf[RXPERF_BUFSIZE];
268 int32_t rxwrite_size = sizeof(somebuf);
269 int32_t rxread_size = sizeof(somebuf);
272 readbytes(struct rx_call *call, int32_t bytes)
280 if (rx_Read(call, somebuf, size) != size)
288 sendbytes(struct rx_call *call, int32_t bytes)
296 if (rx_Write(call, somebuf, size) != size)
305 rxperf_ExecuteRequest(struct rx_call *call)
314 u_int32_t *readwrite;
318 DBFPRINT(("got a request\n"));
320 if (rx_Read32(call, &version) != 4) {
321 warn("rx_Read failed to read version");
325 if (htonl(RX_PERF_VERSION) != version) {
326 warnx("client has wrong version");
330 if (rx_Read32(call, &command) != 4) {
331 warnx("rx_Read failed to read command");
334 command = ntohl(command);
336 if (rx_Read32(call, &data) != 4) {
337 warnx("rx_Read failed to read size");
340 rxread_size = ntohl(data);
341 if (rxread_size > sizeof(somebuf)) {
342 warnx("rxread_size too large %d", rxread_size);
346 if (rx_Read32(call, &data) != 4) {
347 warnx("rx_Read failed to write size");
350 rxwrite_size = ntohl(data);
351 if (rxwrite_size > sizeof(somebuf)) {
352 warnx("rxwrite_size too large %d", rxwrite_size);
358 DBFPRINT(("got a send request\n"));
360 if (rx_Read32(call, &bytes) != 4) {
361 warnx("rx_Read failed to read bytes");
364 bytes = ntohl(bytes);
366 DBFPRINT(("reading(%d) ", bytes));
367 readbytes(call, bytes);
369 data = htonl(RXPERF_MAGIC_COOKIE);
370 if (rx_Write32(call, &data) != 4) {
371 warnx("rx_Write failed when sending back result");
374 DBFPRINT(("done\n"));
378 DBFPRINT(("got a rpc request, reading commands\n"));
380 if (rx_Read32(call, &recvb) != 4) {
381 warnx("rx_Read failed to read recvbytes");
384 recvb = ntohl(recvb);
385 if (rx_Read32(call, &sendb) != 4) {
386 warnx("rx_Read failed to read sendbytes");
389 sendb = ntohl(sendb);
391 DBFPRINT(("read(%d) ", recvb));
392 if (readbytes(call, recvb)) {
393 warnx("readbytes failed");
396 DBFPRINT(("send(%d) ", sendb));
397 if (sendbytes(call, sendb)) {
398 warnx("sendbytes failed");
402 DBFPRINT(("done\n"));
404 data = htonl(RXPERF_MAGIC_COOKIE);
405 if (rx_Write32(call, &data) != 4) {
406 warnx("rx_Write failed when sending back magic cookie");
412 if (rx_Read32(call, &data) != 4)
413 errx(1, "failed to read num from client");
416 readwrite = malloc(num * sizeof(u_int32_t));
417 if (readwrite == NULL)
420 if (rx_Read(call, readwrite, num * sizeof(u_int32_t)) !=
421 num * sizeof(u_int32_t))
422 errx(1, "failed to read recvlist from client");
424 for (i = 0; i < num; i++) {
425 if (readwrite[i] == 0) {
426 DBFPRINT(("readp %d", readwrite[i]));
430 bytes = ntohl(readwrite[i]) * sizeof(u_int32_t);
433 DBFPRINT(("read\n"));
434 readbytes(call, bytes);
436 sendbytes(call, bytes);
437 DBFPRINT(("send\n"));
443 DBFPRINT(("got a recv request\n"));
445 if (rx_Read32(call, &bytes) != 4) {
446 warnx("rx_Read failed to read bytes");
449 bytes = ntohl(bytes);
451 DBFPRINT(("sending(%d) ", bytes));
452 sendbytes(call, bytes);
454 data = htonl(RXPERF_MAGIC_COOKIE);
455 if (rx_Write32(call, &data) != 4) {
456 warnx("rx_Write failed when sending back result");
459 DBFPRINT(("done\n"));
463 warnx("client sent a unsupported command");
466 DBFPRINT(("done with command\n"));
476 do_server(int port, int nojumbo, int maxmtu)
478 struct rx_service *service;
479 struct rx_securityClass *secureobj;
485 errx(1, "rx_Init failed");
490 rx_SetMaxMTU(maxmtu);
491 get_sec(1, &secureobj, &secureindex);
494 rx_NewService(0, RX_SERVER_ID, "rxperf", &secureobj, secureindex,
495 rxperf_ExecuteRequest);
497 errx(1, "Cant create server");
508 readfile(const char *filename, u_int32_t ** readwrite, u_int32_t * size)
515 char buf[RXPERF_BUFSIZE];
517 *readwrite = malloc(sizeof(u_int32_t) * len);
519 if (*readwrite == NULL)
522 f = fopen(filename, "r");
526 while (fgets(buf, sizeof(buf), f) != NULL) {
529 *readwrite = realloc(*readwrite, len * sizeof(u_int32_t));
530 if (*readwrite == NULL)
535 data = htonl(strtol(buf, &ptr, 0));
536 if (ptr && ptr == buf)
537 errx(1, "can't resolve number of bytes to transfer");
542 (*readwrite)[num] = data;
559 do_client(const char *server, int port, char *filename, int32_t command,
560 int32_t times, int32_t bytes, int32_t sendtimes, int32_t recvtimes,
561 int dumpstats, int nojumbo, int maxmtu)
563 struct rx_connection *conn;
564 struct rx_call *call;
565 u_int32_t addr = str2addr(server);
566 struct rx_securityClass *secureobj;
576 u_int32_t *readwrite;
580 errx(1, "rx_Init failed");
585 rx_SetMaxMTU(maxmtu);
586 get_sec(0, &secureobj, &secureindex);
588 conn = rx_NewConnection(addr, port, RX_SERVER_ID, secureobj, secureindex);
590 errx(1, "failed to contact server");
592 sprintf(stamp, "send\t%d times\t%d writes\t%d reads", times, sendtimes,
596 for (i = 0; i < times; i++) {
598 DBFPRINT(("starting command "));
600 call = rx_NewCall(conn);
602 errx(1, "rx_NewCall failed");
604 data = htonl(RX_PERF_VERSION);
605 if (rx_Write32(call, &data) != 4)
606 errx(1, "rx_Write failed to send version (err %d)", rx_Error(call));
608 data = htonl(command);
609 if (rx_Write32(call, &data) != 4)
610 errx(1, "rx_Write failed to send command (err %d)", rx_Error(call));
612 data = htonl(rxread_size);
613 if (rx_Write32(call, &data) != 4)
614 errx(1, "rx_Write failed to send read size (err %d)", rx_Error(call));
615 data = htonl(rxwrite_size);
616 if (rx_Write32(call, &data) != 4)
617 errx(1, "rx_Write failed to send write read (err %d)", rx_Error(call));
622 DBFPRINT(("command "));
625 if (rx_Write32(call, &data) != 4)
626 errx(1, "rx_Write failed to send size (err %d)", rx_Error(call));
628 DBFPRINT(("sending(%d) ", bytes));
629 if (readbytes(call, bytes))
630 errx(1, "sendbytes (err %d)", rx_Error(call));
632 if (rx_Read32(call, &data) != 4)
633 errx(1, "failed to read result from server (err %d)", rx_Error(call));
635 if (data != htonl(RXPERF_MAGIC_COOKIE))
636 warn("server send wrong magic cookie in responce");
638 DBFPRINT(("done\n"));
642 DBFPRINT(("command "));
645 if (rx_Write32(call, &data) != 4)
646 errx(1, "rx_Write failed to send size (err %d)", rx_Error(call));
648 DBFPRINT(("sending(%d) ", bytes));
649 if (sendbytes(call, bytes))
650 errx(1, "sendbytes (err %d)", rx_Error(call));
652 if (rx_Read32(call, &data) != 4)
653 errx(1, "failed to read result from server (err %d)", rx_Error(call));
655 if (data != htonl(RXPERF_MAGIC_COOKIE))
656 warn("server send wrong magic cookie in responce");
658 DBFPRINT(("done\n"));
662 DBFPRINT(("commands "));
664 data = htonl(sendtimes);
665 if (rx_Write32(call, &data) != 4)
666 errx(1, "rx_Write failed to send command (err %d)", rx_Error(call));
668 data = htonl(recvtimes);
669 if (rx_Write32(call, &data) != 4)
670 errx(1, "rx_Write failed to send command (err %d)", rx_Error(call));
672 DBFPRINT(("send(%d) ", sendtimes));
673 if (sendbytes(call, sendtimes))
674 errx(1, "sendbytes (err %d)", rx_Error(call));
676 DBFPRINT(("recv(%d) ", recvtimes));
677 if (readbytes(call, recvtimes))
678 errx(1, "sendbytes (err %d)", rx_Error(call));
680 if (rx_Read32(call, &bytes) != 4)
681 errx(1, "failed to read result from server (err %d)", rx_Error(call));
683 if (bytes != htonl(RXPERF_MAGIC_COOKIE))
684 warn("server send wrong magic cookie in responce");
686 DBFPRINT(("done\n"));
690 readfile(filename, &readwrite, &num);
693 if (rx_Write32(call, &data) != 4)
694 errx(1, "rx_Write failed to send size (err %d)", rx_Error(call));
696 if (rx_Write(call, readwrite, num * sizeof(u_int32_t))
697 != num * sizeof(u_int32_t))
698 errx(1, "rx_Write failed to send list (err %d)", rx_Error(call));
700 for (i = 0; i < num; i++) {
701 if (readwrite[i] == 0)
704 size = ntohl(readwrite[i]) * sizeof(u_int32_t);
707 if (readbytes(call, size))
708 errx(1, "sendbytes (err %d)", rx_Error(call));
709 DBFPRINT(("read\n"));
711 if (sendbytes(call, size))
712 errx(1, "sendbytes (err %d)", rx_Error(call));
713 DBFPRINT(("send\n"));
724 end_and_print_timer(stamp);
725 DBFPRINT(("done for good\n"));
728 rx_PrintStats(stdout);
729 rx_PrintPeerStats(stdout, conn->peer);
739 fprintf(stderr, "usage: %s client -c send -b <bytes>\n", __progname);
740 fprintf(stderr, "usage: %s client -c recv -b <bytes>\n", __progname);
742 "usage: %s client -c rpc -S <sendbytes> -R <recvbytes>\n",
744 fprintf(stderr, "usage: %s client -c file -f filename\n", __progname);
746 "%s: usage: common option to the client "
747 "-w <write-bytes> -r <read-bytes> -T times -p port -s server -D\n",
749 fprintf(stderr, "usage: %s server -p port\n", __progname);
755 * do argument processing and call networking functions
759 rxperf_server(int argc, char **argv)
761 int port = DEFAULT_PORT;
767 while ((ch = getopt(argc, argv, "r:d:p:w:jm:4")) != -1) {
771 rx_debugFile = fopen(optarg, "w");
772 if (rx_debugFile == NULL)
773 err(1, "fopen %s", optarg);
775 errx(1, "compiled without RXDEBUG");
779 rxread_size = strtol(optarg, &ptr, 0);
780 if (ptr != 0 && ptr[0] != '\0')
781 errx(1, "can't resolve readsize");
782 if (rxread_size > sizeof(somebuf))
783 errx(1, "%d > sizeof(somebuf) (%d)", rxread_size,
787 port = strtol(optarg, &ptr, 0);
788 if (ptr != 0 && ptr[0] != '\0')
789 errx(1, "can't resolve portname");
792 rxwrite_size = strtol(optarg, &ptr, 0);
793 if (ptr != 0 && ptr[0] != '\0')
794 errx(1, "can't resolve writesize");
795 if (rxwrite_size > sizeof(somebuf))
796 errx(1, "%d > sizeof(somebuf) (%d)", rxwrite_size,
803 maxmtu = strtol(optarg, &ptr, 0);
804 if (ptr && *ptr != '\0')
805 errx(1, "can't resolve rx maxmtu to use");
818 do_server(htons(port), nojumbo, maxmtu);
824 * do argument processing and call networking functions
828 rxperf_client(int argc, char **argv)
830 char *host = DEFAULT_HOST;
831 int bytes = DEFAULT_BYTES;
832 int port = DEFAULT_PORT;
833 char *filename = NULL;
844 cmd = RX_PERF_UNKNOWN;
846 while ((ch = getopt(argc, argv, "T:S:R:b:c:d:p:r:s:w:f:Djm:4")) != -1) {
849 bytes = strtol(optarg, &ptr, 0);
850 if (ptr && *ptr != '\0')
851 errx(1, "can't resolve number of bytes to transfer");
854 if (strcasecmp(optarg, "send") == 0)
856 else if (strcasecmp(optarg, "recv") == 0)
858 else if (strcasecmp(optarg, "rpc") == 0)
860 else if (strcasecmp(optarg, "file") == 0)
863 errx(1, "unknown command %s", optarg);
867 rx_debugFile = fopen(optarg, "w");
868 if (rx_debugFile == NULL)
869 err(1, "fopen %s", optarg);
871 errx(1, "compiled without RXDEBUG");
875 port = strtol(optarg, &ptr, 0);
876 if (ptr != 0 && ptr[0] != '\0')
877 errx(1, "can't resolve portname");
880 rxread_size = strtol(optarg, &ptr, 0);
881 if (ptr != 0 && ptr[0] != '\0')
882 errx(1, "can't resolve readsize");
883 if (rxread_size > sizeof(somebuf))
884 errx(1, "%d > sizeof(somebuf) (%d)", rxread_size,
888 host = strdup(optarg);
893 rxwrite_size = strtol(optarg, &ptr, 0);
894 if (ptr != 0 && ptr[0] != '\0')
895 errx(1, "can't resolve writesize");
896 if (rxwrite_size > sizeof(somebuf))
897 errx(1, "%d > sizeof(somebuf) (%d)", rxwrite_size,
901 times = strtol(optarg, &ptr, 0);
902 if (ptr && *ptr != '\0')
903 errx(1, "can't resolve number of bytes to transfer");
906 sendtimes = strtol(optarg, &ptr, 0);
907 if (ptr && *ptr != '\0')
908 errx(1, "can't resolve number of bytes to transfer");
911 recvtimes = strtol(optarg, &ptr, 0);
912 if (ptr && *ptr != '\0')
913 errx(1, "can't resolve number of bytes to transfer");
922 errx(1, "compiled without RXDEBUG");
929 maxmtu = strtol(optarg, &ptr, 0);
930 if (ptr && *ptr != '\0')
931 errx(1, "can't resolve rx maxmtu to use");
944 if (cmd == RX_PERF_UNKNOWN)
945 errx(1, "no command given to the client");
947 do_client(host, htons(port), filename, cmd, times, bytes, sendtimes,
948 recvtimes, dumpstats, nojumbo, maxmtu);
954 * setup world and call cmd
958 main(int argc, char **argv)
962 __progname = strrchr(argv[0], '/');
964 __progname = argv[0];
966 signal(SIGUSR1, sigusr1);
967 signal(SIGINT, sigint);
969 LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY, &pid);
971 memset(somebuf, 0, sizeof(somebuf));
973 if (argc >= 2 && strcmp(argv[1], "server") == 0)
974 rxperf_server(argc - 1, argv + 1);
975 else if (argc >= 2 && strcmp(argv[1], "client") == 0)
976 rxperf_client(argc - 1, argv + 1);