From 18f5f636dd6c1121a50614cf4860086db9f7842e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Love=20H=C3=B6rnquist-=C3=85strand?= Date: Thu, 6 Dec 2001 23:39:08 +0000 Subject: [PATCH] rx-add-performance-testing-client-20011206 add rxperf with modified license which allows us to distribute it now pending more useful OpenAFS documentation existing at some point in the future. --- src/rx/Makefile.in | 5 + src/rx/rxperf.c | 931 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 936 insertions(+) create mode 100644 src/rx/rxperf.c diff --git a/src/rx/Makefile.in b/src/rx/Makefile.in index 8a19989188..d7fd900853 100644 --- a/src/rx/Makefile.in +++ b/src/rx/Makefile.in @@ -69,6 +69,8 @@ ${MULTIOBJS}: rx.h rx_multi.h ${XDROBJS}: xdr.h +rxperf.o: rx.h rx_null.h rx_globals.h + rx_user.o: rx.h rx_user.h rx_packet.o: rx_packet.c rx_packet.h @@ -89,6 +91,9 @@ xdr_rx.o: xdr.h rx.h xdr_refernce.o: xdr_refernce.c xdr.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 new file mode 100644 index 0000000000..a5848a8d6b --- /dev/null +++ b/src/rx/rxperf.c @@ -0,0 +1,931 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* +nn * We are using getopt since we want it to be possible to link to + * transarc libs. + */ + +#ifdef RCSID +RCSID("$Id$"); +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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_Read (call, &version, 4) != 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_Read (call, &command, 4) != 4) { + warnx ("rx_Read failed to read command"); + return -1; + } + command = ntohl(command); + + if (rx_Read (call, &data, 4) != 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_Read (call, &data, 4) != 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_Read (call, &bytes, 4) != 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_Write (call, &data, 4) != 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_Read (call, &recvb, 4) != 4) { + warnx ("rx_Read failed to read recvbytes"); + return -1; + } + recvb = ntohl(recvb); + if (rx_Read (call, &sendb, 4) != 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_Write (call, &data, 4) != 4) { + warnx ( "rx_Write failed when sending back magic cookie"); + return -1; + } + + break; + case RX_PERF_FILE: + if (rx_Read (call, &data, 4) != 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_Read (call, &bytes, 4) != 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_Write (call, &data, 4) != 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) +{ + struct rx_service *service; + struct rx_securityClass *secureobj; + int secureindex; + int ret; + + ret = rx_Init (port); + if (ret) + errx (1, "rx_Init failed"); + + 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) +{ + 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"); + + 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_Write (call, &data, 4) != 4) + errx (1, "rx_Write failed to send version"); + + data = htonl(command); + if (rx_Write (call, &data, 4) != 4) + errx (1, "rx_Write failed to send command"); + + data = htonl(rxread_size); + if (rx_Write (call, &data, 4) != 4) + errx (1, "rx_Write failed to send read size"); + data = htonl(rxwrite_size); + if (rx_Write (call, &data, 4) != 4) + errx (1, "rx_Write failed to send write read"); + + + switch (command) { + case RX_PERF_RECV: + DBFPRINT(("command ")); + + data = htonl (bytes); + if (rx_Write (call, &data, 4) != 4) + errx (1, "rx_Write failed to send size"); + + DBFPRINT(("sending(%d) ", bytes)); + if (readbytes(call, bytes)) + errx(1, "sendbytes"); + + if (rx_Read (call, &data, 4) != 4) + errx (1, "failed to read result from server"); + + 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_Write (call, &data, 4) != 4) + errx (1, "rx_Write failed to send size"); + + DBFPRINT(("sending(%d) ", bytes)); + if (sendbytes(call, bytes)) + errx(1, "sendbytes"); + + if (rx_Read (call, &data, 4) != 4) + errx (1, "failed to read result from server"); + + 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_Write(call, &data, 4) != 4) + errx (1, "rx_Write failed to send command"); + + data = htonl(recvtimes); + if (rx_Write (call, &data, 4) != 4) + errx (1, "rx_Write failed to send command"); + + DBFPRINT(("send(%d) ", sendtimes)); + sendbytes(call, sendtimes); + + DBFPRINT(("recv(%d) ", recvtimes)); + readbytes(call, recvtimes); + + if (rx_Read (call, &bytes, 4) != 4) + errx (1, "failed to read result from server"); + + 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_Write(call, &data, sizeof(data)) != 4) + errx (1, "rx_Write failed to send size"); + + if (rx_Write(call, readwrite, num*sizeof(u_int32_t)) + != num*sizeof(u_int32_t)) + errx (1, "rx_Write failed to send list"); + + for(i=0; i < num; i++) { + if(readwrite[i] == 0) + readp = !readp; + + size = ntohl(readwrite[i])*sizeof(u_int32_t); + + if(readp) { + readbytes(call, size); + DBFPRINT(("read\n")); + } else { + sendbytes(call, size); + DBFPRINT(("send\n")); + } + } + break; + default: + abort(); + } + + rx_EndCall (call, 0); + } + + end_and_print_timer (stamp); + DBFPRINT(("done for good\n")); + + 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\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; + char *ptr; + int ch; + + while ((ch = getopt(argc, argv, "r:d:p:w:")) != -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; + default: + usage(); + } + } + + if (optind != argc) + usage(); + + do_server (htons(port)); + + 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; + char *ptr; + int ch; + + cmd = RX_PERF_UNKNOWN; + + while ((ch = getopt(argc, argv, "T:S:R:b:c:d:p:r:s:w:f:")) != -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; + 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); + + 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; +} +