From: Simon Wilkinson Date: Tue, 17 Apr 2012 22:19:17 +0000 (+0100) Subject: rxperf: Move into the tools directory X-Git-Tag: upstream/1.8.0_pre1^2~2503 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=06cc5bec2c2485f49a39fcd4af378279178fab36;p=packages%2Fo%2Fopenafs.git rxperf: Move into the tools directory Move the 'rxperf' RX performance testing utility out of the src/rx/test directory, and into the slightly more visible top level src/tools/ directory As this is the first time that rxperf has been built as part of the default build, make a number of changes so that it will build on all of our supported platforms. Change-Id: Ice37e7db694dbfed34009bf76d24f1e0bf272e47 Reviewed-on: http://gerrit.openafs.org/7240 Tested-by: BuildBot Reviewed-by: Derrick Brashear --- diff --git a/Makefile.in b/Makefile.in index d35f4a6f3..714f2f60b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -909,6 +909,7 @@ distclean: clean src/tests/auth/Makefile \ src/tools/Makefile \ src/tools/dumpscan/Makefile \ + src/tools/rxperf/Makefile \ src/tsalvaged/Makefile \ src/tsm41/Makefile \ src/tvolser/Makefile \ diff --git a/NTMakefile b/NTMakefile index 3d2de46b9..0f1fa1b6e 100644 --- a/NTMakefile +++ b/NTMakefile @@ -714,8 +714,15 @@ extra: afsrdr rpctestlib ! ELSE @echo ***** Skipping $@ ***** Not found. ! ENDIF - -finale: extra + +tools: extra + @echo ***** $@ + $(DOCD) $(SRC)\tools\rxperf + $(CD) $(SRC)\tools\rxperf + $(NTMAKE) + $(CD) ..\..\.. + +finale: tools @echo ***** $@ $(DOCD) $(SRC)\$@ $(CD) $(SRC)\$@ diff --git a/configure.ac b/configure.ac index 6d3dc5ce8..35c869435 100644 --- a/configure.ac +++ b/configure.ac @@ -229,6 +229,7 @@ src/tests/Makefile \ src/tests/run-tests \ src/tools/Makefile \ src/tools/dumpscan/Makefile \ +src/tools/rxperf/Makefile \ src/tsalvaged/Makefile \ src/tsm41/Makefile \ src/tvolser/Makefile \ diff --git a/src/config/NTMakefile b/src/config/NTMakefile index ff94d5c61..cefdaee5c 100644 --- a/src/config/NTMakefile +++ b/src/config/NTMakefile @@ -214,6 +214,12 @@ idirs: doclink ! IF (!EXIST($(OJT)\tvolser)) $(MKDIR) $(OJT)\tvolser ! ENDIF +! IF (!EXIST($(OJT)\tools)) + $(MKDIR) $(OJT)\tools +! ENDIF +! IF (!EXIST($(OJT)\tools\rxperf)) + $(MKDIR) $(OJT)\tools\rxperf +! ENDIF ! IF (!EXIST($(OJT)\dviced)) $(MKDIR) $(OJT)\dviced ! ENDIF diff --git a/src/rx/test/.gitignore b/src/rx/test/.gitignore index c99ab9962..f1fecd2eb 100644 --- a/src/rx/test/.gitignore +++ b/src/rx/test/.gitignore @@ -2,7 +2,6 @@ # git ls-files -i --exclude-standard # to check that you haven't inadvertently ignored any tracked files. -/rxperf /testclient /testserver /generator diff --git a/src/rx/test/NTMakefile b/src/rx/test/NTMakefile index 3fa8ed5da..38fa7df2e 100644 --- a/src/rx/test/NTMakefile +++ b/src/rx/test/NTMakefile @@ -25,15 +25,7 @@ LIBS = \ RXTESTOBJS = $(OUT)\testclient.obj $(OUT)\testserver.obj -tests: $(OUT)\rxperf.exe $(OUT)\testclient.exe $(OUT)\testserver.exe $(OUT)\tableGen.exe $(OUT)\generator.exe - -$(OUT)\rxperf.res: rxperf.rc AFS_component_version_number.h - -$(OUT)\rxperf.exe: $(OUT)\rxperf.obj $(OUT)\rxperf.res $(LIBS) - $(EXECONLINK) - $(_VC_MANIFEST_EMBED_EXE) - $(CODESIGN_USERLAND) - $(SYMSTORE_IMPORT) +tests: $(OUT)\testclient.exe $(OUT)\testserver.exe $(OUT)\tableGen.exe $(OUT)\generator.exe $(OUT)\testclient.exe: $(OUT)\testclient.obj $(LIBS) $(EXECONLINK) @@ -66,4 +58,4 @@ mkdir: install: tests clean:: - $(DEL) $(TESTS) $(OUT)\rxperf.res + $(DEL) $(TESTS) diff --git a/src/rx/test/rxperf.c b/src/rx/test/rxperf.c deleted file mode 100644 index 67f2418a2..000000000 --- a/src/rx/test/rxperf.c +++ /dev/null @@ -1,1222 +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 - -#ifdef HAVE_SYS_FILE_H -#include -#endif - -#include - -#include -#include -#include -#include - -#ifdef AFS_PTHREAD_ENV -#include -#define MAX_THREADS 128 -#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 1024 * 1024 -#define RXPERF_BUFSIZE 512 * 1024 - -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 RXPERF_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]; - -afs_int32 rxwrite_size = sizeof(somebuf); -afs_int32 rxread_size = sizeof(somebuf); -afs_int32 use_rx_readv = 0; - -static int -do_readbytes(struct rx_call *call, afs_int32 bytes) -{ - struct iovec tiov[RX_MAXIOVECS]; - afs_int32 size; - int tnio; - int code; - - while (bytes > 0) { - size = rxread_size; - - if (size > bytes) - size = bytes; - if (use_rx_readv) { - if (size > RX_MAX_PACKET_DATA_SIZE) - size = RX_MAX_PACKET_DATA_SIZE; - code = rx_Readv(call, tiov, &tnio, RX_MAXIOVECS, size); - } else - code = rx_Read(call, somebuf, size); - if (code != size) - return 1; - - bytes -= size; - } - return 0; -} - -static int -do_sendbytes(struct rx_call *call, afs_int32 bytes) -{ - afs_int32 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 afs_int32 -rxperf_ExecuteRequest(struct rx_call *call) -{ - afs_int32 version; - afs_int32 command; - afs_int32 bytes; - afs_int32 recvb; - afs_int32 sendb; - afs_int32 data; - afs_uint32 num; - afs_uint32 *readwrite; - afs_uint32 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)); - do_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 (do_readbytes(call, recvb)) { - warnx("do_readbytes failed"); - return -1; - } - DBFPRINT(("send(%d) ", sendb)); - if (do_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(afs_uint32)); - if (readwrite == NULL) - err(1, "malloc"); - - if (rx_Read(call, (char*)readwrite, num * sizeof(afs_uint32)) != - num * sizeof(afs_uint32)) - 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(afs_uint32); - - if (readp) { - DBFPRINT(("read\n")); - do_readbytes(call, bytes); - } else { - do_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)); - do_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(short port, int nojumbo, int maxmtu, int maxwsize, int minpeertimeout, - int udpbufsz, int nostats, int hotthread, - int minprocs, int maxprocs) -{ - struct rx_service *service; - struct rx_securityClass *secureobj; - int secureindex; - int ret; - -#ifdef AFS_NT40_ENV - if (afs_winsockInit() < 0) { - printf("Can't initialize winsock.\n"); - exit(1); - } -#endif - - if (hotthread) - rx_EnableHotThread(); - - if (nostats) - rx_enable_stats = 0; - - rx_SetUdpBufSize(udpbufsz); - - ret = rx_Init(htons(port)); - if (ret) - errx(1, "rx_Init failed"); - - if (nojumbo) - rx_SetNoJumbo(); - - if (maxmtu) - rx_SetMaxMTU(maxmtu); - - if (maxwsize) { - rx_SetMaxReceiveWindow(maxwsize); - rx_SetMaxSendWindow(maxwsize); - } - - if (minpeertimeout) - rx_SetMinPeerTimeout(minpeertimeout); - - - 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_SetMinProcs(service, minprocs); - rx_SetMaxProcs(service, maxprocs); - - rx_SetCheckReach(service, 1); - - rx_StartServer(1); - - abort(); -} - -/* - * - */ - -static void -readfile(const char *filename, afs_uint32 ** readwrite, afs_uint32 * size) -{ - FILE *f; - afs_uint32 len = 16; - afs_uint32 num = 0; - afs_uint32 data; - char *ptr; - char *buf; - - *readwrite = malloc(sizeof(afs_uint32) * len); - buf = malloc(RXPERF_BUFSIZE); - - 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(afs_uint32)); - 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"); - free(buf); -} - -struct client_data { - struct rx_connection *conn; - char *filename; - int command; - afs_int32 times; - afs_int32 bytes; - afs_int32 sendbytes; - afs_int32 readbytes; -}; - -static void * -client_thread( void *vparams) -{ - struct client_data *params = (struct client_data *)vparams; - struct rx_call *call; - afs_int32 data; - int i, j; - afs_uint32 *readwrite; - int readp = FALSE; - afs_uint32 size; - afs_uint32 num; - - for (i = 0; i < params->times; i++) { - - DBFPRINT(("starting command ")); - - call = rx_NewCall(params->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(params->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 (params->command) { - case RX_PERF_RECV: - DBFPRINT(("command ")); - - data = htonl(params->bytes); - if (rx_Write32(call, &data) != 4) - errx(1, "rx_Write failed to send size (err %d)", rx_Error(call)); - - DBFPRINT(("sending(%d) ", params->bytes)); - if (do_readbytes(call, params->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(params->bytes); - if (rx_Write32(call, &data) != 4) - errx(1, "rx_Write failed to send size (err %d)", rx_Error(call)); - - DBFPRINT(("sending(%d) ", params->bytes)); - if (do_sendbytes(call, params->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(params->sendbytes); - if (rx_Write32(call, &data) != 4) - errx(1, "rx_Write failed to send command (err %d)", rx_Error(call)); - - data = htonl(params->readbytes); - if (rx_Write32(call, &data) != 4) - errx(1, "rx_Write failed to send command (err %d)", rx_Error(call)); - - DBFPRINT(("send(%d) ", params->sendbytes)); - if (do_sendbytes(call, params->sendbytes)) - errx(1, "sendbytes (err %d)", rx_Error(call)); - - DBFPRINT(("recv(%d) ", params->readbytes)); - if (do_readbytes(call, params->readbytes)) - 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_FILE: - readfile(params->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, (char *)readwrite, num * sizeof(afs_uint32)) - != num * sizeof(afs_uint32)) - errx(1, "rx_Write failed to send list (err %d)", rx_Error(call)); - - for (j = 0; j < num; j++) { - if (readwrite[j] == 0) - readp = !readp; - - size = ntohl(readwrite[j]) * sizeof(afs_uint32); - - if (readp) { - if (do_readbytes(call, size)) - errx(1, "sendbytes (err %d)", rx_Error(call)); - DBFPRINT(("read\n")); - } else { - if (do_sendbytes(call, size)) - errx(1, "sendbytes (err %d)", rx_Error(call)); - DBFPRINT(("send\n")); - } - } - break; - default: - abort(); - } - - rx_EndCall(call, 0); - } - -#ifdef AFS_PTHREAD_ENV - pthread_exit(NULL); -#endif - - return NULL; -} - -/* - * - */ - -static void -do_client(const char *server, short port, char *filename, afs_int32 command, - afs_int32 times, afs_int32 bytes, afs_int32 sendbytes, afs_int32 readbytes, - int dumpstats, int nojumbo, int maxmtu, int maxwsize, int minpeertimeout, - int udpbufsz, int nostats, int hotthread, int threads) -{ - struct rx_connection *conn; - afs_uint32 addr; - struct rx_securityClass *secureobj; - int secureindex; - int ret; - char stamp[2048]; - struct client_data *params; - -#ifdef AFS_PTHREAD_ENV - int i; - pthread_t thread[MAX_THREADS]; - pthread_attr_t tattr; - void *status; -#endif - - params = malloc(sizeof(struct client_data)); - memset(params, 0, sizeof(struct client_data)); - -#ifdef AFS_NT40_ENV - if (afs_winsockInit() < 0) { - printf("Can't initialize winsock.\n"); - exit(1); - } -#endif - - if (hotthread) - rx_EnableHotThread(); - - if (nostats) - rx_enable_stats = 0; - - addr = str2addr(server); - - rx_SetUdpBufSize(udpbufsz); - - ret = rx_Init(0); - if (ret) - errx(1, "rx_Init failed"); - - if (nojumbo) - rx_SetNoJumbo(); - - if (maxmtu) - rx_SetMaxMTU(maxmtu); - - if (maxwsize) { - rx_SetMaxReceiveWindow(maxwsize); - rx_SetMaxSendWindow(maxwsize); - } - - if (minpeertimeout) - rx_SetMinPeerTimeout(minpeertimeout); - - - get_sec(0, &secureobj, &secureindex); - - switch (command) { - case RX_PERF_RPC: - sprintf(stamp, "RPC: threads\t%d, times\t%d, write bytes\t%d, read bytes\t%d", - threads, times, sendbytes, readbytes); - break; - case RX_PERF_RECV: - sprintf(stamp, "RECV: threads\t%d, times\t%d, bytes\t%d", - threads, times, bytes); - break; - case RX_PERF_SEND: - sprintf(stamp, "SEND: threads\t%d, times\t%d, bytes\t%d", - threads, times, bytes); - break; - case RX_PERF_FILE: - sprintf(stamp, "FILE %s: threads\t%d, times\t%d, bytes\t%d", - filename, threads, times, bytes); - break; - } - - conn = rx_NewConnection(addr, htons(port), RX_SERVER_ID, secureobj, secureindex); - if (conn == NULL) - errx(1, "failed to contact server"); - -#ifdef AFS_PTHREAD_ENV - pthread_attr_init(&tattr); - pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE); -#endif - - params->conn = conn; - params->filename = filename; - params->command = command; - params->times = times; - params->bytes = bytes; - params->sendbytes = sendbytes; - params->readbytes = readbytes; - - start_timer(); - -#ifdef AFS_PTHREAD_ENV - for ( i=0; iconn = conn; - params = new_params; - } - } - } -#else - client_thread(params); -#endif - -#ifdef AFS_PTHREAD_ENV - for ( i=0; i\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) -{ - short port = DEFAULT_PORT; - int nojumbo = 0; - int maxmtu = 0; - int nostats = 0; - int udpbufsz = 64 * 1024; - int hotthreads = 0; - int minprocs = 2; - int maxprocs = 20; - int maxwsize = 0; - int minpeertimeout = 0; - char *ptr; - int ch; - - while ((ch = getopt(argc, argv, "r:d:p:P:w:W:HNjm:u:4:s:S:V")) != -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) (%"AFS_SIZET_FMT")", rxread_size, - sizeof(somebuf)); - break; - case 's': - minprocs = strtol(optarg, &ptr, 0); - if (ptr != 0 && ptr[0] != '\0') - errx(1, "can't resolve minprocs"); - break; - case 'S': - maxprocs = strtol(optarg, &ptr, 0); - if (ptr != 0 && ptr[0] != '\0') - errx(1, "can't resolve maxprocs"); - break; - case 'P': - minpeertimeout = strtol(optarg, &ptr, 0); - if (ptr != 0 && ptr[0] != '\0') - errx(1, "can't resolve min peer timeout"); - break; - case 'p': - port = (short) 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) (%"AFS_SIZET_FMT")", rxwrite_size, - sizeof(somebuf)); - break; - case 'j': - nojumbo=1; - break; - case 'N': - nostats=1; - break; - case 'H': - hotthreads = 1; - break; - case 'm': - maxmtu = strtol(optarg, &ptr, 0); - if (ptr && *ptr != '\0') - errx(1, "can't resolve rx maxmtu to use"); - break; - case 'u': - udpbufsz = strtol(optarg, &ptr, 0) * 1024; - if (ptr && *ptr != '\0') - errx(1, "can't resolve upd buffer size (Kbytes)"); - break; - case 'V': - use_rx_readv = 1; - break; - case 'W': - maxwsize = strtol(optarg, &ptr, 0); - if (ptr && *ptr != '\0') - errx(1, "can't resolve max send/recv window size (packets)"); - break; - case '4': - RX_IPUDP_SIZE = 28; - break; - default: - usage(); - } - } - - if (optind != argc) - usage(); - - do_server(port, nojumbo, maxmtu, maxwsize, minpeertimeout, udpbufsz, - nostats, hotthreads, minprocs, maxprocs); - - 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; - short port = DEFAULT_PORT; - char *filename = NULL; - afs_int32 cmd; - int sendbytes = 3; - int readbytes = 30; - int times = 100; - int dumpstats = 0; - int nojumbo = 0; - int nostats = 0; - int maxmtu = 0; - int hotthreads = 0; - int threads = 1; - int udpbufsz = 64 * 1024; - int maxwsize = 0; - int minpeertimeout = 0; - char *ptr; - int ch; - - cmd = RX_PERF_UNKNOWN; - - while ((ch = getopt(argc, argv, "T:S:R:b:c:d:p:P:r:s:w:W:f:HDNjm:u:4:t:V")) != -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': - minpeertimeout = strtol(optarg, &ptr, 0); - if (ptr != 0 && ptr[0] != '\0') - errx(1, "can't resolve min peer timeout"); - break; - case 'p': - port = (short) 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) (%"AFS_SIZET_FMT")", rxread_size, - sizeof(somebuf)); - break; - case 's': - host = strdup(optarg); - if (host == NULL) - err(1, "strdup"); - break; - case 'V': - use_rx_readv = 1; - 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) (%"AFS_SIZET_FMT")", rxwrite_size, - sizeof(somebuf)); - break; - case 'W': - maxwsize = strtol(optarg, &ptr, 0); - if (ptr && *ptr != '\0') - errx(1, "can't resolve max send/recv window size (packets)"); - break; - case 'T': - times = strtol(optarg, &ptr, 0); - if (ptr && *ptr != '\0') - errx(1, "can't resolve number of times to execute rpc"); - break; - case 'S': - sendbytes = strtol(optarg, &ptr, 0); - if (ptr && *ptr != '\0') - errx(1, "can't resolve number of bytes to send"); - break; - case 'R': - readbytes = strtol(optarg, &ptr, 0); - if (ptr && *ptr != '\0') - errx(1, "can't resolve number of bytes to receive"); - break; - case 't': -#ifdef AFS_PTHREAD_ENV - threads = strtol(optarg, &ptr, 0); - if (ptr && *ptr != '\0') - errx(1, "can't resolve number of threads to execute"); - if (threads > MAX_THREADS) - errx(1, "too many threads"); -#else - errx(1, "Not built for pthreads"); -#endif - break; - case 'f': - filename = optarg; - break; - case 'D': - dumpstats = 1; - break; - case 'N': - nostats = 1; - break; - case 'H': - hotthreads = 1; - 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 'u': - udpbufsz = strtol(optarg, &ptr, 0) * 1024; - if (ptr && *ptr != '\0') - errx(1, "can't resolve upd buffer size (Kbytes)"); - break; - case '4': - RX_IPUDP_SIZE = 28; - break; - default: - usage(); - } - } - - if (nostats && dumpstats) - errx(1, "cannot set both -N and -D"); - - if (threads > 1 && cmd == RX_PERF_FILE) - errx(1, "cannot use multiple threads with file command"); - - if (optind != argc) - usage(); - - if (cmd == RX_PERF_UNKNOWN) - errx(1, "no command given to the client"); - - do_client(host, port, filename, cmd, times, bytes, sendbytes, - readbytes, dumpstats, nojumbo, maxmtu, maxwsize, minpeertimeout, - udpbufsz, nostats, hotthreads, threads); - - return 0; -} - -/* - * setup world and call cmd - */ - -int -main(int argc, char **argv) -{ -#ifndef AFS_PTHREAD_ENV - PROCESS pid; -#endif - - __progname = strrchr(argv[0], '/'); - if (__progname == 0) - __progname = argv[0]; - -#ifndef AFS_NT40_ENV - signal(SIGUSR1, sigusr1); - signal(SIGINT, sigint); -#endif - -#ifndef AFS_PTHREAD_ENV - LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY, &pid); -#endif - - 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/rxperf.rc b/src/rx/test/rxperf.rc deleted file mode 100644 index ea52ab85f..000000000 --- a/src/rx/test/rxperf.rc +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2000, International Business Machines Corporation and others. - * All Rights Reserved. - * - * This software has been released under the terms of the IBM Public - * License. For details, see the LICENSE file in the top-level source - * directory or online at http://www.openafs.org/dl/license10.html - */ - -/* Define VERSIONINFO resource */ - -#define AFS_VERINFO_FILE_DESCRIPTION "RX Performance Test (pthread)" -#define AFS_VERINFO_NAME "rxperf" -#define AFS_VERINFO_FILENAME "rxperf.exe" - -#include "AFS_component_version_number.h" -#include "..\..\config\NTVersioninfo.rc" diff --git a/src/tools/Makefile.in b/src/tools/Makefile.in index d61a947c3..45da45a1d 100644 --- a/src/tools/Makefile.in +++ b/src/tools/Makefile.in @@ -1,6 +1,6 @@ srcdir=@srcdir@ -SUBDIRS=dumpscan +SUBDIRS=dumpscan rxperf all dest install clean distclean: @for A in $(SUBDIRS); do cd $$A && $(MAKE) $@ && cd .. || exit 1; done diff --git a/src/tools/rxperf/.gitignore b/src/tools/rxperf/.gitignore new file mode 100644 index 000000000..5a2f4656e --- /dev/null +++ b/src/tools/rxperf/.gitignore @@ -0,0 +1,5 @@ +# After changing this file, please run +# git ls-files -i --exclude-standard +# to check that you haven't inadvertently ignored any tracked files. + +/rxperf diff --git a/src/tools/rxperf/Makefile.in b/src/tools/rxperf/Makefile.in new file mode 100644 index 000000000..ca9943010 --- /dev/null +++ b/src/tools/rxperf/Makefile.in @@ -0,0 +1,20 @@ +srcdir=@srcdir@ + +include @TOP_OBJDIR@/src/config/Makefile.config +include @TOP_OBJDIR@/src/config/Makefile.pthread + +LIBS= $(TOP_LIBDIR)/libafsrpc.a \ + $(TOP_LIBDIR)/libopr.a + +all: rxperf + +rxperf: rxperf.o $(LIBS) + $(AFS_LDRULE) rxperf.o $(LIBS) $(LIB_hcrypto) $(LIB_roken) \ + $(MT_LIBS) $(XLIBS) + +install: + +dest: + +clean: + $(RM) -f rxperf.o rxperf diff --git a/src/tools/rxperf/NTMakefile b/src/tools/rxperf/NTMakefile new file mode 100644 index 000000000..3f79180b4 --- /dev/null +++ b/src/tools/rxperf/NTMakefile @@ -0,0 +1,41 @@ +# Copyright 2000, International Business Machines Corporation and others. +# All Rights Reserved. +# +# This software has been released under the terms of the IBM Public +# License. For details, see the LICENSE file in the top-level source +# directory or online at http://www.openafs.org/dl/license10.html + +AFSDEV_AUXCDEFINES = -DAFS_PTHREAD_ENV -DHAVE_WARNX -DHAVE_ERRX -DHAVE_WARN -DHAVE_ERR +!IF ("$(AFSDEV_BUILDTYPE)" == "CHECKED") +AFSDEV_AUXCDEFINES = $(AFSDEV_AUXCDEFINES) -DRXDEBUG +!ENDIF + +RELDIR=tools/rxperf +!INCLUDE ..\..\config\NTMakefile.$(SYS_NAME) +!INCLUDE ..\..\config\NTMakefile.version + +LIBS = \ + $(DESTDIR)\lib\afs\afsreg.lib \ + $(DESTDIR)\lib\afs\mtafsutil.lib \ + $(DESTDIR)\lib\afsrpc.lib \ + $(DESTDIR)\lib\afspthread.lib \ + $(DESTDIR)\lib\afsroken.lib \ + $(DESTDIR)\lib\opr.lib + + +all: $(OUT)\rxperf.exe + +$(OUT)\rxperf.res: rxperf.rc AFS_component_version_number.h + +$(OUT)\rxperf.exe: $(OUT)\rxperf.obj $(OUT)\rxperf.res $(LIBS) + $(EXECONLINK) + $(_VC_MANIFEST_EMBED_EXE) + $(CODESIGN_USERLAND) + $(SYMSTORE_IMPORT) + +mkdir: + +install: all + +clean:: + $(DEL) $(OUT)\rxperf.res diff --git a/src/tools/rxperf/rxperf.c b/src/tools/rxperf/rxperf.c new file mode 100644 index 000000000..3367fd290 --- /dev/null +++ b/src/tools/rxperf/rxperf.c @@ -0,0 +1,1150 @@ +/* + * 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 + +#ifdef HAVE_SYS_FILE_H +#include +#endif + +#include + +#include +#include +#include +#include + +#ifdef AFS_PTHREAD_ENV +#include +#define MAX_THREADS 128 +#endif + +#define DEFAULT_PORT 7009 /* To match tcpdump */ +#define DEFAULT_HOST "127.0.0.1" +#define DEFAULT_BYTES 1024 * 1024 +#define RXPERF_BUFSIZE 512 * 1024 + +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 RXPERF_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]; + +afs_int32 rxwrite_size = sizeof(somebuf); +afs_int32 rxread_size = sizeof(somebuf); +afs_int32 use_rx_readv = 0; + +static int +do_readbytes(struct rx_call *call, afs_int32 bytes) +{ + struct iovec tiov[RX_MAXIOVECS]; + afs_int32 size; + int tnio; + int code; + + while (bytes > 0) { + size = rxread_size; + + if (size > bytes) + size = bytes; + if (use_rx_readv) { + if (size > RX_MAX_PACKET_DATA_SIZE) + size = RX_MAX_PACKET_DATA_SIZE; + code = rx_Readv(call, tiov, &tnio, RX_MAXIOVECS, size); + } else + code = rx_Read(call, somebuf, size); + if (code != size) + return 1; + + bytes -= size; + } + return 0; +} + +static int +do_sendbytes(struct rx_call *call, afs_int32 bytes) +{ + afs_int32 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 afs_int32 +rxperf_ExecuteRequest(struct rx_call *call) +{ + afs_int32 version; + afs_int32 command; + afs_int32 bytes; + afs_int32 recvb; + afs_int32 sendb; + afs_int32 data; + afs_uint32 num; + afs_uint32 *readwrite; + afs_uint32 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)); + do_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 (do_readbytes(call, recvb)) { + warnx("do_readbytes failed"); + return -1; + } + DBFPRINT(("send(%d) ", sendb)); + if (do_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(afs_uint32)); + if (readwrite == NULL) + err(1, "malloc"); + + if (rx_Read(call, (char*)readwrite, num * sizeof(afs_uint32)) != + num * sizeof(afs_uint32)) + 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(afs_uint32); + + if (readp) { + DBFPRINT(("read\n")); + do_readbytes(call, bytes); + } else { + do_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)); + do_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(short port, int nojumbo, int maxmtu, int maxwsize, int minpeertimeout, + int udpbufsz, int nostats, int hotthread, + int minprocs, int maxprocs) +{ + struct rx_service *service; + struct rx_securityClass *secureobj; + int secureindex; + int ret; + +#ifdef AFS_NT40_ENV + if (afs_winsockInit() < 0) { + printf("Can't initialize winsock.\n"); + exit(1); + } +#endif + + if (hotthread) + rx_EnableHotThread(); + + if (nostats) + rx_enable_stats = 0; + + rx_SetUdpBufSize(udpbufsz); + + ret = rx_Init(htons(port)); + if (ret) + errx(1, "rx_Init failed"); + + if (nojumbo) + rx_SetNoJumbo(); + + if (maxmtu) + rx_SetMaxMTU(maxmtu); + + if (maxwsize) { + rx_SetMaxReceiveWindow(maxwsize); + rx_SetMaxSendWindow(maxwsize); + } + + if (minpeertimeout) + rx_SetMinPeerTimeout(minpeertimeout); + + + 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_SetMinProcs(service, minprocs); + rx_SetMaxProcs(service, maxprocs); + + rx_SetCheckReach(service, 1); + + rx_StartServer(1); + + abort(); +} + +/* + * + */ + +static void +readfile(const char *filename, afs_uint32 ** readwrite, afs_uint32 * size) +{ + FILE *f; + afs_uint32 len = 16; + afs_uint32 num = 0; + afs_uint32 data; + char *ptr; + char *buf; + + *readwrite = malloc(sizeof(afs_uint32) * len); + buf = malloc(RXPERF_BUFSIZE); + + 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(afs_uint32)); + 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"); + free(buf); +} + +struct client_data { + struct rx_connection *conn; + char *filename; + int command; + afs_int32 times; + afs_int32 bytes; + afs_int32 sendbytes; + afs_int32 readbytes; +}; + +static void * +client_thread( void *vparams) +{ + struct client_data *params = (struct client_data *)vparams; + struct rx_call *call; + afs_int32 data; + int i, j; + afs_uint32 *readwrite; + int readp = FALSE; + afs_uint32 size; + afs_uint32 num; + + for (i = 0; i < params->times; i++) { + + DBFPRINT(("starting command ")); + + call = rx_NewCall(params->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(params->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 (params->command) { + case RX_PERF_RECV: + DBFPRINT(("command ")); + + data = htonl(params->bytes); + if (rx_Write32(call, &data) != 4) + errx(1, "rx_Write failed to send size (err %d)", rx_Error(call)); + + DBFPRINT(("sending(%d) ", params->bytes)); + if (do_readbytes(call, params->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(params->bytes); + if (rx_Write32(call, &data) != 4) + errx(1, "rx_Write failed to send size (err %d)", rx_Error(call)); + + DBFPRINT(("sending(%d) ", params->bytes)); + if (do_sendbytes(call, params->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(params->sendbytes); + if (rx_Write32(call, &data) != 4) + errx(1, "rx_Write failed to send command (err %d)", rx_Error(call)); + + data = htonl(params->readbytes); + if (rx_Write32(call, &data) != 4) + errx(1, "rx_Write failed to send command (err %d)", rx_Error(call)); + + DBFPRINT(("send(%d) ", params->sendbytes)); + if (do_sendbytes(call, params->sendbytes)) + errx(1, "sendbytes (err %d)", rx_Error(call)); + + DBFPRINT(("recv(%d) ", params->readbytes)); + if (do_readbytes(call, params->readbytes)) + 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_FILE: + readfile(params->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, (char *)readwrite, num * sizeof(afs_uint32)) + != num * sizeof(afs_uint32)) + errx(1, "rx_Write failed to send list (err %d)", rx_Error(call)); + + for (j = 0; j < num; j++) { + if (readwrite[j] == 0) + readp = !readp; + + size = ntohl(readwrite[j]) * sizeof(afs_uint32); + + if (readp) { + if (do_readbytes(call, size)) + errx(1, "sendbytes (err %d)", rx_Error(call)); + DBFPRINT(("read\n")); + } else { + if (do_sendbytes(call, size)) + errx(1, "sendbytes (err %d)", rx_Error(call)); + DBFPRINT(("send\n")); + } + } + break; + default: + abort(); + } + + rx_EndCall(call, 0); + } + +#ifdef AFS_PTHREAD_ENV + pthread_exit(NULL); +#endif + + return NULL; +} + +/* + * + */ + +static void +do_client(const char *server, short port, char *filename, afs_int32 command, + afs_int32 times, afs_int32 bytes, afs_int32 sendbytes, afs_int32 readbytes, + int dumpstats, int nojumbo, int maxmtu, int maxwsize, int minpeertimeout, + int udpbufsz, int nostats, int hotthread, int threads) +{ + struct rx_connection *conn; + afs_uint32 addr; + struct rx_securityClass *secureobj; + int secureindex; + int ret; + char stamp[2048]; + struct client_data *params; + +#ifdef AFS_PTHREAD_ENV + int i; + pthread_t thread[MAX_THREADS]; + pthread_attr_t tattr; + void *status; +#endif + + params = malloc(sizeof(struct client_data)); + memset(params, 0, sizeof(struct client_data)); + +#ifdef AFS_NT40_ENV + if (afs_winsockInit() < 0) { + printf("Can't initialize winsock.\n"); + exit(1); + } +#endif + + if (hotthread) + rx_EnableHotThread(); + + if (nostats) + rx_enable_stats = 0; + + addr = str2addr(server); + + rx_SetUdpBufSize(udpbufsz); + + ret = rx_Init(0); + if (ret) + errx(1, "rx_Init failed"); + + if (nojumbo) + rx_SetNoJumbo(); + + if (maxmtu) + rx_SetMaxMTU(maxmtu); + + if (maxwsize) { + rx_SetMaxReceiveWindow(maxwsize); + rx_SetMaxSendWindow(maxwsize); + } + + if (minpeertimeout) + rx_SetMinPeerTimeout(minpeertimeout); + + + get_sec(0, &secureobj, &secureindex); + + switch (command) { + case RX_PERF_RPC: + sprintf(stamp, "RPC: threads\t%d, times\t%d, write bytes\t%d, read bytes\t%d", + threads, times, sendbytes, readbytes); + break; + case RX_PERF_RECV: + sprintf(stamp, "RECV: threads\t%d, times\t%d, bytes\t%d", + threads, times, bytes); + break; + case RX_PERF_SEND: + sprintf(stamp, "SEND: threads\t%d, times\t%d, bytes\t%d", + threads, times, bytes); + break; + case RX_PERF_FILE: + sprintf(stamp, "FILE %s: threads\t%d, times\t%d, bytes\t%d", + filename, threads, times, bytes); + break; + } + + conn = rx_NewConnection(addr, htons(port), RX_SERVER_ID, secureobj, secureindex); + if (conn == NULL) + errx(1, "failed to contact server"); + +#ifdef AFS_PTHREAD_ENV + pthread_attr_init(&tattr); + pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE); +#endif + + params->conn = conn; + params->filename = filename; + params->command = command; + params->times = times; + params->bytes = bytes; + params->sendbytes = sendbytes; + params->readbytes = readbytes; + + start_timer(); + +#ifdef AFS_PTHREAD_ENV + for ( i=0; iconn = conn; + params = new_params; + } + } + } +#else + client_thread(params); +#endif + +#ifdef AFS_PTHREAD_ENV + for ( i=0; i\n", getprogname()); + fprintf(stderr, "usage: %s client -c recv -b \n", getprogname()); + fprintf(stderr, + "usage: %s client -c rpc -S -R \n", + getprogname()); + fprintf(stderr, "usage: %s client -c file -f filename\n", getprogname()); + fprintf(stderr, + "%s: usage: common option to the client " + "-w -r -T times -p port -s server -D\n", + getprogname()); + fprintf(stderr, "usage: %s server -p port\n", getprogname()); +#undef COMMMON + exit(1); +} + + + +/* + * do argument processing and call networking functions + */ + +static int +rxperf_server(int argc, char **argv) +{ + short port = DEFAULT_PORT; + int nojumbo = 0; + int maxmtu = 0; + int nostats = 0; + int udpbufsz = 64 * 1024; + int hotthreads = 0; + int minprocs = 2; + int maxprocs = 20; + int maxwsize = 0; + int minpeertimeout = 0; + char *ptr; + int ch; + + while ((ch = getopt(argc, argv, "r:d:p:P:w:W:HNjm:u:4:s:S:V")) != -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) (%"AFS_SIZET_FMT")", rxread_size, + sizeof(somebuf)); + break; + case 's': + minprocs = strtol(optarg, &ptr, 0); + if (ptr != 0 && ptr[0] != '\0') + errx(1, "can't resolve minprocs"); + break; + case 'S': + maxprocs = strtol(optarg, &ptr, 0); + if (ptr != 0 && ptr[0] != '\0') + errx(1, "can't resolve maxprocs"); + break; + case 'P': + minpeertimeout = strtol(optarg, &ptr, 0); + if (ptr != 0 && ptr[0] != '\0') + errx(1, "can't resolve min peer timeout"); + break; + case 'p': + port = (short) 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) (%"AFS_SIZET_FMT")", rxwrite_size, + sizeof(somebuf)); + break; + case 'j': + nojumbo=1; + break; + case 'N': + nostats=1; + break; + case 'H': + hotthreads = 1; + break; + case 'm': + maxmtu = strtol(optarg, &ptr, 0); + if (ptr && *ptr != '\0') + errx(1, "can't resolve rx maxmtu to use"); + break; + case 'u': + udpbufsz = strtol(optarg, &ptr, 0) * 1024; + if (ptr && *ptr != '\0') + errx(1, "can't resolve upd buffer size (Kbytes)"); + break; + case 'V': + use_rx_readv = 1; + break; + case 'W': + maxwsize = strtol(optarg, &ptr, 0); + if (ptr && *ptr != '\0') + errx(1, "can't resolve max send/recv window size (packets)"); + break; + case '4': + RX_IPUDP_SIZE = 28; + break; + default: + usage(); + } + } + + if (optind != argc) + usage(); + + do_server(port, nojumbo, maxmtu, maxwsize, minpeertimeout, udpbufsz, + nostats, hotthreads, minprocs, maxprocs); + + 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; + short port = DEFAULT_PORT; + char *filename = NULL; + afs_int32 cmd; + int sendbytes = 3; + int readbytes = 30; + int times = 100; + int dumpstats = 0; + int nojumbo = 0; + int nostats = 0; + int maxmtu = 0; + int hotthreads = 0; + int threads = 1; + int udpbufsz = 64 * 1024; + int maxwsize = 0; + int minpeertimeout = 0; + char *ptr; + int ch; + + cmd = RX_PERF_UNKNOWN; + + while ((ch = getopt(argc, argv, "T:S:R:b:c:d:p:P:r:s:w:W:f:HDNjm:u:4:t:V")) != -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': + minpeertimeout = strtol(optarg, &ptr, 0); + if (ptr != 0 && ptr[0] != '\0') + errx(1, "can't resolve min peer timeout"); + break; + case 'p': + port = (short) 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) (%"AFS_SIZET_FMT")", rxread_size, + sizeof(somebuf)); + break; + case 's': + host = strdup(optarg); + if (host == NULL) + err(1, "strdup"); + break; + case 'V': + use_rx_readv = 1; + 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) (%"AFS_SIZET_FMT")", rxwrite_size, + sizeof(somebuf)); + break; + case 'W': + maxwsize = strtol(optarg, &ptr, 0); + if (ptr && *ptr != '\0') + errx(1, "can't resolve max send/recv window size (packets)"); + break; + case 'T': + times = strtol(optarg, &ptr, 0); + if (ptr && *ptr != '\0') + errx(1, "can't resolve number of times to execute rpc"); + break; + case 'S': + sendbytes = strtol(optarg, &ptr, 0); + if (ptr && *ptr != '\0') + errx(1, "can't resolve number of bytes to send"); + break; + case 'R': + readbytes = strtol(optarg, &ptr, 0); + if (ptr && *ptr != '\0') + errx(1, "can't resolve number of bytes to receive"); + break; + case 't': +#ifdef AFS_PTHREAD_ENV + threads = strtol(optarg, &ptr, 0); + if (ptr && *ptr != '\0') + errx(1, "can't resolve number of threads to execute"); + if (threads > MAX_THREADS) + errx(1, "too many threads"); +#else + errx(1, "Not built for pthreads"); +#endif + break; + case 'f': + filename = optarg; + break; + case 'D': + dumpstats = 1; + break; + case 'N': + nostats = 1; + break; + case 'H': + hotthreads = 1; + 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 'u': + udpbufsz = strtol(optarg, &ptr, 0) * 1024; + if (ptr && *ptr != '\0') + errx(1, "can't resolve upd buffer size (Kbytes)"); + break; + case '4': + RX_IPUDP_SIZE = 28; + break; + default: + usage(); + } + } + + if (nostats && dumpstats) + errx(1, "cannot set both -N and -D"); + + if (threads > 1 && cmd == RX_PERF_FILE) + errx(1, "cannot use multiple threads with file command"); + + if (optind != argc) + usage(); + + if (cmd == RX_PERF_UNKNOWN) + errx(1, "no command given to the client"); + + do_client(host, port, filename, cmd, times, bytes, sendbytes, + readbytes, dumpstats, nojumbo, maxmtu, maxwsize, minpeertimeout, + udpbufsz, nostats, hotthreads, threads); + + return 0; +} + +/* + * setup world and call cmd + */ + +int +main(int argc, char **argv) +{ +#ifndef AFS_PTHREAD_ENV + PROCESS pid; +#endif + + setprogname(argv[0]); + +#ifndef AFS_NT40_ENV + signal(SIGUSR1, sigusr1); + signal(SIGINT, sigint); +#endif + +#ifndef AFS_PTHREAD_ENV + LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY, &pid); +#endif + + 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/tools/rxperf/rxperf.rc b/src/tools/rxperf/rxperf.rc new file mode 100644 index 000000000..ea52ab85f --- /dev/null +++ b/src/tools/rxperf/rxperf.rc @@ -0,0 +1,17 @@ +/* + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + */ + +/* Define VERSIONINFO resource */ + +#define AFS_VERINFO_FILE_DESCRIPTION "RX Performance Test (pthread)" +#define AFS_VERINFO_NAME "rxperf" +#define AFS_VERINFO_FILENAME "rxperf.exe" + +#include "AFS_component_version_number.h" +#include "..\..\config\NTVersioninfo.rc"