+++ /dev/null
-Bottom: 2a1d1a24a767c8fd0bc9fda9532541008404ecc6
-Top: cf8998b9f06f893b499b9478f40610fb02b1993a
-Author: Sean Hefty <sean.hefty@intel.com>
-Date: 2012-12-05 15:58:03 -0800
-
-examples/udpong: Add test program for rsocket datagrams
-
-Add a sample test program to test datagram rsockets. Move
-common routines used by udpong and other test programs into
-a common source file.
-
-Signed-off-by: Sean Hefty <sean.hefty@intel.com>
-
-
----
-
-diff --git a/Makefile.am b/Makefile.am
-index d72016d..3198165 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -29,7 +29,7 @@ src_librspreload_la_LIBADD = $(top_builddir)/src/librdmacm.la
- bin_PROGRAMS = examples/ucmatose examples/rping examples/udaddy examples/mckey \
- examples/rdma_client examples/rdma_server examples/rdma_xclient \
- examples/rdma_xserver examples/rstream examples/rcopy \
-- examples/riostream
-+ examples/riostream examples/udpong
- examples_ucmatose_SOURCES = examples/cmatose.c examples/common.c
- examples_ucmatose_LDADD = $(top_builddir)/src/librdmacm.la
- examples_rping_SOURCES = examples/rping.c
-@@ -46,12 +46,14 @@ examples_rdma_xclient_SOURCES = examples/rdma_xclient.c
- examples_rdma_xclient_LDADD = $(top_builddir)/src/librdmacm.la
- examples_rdma_xserver_SOURCES = examples/rdma_xserver.c
- examples_rdma_xserver_LDADD = $(top_builddir)/src/librdmacm.la
--examples_rstream_SOURCES = examples/rstream.c
-+examples_rstream_SOURCES = examples/rstream.c examples/common.c
- examples_rstream_LDADD = $(top_builddir)/src/librdmacm.la
--examples_riostream_SOURCES = examples/riostream.c
-+examples_riostream_SOURCES = examples/riostream.c examples/common.c
- examples_riostream_LDADD = $(top_builddir)/src/librdmacm.la
- examples_rcopy_SOURCES = examples/rcopy.c
- examples_rcopy_LDADD = $(top_builddir)/src/librdmacm.la
-+examples_udpong_SOURCES = examples/udpong.c examples/common.c
-+examples_udpong_LDADD = $(top_builddir)/src/librdmacm.la
-
- librdmacmincludedir = $(includedir)/rdma
- infinibandincludedir = $(includedir)/infiniband
-diff --git a/examples/common.c b/examples/common.c
-index 3eeb1e9..939f50c 100644
---- a/examples/common.c
-+++ b/examples/common.c
-@@ -45,6 +45,8 @@
- #include <rdma/rdma_cma.h>
- #include "common.h"
-
-+int use_rs = 1;
-+
- int get_rdma_addr(char *src, char *dst, char *port,
- struct rdma_addrinfo *hints, struct rdma_addrinfo **rai)
- {
-@@ -72,3 +74,94 @@ int get_rdma_addr(char *src, char *dst, char *port,
-
- return ret;
- }
-+
-+void size_str(char *str, size_t ssize, long long size)
-+{
-+ long long base, fraction = 0;
-+ char mag;
-+
-+ if (size >= (1 << 30)) {
-+ base = 1 << 30;
-+ mag = 'g';
-+ } else if (size >= (1 << 20)) {
-+ base = 1 << 20;
-+ mag = 'm';
-+ } else if (size >= (1 << 10)) {
-+ base = 1 << 10;
-+ mag = 'k';
-+ } else {
-+ base = 1;
-+ mag = '\0';
-+ }
-+
-+ if (size / base < 10)
-+ fraction = (size % base) * 10 / base;
-+ if (fraction) {
-+ snprintf(str, ssize, "%lld.%lld%c", size / base, fraction, mag);
-+ } else {
-+ snprintf(str, ssize, "%lld%c", size / base, mag);
-+ }
-+}
-+
-+void cnt_str(char *str, size_t ssize, long long cnt)
-+{
-+ if (cnt >= 1000000000)
-+ snprintf(str, ssize, "%lldb", cnt / 1000000000);
-+ else if (cnt >= 1000000)
-+ snprintf(str, ssize, "%lldm", cnt / 1000000);
-+ else if (cnt >= 1000)
-+ snprintf(str, ssize, "%lldk", cnt / 1000);
-+ else
-+ snprintf(str, ssize, "%lld", cnt);
-+}
-+
-+int size_to_count(int size)
-+{
-+ if (size >= 1000000)
-+ return 100;
-+ else if (size >= 100000)
-+ return 1000;
-+ else if (size >= 10000)
-+ return 10000;
-+ else if (size >= 1000)
-+ return 100000;
-+ else
-+ return 1000000;
-+}
-+
-+void format_buf(void *buf, int size)
-+{
-+ uint8_t *array = buf;
-+ static uint8_t data;
-+ int i;
-+
-+ for (i = 0; i < size; i++)
-+ array[i] = data++;
-+}
-+
-+int verify_buf(void *buf, int size)
-+{
-+ static long long total_bytes;
-+ uint8_t *array = buf;
-+ static uint8_t data;
-+ int i;
-+
-+ for (i = 0; i < size; i++, total_bytes++) {
-+ if (array[i] != data++) {
-+ printf("data verification failed byte %lld\n", total_bytes);
-+ return -1;
-+ }
-+ }
-+ return 0;
-+}
-+
-+int do_poll(struct pollfd *fds, int timeout)
-+{
-+ int ret;
-+
-+ do {
-+ ret = rs_poll(fds, 1, timeout);
-+ } while (!ret);
-+
-+ return ret == 1 ? 0 : ret;
-+}
-diff --git a/examples/common.h b/examples/common.h
-index 8d9fea0..7cf16d2 100644
---- a/examples/common.h
-+++ b/examples/common.h
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (c) 2005-2011 Intel Corporation. All rights reserved.
-+ * Copyright (c) 2005-2012 Intel Corporation. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses. You may choose to be licensed under the terms of the GNU
-@@ -35,8 +35,10 @@
- #include <stdlib.h>
- #include <sys/types.h>
- #include <byteswap.h>
-+#include <poll.h>
-
- #include <rdma/rdma_cma.h>
-+#include <rdma/rsocket.h>
-
- #if __BYTE_ORDER == __BIG_ENDIAN
- static inline uint64_t cpu_to_be64(uint64_t x) { return x; }
-@@ -46,5 +48,46 @@ static inline uint64_t cpu_to_be64(uint64_t x) { return bswap_64(x); }
- static inline uint32_t cpu_to_be32(uint32_t x) { return bswap_32(x); }
- #endif
-
-+extern int use_rs;
-+
-+#define rs_socket(f,t,p) use_rs ? rsocket(f,t,p) : socket(f,t,p)
-+#define rs_bind(s,a,l) use_rs ? rbind(s,a,l) : bind(s,a,l)
-+#define rs_listen(s,b) use_rs ? rlisten(s,b) : listen(s,b)
-+#define rs_connect(s,a,l) use_rs ? rconnect(s,a,l) : connect(s,a,l)
-+#define rs_accept(s,a,l) use_rs ? raccept(s,a,l) : accept(s,a,l)
-+#define rs_shutdown(s,h) use_rs ? rshutdown(s,h) : shutdown(s,h)
-+#define rs_close(s) use_rs ? rclose(s) : close(s)
-+#define rs_recv(s,b,l,f) use_rs ? rrecv(s,b,l,f) : recv(s,b,l,f)
-+#define rs_send(s,b,l,f) use_rs ? rsend(s,b,l,f) : send(s,b,l,f)
-+#define rs_recvfrom(s,b,l,f,a,al) \
-+ use_rs ? rrecvfrom(s,b,l,f,a,al) : recvfrom(s,b,l,f,a,al)
-+#define rs_sendto(s,b,l,f,a,al) \
-+ use_rs ? rsendto(s,b,l,f,a,al) : sendto(s,b,l,f,a,al)
-+#define rs_poll(f,n,t) use_rs ? rpoll(f,n,t) : poll(f,n,t)
-+#define rs_fcntl(s,c,p) use_rs ? rfcntl(s,c,p) : fcntl(s,c,p)
-+#define rs_setsockopt(s,l,n,v,ol) \
-+ use_rs ? rsetsockopt(s,l,n,v,ol) : setsockopt(s,l,n,v,ol)
-+#define rs_getsockopt(s,l,n,v,ol) \
-+ use_rs ? rgetsockopt(s,l,n,v,ol) : getsockopt(s,l,n,v,ol)
-+
-+union socket_addr {
-+ struct sockaddr sa;
-+ struct sockaddr_in sin;
-+ struct sockaddr_in6 sin6;
-+};
-+
-+enum rs_optimization {
-+ opt_mixed,
-+ opt_latency,
-+ opt_bandwidth
-+};
-+
- int get_rdma_addr(char *src, char *dst, char *port,
- struct rdma_addrinfo *hints, struct rdma_addrinfo **rai);
-+
-+void size_str(char *str, size_t ssize, long long size);
-+void cnt_str(char *str, size_t ssize, long long cnt);
-+int size_to_count(int size);
-+void format_buf(void *buf, int size);
-+int verify_buf(void *buf, int size);
-+int do_poll(struct pollfd *fds, int timeout);
-diff --git a/examples/riostream.c b/examples/riostream.c
-index dfb03e5..a1d3671 100644
---- a/examples/riostream.c
-+++ b/examples/riostream.c
-@@ -45,6 +45,7 @@
-
- #include <rdma/rdma_cma.h>
- #include <rdma/rsocket.h>
-+#include "common.h"
-
- struct test_size_param {
- int size;
-@@ -72,12 +73,6 @@ static struct test_size_param test_size[] = {
- };
- #define TEST_CNT (sizeof test_size / sizeof test_size[0])
-
--enum rs_optimization {
-- opt_mixed,
-- opt_latency,
-- opt_bandwidth
--};
--
- static int rs, lrs;
- static int use_async;
- static int verify;
-@@ -98,46 +93,6 @@ static struct timeval start, end;
- static void *buf;
- static volatile uint8_t *poll_byte;
-
--static void size_str(char *str, size_t ssize, long long size)
--{
-- long long base, fraction = 0;
-- char mag;
--
-- if (size >= (1 << 30)) {
-- base = 1 << 30;
-- mag = 'g';
-- } else if (size >= (1 << 20)) {
-- base = 1 << 20;
-- mag = 'm';
-- } else if (size >= (1 << 10)) {
-- base = 1 << 10;
-- mag = 'k';
-- } else {
-- base = 1;
-- mag = '\0';
-- }
--
-- if (size / base < 10)
-- fraction = (size % base) * 10 / base;
-- if (fraction) {
-- snprintf(str, ssize, "%lld.%lld%c", size / base, fraction, mag);
-- } else {
-- snprintf(str, ssize, "%lld%c", size / base, mag);
-- }
--}
--
--static void cnt_str(char *str, size_t ssize, long long cnt)
--{
-- if (cnt >= 1000000000)
-- snprintf(str, ssize, "%lldb", cnt / 1000000000);
-- else if (cnt >= 1000000)
-- snprintf(str, ssize, "%lldm", cnt / 1000000);
-- else if (cnt >= 1000)
-- snprintf(str, ssize, "%lldk", cnt / 1000);
-- else
-- snprintf(str, ssize, "%lld", cnt);
--}
--
- static void show_perf(void)
- {
- char str[32];
-@@ -162,20 +117,6 @@ static void show_perf(void)
- (usec / iterations) / (transfer_count * 2));
- }
-
--static int size_to_count(int size)
--{
-- if (size >= 1000000)
-- return 100;
-- else if (size >= 100000)
-- return 1000;
-- else if (size >= 10000)
-- return 10000;
-- else if (size >= 1000)
-- return 100000;
-- else
-- return 1000000;
--}
--
- static void init_latency_test(int size)
- {
- char sstr[5];
-@@ -198,43 +139,6 @@ static void init_bandwidth_test(int size)
- transfer_count = size_to_count(transfer_size);
- }
-
--static void format_buf(void *buf, int size)
--{
-- uint8_t *array = buf;
-- static uint8_t data;
-- int i;
--
-- for (i = 0; i < size; i++)
-- array[i] = data++;
--}
--
--static int verify_buf(void *buf, int size)
--{
-- static long long total_bytes;
-- uint8_t *array = buf;
-- static uint8_t data;
-- int i;
--
-- for (i = 0; i < size; i++, total_bytes++) {
-- if (array[i] != data++) {
-- printf("data verification failed byte %lld\n", total_bytes);
-- return -1;
-- }
-- }
-- return 0;
--}
--
--static int do_poll(struct pollfd *fds)
--{
-- int ret;
--
-- do {
-- ret = rpoll(fds, 1, poll_timeout);
-- } while (!ret);
--
-- return ret == 1 ? 0 : ret;
--}
--
- static int send_msg(int size)
- {
- struct pollfd fds;
-@@ -250,7 +154,7 @@ static int send_msg(int size)
-
- for (offset = 0; offset < size; ) {
- if (use_async) {
-- ret = do_poll(&fds);
-+ ret = do_poll(&fds, poll_timeout);
- if (ret)
- return ret;
- }
-@@ -282,7 +186,7 @@ static int send_xfer(int size)
-
- for (offset = 0; offset < size; ) {
- if (use_async) {
-- ret = do_poll(&fds);
-+ ret = do_poll(&fds, poll_timeout);
- if (ret)
- return ret;
- }
-@@ -311,7 +215,7 @@ static int recv_msg(int size)
-
- for (offset = 0; offset < size; ) {
- if (use_async) {
-- ret = do_poll(&fds);
-+ ret = do_poll(&fds, poll_timeout);
- if (ret)
- return ret;
- }
-@@ -455,7 +359,7 @@ static int server_listen(void)
- int val, ret;
-
- memset(&hints, 0, sizeof hints);
-- hints.ai_flags = RAI_PASSIVE;
-+ hints.ai_flags = AI_PASSIVE;
- ret = getaddrinfo(src_addr, port, &hints, &res);
- if (ret) {
- perror("getaddrinfo");
-@@ -505,7 +409,7 @@ static int server_connect(void)
- fds.fd = lrs;
- fds.events = POLLIN;
-
-- ret = do_poll(&fds);
-+ ret = do_poll(&fds, poll_timeout);
- if (ret) {
- perror("rpoll");
- return ret;
-@@ -555,7 +459,7 @@ static int client_connect(void)
- if (ret && (errno == EINPROGRESS)) {
- fds.fd = rs;
- fds.events = POLLOUT;
-- ret = do_poll(&fds);
-+ ret = do_poll(&fds, poll_timeout);
- if (ret)
- goto close;
-
-diff --git a/examples/rstream.c b/examples/rstream.c
-index 069b7c9..a408b9e 100644
---- a/examples/rstream.c
-+++ b/examples/rstream.c
-@@ -45,6 +45,7 @@
-
- #include <rdma/rdma_cma.h>
- #include <rdma/rsocket.h>
-+#include "common.h"
-
- struct test_size_param {
- int size;
-@@ -72,14 +73,7 @@ static struct test_size_param test_size[] = {
- };
- #define TEST_CNT (sizeof test_size / sizeof test_size[0])
-
--enum rs_optimization {
-- opt_mixed,
-- opt_latency,
-- opt_bandwidth
--};
--
- static int rs, lrs;
--static int use_rs = 1;
- static int use_async;
- static int verify;
- static int flags = MSG_DONTWAIT;
-@@ -100,62 +94,6 @@ static char *src_addr;
- static struct timeval start, end;
- static void *buf;
-
--#define rs_socket(f,t,p) use_rs ? rsocket(f,t,p) : socket(f,t,p)
--#define rs_bind(s,a,l) use_rs ? rbind(s,a,l) : bind(s,a,l)
--#define rs_listen(s,b) use_rs ? rlisten(s,b) : listen(s,b)
--#define rs_connect(s,a,l) use_rs ? rconnect(s,a,l) : connect(s,a,l)
--#define rs_accept(s,a,l) use_rs ? raccept(s,a,l) : accept(s,a,l)
--#define rs_shutdown(s,h) use_rs ? rshutdown(s,h) : shutdown(s,h)
--#define rs_close(s) use_rs ? rclose(s) : close(s)
--#define rs_recv(s,b,l,f) use_rs ? rrecv(s,b,l,f) : recv(s,b,l,f)
--#define rs_send(s,b,l,f) use_rs ? rsend(s,b,l,f) : send(s,b,l,f)
--#define rs_poll(f,n,t) use_rs ? rpoll(f,n,t) : poll(f,n,t)
--#define rs_fcntl(s,c,p) use_rs ? rfcntl(s,c,p) : fcntl(s,c,p)
--#define rs_setsockopt(s,l,n,v,ol) \
-- use_rs ? rsetsockopt(s,l,n,v,ol) : setsockopt(s,l,n,v,ol)
--#define rs_getsockopt(s,l,n,v,ol) \
-- use_rs ? rgetsockopt(s,l,n,v,ol) : getsockopt(s,l,n,v,ol)
--
--static void size_str(char *str, size_t ssize, long long size)
--{
-- long long base, fraction = 0;
-- char mag;
--
-- if (size >= (1 << 30)) {
-- base = 1 << 30;
-- mag = 'g';
-- } else if (size >= (1 << 20)) {
-- base = 1 << 20;
-- mag = 'm';
-- } else if (size >= (1 << 10)) {
-- base = 1 << 10;
-- mag = 'k';
-- } else {
-- base = 1;
-- mag = '\0';
-- }
--
-- if (size / base < 10)
-- fraction = (size % base) * 10 / base;
-- if (fraction) {
-- snprintf(str, ssize, "%lld.%lld%c", size / base, fraction, mag);
-- } else {
-- snprintf(str, ssize, "%lld%c", size / base, mag);
-- }
--}
--
--static void cnt_str(char *str, size_t ssize, long long cnt)
--{
-- if (cnt >= 1000000000)
-- snprintf(str, ssize, "%lldb", cnt / 1000000000);
-- else if (cnt >= 1000000)
-- snprintf(str, ssize, "%lldm", cnt / 1000000);
-- else if (cnt >= 1000)
-- snprintf(str, ssize, "%lldk", cnt / 1000);
-- else
-- snprintf(str, ssize, "%lld", cnt);
--}
--
- static void show_perf(void)
- {
- char str[32];
-@@ -180,20 +118,6 @@ static void show_perf(void)
- (usec / iterations) / (transfer_count * 2));
- }
-
--static int size_to_count(int size)
--{
-- if (size >= 1000000)
-- return 100;
-- else if (size >= 100000)
-- return 1000;
-- else if (size >= 10000)
-- return 10000;
-- else if (size >= 1000)
-- return 100000;
-- else
-- return 1000000;
--}
--
- static void init_latency_test(int size)
- {
- char sstr[5];
-@@ -216,43 +140,6 @@ static void init_bandwidth_test(int size)
- transfer_count = size_to_count(transfer_size);
- }
-
--static void format_buf(void *buf, int size)
--{
-- uint8_t *array = buf;
-- static uint8_t data;
-- int i;
--
-- for (i = 0; i < size; i++)
-- array[i] = data++;
--}
--
--static int verify_buf(void *buf, int size)
--{
-- static long long total_bytes;
-- uint8_t *array = buf;
-- static uint8_t data;
-- int i;
--
-- for (i = 0; i < size; i++, total_bytes++) {
-- if (array[i] != data++) {
-- printf("data verification failed byte %lld\n", total_bytes);
-- return -1;
-- }
-- }
-- return 0;
--}
--
--static int do_poll(struct pollfd *fds)
--{
-- int ret;
--
-- do {
-- ret = rs_poll(fds, 1, poll_timeout);
-- } while (!ret);
--
-- return ret == 1 ? 0 : ret;
--}
--
- static int send_xfer(int size)
- {
- struct pollfd fds;
-@@ -268,7 +155,7 @@ static int send_xfer(int size)
-
- for (offset = 0; offset < size; ) {
- if (use_async) {
-- ret = do_poll(&fds);
-+ ret = do_poll(&fds, poll_timeout);
- if (ret)
- return ret;
- }
-@@ -297,7 +184,7 @@ static int recv_xfer(int size)
-
- for (offset = 0; offset < size; ) {
- if (use_async) {
-- ret = do_poll(&fds);
-+ ret = do_poll(&fds, poll_timeout);
- if (ret)
- return ret;
- }
-@@ -402,7 +289,7 @@ static int server_listen(void)
- int val, ret;
-
- memset(&hints, 0, sizeof hints);
-- hints.ai_flags = RAI_PASSIVE;
-+ hints.ai_flags = AI_PASSIVE;
- ret = getaddrinfo(src_addr, port, &hints, &res);
- if (ret) {
- perror("getaddrinfo");
-@@ -452,7 +339,7 @@ static int server_connect(void)
- fds.fd = lrs;
- fds.events = POLLIN;
-
-- ret = do_poll(&fds);
-+ ret = do_poll(&fds, poll_timeout);
- if (ret) {
- perror("rpoll");
- return ret;
-@@ -505,7 +392,7 @@ static int client_connect(void)
- if (ret && (errno == EINPROGRESS)) {
- fds.fd = rs;
- fds.events = POLLOUT;
-- ret = do_poll(&fds);
-+ ret = do_poll(&fds, poll_timeout);
- if (ret)
- goto close;
-
-diff --git a/examples/udpong.c b/examples/udpong.c
-new file mode 100644
-index 0000000..af8deb9
---- /dev/null
-+++ b/examples/udpong.c
-@@ -0,0 +1,568 @@
-+/*
-+ * Copyright (c) 2012 Intel Corporation. All rights reserved.
-+ *
-+ * This software is available to you under the OpenIB.org BSD license
-+ * below:
-+ *
-+ * Redistribution and use in source and binary forms, with or
-+ * without modification, are permitted provided that the following
-+ * conditions are met:
-+ *
-+ * - Redistributions of source code must retain the above
-+ * copyright notice, this list of conditions and the following
-+ * disclaimer.
-+ *
-+ * - 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.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
-+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-+ * SOFTWARE.
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <strings.h>
-+#include <errno.h>
-+#include <getopt.h>
-+#include <sys/types.h>
-+#include <sys/socket.h>
-+#include <sys/time.h>
-+#include <sys/wait.h>
-+#include <netdb.h>
-+#include <fcntl.h>
-+#include <unistd.h>
-+#include <netinet/in.h>
-+#include <netinet/tcp.h>
-+#include <arpa/inet.h>
-+
-+#include <rdma/rdma_cma.h>
-+#include <rdma/rsocket.h>
-+#include "common.h"
-+
-+static int test_size[] = {
-+ (1 << 6),
-+ (1 << 7), ((1 << 7) + (1 << 6)),
-+ (1 << 8), ((1 << 8) + (1 << 7)),
-+ (1 << 9), ((1 << 9) + (1 << 8)),
-+ (1 << 10), ((1 << 10) + (1 << 9)),
-+};
-+#define TEST_CNT (sizeof test_size / sizeof test_size[0])
-+
-+enum {
-+ msg_op_login,
-+ msg_op_start,
-+ msg_op_data,
-+ msg_op_echo,
-+ msg_op_end
-+};
-+
-+struct message {
-+ uint8_t op;
-+ uint8_t id;
-+ uint8_t seqno;
-+ uint8_t reserved;
-+ uint32_t data;
-+ uint8_t buf[2048];
-+};
-+
-+#define CTRL_MSG_SIZE 16
-+
-+struct client {
-+ uint64_t recvcnt;
-+};
-+
-+static struct client clients[256];
-+static uint8_t id;
-+
-+static int rs;
-+static int use_async;
-+static int flags = MSG_DONTWAIT;
-+static int poll_timeout;
-+static int custom;
-+static int echo;
-+static int transfer_size = 1000;
-+static int transfer_count = 1000;
-+static int buffer_size;
-+static char test_name[10] = "custom";
-+static char *port = "7174";
-+static char *dst_addr;
-+static char *src_addr;
-+static union socket_addr addr;
-+static socklen_t addrlen;
-+static struct timeval start, end;
-+static struct message msg;
-+
-+static void show_perf(void)
-+{
-+ char str[32];
-+ float usec;
-+ long long bytes;
-+ int transfers;
-+
-+ usec = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
-+ transfers = echo ? transfer_count * 2 : ntohl(msg.data);
-+ bytes = (long long) transfers * transfer_size;
-+
-+ /* name size transfers bytes seconds Gb/sec usec/xfer */
-+ printf("%-10s", test_name);
-+ size_str(str, sizeof str, transfer_size);
-+ printf("%-8s", str);
-+ cnt_str(str, sizeof str, transfers);
-+ printf("%-8s", str);
-+ size_str(str, sizeof str, bytes);
-+ printf("%-8s", str);
-+ printf("%8.2fs%10.2f%11.2f\n",
-+ usec / 1000000., (bytes * 8) / (1000. * usec),
-+ (usec / transfers));
-+}
-+
-+static void init_latency_test(int size)
-+{
-+ char sstr[5];
-+
-+ size_str(sstr, sizeof sstr, size);
-+ snprintf(test_name, sizeof test_name, "%s_lat", sstr);
-+ transfer_size = size;
-+ transfer_count = size_to_count(transfer_size) / 10;
-+ echo = 1;
-+}
-+
-+static void init_bandwidth_test(int size)
-+{
-+ char sstr[5];
-+
-+ size_str(sstr, sizeof sstr, size);
-+ snprintf(test_name, sizeof test_name, "%s_bw", sstr);
-+ transfer_size = size;
-+ transfer_count = size_to_count(transfer_size);
-+ echo = 0;
-+}
-+
-+static void set_options(int rs)
-+{
-+ int val;
-+
-+ if (buffer_size) {
-+ rs_setsockopt(rs, SOL_SOCKET, SO_SNDBUF, (void *) &buffer_size,
-+ sizeof buffer_size);
-+ rs_setsockopt(rs, SOL_SOCKET, SO_RCVBUF, (void *) &buffer_size,
-+ sizeof buffer_size);
-+ } else {
-+ val = 1 << 19;
-+ rs_setsockopt(rs, SOL_SOCKET, SO_SNDBUF, (void *) &val, sizeof val);
-+ rs_setsockopt(rs, SOL_SOCKET, SO_RCVBUF, (void *) &val, sizeof val);
-+ }
-+
-+ if (flags & MSG_DONTWAIT)
-+ rs_fcntl(rs, F_SETFL, O_NONBLOCK);
-+}
-+
-+static ssize_t svr_send(struct message *msg, size_t size,
-+ union socket_addr *addr, socklen_t addrlen)
-+{
-+ struct pollfd fds;
-+ ssize_t ret;
-+
-+ if (use_async) {
-+ fds.fd = rs;
-+ fds.events = POLLOUT;
-+ }
-+
-+ do {
-+ if (use_async) {
-+ ret = do_poll(&fds, poll_timeout);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ ret = rs_sendto(rs, msg, size, flags, &addr->sa, addrlen);
-+ } while (ret < 0 && (errno == EWOULDBLOCK || errno == EAGAIN));
-+
-+ if (ret < 0)
-+ perror("rsend");
-+
-+ return ret;
-+}
-+
-+static ssize_t svr_recv(struct message *msg, size_t size,
-+ union socket_addr *addr, socklen_t *addrlen)
-+{
-+ struct pollfd fds;
-+ ssize_t ret;
-+
-+ if (use_async) {
-+ fds.fd = rs;
-+ fds.events = POLLIN;
-+ }
-+
-+ do {
-+ if (use_async) {
-+ ret = do_poll(&fds, poll_timeout);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ ret = rs_recvfrom(rs, msg, size, flags, &addr->sa, addrlen);
-+ } while (ret < 0 && (errno == EWOULDBLOCK || errno == EAGAIN));
-+
-+ if (ret < 0)
-+ perror("rrecv");
-+
-+ return ret;
-+}
-+
-+static int svr_process(struct message *msg, size_t size,
-+ union socket_addr *addr, socklen_t addrlen)
-+{
-+ char str[64];
-+ ssize_t ret;
-+
-+ switch (msg->op) {
-+ case msg_op_login:
-+ if (addr->sa.sa_family == AF_INET) {
-+ printf("client login from %s\n",
-+ inet_ntop(AF_INET, &addr->sin.sin_addr.s_addr,
-+ str, sizeof str));
-+ } else {
-+ printf("client login from %s\n",
-+ inet_ntop(AF_INET6, &addr->sin6.sin6_addr.s6_addr,
-+ str, sizeof str));
-+ }
-+ msg->id = id++;
-+ /* fall through */
-+ case msg_op_start:
-+ memset(&clients[msg->id], 0, sizeof clients[msg->id]);
-+ break;
-+ case msg_op_echo:
-+ clients[msg->id].recvcnt++;
-+ break;
-+ case msg_op_end:
-+ msg->data = htonl(clients[msg->id].recvcnt);
-+ break;
-+ default:
-+ clients[msg->id].recvcnt++;
-+ return 0;
-+ }
-+
-+ ret = svr_send(msg, size, addr, addrlen);
-+ return (ret == size) ? 0 : (int) ret;
-+}
-+
-+static int svr_bind(void)
-+{
-+ struct addrinfo hints, *res;
-+ int ret;
-+
-+ memset(&hints, 0, sizeof hints);
-+ hints.ai_socktype = SOCK_DGRAM;
-+ ret = getaddrinfo(src_addr, port, &hints, &res);
-+ if (ret) {
-+ perror("getaddrinfo");
-+ return ret;
-+ }
-+
-+ rs = rs_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
-+ if (rs < 0) {
-+ perror("rsocket");
-+ ret = rs;
-+ goto out;
-+ }
-+
-+ set_options(rs);
-+ ret = rs_bind(rs, res->ai_addr, res->ai_addrlen);
-+ if (ret) {
-+ perror("rbind");
-+ rs_close(rs);
-+ }
-+
-+out:
-+ free(res);
-+ return ret;
-+}
-+
-+static int svr_run(void)
-+{
-+ size_t len;
-+ int ret;
-+
-+ ret = svr_bind();
-+ while (!ret) {
-+ addrlen = sizeof addr;
-+ len = svr_recv(&msg, sizeof msg, &addr, &addrlen);
-+ if (len < 0)
-+ return len;
-+
-+ ret = svr_process(&msg, len, &addr, addrlen);
-+ }
-+ return ret;
-+}
-+
-+static ssize_t client_send(struct message *msg, size_t size)
-+{
-+ struct pollfd fds;
-+ int ret;
-+
-+ if (use_async) {
-+ fds.fd = rs;
-+ fds.events = POLLOUT;
-+ }
-+
-+ do {
-+ if (use_async) {
-+ ret = do_poll(&fds, poll_timeout);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ ret = rs_send(rs, msg, size, flags);
-+ } while (ret < 0 && (errno == EWOULDBLOCK || errno == EAGAIN));
-+
-+ if (ret < 0)
-+ perror("rsend");
-+
-+ return ret;
-+}
-+
-+static ssize_t client_recv(struct message *msg, size_t size, int timeout)
-+{
-+ struct pollfd fds;
-+ int ret;
-+
-+ if (timeout) {
-+ fds.fd = rs;
-+ fds.events = POLLIN;
-+
-+ ret = rs_poll(&fds, 1, timeout);
-+ if (ret <= 0)
-+ return ret;
-+ }
-+
-+ ret = rs_recv(rs, msg, size, flags | MSG_DONTWAIT);
-+ if (ret < 0 && (errno == EWOULDBLOCK || errno == EAGAIN))
-+ perror("rrecv");
-+
-+ return ret;
-+}
-+
-+static int client_send_recv(struct message *msg, size_t size, int timeout)
-+{
-+ static uint8_t seqno;
-+ int ret;
-+
-+ msg->seqno = seqno;
-+ do {
-+ ret = client_send(msg, size);
-+ if (ret != size)
-+ return ret;
-+
-+ ret = client_recv(msg, size, timeout);
-+ } while (ret <= 0 || msg->seqno != seqno);
-+
-+ seqno++;
-+ return ret;
-+}
-+
-+static int run_test(void)
-+{
-+ int ret, i;
-+
-+ msg.op = msg_op_start;
-+ ret = client_send_recv(&msg, CTRL_MSG_SIZE, 1000);
-+ if (ret != CTRL_MSG_SIZE)
-+ goto out;
-+
-+ msg.op = echo ? msg_op_echo : msg_op_data;
-+ gettimeofday(&start, NULL);
-+ for (i = 0; i < transfer_count; i++) {
-+ ret = echo ? client_send_recv(&msg, transfer_size, 1) :
-+ client_send(&msg, transfer_size);
-+ if (ret != transfer_size)
-+ goto out;
-+ }
-+
-+ msg.op = msg_op_end;
-+ ret = client_send_recv(&msg, CTRL_MSG_SIZE, 1);
-+ if (ret != CTRL_MSG_SIZE)
-+ goto out;
-+
-+ gettimeofday(&end, NULL);
-+ show_perf();
-+ ret = 0;
-+
-+out:
-+ return ret;
-+}
-+
-+static int client_connect(void)
-+{
-+ struct addrinfo hints, *res;
-+ int ret;
-+
-+ memset(&hints, 0, sizeof hints);
-+ hints.ai_socktype = SOCK_DGRAM;
-+ ret = getaddrinfo(dst_addr, port, &hints, &res);
-+ if (ret) {
-+ perror("getaddrinfo");
-+ return ret;
-+ }
-+
-+ rs = rs_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
-+ if (rs < 0) {
-+ perror("rsocket");
-+ ret = rs;
-+ goto out;
-+ }
-+
-+ set_options(rs);
-+ ret = rs_connect(rs, res->ai_addr, res->ai_addrlen);
-+ if (ret) {
-+ perror("rconnect");
-+ rs_close(rs);
-+ }
-+
-+ msg.op = msg_op_login;
-+ ret = client_send_recv(&msg, CTRL_MSG_SIZE, 1000);
-+ if (ret == CTRL_MSG_SIZE)
-+ ret = 0;
-+
-+out:
-+ freeaddrinfo(res);
-+ return ret;
-+}
-+
-+static int client_run(void)
-+{
-+ int i, ret;
-+
-+ printf("%-10s%-8s%-8s%-8s%8s %10s%13s\n",
-+ "name", "bytes", "xfers", "total", "time", "Gb/sec", "usec/xfer");
-+
-+ ret = client_connect();
-+ if (ret)
-+ return ret;
-+
-+ if (!custom) {
-+ for (i = 0; i < TEST_CNT; i++) {
-+ init_latency_test(test_size[i]);
-+ run_test();
-+ }
-+ for (i = 0; i < TEST_CNT; i++) {
-+ init_bandwidth_test(test_size[i]);
-+ run_test();
-+ }
-+ } else {
-+ run_test();
-+ }
-+ rs_close(rs);
-+
-+ return ret;
-+}
-+
-+static int set_test_opt(char *optarg)
-+{
-+ if (strlen(optarg) == 1) {
-+ switch (optarg[0]) {
-+ case 's':
-+ use_rs = 0;
-+ break;
-+ case 'a':
-+ use_async = 1;
-+ break;
-+ case 'b':
-+ flags = 0;
-+ break;
-+ case 'n':
-+ flags = MSG_DONTWAIT;
-+ break;
-+ case 'e':
-+ echo = 1;
-+ break;
-+ default:
-+ return -1;
-+ }
-+ } else {
-+ if (!strncasecmp("socket", optarg, 6)) {
-+ use_rs = 0;
-+ } else if (!strncasecmp("async", optarg, 5)) {
-+ use_async = 1;
-+ } else if (!strncasecmp("block", optarg, 5)) {
-+ flags = 0;
-+ } else if (!strncasecmp("nonblock", optarg, 8)) {
-+ flags = MSG_DONTWAIT;
-+ } else if (!strncasecmp("echo", optarg, 4)) {
-+ echo = 1;
-+ } else {
-+ return -1;
-+ }
-+ }
-+ return 0;
-+}
-+
-+int main(int argc, char **argv)
-+{
-+ int op, ret;
-+
-+ while ((op = getopt(argc, argv, "s:b:B:C:S:p:T:")) != -1) {
-+ switch (op) {
-+ case 's':
-+ dst_addr = optarg;
-+ break;
-+ case 'b':
-+ src_addr = optarg;
-+ break;
-+ case 'B':
-+ buffer_size = atoi(optarg);
-+ break;
-+ case 'C':
-+ custom = 1;
-+ transfer_count = atoi(optarg);
-+ break;
-+ case 'S':
-+ custom = 1;
-+ transfer_size = atoi(optarg);
-+ if (transfer_size < CTRL_MSG_SIZE) {
-+ printf("size must be at least %d bytes\n",
-+ CTRL_MSG_SIZE);
-+ exit(1);
-+ }
-+ break;
-+ case 'p':
-+ port = optarg;
-+ break;
-+ case 'T':
-+ if (!set_test_opt(optarg))
-+ break;
-+ /* invalid option - fall through */
-+ default:
-+ printf("usage: %s\n", argv[0]);
-+ printf("\t[-s server_address]\n");
-+ printf("\t[-b bind_address]\n");
-+ printf("\t[-B buffer_size]\n");
-+ printf("\t[-C transfer_count]\n");
-+ printf("\t[-S transfer_size]\n");
-+ printf("\t[-p port_number]\n");
-+ printf("\t[-T test_option]\n");
-+ printf("\t s|sockets - use standard tcp/ip sockets\n");
-+ printf("\t a|async - asynchronous operation (use poll)\n");
-+ printf("\t b|blocking - use blocking calls\n");
-+ printf("\t n|nonblocking - use nonblocking calls\n");
-+ printf("\t e|echo - server echoes all messages\n");
-+ exit(1);
-+ }
-+ }
-+
-+ if (flags)
-+ poll_timeout = -1;
-+
-+ ret = dst_addr ? client_run() : svr_run();
-+ return ret;
-+}