[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-rdma
Subject:    [RFC] [PATCH 2/2] [librdmacm] examples/udpong: Add test program for rsocket datagrams
From:       "Hefty, Sean" <sean.hefty () intel ! com>
Date:       2012-12-19 0:39:33
Message-ID: 1828884A29C6694DAF28B7E6B8A8237346ADFE3C () ORSMSX101 ! amr ! corp ! intel ! com
[Download RAW message or body]

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>
---
 Makefile.am          |    8 -
 examples/common.c    |   93 ++++++++
 examples/common.h    |   39 +++
 examples/riostream.c |  104 +--------
 examples/rstream.c   |  119 +---------
 examples/udpong.c    |  568 ++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 717 insertions(+), 214 deletions(-)
 create mode 100644 examples/udpong.c

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..eaffb57 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,40 @@ 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;
+};
+
 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..718b20d 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;
@@ -98,46 +99,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 +123,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 +145,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 +160,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 +192,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 +221,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 +365,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 +415,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 +465,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..617710e 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;
@@ -79,7 +80,6 @@ enum rs_optimization {
 };
 
 static int rs, lrs;
-static int use_rs = 1;
 static int use_async;
 static int verify;
 static int flags = MSG_DONTWAIT;
@@ -100,62 +100,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 +124,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 +146,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 +161,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 +190,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 +295,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 +345,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 +398,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;
+}


--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic