From: Jeffrey Altman Date: Sun, 19 Sep 2010 15:03:50 +0000 (-0700) Subject: Rx: Move rxperf test application to src/rx/tests X-Git-Tag: upstream/1.8.0_pre1^2~4810 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=5c3a1ed88de16db4c2081bbf1a4e397ce459bcf3;p=packages%2Fo%2Fopenafs.git Rx: Move rxperf test application to src/rx/tests rxperf is a test application. Move it to the tests directory Change-Id: I946a8026760d860667ea5707d8a3e0d3b895d908 Reviewed-on: http://gerrit.openafs.org/2772 Tested-by: BuildBot Reviewed-by: Derrick Brashear --- diff --git a/src/rx/Makefile.in b/src/rx/Makefile.in index 278d0150d..9cd852ef9 100644 --- a/src/rx/Makefile.in +++ b/src/rx/Makefile.in @@ -55,8 +55,6 @@ ${MULTIOBJS}: rx.h rx_multi.h rx_prototypes.h ${XDROBJS}: xdr.h xdr_prototypes.h -rxperf.o: rx.h rx_null.h rx_globals.h rx_prototypes.h - rx_user.o: rx.h rx_user.h rx_prototypes.h rx_packet.o: rx_packet.c rx_packet.h rx.h @@ -77,9 +75,6 @@ xdr_rx.o: xdr.h rx.h xdr_prototypes.h rx_prototypes.h xdr_refernce.o: xdr_refernce.c xdr.h xdr_prototypes.h -rxperf: rxperf.o librx.a - ${CC} -o $@ rxperf.o ${LIBS} - librx.a: ${LIBOBJS} RX_component_version_number.o -$(RM) -f $@ $(AR) crv $@ ${LIBOBJS} RX_component_version_number.o diff --git a/src/rx/rxperf.c b/src/rx/rxperf.c deleted file mode 100644 index de00160e3..000000000 --- a/src/rx/rxperf.c +++ /dev/null @@ -1,976 +0,0 @@ -/* - * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution - * at such time that OpenAFS documentation is written. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include - -/* -nn * We are using getopt since we want it to be possible to link to - * transarc libs. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_STRING_H -#include -#else -#ifdef HAVE_STRINGS_H -#include -#endif -#endif -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#ifdef HAVE_ERRX -#include /* not stricly right, but if we have a errx() there - * is hopefully a err.h */ -#endif -#include "rx.h" -#include "rx_null.h" -#include "rx_globals.h" - -#if defined(u_int32) -#define u_int32_t u_int32 -#elif defined(hget32) -#define u_int32_t afs_uint32 -#endif - -static const char *__progname; - -#ifndef HAVE_WARNX -static void -warnx(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - fprintf(stderr, "%s: ", __progname); - vfprintf(stderr, fmt, args); - fprintf(stderr, "\n"); - va_end(args); -} -#endif /* !HAVE_WARNX */ - -#ifndef HAVE_ERRX -static void -errx(int eval, const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - fprintf(stderr, "%s: ", __progname); - vfprintf(stderr, fmt, args); - fprintf(stderr, "\n"); - va_end(args); - - exit(eval); -} -#endif /* !HAVE_ERRX */ - -#ifndef HAVE_WARN -static void -warn(const char *fmt, ...) -{ - va_list args; - char *errstr; - - va_start(args, fmt); - fprintf(stderr, "%s: ", __progname); - vfprintf(stderr, fmt, args); - - errstr = strerror(errno); - - fprintf(stderr, ": %s\n", errstr ? errstr : "unknown error"); - va_end(args); -} -#endif /* !HAVE_WARN */ - -#ifndef HAVE_ERR -static void -err(int eval, const char *fmt, ...) -{ - va_list args; - char *errstr; - - va_start(args, fmt); - fprintf(stderr, "%s: ", __progname); - vfprintf(stderr, fmt, args); - - errstr = strerror(errno); - - fprintf(stderr, ": %s\n", errstr ? errstr : "unknown error"); - va_end(args); - - exit(eval); -} -#endif /* !HAVE_ERR */ - -#define DEFAULT_PORT 7009 /* To match tcpdump */ -#define DEFAULT_HOST "127.0.0.1" -#define DEFAULT_BYTES 1000000 -#define RXPERF_BUFSIZE 10000 - -enum { RX_PERF_VERSION = 3 }; -enum { RX_SERVER_ID = 147 }; -enum { RX_PERF_UNKNOWN = -1, RX_PERF_SEND = 0, RX_PERF_RECV = 1, - RX_PERF_RPC = 3, RX_PERF_FILE = 4 -}; - -enum { RXPERF_MAGIC_COOKIE = 0x4711 }; - -/* - * - */ - -#if DEBUG -#define DBFPRINT(x) do { printf x ; } while(0) -#else -#define DBFPRINT(x) -#endif - -static void -sigusr1(int foo) -{ - exit(2); /* XXX profiler */ -} - -static void -sigint(int foo) -{ - rx_Finalize(); - exit(2); /* XXX profiler */ -} - -/* - * - */ - -static struct timeval timer_start; -static struct timeval timer_stop; -static int timer_check = 0; - -static void -start_timer(void) -{ - timer_check++; - gettimeofday(&timer_start, NULL); -} - -/* - * - */ - -static void -end_and_print_timer(char *str) -{ - long long start_l, stop_l; - - timer_check--; - assert(timer_check == 0); - gettimeofday(&timer_stop, NULL); - start_l = timer_start.tv_sec * 1000000 + timer_start.tv_usec; - stop_l = timer_stop.tv_sec * 1000000 + timer_stop.tv_usec; - printf("%s:\t%8llu msec\n", str, (stop_l - start_l) / 1000); -} - -/* - * - */ - -static u_long -str2addr(const char *s) -{ - struct in_addr server; - struct hostent *h; - -#ifndef INADDR_NONE -#define INADDR_NONE 0xffffffff -#endif - if (inet_addr(s) != INADDR_NONE) - return inet_addr(s); - h = gethostbyname(s); - if (h != NULL) { - memcpy(&server, h->h_addr_list[0], sizeof(server)); - return server.s_addr; - } - return 0; -} - - -/* - * - */ - -static void -get_sec(int serverp, struct rx_securityClass **sec, int *secureindex) -{ - if (serverp) { - *sec = rxnull_NewServerSecurityObject(); - *secureindex = 1; - } else { - *sec = rxnull_NewClientSecurityObject(); - *secureindex = 0; - } -} - -/* - * process the "RPC" and return the results - */ - -char somebuf[RXPERF_BUFSIZE]; - -int32_t rxwrite_size = sizeof(somebuf); -int32_t rxread_size = sizeof(somebuf); - -static int -readbytes(struct rx_call *call, int32_t bytes) -{ - int32_t size; - - while (bytes > 0) { - size = rxread_size; - if (size > bytes) - size = bytes; - if (rx_Read(call, somebuf, size) != size) - return 1; - bytes -= size; - } - return 0; -} - -static int -sendbytes(struct rx_call *call, int32_t bytes) -{ - int32_t size; - - while (bytes > 0) { - size = rxwrite_size; - if (size > bytes) - size = bytes; - if (rx_Write(call, somebuf, size) != size) - return 1; - bytes -= size; - } - return 0; -} - - -static int32_t -rxperf_ExecuteRequest(struct rx_call *call) -{ - int32_t version; - int32_t command; - u_int32_t bytes; - u_int32_t recvb; - u_int32_t sendb; - u_int32_t data; - u_int32_t num; - u_int32_t *readwrite; - int i; - int readp = TRUE; - - DBFPRINT(("got a request\n")); - - if (rx_Read32(call, &version) != 4) { - warn("rx_Read failed to read version"); - return -1; - } - - if (htonl(RX_PERF_VERSION) != version) { - warnx("client has wrong version"); - return -1; - } - - if (rx_Read32(call, &command) != 4) { - warnx("rx_Read failed to read command"); - return -1; - } - command = ntohl(command); - - if (rx_Read32(call, &data) != 4) { - warnx("rx_Read failed to read size"); - return -1; - } - rxread_size = ntohl(data); - if (rxread_size > sizeof(somebuf)) { - warnx("rxread_size too large %d", rxread_size); - return -1; - } - - if (rx_Read32(call, &data) != 4) { - warnx("rx_Read failed to write size"); - return -1; - } - rxwrite_size = ntohl(data); - if (rxwrite_size > sizeof(somebuf)) { - warnx("rxwrite_size too large %d", rxwrite_size); - return -1; - } - - switch (command) { - case RX_PERF_SEND: - DBFPRINT(("got a send request\n")); - - if (rx_Read32(call, &bytes) != 4) { - warnx("rx_Read failed to read bytes"); - return -1; - } - bytes = ntohl(bytes); - - DBFPRINT(("reading(%d) ", bytes)); - readbytes(call, bytes); - - data = htonl(RXPERF_MAGIC_COOKIE); - if (rx_Write32(call, &data) != 4) { - warnx("rx_Write failed when sending back result"); - return -1; - } - DBFPRINT(("done\n")); - - break; - case RX_PERF_RPC: - DBFPRINT(("got a rpc request, reading commands\n")); - - if (rx_Read32(call, &recvb) != 4) { - warnx("rx_Read failed to read recvbytes"); - return -1; - } - recvb = ntohl(recvb); - if (rx_Read32(call, &sendb) != 4) { - warnx("rx_Read failed to read sendbytes"); - return -1; - } - sendb = ntohl(sendb); - - DBFPRINT(("read(%d) ", recvb)); - if (readbytes(call, recvb)) { - warnx("readbytes failed"); - return -1; - } - DBFPRINT(("send(%d) ", sendb)); - if (sendbytes(call, sendb)) { - warnx("sendbytes failed"); - return -1; - } - - DBFPRINT(("done\n")); - - data = htonl(RXPERF_MAGIC_COOKIE); - if (rx_Write32(call, &data) != 4) { - warnx("rx_Write failed when sending back magic cookie"); - return -1; - } - - break; - case RX_PERF_FILE: - if (rx_Read32(call, &data) != 4) - errx(1, "failed to read num from client"); - num = ntohl(data); - - readwrite = malloc(num * sizeof(u_int32_t)); - if (readwrite == NULL) - err(1, "malloc"); - - if (rx_Read(call, readwrite, num * sizeof(u_int32_t)) != - num * sizeof(u_int32_t)) - errx(1, "failed to read recvlist from client"); - - for (i = 0; i < num; i++) { - if (readwrite[i] == 0) { - DBFPRINT(("readp %d", readwrite[i])); - readp = !readp; - } - - bytes = ntohl(readwrite[i]) * sizeof(u_int32_t); - - if (readp) { - DBFPRINT(("read\n")); - readbytes(call, bytes); - } else { - sendbytes(call, bytes); - DBFPRINT(("send\n")); - } - } - - break; - case RX_PERF_RECV: - DBFPRINT(("got a recv request\n")); - - if (rx_Read32(call, &bytes) != 4) { - warnx("rx_Read failed to read bytes"); - return -1; - } - bytes = ntohl(bytes); - - DBFPRINT(("sending(%d) ", bytes)); - sendbytes(call, bytes); - - data = htonl(RXPERF_MAGIC_COOKIE); - if (rx_Write32(call, &data) != 4) { - warnx("rx_Write failed when sending back result"); - return -1; - } - DBFPRINT(("done\n")); - - break; - default: - warnx("client sent a unsupported command"); - return -1; - } - DBFPRINT(("done with command\n")); - - return 0; -} - -/* - * - */ - -static void -do_server(int port, int nojumbo, int maxmtu) -{ - struct rx_service *service; - struct rx_securityClass *secureobj; - int secureindex; - int ret; - - ret = rx_Init(port); - if (ret) - errx(1, "rx_Init failed"); - - if (nojumbo) - rx_SetNoJumbo(); - if (maxmtu) - rx_SetMaxMTU(maxmtu); - get_sec(1, &secureobj, &secureindex); - - service = - rx_NewService(0, RX_SERVER_ID, "rxperf", &secureobj, secureindex, - rxperf_ExecuteRequest); - if (service == NULL) - errx(1, "Cant create server"); - - rx_StartServer(1); - abort(); -} - -/* - * - */ - -static void -readfile(const char *filename, u_int32_t ** readwrite, u_int32_t * size) -{ - FILE *f; - u_int32_t len = 16; - u_int32_t num = 0; - u_int32_t data; - char *ptr; - char buf[RXPERF_BUFSIZE]; - - *readwrite = malloc(sizeof(u_int32_t) * len); - - if (*readwrite == NULL) - err(1, "malloc"); - - f = fopen(filename, "r"); - if (f == NULL) - err(1, "fopen"); - - while (fgets(buf, sizeof(buf), f) != NULL) { - if (num >= len) { - len = len * 2; - *readwrite = realloc(*readwrite, len * sizeof(u_int32_t)); - if (*readwrite == NULL) - err(1, "realloc"); - } - - if (*buf != '\n') { - data = htonl(strtol(buf, &ptr, 0)); - if (ptr && ptr == buf) - errx(1, "can't resolve number of bytes to transfer"); - } else { - data = 0; - } - - (*readwrite)[num] = data; - num++; - } - - *size = num; - - - if (fclose(f) == -1) - err(1, "fclose"); -} - - -/* - * - */ - -static void -do_client(const char *server, int port, char *filename, int32_t command, - int32_t times, int32_t bytes, int32_t sendtimes, int32_t recvtimes, - int dumpstats, int nojumbo, int maxmtu) -{ - struct rx_connection *conn; - struct rx_call *call; - u_int32_t addr = str2addr(server); - struct rx_securityClass *secureobj; - int secureindex; - int32_t data; - int32_t num; - int ret; - int i; - int readp = FALSE; - char stamp[1024]; - u_int32_t size; - - u_int32_t *readwrite; - - ret = rx_Init(0); - if (ret) - errx(1, "rx_Init failed"); - - if (nojumbo) - rx_SetNoJumbo(); - if (maxmtu) - rx_SetMaxMTU(maxmtu); - get_sec(0, &secureobj, &secureindex); - - conn = rx_NewConnection(addr, port, RX_SERVER_ID, secureobj, secureindex); - if (conn == NULL) - errx(1, "failed to contact server"); - - sprintf(stamp, "send\t%d times\t%d writes\t%d reads", times, sendtimes, - recvtimes); - start_timer(); - - for (i = 0; i < times; i++) { - - DBFPRINT(("starting command ")); - - call = rx_NewCall(conn); - if (call == NULL) - errx(1, "rx_NewCall failed"); - - data = htonl(RX_PERF_VERSION); - if (rx_Write32(call, &data) != 4) - errx(1, "rx_Write failed to send version (err %d)", rx_Error(call)); - - data = htonl(command); - if (rx_Write32(call, &data) != 4) - errx(1, "rx_Write failed to send command (err %d)", rx_Error(call)); - - data = htonl(rxread_size); - if (rx_Write32(call, &data) != 4) - errx(1, "rx_Write failed to send read size (err %d)", rx_Error(call)); - data = htonl(rxwrite_size); - if (rx_Write32(call, &data) != 4) - errx(1, "rx_Write failed to send write read (err %d)", rx_Error(call)); - - - switch (command) { - case RX_PERF_RECV: - DBFPRINT(("command ")); - - data = htonl(bytes); - if (rx_Write32(call, &data) != 4) - errx(1, "rx_Write failed to send size (err %d)", rx_Error(call)); - - DBFPRINT(("sending(%d) ", bytes)); - if (readbytes(call, bytes)) - errx(1, "sendbytes (err %d)", rx_Error(call)); - - if (rx_Read32(call, &data) != 4) - errx(1, "failed to read result from server (err %d)", rx_Error(call)); - - if (data != htonl(RXPERF_MAGIC_COOKIE)) - warn("server send wrong magic cookie in responce"); - - DBFPRINT(("done\n")); - - break; - case RX_PERF_SEND: - DBFPRINT(("command ")); - - data = htonl(bytes); - if (rx_Write32(call, &data) != 4) - errx(1, "rx_Write failed to send size (err %d)", rx_Error(call)); - - DBFPRINT(("sending(%d) ", bytes)); - if (sendbytes(call, bytes)) - errx(1, "sendbytes (err %d)", rx_Error(call)); - - if (rx_Read32(call, &data) != 4) - errx(1, "failed to read result from server (err %d)", rx_Error(call)); - - if (data != htonl(RXPERF_MAGIC_COOKIE)) - warn("server send wrong magic cookie in responce"); - - DBFPRINT(("done\n")); - - break; - case RX_PERF_RPC: - DBFPRINT(("commands ")); - - data = htonl(sendtimes); - if (rx_Write32(call, &data) != 4) - errx(1, "rx_Write failed to send command (err %d)", rx_Error(call)); - - data = htonl(recvtimes); - if (rx_Write32(call, &data) != 4) - errx(1, "rx_Write failed to send command (err %d)", rx_Error(call)); - - DBFPRINT(("send(%d) ", sendtimes)); - if (sendbytes(call, sendtimes)) - errx(1, "sendbytes (err %d)", rx_Error(call)); - - DBFPRINT(("recv(%d) ", recvtimes)); - if (readbytes(call, recvtimes)) - errx(1, "sendbytes (err %d)", rx_Error(call)); - - if (rx_Read32(call, &bytes) != 4) - errx(1, "failed to read result from server (err %d)", rx_Error(call)); - - if (bytes != htonl(RXPERF_MAGIC_COOKIE)) - warn("server send wrong magic cookie in responce"); - - DBFPRINT(("done\n")); - - break; - case RX_PERF_FILE: - readfile(filename, &readwrite, &num); - - data = htonl(num); - if (rx_Write32(call, &data) != 4) - errx(1, "rx_Write failed to send size (err %d)", rx_Error(call)); - - if (rx_Write(call, readwrite, num * sizeof(u_int32_t)) - != num * sizeof(u_int32_t)) - errx(1, "rx_Write failed to send list (err %d)", rx_Error(call)); - - for (i = 0; i < num; i++) { - if (readwrite[i] == 0) - readp = !readp; - - size = ntohl(readwrite[i]) * sizeof(u_int32_t); - - if (readp) { - if (readbytes(call, size)) - errx(1, "sendbytes (err %d)", rx_Error(call)); - DBFPRINT(("read\n")); - } else { - if (sendbytes(call, size)) - errx(1, "sendbytes (err %d)", rx_Error(call)); - DBFPRINT(("send\n")); - } - } - break; - default: - abort(); - } - - rx_EndCall(call, 0); - } - - end_and_print_timer(stamp); - DBFPRINT(("done for good\n")); - - if (dumpstats) { - rx_PrintStats(stdout); - rx_PrintPeerStats(stdout, conn->peer); - } - rx_Finalize(); -} - -static void -usage() -{ -#define COMMON "" - - fprintf(stderr, "usage: %s client -c send -b \n", __progname); - fprintf(stderr, "usage: %s client -c recv -b \n", __progname); - fprintf(stderr, - "usage: %s client -c rpc -S -R \n", - __progname); - fprintf(stderr, "usage: %s client -c file -f filename\n", __progname); - fprintf(stderr, - "%s: usage: common option to the client " - "-w -r -T times -p port -s server -D\n", - __progname); - fprintf(stderr, "usage: %s server -p port\n", __progname); -#undef COMMMON - exit(1); -} - -/* - * do argument processing and call networking functions - */ - -static int -rxperf_server(int argc, char **argv) -{ - int port = DEFAULT_PORT; - int nojumbo = 0; - int maxmtu = 0; - char *ptr; - int ch; - - while ((ch = getopt(argc, argv, "r:d:p:w:jm:4")) != -1) { - switch (ch) { - case 'd': -#ifdef RXDEBUG - rx_debugFile = fopen(optarg, "w"); - if (rx_debugFile == NULL) - err(1, "fopen %s", optarg); -#else - errx(1, "compiled without RXDEBUG"); -#endif - break; - case 'r': - rxread_size = strtol(optarg, &ptr, 0); - if (ptr != 0 && ptr[0] != '\0') - errx(1, "can't resolve readsize"); - if (rxread_size > sizeof(somebuf)) - errx(1, "%d > sizeof(somebuf) (%d)", rxread_size, - sizeof(somebuf)); - break; - case 'p': - port = strtol(optarg, &ptr, 0); - if (ptr != 0 && ptr[0] != '\0') - errx(1, "can't resolve portname"); - break; - case 'w': - rxwrite_size = strtol(optarg, &ptr, 0); - if (ptr != 0 && ptr[0] != '\0') - errx(1, "can't resolve writesize"); - if (rxwrite_size > sizeof(somebuf)) - errx(1, "%d > sizeof(somebuf) (%d)", rxwrite_size, - sizeof(somebuf)); - break; - case 'j': - nojumbo=1; - break; - case 'm': - maxmtu = strtol(optarg, &ptr, 0); - if (ptr && *ptr != '\0') - errx(1, "can't resolve rx maxmtu to use"); - break; - case '4': - RX_IPUDP_SIZE = 28; - break; - default: - usage(); - } - } - - if (optind != argc) - usage(); - - do_server(htons(port), nojumbo, maxmtu); - - return 0; -} - -/* - * do argument processing and call networking functions - */ - -static int -rxperf_client(int argc, char **argv) -{ - char *host = DEFAULT_HOST; - int bytes = DEFAULT_BYTES; - int port = DEFAULT_PORT; - char *filename = NULL; - int32_t cmd; - int sendtimes = 3; - int recvtimes = 30; - int times = 100; - int dumpstats = 0; - int nojumbo = 0; - int maxmtu = 0; - char *ptr; - int ch; - - cmd = RX_PERF_UNKNOWN; - - while ((ch = getopt(argc, argv, "T:S:R:b:c:d:p:r:s:w:f:Djm:4")) != -1) { - switch (ch) { - case 'b': - bytes = strtol(optarg, &ptr, 0); - if (ptr && *ptr != '\0') - errx(1, "can't resolve number of bytes to transfer"); - break; - case 'c': - if (strcasecmp(optarg, "send") == 0) - cmd = RX_PERF_SEND; - else if (strcasecmp(optarg, "recv") == 0) - cmd = RX_PERF_RECV; - else if (strcasecmp(optarg, "rpc") == 0) - cmd = RX_PERF_RPC; - else if (strcasecmp(optarg, "file") == 0) - cmd = RX_PERF_FILE; - else - errx(1, "unknown command %s", optarg); - break; - case 'd': -#ifdef RXDEBUG - rx_debugFile = fopen(optarg, "w"); - if (rx_debugFile == NULL) - err(1, "fopen %s", optarg); -#else - errx(1, "compiled without RXDEBUG"); -#endif - break; - case 'p': - port = strtol(optarg, &ptr, 0); - if (ptr != 0 && ptr[0] != '\0') - errx(1, "can't resolve portname"); - break; - case 'r': - rxread_size = strtol(optarg, &ptr, 0); - if (ptr != 0 && ptr[0] != '\0') - errx(1, "can't resolve readsize"); - if (rxread_size > sizeof(somebuf)) - errx(1, "%d > sizeof(somebuf) (%d)", rxread_size, - sizeof(somebuf)); - break; - case 's': - host = strdup(optarg); - if (host == NULL) - err(1, "strdup"); - break; - case 'w': - rxwrite_size = strtol(optarg, &ptr, 0); - if (ptr != 0 && ptr[0] != '\0') - errx(1, "can't resolve writesize"); - if (rxwrite_size > sizeof(somebuf)) - errx(1, "%d > sizeof(somebuf) (%d)", rxwrite_size, - sizeof(somebuf)); - break; - case 'T': - times = strtol(optarg, &ptr, 0); - if (ptr && *ptr != '\0') - errx(1, "can't resolve number of bytes to transfer"); - break; - case 'S': - sendtimes = strtol(optarg, &ptr, 0); - if (ptr && *ptr != '\0') - errx(1, "can't resolve number of bytes to transfer"); - break; - case 'R': - recvtimes = strtol(optarg, &ptr, 0); - if (ptr && *ptr != '\0') - errx(1, "can't resolve number of bytes to transfer"); - break; - case 'f': - filename = optarg; - break; - case 'D': -#ifdef RXDEBUG - dumpstats = 1; -#else - errx(1, "compiled without RXDEBUG"); -#endif - break; - case 'j': - nojumbo=1; - break; - case 'm': - maxmtu = strtol(optarg, &ptr, 0); - if (ptr && *ptr != '\0') - errx(1, "can't resolve rx maxmtu to use"); - break; - case '4': - RX_IPUDP_SIZE = 28; - break; - default: - usage(); - } - } - - if (optind != argc) - usage(); - - if (cmd == RX_PERF_UNKNOWN) - errx(1, "no command given to the client"); - - do_client(host, htons(port), filename, cmd, times, bytes, sendtimes, - recvtimes, dumpstats, nojumbo, maxmtu); - - return 0; -} - -/* - * setup world and call cmd - */ - -int -main(int argc, char **argv) -{ - PROCESS pid; - - __progname = strrchr(argv[0], '/'); - if (__progname == 0) - __progname = argv[0]; - - signal(SIGUSR1, sigusr1); - signal(SIGINT, sigint); - - LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY, &pid); - - memset(somebuf, 0, sizeof(somebuf)); - - if (argc >= 2 && strcmp(argv[1], "server") == 0) - rxperf_server(argc - 1, argv + 1); - else if (argc >= 2 && strcmp(argv[1], "client") == 0) - rxperf_client(argc - 1, argv + 1); - else - usage(); - return 0; -} diff --git a/src/rx/test/Makefile.in b/src/rx/test/Makefile.in index ed27cb29c..aa8d46c0b 100644 --- a/src/rx/test/Makefile.in +++ b/src/rx/test/Makefile.in @@ -51,6 +51,9 @@ kstest: ../librx.a kstest.o kctest: ../librx.a kctest.o -${LINK} +rxperf: rxperf.o ../librx.a + -${LINK} + # th_ versions only have link lines for Solaris now. th_testclient: th_testclient.o ../../libafsrpc/libafsrpc.so ${CC} ${CFLAGS} -mt -o th_testclient th_testclient.o \ diff --git a/src/rx/test/rxperf.c b/src/rx/test/rxperf.c new file mode 100644 index 000000000..de00160e3 --- /dev/null +++ b/src/rx/test/rxperf.c @@ -0,0 +1,976 @@ +/* + * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution + * at such time that OpenAFS documentation is written. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +/* +nn * We are using getopt since we want it to be possible to link to + * transarc libs. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#ifdef HAVE_ERRX +#include /* not stricly right, but if we have a errx() there + * is hopefully a err.h */ +#endif +#include "rx.h" +#include "rx_null.h" +#include "rx_globals.h" + +#if defined(u_int32) +#define u_int32_t u_int32 +#elif defined(hget32) +#define u_int32_t afs_uint32 +#endif + +static const char *__progname; + +#ifndef HAVE_WARNX +static void +warnx(const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + fprintf(stderr, "%s: ", __progname); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); +} +#endif /* !HAVE_WARNX */ + +#ifndef HAVE_ERRX +static void +errx(int eval, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + fprintf(stderr, "%s: ", __progname); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); + + exit(eval); +} +#endif /* !HAVE_ERRX */ + +#ifndef HAVE_WARN +static void +warn(const char *fmt, ...) +{ + va_list args; + char *errstr; + + va_start(args, fmt); + fprintf(stderr, "%s: ", __progname); + vfprintf(stderr, fmt, args); + + errstr = strerror(errno); + + fprintf(stderr, ": %s\n", errstr ? errstr : "unknown error"); + va_end(args); +} +#endif /* !HAVE_WARN */ + +#ifndef HAVE_ERR +static void +err(int eval, const char *fmt, ...) +{ + va_list args; + char *errstr; + + va_start(args, fmt); + fprintf(stderr, "%s: ", __progname); + vfprintf(stderr, fmt, args); + + errstr = strerror(errno); + + fprintf(stderr, ": %s\n", errstr ? errstr : "unknown error"); + va_end(args); + + exit(eval); +} +#endif /* !HAVE_ERR */ + +#define DEFAULT_PORT 7009 /* To match tcpdump */ +#define DEFAULT_HOST "127.0.0.1" +#define DEFAULT_BYTES 1000000 +#define RXPERF_BUFSIZE 10000 + +enum { RX_PERF_VERSION = 3 }; +enum { RX_SERVER_ID = 147 }; +enum { RX_PERF_UNKNOWN = -1, RX_PERF_SEND = 0, RX_PERF_RECV = 1, + RX_PERF_RPC = 3, RX_PERF_FILE = 4 +}; + +enum { RXPERF_MAGIC_COOKIE = 0x4711 }; + +/* + * + */ + +#if DEBUG +#define DBFPRINT(x) do { printf x ; } while(0) +#else +#define DBFPRINT(x) +#endif + +static void +sigusr1(int foo) +{ + exit(2); /* XXX profiler */ +} + +static void +sigint(int foo) +{ + rx_Finalize(); + exit(2); /* XXX profiler */ +} + +/* + * + */ + +static struct timeval timer_start; +static struct timeval timer_stop; +static int timer_check = 0; + +static void +start_timer(void) +{ + timer_check++; + gettimeofday(&timer_start, NULL); +} + +/* + * + */ + +static void +end_and_print_timer(char *str) +{ + long long start_l, stop_l; + + timer_check--; + assert(timer_check == 0); + gettimeofday(&timer_stop, NULL); + start_l = timer_start.tv_sec * 1000000 + timer_start.tv_usec; + stop_l = timer_stop.tv_sec * 1000000 + timer_stop.tv_usec; + printf("%s:\t%8llu msec\n", str, (stop_l - start_l) / 1000); +} + +/* + * + */ + +static u_long +str2addr(const char *s) +{ + struct in_addr server; + struct hostent *h; + +#ifndef INADDR_NONE +#define INADDR_NONE 0xffffffff +#endif + if (inet_addr(s) != INADDR_NONE) + return inet_addr(s); + h = gethostbyname(s); + if (h != NULL) { + memcpy(&server, h->h_addr_list[0], sizeof(server)); + return server.s_addr; + } + return 0; +} + + +/* + * + */ + +static void +get_sec(int serverp, struct rx_securityClass **sec, int *secureindex) +{ + if (serverp) { + *sec = rxnull_NewServerSecurityObject(); + *secureindex = 1; + } else { + *sec = rxnull_NewClientSecurityObject(); + *secureindex = 0; + } +} + +/* + * process the "RPC" and return the results + */ + +char somebuf[RXPERF_BUFSIZE]; + +int32_t rxwrite_size = sizeof(somebuf); +int32_t rxread_size = sizeof(somebuf); + +static int +readbytes(struct rx_call *call, int32_t bytes) +{ + int32_t size; + + while (bytes > 0) { + size = rxread_size; + if (size > bytes) + size = bytes; + if (rx_Read(call, somebuf, size) != size) + return 1; + bytes -= size; + } + return 0; +} + +static int +sendbytes(struct rx_call *call, int32_t bytes) +{ + int32_t size; + + while (bytes > 0) { + size = rxwrite_size; + if (size > bytes) + size = bytes; + if (rx_Write(call, somebuf, size) != size) + return 1; + bytes -= size; + } + return 0; +} + + +static int32_t +rxperf_ExecuteRequest(struct rx_call *call) +{ + int32_t version; + int32_t command; + u_int32_t bytes; + u_int32_t recvb; + u_int32_t sendb; + u_int32_t data; + u_int32_t num; + u_int32_t *readwrite; + int i; + int readp = TRUE; + + DBFPRINT(("got a request\n")); + + if (rx_Read32(call, &version) != 4) { + warn("rx_Read failed to read version"); + return -1; + } + + if (htonl(RX_PERF_VERSION) != version) { + warnx("client has wrong version"); + return -1; + } + + if (rx_Read32(call, &command) != 4) { + warnx("rx_Read failed to read command"); + return -1; + } + command = ntohl(command); + + if (rx_Read32(call, &data) != 4) { + warnx("rx_Read failed to read size"); + return -1; + } + rxread_size = ntohl(data); + if (rxread_size > sizeof(somebuf)) { + warnx("rxread_size too large %d", rxread_size); + return -1; + } + + if (rx_Read32(call, &data) != 4) { + warnx("rx_Read failed to write size"); + return -1; + } + rxwrite_size = ntohl(data); + if (rxwrite_size > sizeof(somebuf)) { + warnx("rxwrite_size too large %d", rxwrite_size); + return -1; + } + + switch (command) { + case RX_PERF_SEND: + DBFPRINT(("got a send request\n")); + + if (rx_Read32(call, &bytes) != 4) { + warnx("rx_Read failed to read bytes"); + return -1; + } + bytes = ntohl(bytes); + + DBFPRINT(("reading(%d) ", bytes)); + readbytes(call, bytes); + + data = htonl(RXPERF_MAGIC_COOKIE); + if (rx_Write32(call, &data) != 4) { + warnx("rx_Write failed when sending back result"); + return -1; + } + DBFPRINT(("done\n")); + + break; + case RX_PERF_RPC: + DBFPRINT(("got a rpc request, reading commands\n")); + + if (rx_Read32(call, &recvb) != 4) { + warnx("rx_Read failed to read recvbytes"); + return -1; + } + recvb = ntohl(recvb); + if (rx_Read32(call, &sendb) != 4) { + warnx("rx_Read failed to read sendbytes"); + return -1; + } + sendb = ntohl(sendb); + + DBFPRINT(("read(%d) ", recvb)); + if (readbytes(call, recvb)) { + warnx("readbytes failed"); + return -1; + } + DBFPRINT(("send(%d) ", sendb)); + if (sendbytes(call, sendb)) { + warnx("sendbytes failed"); + return -1; + } + + DBFPRINT(("done\n")); + + data = htonl(RXPERF_MAGIC_COOKIE); + if (rx_Write32(call, &data) != 4) { + warnx("rx_Write failed when sending back magic cookie"); + return -1; + } + + break; + case RX_PERF_FILE: + if (rx_Read32(call, &data) != 4) + errx(1, "failed to read num from client"); + num = ntohl(data); + + readwrite = malloc(num * sizeof(u_int32_t)); + if (readwrite == NULL) + err(1, "malloc"); + + if (rx_Read(call, readwrite, num * sizeof(u_int32_t)) != + num * sizeof(u_int32_t)) + errx(1, "failed to read recvlist from client"); + + for (i = 0; i < num; i++) { + if (readwrite[i] == 0) { + DBFPRINT(("readp %d", readwrite[i])); + readp = !readp; + } + + bytes = ntohl(readwrite[i]) * sizeof(u_int32_t); + + if (readp) { + DBFPRINT(("read\n")); + readbytes(call, bytes); + } else { + sendbytes(call, bytes); + DBFPRINT(("send\n")); + } + } + + break; + case RX_PERF_RECV: + DBFPRINT(("got a recv request\n")); + + if (rx_Read32(call, &bytes) != 4) { + warnx("rx_Read failed to read bytes"); + return -1; + } + bytes = ntohl(bytes); + + DBFPRINT(("sending(%d) ", bytes)); + sendbytes(call, bytes); + + data = htonl(RXPERF_MAGIC_COOKIE); + if (rx_Write32(call, &data) != 4) { + warnx("rx_Write failed when sending back result"); + return -1; + } + DBFPRINT(("done\n")); + + break; + default: + warnx("client sent a unsupported command"); + return -1; + } + DBFPRINT(("done with command\n")); + + return 0; +} + +/* + * + */ + +static void +do_server(int port, int nojumbo, int maxmtu) +{ + struct rx_service *service; + struct rx_securityClass *secureobj; + int secureindex; + int ret; + + ret = rx_Init(port); + if (ret) + errx(1, "rx_Init failed"); + + if (nojumbo) + rx_SetNoJumbo(); + if (maxmtu) + rx_SetMaxMTU(maxmtu); + get_sec(1, &secureobj, &secureindex); + + service = + rx_NewService(0, RX_SERVER_ID, "rxperf", &secureobj, secureindex, + rxperf_ExecuteRequest); + if (service == NULL) + errx(1, "Cant create server"); + + rx_StartServer(1); + abort(); +} + +/* + * + */ + +static void +readfile(const char *filename, u_int32_t ** readwrite, u_int32_t * size) +{ + FILE *f; + u_int32_t len = 16; + u_int32_t num = 0; + u_int32_t data; + char *ptr; + char buf[RXPERF_BUFSIZE]; + + *readwrite = malloc(sizeof(u_int32_t) * len); + + if (*readwrite == NULL) + err(1, "malloc"); + + f = fopen(filename, "r"); + if (f == NULL) + err(1, "fopen"); + + while (fgets(buf, sizeof(buf), f) != NULL) { + if (num >= len) { + len = len * 2; + *readwrite = realloc(*readwrite, len * sizeof(u_int32_t)); + if (*readwrite == NULL) + err(1, "realloc"); + } + + if (*buf != '\n') { + data = htonl(strtol(buf, &ptr, 0)); + if (ptr && ptr == buf) + errx(1, "can't resolve number of bytes to transfer"); + } else { + data = 0; + } + + (*readwrite)[num] = data; + num++; + } + + *size = num; + + + if (fclose(f) == -1) + err(1, "fclose"); +} + + +/* + * + */ + +static void +do_client(const char *server, int port, char *filename, int32_t command, + int32_t times, int32_t bytes, int32_t sendtimes, int32_t recvtimes, + int dumpstats, int nojumbo, int maxmtu) +{ + struct rx_connection *conn; + struct rx_call *call; + u_int32_t addr = str2addr(server); + struct rx_securityClass *secureobj; + int secureindex; + int32_t data; + int32_t num; + int ret; + int i; + int readp = FALSE; + char stamp[1024]; + u_int32_t size; + + u_int32_t *readwrite; + + ret = rx_Init(0); + if (ret) + errx(1, "rx_Init failed"); + + if (nojumbo) + rx_SetNoJumbo(); + if (maxmtu) + rx_SetMaxMTU(maxmtu); + get_sec(0, &secureobj, &secureindex); + + conn = rx_NewConnection(addr, port, RX_SERVER_ID, secureobj, secureindex); + if (conn == NULL) + errx(1, "failed to contact server"); + + sprintf(stamp, "send\t%d times\t%d writes\t%d reads", times, sendtimes, + recvtimes); + start_timer(); + + for (i = 0; i < times; i++) { + + DBFPRINT(("starting command ")); + + call = rx_NewCall(conn); + if (call == NULL) + errx(1, "rx_NewCall failed"); + + data = htonl(RX_PERF_VERSION); + if (rx_Write32(call, &data) != 4) + errx(1, "rx_Write failed to send version (err %d)", rx_Error(call)); + + data = htonl(command); + if (rx_Write32(call, &data) != 4) + errx(1, "rx_Write failed to send command (err %d)", rx_Error(call)); + + data = htonl(rxread_size); + if (rx_Write32(call, &data) != 4) + errx(1, "rx_Write failed to send read size (err %d)", rx_Error(call)); + data = htonl(rxwrite_size); + if (rx_Write32(call, &data) != 4) + errx(1, "rx_Write failed to send write read (err %d)", rx_Error(call)); + + + switch (command) { + case RX_PERF_RECV: + DBFPRINT(("command ")); + + data = htonl(bytes); + if (rx_Write32(call, &data) != 4) + errx(1, "rx_Write failed to send size (err %d)", rx_Error(call)); + + DBFPRINT(("sending(%d) ", bytes)); + if (readbytes(call, bytes)) + errx(1, "sendbytes (err %d)", rx_Error(call)); + + if (rx_Read32(call, &data) != 4) + errx(1, "failed to read result from server (err %d)", rx_Error(call)); + + if (data != htonl(RXPERF_MAGIC_COOKIE)) + warn("server send wrong magic cookie in responce"); + + DBFPRINT(("done\n")); + + break; + case RX_PERF_SEND: + DBFPRINT(("command ")); + + data = htonl(bytes); + if (rx_Write32(call, &data) != 4) + errx(1, "rx_Write failed to send size (err %d)", rx_Error(call)); + + DBFPRINT(("sending(%d) ", bytes)); + if (sendbytes(call, bytes)) + errx(1, "sendbytes (err %d)", rx_Error(call)); + + if (rx_Read32(call, &data) != 4) + errx(1, "failed to read result from server (err %d)", rx_Error(call)); + + if (data != htonl(RXPERF_MAGIC_COOKIE)) + warn("server send wrong magic cookie in responce"); + + DBFPRINT(("done\n")); + + break; + case RX_PERF_RPC: + DBFPRINT(("commands ")); + + data = htonl(sendtimes); + if (rx_Write32(call, &data) != 4) + errx(1, "rx_Write failed to send command (err %d)", rx_Error(call)); + + data = htonl(recvtimes); + if (rx_Write32(call, &data) != 4) + errx(1, "rx_Write failed to send command (err %d)", rx_Error(call)); + + DBFPRINT(("send(%d) ", sendtimes)); + if (sendbytes(call, sendtimes)) + errx(1, "sendbytes (err %d)", rx_Error(call)); + + DBFPRINT(("recv(%d) ", recvtimes)); + if (readbytes(call, recvtimes)) + errx(1, "sendbytes (err %d)", rx_Error(call)); + + if (rx_Read32(call, &bytes) != 4) + errx(1, "failed to read result from server (err %d)", rx_Error(call)); + + if (bytes != htonl(RXPERF_MAGIC_COOKIE)) + warn("server send wrong magic cookie in responce"); + + DBFPRINT(("done\n")); + + break; + case RX_PERF_FILE: + readfile(filename, &readwrite, &num); + + data = htonl(num); + if (rx_Write32(call, &data) != 4) + errx(1, "rx_Write failed to send size (err %d)", rx_Error(call)); + + if (rx_Write(call, readwrite, num * sizeof(u_int32_t)) + != num * sizeof(u_int32_t)) + errx(1, "rx_Write failed to send list (err %d)", rx_Error(call)); + + for (i = 0; i < num; i++) { + if (readwrite[i] == 0) + readp = !readp; + + size = ntohl(readwrite[i]) * sizeof(u_int32_t); + + if (readp) { + if (readbytes(call, size)) + errx(1, "sendbytes (err %d)", rx_Error(call)); + DBFPRINT(("read\n")); + } else { + if (sendbytes(call, size)) + errx(1, "sendbytes (err %d)", rx_Error(call)); + DBFPRINT(("send\n")); + } + } + break; + default: + abort(); + } + + rx_EndCall(call, 0); + } + + end_and_print_timer(stamp); + DBFPRINT(("done for good\n")); + + if (dumpstats) { + rx_PrintStats(stdout); + rx_PrintPeerStats(stdout, conn->peer); + } + rx_Finalize(); +} + +static void +usage() +{ +#define COMMON "" + + fprintf(stderr, "usage: %s client -c send -b \n", __progname); + fprintf(stderr, "usage: %s client -c recv -b \n", __progname); + fprintf(stderr, + "usage: %s client -c rpc -S -R \n", + __progname); + fprintf(stderr, "usage: %s client -c file -f filename\n", __progname); + fprintf(stderr, + "%s: usage: common option to the client " + "-w -r -T times -p port -s server -D\n", + __progname); + fprintf(stderr, "usage: %s server -p port\n", __progname); +#undef COMMMON + exit(1); +} + +/* + * do argument processing and call networking functions + */ + +static int +rxperf_server(int argc, char **argv) +{ + int port = DEFAULT_PORT; + int nojumbo = 0; + int maxmtu = 0; + char *ptr; + int ch; + + while ((ch = getopt(argc, argv, "r:d:p:w:jm:4")) != -1) { + switch (ch) { + case 'd': +#ifdef RXDEBUG + rx_debugFile = fopen(optarg, "w"); + if (rx_debugFile == NULL) + err(1, "fopen %s", optarg); +#else + errx(1, "compiled without RXDEBUG"); +#endif + break; + case 'r': + rxread_size = strtol(optarg, &ptr, 0); + if (ptr != 0 && ptr[0] != '\0') + errx(1, "can't resolve readsize"); + if (rxread_size > sizeof(somebuf)) + errx(1, "%d > sizeof(somebuf) (%d)", rxread_size, + sizeof(somebuf)); + break; + case 'p': + port = strtol(optarg, &ptr, 0); + if (ptr != 0 && ptr[0] != '\0') + errx(1, "can't resolve portname"); + break; + case 'w': + rxwrite_size = strtol(optarg, &ptr, 0); + if (ptr != 0 && ptr[0] != '\0') + errx(1, "can't resolve writesize"); + if (rxwrite_size > sizeof(somebuf)) + errx(1, "%d > sizeof(somebuf) (%d)", rxwrite_size, + sizeof(somebuf)); + break; + case 'j': + nojumbo=1; + break; + case 'm': + maxmtu = strtol(optarg, &ptr, 0); + if (ptr && *ptr != '\0') + errx(1, "can't resolve rx maxmtu to use"); + break; + case '4': + RX_IPUDP_SIZE = 28; + break; + default: + usage(); + } + } + + if (optind != argc) + usage(); + + do_server(htons(port), nojumbo, maxmtu); + + return 0; +} + +/* + * do argument processing and call networking functions + */ + +static int +rxperf_client(int argc, char **argv) +{ + char *host = DEFAULT_HOST; + int bytes = DEFAULT_BYTES; + int port = DEFAULT_PORT; + char *filename = NULL; + int32_t cmd; + int sendtimes = 3; + int recvtimes = 30; + int times = 100; + int dumpstats = 0; + int nojumbo = 0; + int maxmtu = 0; + char *ptr; + int ch; + + cmd = RX_PERF_UNKNOWN; + + while ((ch = getopt(argc, argv, "T:S:R:b:c:d:p:r:s:w:f:Djm:4")) != -1) { + switch (ch) { + case 'b': + bytes = strtol(optarg, &ptr, 0); + if (ptr && *ptr != '\0') + errx(1, "can't resolve number of bytes to transfer"); + break; + case 'c': + if (strcasecmp(optarg, "send") == 0) + cmd = RX_PERF_SEND; + else if (strcasecmp(optarg, "recv") == 0) + cmd = RX_PERF_RECV; + else if (strcasecmp(optarg, "rpc") == 0) + cmd = RX_PERF_RPC; + else if (strcasecmp(optarg, "file") == 0) + cmd = RX_PERF_FILE; + else + errx(1, "unknown command %s", optarg); + break; + case 'd': +#ifdef RXDEBUG + rx_debugFile = fopen(optarg, "w"); + if (rx_debugFile == NULL) + err(1, "fopen %s", optarg); +#else + errx(1, "compiled without RXDEBUG"); +#endif + break; + case 'p': + port = strtol(optarg, &ptr, 0); + if (ptr != 0 && ptr[0] != '\0') + errx(1, "can't resolve portname"); + break; + case 'r': + rxread_size = strtol(optarg, &ptr, 0); + if (ptr != 0 && ptr[0] != '\0') + errx(1, "can't resolve readsize"); + if (rxread_size > sizeof(somebuf)) + errx(1, "%d > sizeof(somebuf) (%d)", rxread_size, + sizeof(somebuf)); + break; + case 's': + host = strdup(optarg); + if (host == NULL) + err(1, "strdup"); + break; + case 'w': + rxwrite_size = strtol(optarg, &ptr, 0); + if (ptr != 0 && ptr[0] != '\0') + errx(1, "can't resolve writesize"); + if (rxwrite_size > sizeof(somebuf)) + errx(1, "%d > sizeof(somebuf) (%d)", rxwrite_size, + sizeof(somebuf)); + break; + case 'T': + times = strtol(optarg, &ptr, 0); + if (ptr && *ptr != '\0') + errx(1, "can't resolve number of bytes to transfer"); + break; + case 'S': + sendtimes = strtol(optarg, &ptr, 0); + if (ptr && *ptr != '\0') + errx(1, "can't resolve number of bytes to transfer"); + break; + case 'R': + recvtimes = strtol(optarg, &ptr, 0); + if (ptr && *ptr != '\0') + errx(1, "can't resolve number of bytes to transfer"); + break; + case 'f': + filename = optarg; + break; + case 'D': +#ifdef RXDEBUG + dumpstats = 1; +#else + errx(1, "compiled without RXDEBUG"); +#endif + break; + case 'j': + nojumbo=1; + break; + case 'm': + maxmtu = strtol(optarg, &ptr, 0); + if (ptr && *ptr != '\0') + errx(1, "can't resolve rx maxmtu to use"); + break; + case '4': + RX_IPUDP_SIZE = 28; + break; + default: + usage(); + } + } + + if (optind != argc) + usage(); + + if (cmd == RX_PERF_UNKNOWN) + errx(1, "no command given to the client"); + + do_client(host, htons(port), filename, cmd, times, bytes, sendtimes, + recvtimes, dumpstats, nojumbo, maxmtu); + + return 0; +} + +/* + * setup world and call cmd + */ + +int +main(int argc, char **argv) +{ + PROCESS pid; + + __progname = strrchr(argv[0], '/'); + if (__progname == 0) + __progname = argv[0]; + + signal(SIGUSR1, sigusr1); + signal(SIGINT, sigint); + + LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY, &pid); + + memset(somebuf, 0, sizeof(somebuf)); + + if (argc >= 2 && strcmp(argv[1], "server") == 0) + rxperf_server(argc - 1, argv + 1); + else if (argc >= 2 && strcmp(argv[1], "client") == 0) + rxperf_client(argc - 1, argv + 1); + else + usage(); + return 0; +}