2 * Copyright (c) 2000 - 2002 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.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * We are using getopt since we want it to be possible to link to
43 #define HAVE_GETRUSAGE 1
50 #include <sys/types.h>
52 #include <sys/socket.h>
56 #include <sys/resource.h>
58 #include <netinet/in.h>
59 #include <arpa/inet.h>
69 #include <err.h> /* not stricly right, but if we have a errx() there
70 * is hopefully a err.h */
73 #include <roken.h> /* sometimes needed for getprogname/setprogname */
80 #define uint32_t u_int32
82 #define uint32_t afs_uint32
87 warnx(const char *fmt
, ...)
92 fprintf(stderr
, "%s: ", "rxperf");
93 vfprintf (stderr
, fmt
, args
);
94 fprintf(stderr
, "\n");
97 #endif /* !HAVE_WARNX */
101 errx(int eval
, const char *fmt
, ...)
106 fprintf(stderr
, "%s: ", "rxperf");
107 vfprintf (stderr
, fmt
, args
);
108 fprintf(stderr
, "\n");
113 #endif /* !HAVE_ERRX */
117 warn(const char *fmt
, ...)
123 fprintf(stderr
, "%s: ", "rxperf");
124 vfprintf (stderr
, fmt
, args
);
126 errstr
= strerror(errno
);
128 fprintf(stderr
, ": %s\n", errstr
? errstr
: "unknown error");
131 #endif /* !HAVE_WARN */
135 err(int eval
, const char *fmt
, ...)
141 fprintf(stderr
, "%s: ", "rxperf");
142 vfprintf (stderr
, fmt
, args
);
144 errstr
= strerror(errno
);
146 fprintf(stderr
, ": %s\n", errstr
? errstr
: "unknown error");
151 #endif /* !HAVE_ERR */
153 #define DEFAULT_PORT 7009 /* To match tcpdump */
154 #define DEFAULT_HOST "127.0.0.1"
155 #define DEFAULT_BYTES 1000000
156 #define RXPERF_BUFSIZE 10000
158 enum { RX_PERF_VERSION
= 3 };
159 enum { RX_SERVER_ID
= 147 };
160 enum { RX_PERF_UNKNOWN
= -1, RX_PERF_SEND
= 0, RX_PERF_RECV
= 1,
161 RX_PERF_RPC
=3, RX_PERF_FILE
=4 };
163 enum { RXPERF_MAGIC_COOKIE
= 0x4711 };
170 #define DBFPRINT(x) do { printf x ; } while(0)
178 exit (2); /* XXX profiler */
185 exit (2); /* XXX profiler */
192 static struct timeval timer_start
;
193 static struct timeval timer_stop
;
194 static int timer_check
= 0;
200 gettimeofday (&timer_start
, NULL
);
208 end_and_print_timer (char *str
)
210 long long start_l
, stop_l
;
213 assert (timer_check
== 0);
214 gettimeofday(&timer_stop
, NULL
);
215 start_l
= timer_start
.tv_sec
* 1000000 + timer_start
.tv_usec
;
216 stop_l
= timer_stop
.tv_sec
* 1000000 + timer_stop
.tv_usec
;
217 printf("%s:\t%8llu msec\n", str
, (stop_l
-start_l
)/1000);
225 str2addr (const char *s
)
227 struct in_addr server
;
231 #define INADDR_NONE 0xffffffff
233 if (inet_addr(s
) != INADDR_NONE
)
235 h
= gethostbyname (s
);
237 memcpy (&server
, h
->h_addr_list
[0], sizeof(server
));
238 return server
.s_addr
;
249 get_sec(int serverp
, struct rx_securityClass
** sec
, int *secureindex
)
252 *sec
= rxnull_NewServerSecurityObject();
255 *sec
= rxnull_NewClientSecurityObject();
261 * process the "RPC" and return the results
264 char somebuf
[RXPERF_BUFSIZE
];
266 int32_t rxwrite_size
= sizeof(somebuf
);
267 int32_t rxread_size
= sizeof(somebuf
);
270 readbytes(struct rx_call
*call
, int32_t bytes
)
278 if (rx_Read (call
, somebuf
, size
) != size
)
286 sendbytes(struct rx_call
*call
, int32_t bytes
)
294 if (rx_Write (call
, somebuf
, size
) != size
)
303 rxperf_ExecuteRequest(struct rx_call
*call
)
316 DBFPRINT(("got a request\n"));
318 if (rx_Read (call
, &version
, 4) != 4) {
319 warn ("rx_Read failed to read version");
323 if (htonl(RX_PERF_VERSION
) != version
) {
324 warnx ("client has wrong version");
328 if (rx_Read (call
, &command
, 4) != 4) {
329 warnx ("rx_Read failed to read command");
332 command
= ntohl(command
);
334 if (rx_Read (call
, &data
, 4) != 4) {
335 warnx ("rx_Read failed to read size");
338 rxread_size
= ntohl(data
);
339 if (rxread_size
> sizeof(somebuf
)) {
340 warnx("rxread_size too large %d", rxread_size
);
344 if (rx_Read (call
, &data
, 4) != 4) {
345 warnx ("rx_Read failed to write size");
348 rxwrite_size
= ntohl(data
);
349 if (rxwrite_size
> sizeof(somebuf
)) {
350 warnx("rxwrite_size too large %d", rxwrite_size
);
356 DBFPRINT(("got a send request\n"));
358 if (rx_Read (call
, &bytes
, 4) != 4) {
359 warnx ("rx_Read failed to read bytes");
362 bytes
= ntohl(bytes
);
364 DBFPRINT(("reading(%d) ", bytes
));
365 readbytes(call
, bytes
);
367 data
= htonl(RXPERF_MAGIC_COOKIE
);
368 if (rx_Write (call
, &data
, 4) != 4) {
369 warnx ("rx_Write failed when sending back result");
372 DBFPRINT(("done\n"));
376 DBFPRINT(("got a rpc request, reading commands\n"));
378 if (rx_Read (call
, &recvb
, 4) != 4) {
379 warnx ("rx_Read failed to read recvbytes");
382 recvb
= ntohl(recvb
);
383 if (rx_Read (call
, &sendb
, 4) != 4) {
384 warnx ("rx_Read failed to read recvbytes");
387 sendb
= ntohl(sendb
);
389 DBFPRINT(("read(%d) ", recvb
));
390 if (readbytes(call
, recvb
)) {
391 warnx("readbytes failed");
394 DBFPRINT(("send(%d) ", sendb
));
395 if (sendbytes(call
, sendb
)) {
396 warnx("sendbytes failed");
400 DBFPRINT(("done\n"));
402 data
= htonl(RXPERF_MAGIC_COOKIE
);
403 if (rx_Write (call
, &data
, 4) != 4) {
404 warnx ( "rx_Write failed when sending back magic cookie");
410 if (rx_Read (call
, &data
, 4) != 4)
411 errx (1, "failed to read num from client");
414 readwrite
= malloc(num
*sizeof(uint32_t));
415 if(readwrite
== NULL
)
418 if (rx_Read (call
, readwrite
, num
*sizeof(uint32_t)) !=
419 num
*sizeof(uint32_t))
420 errx (1, "failed to read recvlist from client");
422 for(i
=0; i
< num
; i
++) {
423 if(readwrite
[i
] == 0) {
424 DBFPRINT(("readp %d", readwrite
[i
] ));
428 bytes
= ntohl(readwrite
[i
])*sizeof(uint32_t);
431 DBFPRINT(("read\n"));
432 readbytes(call
, bytes
);
434 sendbytes(call
, bytes
);
435 DBFPRINT(("send\n"));
441 DBFPRINT(("got a recv request\n"));
443 if (rx_Read (call
, &bytes
, 4) != 4) {
444 warnx ("rx_Read failed to read bytes");
447 bytes
= ntohl(bytes
);
449 DBFPRINT(("sending(%d) ", bytes
));
450 sendbytes(call
, bytes
);
452 data
= htonl(RXPERF_MAGIC_COOKIE
);
453 if (rx_Write (call
, &data
, 4) != 4) {
454 warnx ("rx_Write failed when sending back result");
457 DBFPRINT(("done\n"));
461 warnx ("client sent a unsupported command");
464 DBFPRINT(("done with command\n"));
476 struct rx_service
*service
;
477 struct rx_securityClass
*secureobj
;
481 ret
= rx_Init (port
);
483 errx (1, "rx_Init failed");
485 get_sec(1, &secureobj
, &secureindex
);
487 service
= rx_NewService (0,
492 rxperf_ExecuteRequest
);
494 errx(1, "Cant create server");
505 readfile(const char *filename
, uint32_t **readwrite
, uint32_t *size
)
512 char buf
[RXPERF_BUFSIZE
];
514 *readwrite
= malloc(sizeof(uint32_t)*len
);
516 if(*readwrite
== NULL
)
519 f
=fopen(filename
, "r");
523 while(fgets(buf
, sizeof(buf
), f
) != NULL
) {
525 buf
[strcspn(buf
, "\n")] = '\0';
529 *readwrite
= realloc(*readwrite
, len
*sizeof(uint32_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
,
560 int32_t command
, int32_t times
,
561 int32_t bytes
, int32_t rpc_sendbytes
, int32_t rpc_recvbytes
)
563 struct rx_connection
*conn
;
564 struct rx_call
*call
;
565 uint32_t addr
= str2addr(server
);
566 struct rx_securityClass
*secureobj
;
580 errx (1, "rx_Init failed");
582 get_sec(0, &secureobj
, &secureindex
);
584 conn
= rx_NewConnection(addr
,
590 errx (1, "failed to contact server");
592 if (command
== RX_PERF_RPC
)
593 snprintf (stamp
, sizeof(stamp
),
594 "send\t%d times\t%d writes\t%d reads",
595 times
, rpc_sendbytes
, rpc_recvbytes
);
597 snprintf (stamp
, sizeof(stamp
),
598 "send\t%d times", times
);
602 for(i
=0; i
< times
; i
++) {
604 DBFPRINT(("starting command "));
606 call
= rx_NewCall (conn
);
608 errx (1, "rx_NewCall failed");
610 data
= htonl(RX_PERF_VERSION
);
611 if (rx_Write (call
, &data
, 4) != 4)
612 errx (1, "rx_Write failed to send version");
614 data
= htonl(command
);
615 if (rx_Write (call
, &data
, 4) != 4)
616 errx (1, "rx_Write failed to send command");
618 data
= htonl(rxread_size
);
619 if (rx_Write (call
, &data
, 4) != 4)
620 errx (1, "rx_Write failed to send read size");
621 data
= htonl(rxwrite_size
);
622 if (rx_Write (call
, &data
, 4) != 4)
623 errx (1, "rx_Write failed to send write read");
628 DBFPRINT(("command "));
630 data
= htonl (bytes
);
631 if (rx_Write (call
, &data
, 4) != 4)
632 errx (1, "rx_Write failed to send size");
634 DBFPRINT(("sending(%d) ", bytes
));
635 if (readbytes(call
, bytes
))
636 errx(1, "sendbytes");
638 if (rx_Read (call
, &data
, 4) != 4)
639 errx (1, "failed to read result from server");
641 if (data
!= htonl(RXPERF_MAGIC_COOKIE
))
642 warn("server send wrong magic cookie in responce");
644 DBFPRINT(("done\n"));
648 DBFPRINT(("command "));
650 data
= htonl (bytes
);
651 if (rx_Write (call
, &data
, 4) != 4)
652 errx (1, "rx_Write failed to send size");
654 DBFPRINT(("sending(%d) ", bytes
));
655 if (sendbytes(call
, bytes
))
656 errx(1, "sendbytes");
658 if (rx_Read (call
, &data
, 4) != 4)
659 errx (1, "failed to read result from server");
661 if (data
!= htonl(RXPERF_MAGIC_COOKIE
))
662 warn("server send wrong magic cookie in responce");
664 DBFPRINT(("done\n"));
668 DBFPRINT(("commands "));
670 data
= htonl(rpc_sendbytes
);
671 if (rx_Write(call
, &data
, 4) != 4)
672 errx (1, "rx_Write failed to send command");
674 data
= htonl(rpc_recvbytes
);
675 if (rx_Write (call
, &data
, 4) != 4)
676 errx (1, "rx_Write failed to send command");
678 DBFPRINT(("send(%d) ", rpc_sendbytes
));
679 sendbytes(call
, rpc_sendbytes
);
681 DBFPRINT(("recv(%d) ", rpc_recvbytes
));
682 readbytes(call
, rpc_recvbytes
);
684 if (rx_Read (call
, &bytes
, 4) != 4)
685 errx (1, "failed to read result from server");
687 if (bytes
!= htonl(RXPERF_MAGIC_COOKIE
))
688 warn("server send wrong magic cookie in responce");
690 DBFPRINT(("done\n"));
694 readfile(filename
, &readwrite
, &num
);
697 if (rx_Write(call
, &data
, sizeof(data
)) != 4)
698 errx (1, "rx_Write failed to send size");
700 if (rx_Write(call
, readwrite
, num
*sizeof(uint32_t))
701 != num
*sizeof(uint32_t))
702 errx (1, "rx_Write failed to send list");
704 for(i
=0; i
< num
; i
++) {
705 if(readwrite
[i
] == 0)
708 size
= ntohl(readwrite
[i
])*sizeof(uint32_t);
711 readbytes(call
, size
);
712 DBFPRINT(("read\n"));
714 sendbytes(call
, size
);
715 DBFPRINT(("send\n"));
723 rx_EndCall (call
, 0);
726 end_and_print_timer (stamp
);
727 DBFPRINT(("done for good\n"));
737 fprintf(stderr
, "usage: %s client -c send -b <bytes>\n",
739 fprintf(stderr
, "usage: %s client -c recv -b <bytes>\n",
741 fprintf(stderr
, "usage: %s client -c rpc -S <rpc_sendbytes> -R <rpc_recvbytes>\n",
743 fprintf(stderr
, "usage: %s client -c file -f filename\n",
745 fprintf (stderr
, "%s: usage: common option to the client "
746 "-w <rx_write size> -r <rx_read size> -T times -p port -s server\n",
748 fprintf(stderr
, "usage: %s server -p port\n", getprogname());
754 * do argument processing and call networking functions
758 rxperf_server (int argc
, char **argv
)
760 int port
= DEFAULT_PORT
;
764 while ((ch
= getopt(argc
, argv
, "r:d:p:w:")) != -1) {
768 rx_debugFile
= fopen(optarg
, "w");
769 if (rx_debugFile
== NULL
)
770 err(1, "fopen %s", optarg
);
772 errx(1, "compiled without RXDEBUG");
776 rxread_size
= strtol(optarg
, &ptr
, 0);
777 if (ptr
!= 0 && ptr
[0] != '\0')
778 errx (1, "can't resolve readsize");
779 if (rxread_size
> sizeof(somebuf
))
780 errx(1, "%d > sizeof(somebuf) (%lu)",
781 rxread_size
, (unsigned long)sizeof(somebuf
));
784 port
= strtol(optarg
, &ptr
, 0);
785 if (ptr
!= 0 && ptr
[0] != '\0')
786 errx (1, "can't resolve portname");
789 rxwrite_size
= strtol(optarg
, &ptr
, 0);
790 if (ptr
!= 0 && ptr
[0] != '\0')
791 errx (1, "can't resolve writesize");
792 if (rxwrite_size
> sizeof(somebuf
))
793 errx(1, "%d > sizeof(somebuf) (%lu)",
794 rxwrite_size
, (unsigned long)sizeof(somebuf
));
804 do_server (htons(port
));
810 * do argument processing and call networking functions
814 rxperf_client (int argc
, char **argv
)
816 char *host
= DEFAULT_HOST
;
817 int bytes
= DEFAULT_BYTES
;
818 int port
= DEFAULT_PORT
;
819 char *filename
= NULL
;
821 int rpc_sendbytes
= 3;
822 int rpc_recvbytes
= 30;
828 cmd
= RX_PERF_UNKNOWN
;
830 while ((ch
= getopt(argc
, argv
, "GT:S:R:b:c:d:p:r:s:w:f:")) != -1) {
834 #ifndef HAVE_GETRUSAGE
835 printf("could not find getrusage, can't print stats\n");
839 bytes
= strtol (optarg
, &ptr
, 0);
840 if (ptr
&& *ptr
!= '\0')
841 errx (1, "can't resolve number of bytes to transfer");
844 if (strcasecmp(optarg
, "send") == 0)
846 else if (strcasecmp(optarg
, "recv") == 0)
848 else if (strcasecmp(optarg
, "rpc") == 0)
850 else if (strcasecmp(optarg
, "file") == 0)
853 errx(1, "unknown command %s", optarg
);
857 rx_debugFile
= fopen(optarg
, "w");
858 if (rx_debugFile
== NULL
)
859 err(1, "fopen %s", optarg
);
861 errx(1, "compiled without RXDEBUG");
865 port
= strtol(optarg
, &ptr
, 0);
866 if (ptr
!= 0 && ptr
[0] != '\0')
867 errx (1, "can't resolve portname");
870 rxread_size
= strtol(optarg
, &ptr
, 0);
871 if (ptr
!= 0 && ptr
[0] != '\0')
872 errx (1, "can't resolve readsize");
873 if (rxread_size
> sizeof(somebuf
))
874 errx(1, "%d > sizeof(somebuf) (%lu)",
875 rxread_size
, (unsigned long)sizeof(somebuf
));
878 host
= strdup(optarg
);
883 rxwrite_size
= strtol(optarg
, &ptr
, 0);
884 if (ptr
!= 0 && ptr
[0] != '\0')
885 errx (1, "can't resolve writesize");
886 if (rxwrite_size
> sizeof(somebuf
))
887 errx(1, "%d > sizeof(somebuf) (%lu)",
888 rxwrite_size
, (unsigned long)sizeof(somebuf
));
891 times
= strtol (optarg
, &ptr
, 0);
892 if (ptr
&& *ptr
!= '\0')
893 errx (1, "can't resolve number times to run the test");
896 rpc_sendbytes
= strtol (optarg
, &ptr
, 0);
897 if (ptr
&& *ptr
!= '\0')
898 errx (1, "can't resolve number of bytes to transfer");
901 rpc_recvbytes
= strtol (optarg
, &ptr
, 0);
902 if (ptr
&& *ptr
!= '\0')
903 errx (1, "can't resolve number of bytes to transfer");
916 if (cmd
== RX_PERF_UNKNOWN
)
917 errx(1, "no command given to the client");
919 do_client(host
, htons(port
), filename
, cmd
, times
, bytes
,
920 rpc_sendbytes
, rpc_recvbytes
);
924 struct rusage rusage
;
925 if(getrusage (RUSAGE_SELF
, &rusage
) < 0)
926 printf("no stats\n");
929 "- utime = (%ld, %lu)\n"
930 "- stime = (%ld, %lu)\n"
945 rusage
.ru_utime
.tv_sec
,
946 (unsigned long)rusage
.ru_utime
.tv_usec
,
947 rusage
.ru_stime
.tv_sec
,
948 (unsigned long)rusage
.ru_stime
.tv_usec
,
961 (unsigned long)rusage
.ru_nvcsw
,
962 (unsigned long)rusage
.ru_nivcsw
);
964 #endif /* HAVE_GETRUSAGE */
969 * setup world and call cmd
973 main(int argc
, char **argv
)
977 setprogname(argv
[0]);
979 signal (SIGUSR1
, sigusr1
);
980 signal (SIGINT
, sigint
);
982 LWP_InitializeProcessSupport (LWP_NORMAL_PRIORITY
, &pid
);
984 memset (somebuf
, 0, sizeof(somebuf
));
986 if (argc
>= 2 && strcmp(argv
[1], "server") == 0)
987 rxperf_server(argc
- 1, argv
+ 1);
988 else if (argc
>= 2 && strcmp(argv
[1], "client") == 0)
989 rxperf_client(argc
- 1, argv
+ 1);