]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
Rx: Move rxperf test application to src/rx/tests
authorJeffrey Altman <jaltman@your-file-system.com>
Sun, 19 Sep 2010 15:03:50 +0000 (08:03 -0700)
committerDerrick Brashear <shadow@dementia.org>
Mon, 27 Sep 2010 15:29:08 +0000 (08:29 -0700)
rxperf is a test application.  Move it to the tests directory

Change-Id: I946a8026760d860667ea5707d8a3e0d3b895d908
Reviewed-on: http://gerrit.openafs.org/2772
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementia.org>
(cherry picked from commit 5c3a1ed88de16db4c2081bbf1a4e397ce459bcf3)
Reviewed-on: http://gerrit.openafs.org/2804
Tested-by: Derrick Brashear <shadow@dementia.org>
src/rx/Makefile.in
src/rx/rxperf.c [deleted file]
src/rx/test/Makefile.in
src/rx/test/rxperf.c [new file with mode: 0644]

index 278d0150d975bc1b338ec99cc4629ff3748a2b3f..9cd852ef91bc5425d0d651ec5f0a719b04a7d7b7 100644 (file)
@@ -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 (file)
index de00160..0000000
+++ /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 <afsconfig.h>
-
-/*
-nn * We are using getopt since we want it to be possible to link to
- * transarc libs.
- */
-
-#include <stdarg.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-#include <assert.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <signal.h>
-#ifdef HAVE_ERRX
-#include <err.h>               /* 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 <bytes>\n", __progname);
-    fprintf(stderr, "usage: %s client -c recv -b <bytes>\n", __progname);
-    fprintf(stderr,
-           "usage: %s client -c rpc  -S <sendbytes> -R <recvbytes>\n",
-           __progname);
-    fprintf(stderr, "usage: %s client -c file -f filename\n", __progname);
-    fprintf(stderr,
-           "%s: usage: common option to the client "
-           "-w <write-bytes> -r <read-bytes> -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;
-}
index ed27cb29c8903e8dc567b0c0d1e8f23ce4611ebd..aa8d46c0b27e972db4dfac79730dd470d569bb4c 100644 (file)
@@ -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 (file)
index 0000000..de00160
--- /dev/null
@@ -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 <afsconfig.h>
+
+/*
+nn * We are using getopt since we want it to be possible to link to
+ * transarc libs.
+ */
+
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+#include <assert.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <signal.h>
+#ifdef HAVE_ERRX
+#include <err.h>               /* 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 <bytes>\n", __progname);
+    fprintf(stderr, "usage: %s client -c recv -b <bytes>\n", __progname);
+    fprintf(stderr,
+           "usage: %s client -c rpc  -S <sendbytes> -R <recvbytes>\n",
+           __progname);
+    fprintf(stderr, "usage: %s client -c file -f filename\n", __progname);
+    fprintf(stderr,
+           "%s: usage: common option to the client "
+           "-w <write-bytes> -r <read-bytes> -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;
+}