xref: /freebsd/contrib/ofed/librdmacm/examples/rstream.c (revision 87181516ef48be852d5e5fee53c6e0dbfc62f21e)
1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky  * Copyright (c) 2011-2012 Intel Corporation.  All rights reserved.
3*d6b92ffaSHans Petter Selasky  * Copyright (c) 2014-2015 Mellanox Technologies LTD. All rights reserved.
4*d6b92ffaSHans Petter Selasky  *
5*d6b92ffaSHans Petter Selasky  * This software is available to you under the OpenIB.org BSD license
6*d6b92ffaSHans Petter Selasky  * below:
7*d6b92ffaSHans Petter Selasky  *
8*d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
9*d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
10*d6b92ffaSHans Petter Selasky  *     conditions are met:
11*d6b92ffaSHans Petter Selasky  *
12*d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
13*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
14*d6b92ffaSHans Petter Selasky  *        disclaimer.
15*d6b92ffaSHans Petter Selasky  *
16*d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
17*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
18*d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
19*d6b92ffaSHans Petter Selasky  *        provided with the distribution.
20*d6b92ffaSHans Petter Selasky  *
21*d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22*d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23*d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
24*d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
25*d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
26*d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27*d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28*d6b92ffaSHans Petter Selasky  * SOFTWARE.
29*d6b92ffaSHans Petter Selasky  */
30*d6b92ffaSHans Petter Selasky 
31*d6b92ffaSHans Petter Selasky #include <stdio.h>
32*d6b92ffaSHans Petter Selasky #include <stdlib.h>
33*d6b92ffaSHans Petter Selasky #include <string.h>
34*d6b92ffaSHans Petter Selasky #include <strings.h>
35*d6b92ffaSHans Petter Selasky #include <errno.h>
36*d6b92ffaSHans Petter Selasky #include <getopt.h>
37*d6b92ffaSHans Petter Selasky #include <sys/types.h>
38*d6b92ffaSHans Petter Selasky #include <sys/socket.h>
39*d6b92ffaSHans Petter Selasky #include <sys/time.h>
40*d6b92ffaSHans Petter Selasky #include <sys/wait.h>
41*d6b92ffaSHans Petter Selasky #include <netdb.h>
42*d6b92ffaSHans Petter Selasky #include <fcntl.h>
43*d6b92ffaSHans Petter Selasky #include <unistd.h>
44*d6b92ffaSHans Petter Selasky #include <netinet/tcp.h>
45*d6b92ffaSHans Petter Selasky 
46*d6b92ffaSHans Petter Selasky #include <rdma/rdma_cma.h>
47*d6b92ffaSHans Petter Selasky #include <rdma/rsocket.h>
48*d6b92ffaSHans Petter Selasky #include <util/compiler.h>
49*d6b92ffaSHans Petter Selasky #include "common.h"
50*d6b92ffaSHans Petter Selasky 
51*d6b92ffaSHans Petter Selasky struct test_size_param {
52*d6b92ffaSHans Petter Selasky 	int size;
53*d6b92ffaSHans Petter Selasky 	int option;
54*d6b92ffaSHans Petter Selasky };
55*d6b92ffaSHans Petter Selasky 
56*d6b92ffaSHans Petter Selasky static struct test_size_param test_size[] = {
57*d6b92ffaSHans Petter Selasky 	{ 1 <<  6, 0 },
58*d6b92ffaSHans Petter Selasky 	{ 1 <<  7, 1 }, { (1 <<  7) + (1 <<  6), 1},
59*d6b92ffaSHans Petter Selasky 	{ 1 <<  8, 1 }, { (1 <<  8) + (1 <<  7), 1},
60*d6b92ffaSHans Petter Selasky 	{ 1 <<  9, 1 }, { (1 <<  9) + (1 <<  8), 1},
61*d6b92ffaSHans Petter Selasky 	{ 1 << 10, 1 }, { (1 << 10) + (1 <<  9), 1},
62*d6b92ffaSHans Petter Selasky 	{ 1 << 11, 1 }, { (1 << 11) + (1 << 10), 1},
63*d6b92ffaSHans Petter Selasky 	{ 1 << 12, 0 }, { (1 << 12) + (1 << 11), 1},
64*d6b92ffaSHans Petter Selasky 	{ 1 << 13, 1 }, { (1 << 13) + (1 << 12), 1},
65*d6b92ffaSHans Petter Selasky 	{ 1 << 14, 1 }, { (1 << 14) + (1 << 13), 1},
66*d6b92ffaSHans Petter Selasky 	{ 1 << 15, 1 }, { (1 << 15) + (1 << 14), 1},
67*d6b92ffaSHans Petter Selasky 	{ 1 << 16, 0 }, { (1 << 16) + (1 << 15), 1},
68*d6b92ffaSHans Petter Selasky 	{ 1 << 17, 1 }, { (1 << 17) + (1 << 16), 1},
69*d6b92ffaSHans Petter Selasky 	{ 1 << 18, 1 }, { (1 << 18) + (1 << 17), 1},
70*d6b92ffaSHans Petter Selasky 	{ 1 << 19, 1 }, { (1 << 19) + (1 << 18), 1},
71*d6b92ffaSHans Petter Selasky 	{ 1 << 20, 0 }, { (1 << 20) + (1 << 19), 1},
72*d6b92ffaSHans Petter Selasky 	{ 1 << 21, 1 }, { (1 << 21) + (1 << 20), 1},
73*d6b92ffaSHans Petter Selasky 	{ 1 << 22, 1 }, { (1 << 22) + (1 << 21), 1},
74*d6b92ffaSHans Petter Selasky };
75*d6b92ffaSHans Petter Selasky #define TEST_CNT (sizeof test_size / sizeof test_size[0])
76*d6b92ffaSHans Petter Selasky 
77*d6b92ffaSHans Petter Selasky static int rs, lrs;
78*d6b92ffaSHans Petter Selasky static int use_async;
79*d6b92ffaSHans Petter Selasky static int use_rgai;
80*d6b92ffaSHans Petter Selasky static int verify;
81*d6b92ffaSHans Petter Selasky static int flags = MSG_DONTWAIT;
82*d6b92ffaSHans Petter Selasky static int poll_timeout = 0;
83*d6b92ffaSHans Petter Selasky static int custom;
84*d6b92ffaSHans Petter Selasky static int use_fork;
85*d6b92ffaSHans Petter Selasky static pid_t fork_pid;
86*d6b92ffaSHans Petter Selasky static enum rs_optimization optimization;
87*d6b92ffaSHans Petter Selasky static int size_option;
88*d6b92ffaSHans Petter Selasky static int iterations = 1;
89*d6b92ffaSHans Petter Selasky static int transfer_size = 1000;
90*d6b92ffaSHans Petter Selasky static int transfer_count = 1000;
91*d6b92ffaSHans Petter Selasky static int buffer_size, inline_size = 64;
92*d6b92ffaSHans Petter Selasky static char test_name[10] = "custom";
93*d6b92ffaSHans Petter Selasky static const char *port = "7471";
94*d6b92ffaSHans Petter Selasky static int keepalive;
95*d6b92ffaSHans Petter Selasky static char *dst_addr;
96*d6b92ffaSHans Petter Selasky static char *src_addr;
97*d6b92ffaSHans Petter Selasky static struct timeval start, end;
98*d6b92ffaSHans Petter Selasky static void *buf;
99*d6b92ffaSHans Petter Selasky static struct rdma_addrinfo rai_hints;
100*d6b92ffaSHans Petter Selasky static struct addrinfo ai_hints;
101*d6b92ffaSHans Petter Selasky 
show_perf(void)102*d6b92ffaSHans Petter Selasky static void show_perf(void)
103*d6b92ffaSHans Petter Selasky {
104*d6b92ffaSHans Petter Selasky 	char str[32];
105*d6b92ffaSHans Petter Selasky 	float usec;
106*d6b92ffaSHans Petter Selasky 	long long bytes;
107*d6b92ffaSHans Petter Selasky 
108*d6b92ffaSHans Petter Selasky 	usec = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
109*d6b92ffaSHans Petter Selasky 	bytes = (long long) iterations * transfer_count * transfer_size * 2;
110*d6b92ffaSHans Petter Selasky 
111*d6b92ffaSHans Petter Selasky 	/* name size transfers iterations bytes seconds Gb/sec usec/xfer */
112*d6b92ffaSHans Petter Selasky 	printf("%-10s", test_name);
113*d6b92ffaSHans Petter Selasky 	size_str(str, sizeof str, transfer_size);
114*d6b92ffaSHans Petter Selasky 	printf("%-8s", str);
115*d6b92ffaSHans Petter Selasky 	cnt_str(str, sizeof str, transfer_count);
116*d6b92ffaSHans Petter Selasky 	printf("%-8s", str);
117*d6b92ffaSHans Petter Selasky 	cnt_str(str, sizeof str, iterations);
118*d6b92ffaSHans Petter Selasky 	printf("%-8s", str);
119*d6b92ffaSHans Petter Selasky 	size_str(str, sizeof str, bytes);
120*d6b92ffaSHans Petter Selasky 	printf("%-8s", str);
121*d6b92ffaSHans Petter Selasky 	printf("%8.2fs%10.2f%11.2f\n",
122*d6b92ffaSHans Petter Selasky 		usec / 1000000., (bytes * 8) / (1000. * usec),
123*d6b92ffaSHans Petter Selasky 		(usec / iterations) / (transfer_count * 2));
124*d6b92ffaSHans Petter Selasky }
125*d6b92ffaSHans Petter Selasky 
init_latency_test(int size)126*d6b92ffaSHans Petter Selasky static void init_latency_test(int size)
127*d6b92ffaSHans Petter Selasky {
128*d6b92ffaSHans Petter Selasky 	char sstr[5];
129*d6b92ffaSHans Petter Selasky 
130*d6b92ffaSHans Petter Selasky 	size_str(sstr, sizeof sstr, size);
131*d6b92ffaSHans Petter Selasky 	snprintf(test_name, sizeof test_name, "%s_lat", sstr);
132*d6b92ffaSHans Petter Selasky 	transfer_count = 1;
133*d6b92ffaSHans Petter Selasky 	transfer_size = size;
134*d6b92ffaSHans Petter Selasky 	iterations = size_to_count(transfer_size);
135*d6b92ffaSHans Petter Selasky }
136*d6b92ffaSHans Petter Selasky 
init_bandwidth_test(int size)137*d6b92ffaSHans Petter Selasky static void init_bandwidth_test(int size)
138*d6b92ffaSHans Petter Selasky {
139*d6b92ffaSHans Petter Selasky 	char sstr[5];
140*d6b92ffaSHans Petter Selasky 
141*d6b92ffaSHans Petter Selasky 	size_str(sstr, sizeof sstr, size);
142*d6b92ffaSHans Petter Selasky 	snprintf(test_name, sizeof test_name, "%s_bw", sstr);
143*d6b92ffaSHans Petter Selasky 	iterations = 1;
144*d6b92ffaSHans Petter Selasky 	transfer_size = size;
145*d6b92ffaSHans Petter Selasky 	transfer_count = size_to_count(transfer_size);
146*d6b92ffaSHans Petter Selasky }
147*d6b92ffaSHans Petter Selasky 
send_xfer(int size)148*d6b92ffaSHans Petter Selasky static int send_xfer(int size)
149*d6b92ffaSHans Petter Selasky {
150*d6b92ffaSHans Petter Selasky 	struct pollfd fds;
151*d6b92ffaSHans Petter Selasky 	int offset, ret;
152*d6b92ffaSHans Petter Selasky 
153*d6b92ffaSHans Petter Selasky 	if (verify)
154*d6b92ffaSHans Petter Selasky 		format_buf(buf, size);
155*d6b92ffaSHans Petter Selasky 
156*d6b92ffaSHans Petter Selasky 	if (use_async) {
157*d6b92ffaSHans Petter Selasky 		fds.fd = rs;
158*d6b92ffaSHans Petter Selasky 		fds.events = POLLOUT;
159*d6b92ffaSHans Petter Selasky 	}
160*d6b92ffaSHans Petter Selasky 
161*d6b92ffaSHans Petter Selasky 	for (offset = 0; offset < size; ) {
162*d6b92ffaSHans Petter Selasky 		if (use_async) {
163*d6b92ffaSHans Petter Selasky 			ret = do_poll(&fds, poll_timeout);
164*d6b92ffaSHans Petter Selasky 			if (ret)
165*d6b92ffaSHans Petter Selasky 				return ret;
166*d6b92ffaSHans Petter Selasky 		}
167*d6b92ffaSHans Petter Selasky 
168*d6b92ffaSHans Petter Selasky 		ret = rs_send(rs, buf + offset, size - offset, flags);
169*d6b92ffaSHans Petter Selasky 		if (ret > 0) {
170*d6b92ffaSHans Petter Selasky 			offset += ret;
171*d6b92ffaSHans Petter Selasky 		} else if (errno != EWOULDBLOCK && errno != EAGAIN) {
172*d6b92ffaSHans Petter Selasky 			perror("rsend");
173*d6b92ffaSHans Petter Selasky 			return ret;
174*d6b92ffaSHans Petter Selasky 		}
175*d6b92ffaSHans Petter Selasky 	}
176*d6b92ffaSHans Petter Selasky 
177*d6b92ffaSHans Petter Selasky 	return 0;
178*d6b92ffaSHans Petter Selasky }
179*d6b92ffaSHans Petter Selasky 
recv_xfer(int size)180*d6b92ffaSHans Petter Selasky static int recv_xfer(int size)
181*d6b92ffaSHans Petter Selasky {
182*d6b92ffaSHans Petter Selasky 	struct pollfd fds;
183*d6b92ffaSHans Petter Selasky 	int offset, ret;
184*d6b92ffaSHans Petter Selasky 
185*d6b92ffaSHans Petter Selasky 	if (use_async) {
186*d6b92ffaSHans Petter Selasky 		fds.fd = rs;
187*d6b92ffaSHans Petter Selasky 		fds.events = POLLIN;
188*d6b92ffaSHans Petter Selasky 	}
189*d6b92ffaSHans Petter Selasky 
190*d6b92ffaSHans Petter Selasky 	for (offset = 0; offset < size; ) {
191*d6b92ffaSHans Petter Selasky 		if (use_async) {
192*d6b92ffaSHans Petter Selasky 			ret = do_poll(&fds, poll_timeout);
193*d6b92ffaSHans Petter Selasky 			if (ret)
194*d6b92ffaSHans Petter Selasky 				return ret;
195*d6b92ffaSHans Petter Selasky 		}
196*d6b92ffaSHans Petter Selasky 
197*d6b92ffaSHans Petter Selasky 		ret = rs_recv(rs, buf + offset, size - offset, flags);
198*d6b92ffaSHans Petter Selasky 		if (ret > 0) {
199*d6b92ffaSHans Petter Selasky 			offset += ret;
200*d6b92ffaSHans Petter Selasky 		} else if (errno != EWOULDBLOCK && errno != EAGAIN) {
201*d6b92ffaSHans Petter Selasky 			perror("rrecv");
202*d6b92ffaSHans Petter Selasky 			return ret;
203*d6b92ffaSHans Petter Selasky 		}
204*d6b92ffaSHans Petter Selasky 	}
205*d6b92ffaSHans Petter Selasky 
206*d6b92ffaSHans Petter Selasky 	if (verify) {
207*d6b92ffaSHans Petter Selasky 		ret = verify_buf(buf, size);
208*d6b92ffaSHans Petter Selasky 		if (ret)
209*d6b92ffaSHans Petter Selasky 			return ret;
210*d6b92ffaSHans Petter Selasky 	}
211*d6b92ffaSHans Petter Selasky 
212*d6b92ffaSHans Petter Selasky 	return 0;
213*d6b92ffaSHans Petter Selasky }
214*d6b92ffaSHans Petter Selasky 
sync_test(void)215*d6b92ffaSHans Petter Selasky static int sync_test(void)
216*d6b92ffaSHans Petter Selasky {
217*d6b92ffaSHans Petter Selasky 	int ret;
218*d6b92ffaSHans Petter Selasky 
219*d6b92ffaSHans Petter Selasky 	ret = dst_addr ? send_xfer(16) : recv_xfer(16);
220*d6b92ffaSHans Petter Selasky 	if (ret)
221*d6b92ffaSHans Petter Selasky 		return ret;
222*d6b92ffaSHans Petter Selasky 
223*d6b92ffaSHans Petter Selasky 	return dst_addr ? recv_xfer(16) : send_xfer(16);
224*d6b92ffaSHans Petter Selasky }
225*d6b92ffaSHans Petter Selasky 
run_test(void)226*d6b92ffaSHans Petter Selasky static int run_test(void)
227*d6b92ffaSHans Petter Selasky {
228*d6b92ffaSHans Petter Selasky 	int ret, i, t;
229*d6b92ffaSHans Petter Selasky 
230*d6b92ffaSHans Petter Selasky 	ret = sync_test();
231*d6b92ffaSHans Petter Selasky 	if (ret)
232*d6b92ffaSHans Petter Selasky 		goto out;
233*d6b92ffaSHans Petter Selasky 
234*d6b92ffaSHans Petter Selasky 	gettimeofday(&start, NULL);
235*d6b92ffaSHans Petter Selasky 	for (i = 0; i < iterations; i++) {
236*d6b92ffaSHans Petter Selasky 		for (t = 0; t < transfer_count; t++) {
237*d6b92ffaSHans Petter Selasky 			ret = dst_addr ? send_xfer(transfer_size) :
238*d6b92ffaSHans Petter Selasky 					 recv_xfer(transfer_size);
239*d6b92ffaSHans Petter Selasky 			if (ret)
240*d6b92ffaSHans Petter Selasky 				goto out;
241*d6b92ffaSHans Petter Selasky 		}
242*d6b92ffaSHans Petter Selasky 
243*d6b92ffaSHans Petter Selasky 		for (t = 0; t < transfer_count; t++) {
244*d6b92ffaSHans Petter Selasky 			ret = dst_addr ? recv_xfer(transfer_size) :
245*d6b92ffaSHans Petter Selasky 					 send_xfer(transfer_size);
246*d6b92ffaSHans Petter Selasky 			if (ret)
247*d6b92ffaSHans Petter Selasky 				goto out;
248*d6b92ffaSHans Petter Selasky 		}
249*d6b92ffaSHans Petter Selasky 	}
250*d6b92ffaSHans Petter Selasky 	gettimeofday(&end, NULL);
251*d6b92ffaSHans Petter Selasky 	show_perf();
252*d6b92ffaSHans Petter Selasky 	ret = 0;
253*d6b92ffaSHans Petter Selasky 
254*d6b92ffaSHans Petter Selasky out:
255*d6b92ffaSHans Petter Selasky 	return ret;
256*d6b92ffaSHans Petter Selasky }
257*d6b92ffaSHans Petter Selasky 
set_keepalive(int fd)258*d6b92ffaSHans Petter Selasky static void set_keepalive(int fd)
259*d6b92ffaSHans Petter Selasky {
260*d6b92ffaSHans Petter Selasky 	int optval;
261*d6b92ffaSHans Petter Selasky 	socklen_t optlen = sizeof(optlen);
262*d6b92ffaSHans Petter Selasky 
263*d6b92ffaSHans Petter Selasky 	optval = 1;
264*d6b92ffaSHans Petter Selasky 	if (rs_setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen)) {
265*d6b92ffaSHans Petter Selasky 		perror("rsetsockopt SO_KEEPALIVE");
266*d6b92ffaSHans Petter Selasky 		return;
267*d6b92ffaSHans Petter Selasky 	}
268*d6b92ffaSHans Petter Selasky 
269*d6b92ffaSHans Petter Selasky 	optval = keepalive;
270*d6b92ffaSHans Petter Selasky 	if (rs_setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen))
271*d6b92ffaSHans Petter Selasky 		perror("rsetsockopt TCP_KEEPIDLE");
272*d6b92ffaSHans Petter Selasky 
273*d6b92ffaSHans Petter Selasky 	if (!(rs_getsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen)))
274*d6b92ffaSHans Petter Selasky 		printf("Keepalive: %s\n", (optval ? "ON" : "OFF"));
275*d6b92ffaSHans Petter Selasky 
276*d6b92ffaSHans Petter Selasky 	if (!(rs_getsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, &optlen)))
277*d6b92ffaSHans Petter Selasky 		printf("  time: %i\n", optval);
278*d6b92ffaSHans Petter Selasky }
279*d6b92ffaSHans Petter Selasky 
set_options(int fd)280*d6b92ffaSHans Petter Selasky static void set_options(int fd)
281*d6b92ffaSHans Petter Selasky {
282*d6b92ffaSHans Petter Selasky 	int val;
283*d6b92ffaSHans Petter Selasky 
284*d6b92ffaSHans Petter Selasky 	if (buffer_size) {
285*d6b92ffaSHans Petter Selasky 		rs_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void *) &buffer_size,
286*d6b92ffaSHans Petter Selasky 			      sizeof buffer_size);
287*d6b92ffaSHans Petter Selasky 		rs_setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *) &buffer_size,
288*d6b92ffaSHans Petter Selasky 			      sizeof buffer_size);
289*d6b92ffaSHans Petter Selasky 	} else {
290*d6b92ffaSHans Petter Selasky 		val = 1 << 19;
291*d6b92ffaSHans Petter Selasky 		rs_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void *) &val, sizeof val);
292*d6b92ffaSHans Petter Selasky 		rs_setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *) &val, sizeof val);
293*d6b92ffaSHans Petter Selasky 	}
294*d6b92ffaSHans Petter Selasky 
295*d6b92ffaSHans Petter Selasky 	val = 1;
296*d6b92ffaSHans Petter Selasky 	rs_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *) &val, sizeof(val));
297*d6b92ffaSHans Petter Selasky 
298*d6b92ffaSHans Petter Selasky 	if (flags & MSG_DONTWAIT)
299*d6b92ffaSHans Petter Selasky 		rs_fcntl(fd, F_SETFL, O_NONBLOCK);
300*d6b92ffaSHans Petter Selasky 
301*d6b92ffaSHans Petter Selasky 	if (use_rs) {
302*d6b92ffaSHans Petter Selasky 		/* Inline size based on experimental data */
303*d6b92ffaSHans Petter Selasky 		if (optimization == opt_latency) {
304*d6b92ffaSHans Petter Selasky 			rs_setsockopt(fd, SOL_RDMA, RDMA_INLINE, &inline_size,
305*d6b92ffaSHans Petter Selasky 				      sizeof inline_size);
306*d6b92ffaSHans Petter Selasky 		} else if (optimization == opt_bandwidth) {
307*d6b92ffaSHans Petter Selasky 			val = 0;
308*d6b92ffaSHans Petter Selasky 			rs_setsockopt(fd, SOL_RDMA, RDMA_INLINE, &val, sizeof val);
309*d6b92ffaSHans Petter Selasky 		}
310*d6b92ffaSHans Petter Selasky 	}
311*d6b92ffaSHans Petter Selasky 
312*d6b92ffaSHans Petter Selasky 	if (keepalive)
313*d6b92ffaSHans Petter Selasky 		set_keepalive(fd);
314*d6b92ffaSHans Petter Selasky }
315*d6b92ffaSHans Petter Selasky 
server_listen(void)316*d6b92ffaSHans Petter Selasky static int server_listen(void)
317*d6b92ffaSHans Petter Selasky {
318*d6b92ffaSHans Petter Selasky 	struct rdma_addrinfo *rai = NULL;
319*d6b92ffaSHans Petter Selasky 	struct addrinfo *ai;
320*d6b92ffaSHans Petter Selasky 	int val, ret;
321*d6b92ffaSHans Petter Selasky 
322*d6b92ffaSHans Petter Selasky 	if (use_rgai) {
323*d6b92ffaSHans Petter Selasky 		rai_hints.ai_flags |= RAI_PASSIVE;
324*d6b92ffaSHans Petter Selasky 		ret = rdma_getaddrinfo(src_addr, port, &rai_hints, &rai);
325*d6b92ffaSHans Petter Selasky 	} else {
326*d6b92ffaSHans Petter Selasky 		ai_hints.ai_flags |= AI_PASSIVE;
327*d6b92ffaSHans Petter Selasky 		ret = getaddrinfo(src_addr, port, &ai_hints, &ai);
328*d6b92ffaSHans Petter Selasky 	}
329*d6b92ffaSHans Petter Selasky 	if (ret) {
330*d6b92ffaSHans Petter Selasky 		printf("getaddrinfo: %s\n", gai_strerror(ret));
331*d6b92ffaSHans Petter Selasky 		return ret;
332*d6b92ffaSHans Petter Selasky 	}
333*d6b92ffaSHans Petter Selasky 
334*d6b92ffaSHans Petter Selasky 	lrs = rai ? rs_socket(rai->ai_family, SOCK_STREAM, 0) :
335*d6b92ffaSHans Petter Selasky 		    rs_socket(ai->ai_family, SOCK_STREAM, 0);
336*d6b92ffaSHans Petter Selasky 	if (lrs < 0) {
337*d6b92ffaSHans Petter Selasky 		perror("rsocket");
338*d6b92ffaSHans Petter Selasky 		ret = lrs;
339*d6b92ffaSHans Petter Selasky 		goto free;
340*d6b92ffaSHans Petter Selasky 	}
341*d6b92ffaSHans Petter Selasky 
342*d6b92ffaSHans Petter Selasky 	val = 1;
343*d6b92ffaSHans Petter Selasky 	ret = rs_setsockopt(lrs, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val);
344*d6b92ffaSHans Petter Selasky 	if (ret) {
345*d6b92ffaSHans Petter Selasky 		perror("rsetsockopt SO_REUSEADDR");
346*d6b92ffaSHans Petter Selasky 		goto close;
347*d6b92ffaSHans Petter Selasky 	}
348*d6b92ffaSHans Petter Selasky 
349*d6b92ffaSHans Petter Selasky 	ret = rai ? rs_bind(lrs, rai->ai_src_addr, rai->ai_src_len) :
350*d6b92ffaSHans Petter Selasky 		    rs_bind(lrs, ai->ai_addr, ai->ai_addrlen);
351*d6b92ffaSHans Petter Selasky 	if (ret) {
352*d6b92ffaSHans Petter Selasky 		perror("rbind");
353*d6b92ffaSHans Petter Selasky 		goto close;
354*d6b92ffaSHans Petter Selasky 	}
355*d6b92ffaSHans Petter Selasky 
356*d6b92ffaSHans Petter Selasky 	ret = rs_listen(lrs, 1);
357*d6b92ffaSHans Petter Selasky 	if (ret)
358*d6b92ffaSHans Petter Selasky 		perror("rlisten");
359*d6b92ffaSHans Petter Selasky 
360*d6b92ffaSHans Petter Selasky close:
361*d6b92ffaSHans Petter Selasky 	if (ret)
362*d6b92ffaSHans Petter Selasky 		rs_close(lrs);
363*d6b92ffaSHans Petter Selasky free:
364*d6b92ffaSHans Petter Selasky 	if (rai)
365*d6b92ffaSHans Petter Selasky 		rdma_freeaddrinfo(rai);
366*d6b92ffaSHans Petter Selasky 	else
367*d6b92ffaSHans Petter Selasky 		freeaddrinfo(ai);
368*d6b92ffaSHans Petter Selasky 	return ret;
369*d6b92ffaSHans Petter Selasky }
370*d6b92ffaSHans Petter Selasky 
server_connect(void)371*d6b92ffaSHans Petter Selasky static int server_connect(void)
372*d6b92ffaSHans Petter Selasky {
373*d6b92ffaSHans Petter Selasky 	struct pollfd fds;
374*d6b92ffaSHans Petter Selasky 	int ret = 0;
375*d6b92ffaSHans Petter Selasky 
376*d6b92ffaSHans Petter Selasky 	set_options(lrs);
377*d6b92ffaSHans Petter Selasky 	do {
378*d6b92ffaSHans Petter Selasky 		if (use_async) {
379*d6b92ffaSHans Petter Selasky 			fds.fd = lrs;
380*d6b92ffaSHans Petter Selasky 			fds.events = POLLIN;
381*d6b92ffaSHans Petter Selasky 
382*d6b92ffaSHans Petter Selasky 			ret = do_poll(&fds, poll_timeout);
383*d6b92ffaSHans Petter Selasky 			if (ret) {
384*d6b92ffaSHans Petter Selasky 				perror("rpoll");
385*d6b92ffaSHans Petter Selasky 				return ret;
386*d6b92ffaSHans Petter Selasky 			}
387*d6b92ffaSHans Petter Selasky 		}
388*d6b92ffaSHans Petter Selasky 
389*d6b92ffaSHans Petter Selasky 		rs = rs_accept(lrs, NULL, NULL);
390*d6b92ffaSHans Petter Selasky 	} while (rs < 0 && (errno == EAGAIN || errno == EWOULDBLOCK));
391*d6b92ffaSHans Petter Selasky 	if (rs < 0) {
392*d6b92ffaSHans Petter Selasky 		perror("raccept");
393*d6b92ffaSHans Petter Selasky 		return rs;
394*d6b92ffaSHans Petter Selasky 	}
395*d6b92ffaSHans Petter Selasky 
396*d6b92ffaSHans Petter Selasky 	if (use_fork)
397*d6b92ffaSHans Petter Selasky 		fork_pid = fork();
398*d6b92ffaSHans Petter Selasky 	if (!fork_pid)
399*d6b92ffaSHans Petter Selasky 		set_options(rs);
400*d6b92ffaSHans Petter Selasky 	return ret;
401*d6b92ffaSHans Petter Selasky }
402*d6b92ffaSHans Petter Selasky 
client_connect(void)403*d6b92ffaSHans Petter Selasky static int client_connect(void)
404*d6b92ffaSHans Petter Selasky {
405*d6b92ffaSHans Petter Selasky 	struct rdma_addrinfo *rai = NULL, *rai_src = NULL;
406*d6b92ffaSHans Petter Selasky 	struct addrinfo *ai, *ai_src;
407*d6b92ffaSHans Petter Selasky 	struct pollfd fds;
408*d6b92ffaSHans Petter Selasky 	int ret, err;
409*d6b92ffaSHans Petter Selasky 	socklen_t len;
410*d6b92ffaSHans Petter Selasky 
411*d6b92ffaSHans Petter Selasky 	ret = use_rgai ? rdma_getaddrinfo(dst_addr, port, &rai_hints, &rai) :
412*d6b92ffaSHans Petter Selasky 			 getaddrinfo(dst_addr, port, &ai_hints, &ai);
413*d6b92ffaSHans Petter Selasky 
414*d6b92ffaSHans Petter Selasky 	if (ret) {
415*d6b92ffaSHans Petter Selasky 		printf("getaddrinfo: %s\n", gai_strerror(ret));
416*d6b92ffaSHans Petter Selasky 		return ret;
417*d6b92ffaSHans Petter Selasky 	}
418*d6b92ffaSHans Petter Selasky 
419*d6b92ffaSHans Petter Selasky 	if (src_addr) {
420*d6b92ffaSHans Petter Selasky 		if (use_rgai) {
421*d6b92ffaSHans Petter Selasky 			rai_hints.ai_flags |= RAI_PASSIVE;
422*d6b92ffaSHans Petter Selasky 			ret = rdma_getaddrinfo(src_addr, port, &rai_hints, &rai_src);
423*d6b92ffaSHans Petter Selasky 		} else {
424*d6b92ffaSHans Petter Selasky 			ai_hints.ai_flags |= AI_PASSIVE;
425*d6b92ffaSHans Petter Selasky 			ret = getaddrinfo(src_addr, port, &ai_hints, &ai_src);
426*d6b92ffaSHans Petter Selasky 		}
427*d6b92ffaSHans Petter Selasky 		if (ret) {
428*d6b92ffaSHans Petter Selasky 			printf("getaddrinfo src_addr: %s\n", gai_strerror(ret));
429*d6b92ffaSHans Petter Selasky 			return ret;
430*d6b92ffaSHans Petter Selasky 		}
431*d6b92ffaSHans Petter Selasky 	}
432*d6b92ffaSHans Petter Selasky 
433*d6b92ffaSHans Petter Selasky 	rs = rai ? rs_socket(rai->ai_family, SOCK_STREAM, 0) :
434*d6b92ffaSHans Petter Selasky 		   rs_socket(ai->ai_family, SOCK_STREAM, 0);
435*d6b92ffaSHans Petter Selasky 	if (rs < 0) {
436*d6b92ffaSHans Petter Selasky 		perror("rsocket");
437*d6b92ffaSHans Petter Selasky 		ret = rs;
438*d6b92ffaSHans Petter Selasky 		goto free;
439*d6b92ffaSHans Petter Selasky 	}
440*d6b92ffaSHans Petter Selasky 
441*d6b92ffaSHans Petter Selasky 	set_options(rs);
442*d6b92ffaSHans Petter Selasky 
443*d6b92ffaSHans Petter Selasky 	if (src_addr) {
444*d6b92ffaSHans Petter Selasky 		ret = rai ? rs_bind(rs, rai_src->ai_src_addr, rai_src->ai_src_len) :
445*d6b92ffaSHans Petter Selasky 			    rs_bind(rs, ai_src->ai_addr, ai_src->ai_addrlen);
446*d6b92ffaSHans Petter Selasky 		if (ret) {
447*d6b92ffaSHans Petter Selasky 			perror("rbind");
448*d6b92ffaSHans Petter Selasky 			goto close;
449*d6b92ffaSHans Petter Selasky 		}
450*d6b92ffaSHans Petter Selasky 	}
451*d6b92ffaSHans Petter Selasky 
452*d6b92ffaSHans Petter Selasky 	if (rai && rai->ai_route) {
453*d6b92ffaSHans Petter Selasky 		ret = rs_setsockopt(rs, SOL_RDMA, RDMA_ROUTE, rai->ai_route,
454*d6b92ffaSHans Petter Selasky 				    rai->ai_route_len);
455*d6b92ffaSHans Petter Selasky 		if (ret) {
456*d6b92ffaSHans Petter Selasky 			perror("rsetsockopt RDMA_ROUTE");
457*d6b92ffaSHans Petter Selasky 			goto close;
458*d6b92ffaSHans Petter Selasky 		}
459*d6b92ffaSHans Petter Selasky 	}
460*d6b92ffaSHans Petter Selasky 
461*d6b92ffaSHans Petter Selasky 	ret = rai ? rs_connect(rs, rai->ai_dst_addr, rai->ai_dst_len) :
462*d6b92ffaSHans Petter Selasky 		    rs_connect(rs, ai->ai_addr, ai->ai_addrlen);
463*d6b92ffaSHans Petter Selasky 	if (ret && (errno != EINPROGRESS)) {
464*d6b92ffaSHans Petter Selasky 		perror("rconnect");
465*d6b92ffaSHans Petter Selasky 		goto close;
466*d6b92ffaSHans Petter Selasky 	}
467*d6b92ffaSHans Petter Selasky 
468*d6b92ffaSHans Petter Selasky 	if (ret && (errno == EINPROGRESS)) {
469*d6b92ffaSHans Petter Selasky 		fds.fd = rs;
470*d6b92ffaSHans Petter Selasky 		fds.events = POLLOUT;
471*d6b92ffaSHans Petter Selasky 		ret = do_poll(&fds, poll_timeout);
472*d6b92ffaSHans Petter Selasky 		if (ret) {
473*d6b92ffaSHans Petter Selasky 			perror("rpoll");
474*d6b92ffaSHans Petter Selasky 			goto close;
475*d6b92ffaSHans Petter Selasky 		}
476*d6b92ffaSHans Petter Selasky 
477*d6b92ffaSHans Petter Selasky 		len = sizeof err;
478*d6b92ffaSHans Petter Selasky 		ret = rs_getsockopt(rs, SOL_SOCKET, SO_ERROR, &err, &len);
479*d6b92ffaSHans Petter Selasky 		if (ret)
480*d6b92ffaSHans Petter Selasky 			goto close;
481*d6b92ffaSHans Petter Selasky 		if (err) {
482*d6b92ffaSHans Petter Selasky 			ret = -1;
483*d6b92ffaSHans Petter Selasky 			errno = err;
484*d6b92ffaSHans Petter Selasky 			perror("async rconnect");
485*d6b92ffaSHans Petter Selasky 		}
486*d6b92ffaSHans Petter Selasky 	}
487*d6b92ffaSHans Petter Selasky 
488*d6b92ffaSHans Petter Selasky close:
489*d6b92ffaSHans Petter Selasky 	if (ret)
490*d6b92ffaSHans Petter Selasky 		rs_close(rs);
491*d6b92ffaSHans Petter Selasky free:
492*d6b92ffaSHans Petter Selasky 	if (rai)
493*d6b92ffaSHans Petter Selasky 		rdma_freeaddrinfo(rai);
494*d6b92ffaSHans Petter Selasky 	else
495*d6b92ffaSHans Petter Selasky 		freeaddrinfo(ai);
496*d6b92ffaSHans Petter Selasky 	return ret;
497*d6b92ffaSHans Petter Selasky }
498*d6b92ffaSHans Petter Selasky 
run(void)499*d6b92ffaSHans Petter Selasky static int run(void)
500*d6b92ffaSHans Petter Selasky {
501*d6b92ffaSHans Petter Selasky 	int i, ret = 0;
502*d6b92ffaSHans Petter Selasky 
503*d6b92ffaSHans Petter Selasky 	buf = malloc(!custom ? test_size[TEST_CNT - 1].size : transfer_size);
504*d6b92ffaSHans Petter Selasky 	if (!buf) {
505*d6b92ffaSHans Petter Selasky 		perror("malloc");
506*d6b92ffaSHans Petter Selasky 		return -1;
507*d6b92ffaSHans Petter Selasky 	}
508*d6b92ffaSHans Petter Selasky 
509*d6b92ffaSHans Petter Selasky 	if (!dst_addr) {
510*d6b92ffaSHans Petter Selasky 		ret = server_listen();
511*d6b92ffaSHans Petter Selasky 		if (ret)
512*d6b92ffaSHans Petter Selasky 			goto free;
513*d6b92ffaSHans Petter Selasky 	}
514*d6b92ffaSHans Petter Selasky 
515*d6b92ffaSHans Petter Selasky 	printf("%-10s%-8s%-8s%-8s%-8s%8s %10s%13s\n",
516*d6b92ffaSHans Petter Selasky 	       "name", "bytes", "xfers", "iters", "total", "time", "Gb/sec", "usec/xfer");
517*d6b92ffaSHans Petter Selasky 	if (!custom) {
518*d6b92ffaSHans Petter Selasky 		optimization = opt_latency;
519*d6b92ffaSHans Petter Selasky 		ret = dst_addr ? client_connect() : server_connect();
520*d6b92ffaSHans Petter Selasky 		if (ret)
521*d6b92ffaSHans Petter Selasky 			goto free;
522*d6b92ffaSHans Petter Selasky 
523*d6b92ffaSHans Petter Selasky 		for (i = 0; i < TEST_CNT && !fork_pid; i++) {
524*d6b92ffaSHans Petter Selasky 			if (test_size[i].option > size_option)
525*d6b92ffaSHans Petter Selasky 				continue;
526*d6b92ffaSHans Petter Selasky 			init_latency_test(test_size[i].size);
527*d6b92ffaSHans Petter Selasky 			run_test();
528*d6b92ffaSHans Petter Selasky 		}
529*d6b92ffaSHans Petter Selasky 		if (fork_pid)
530*d6b92ffaSHans Petter Selasky 			waitpid(fork_pid, NULL, 0);
531*d6b92ffaSHans Petter Selasky 		else
532*d6b92ffaSHans Petter Selasky 			rs_shutdown(rs, SHUT_RDWR);
533*d6b92ffaSHans Petter Selasky 		rs_close(rs);
534*d6b92ffaSHans Petter Selasky 
535*d6b92ffaSHans Petter Selasky 		if (!dst_addr && use_fork && !fork_pid)
536*d6b92ffaSHans Petter Selasky 			goto free;
537*d6b92ffaSHans Petter Selasky 
538*d6b92ffaSHans Petter Selasky 		optimization = opt_bandwidth;
539*d6b92ffaSHans Petter Selasky 		ret = dst_addr ? client_connect() : server_connect();
540*d6b92ffaSHans Petter Selasky 		if (ret)
541*d6b92ffaSHans Petter Selasky 			goto free;
542*d6b92ffaSHans Petter Selasky 		for (i = 0; i < TEST_CNT && !fork_pid; i++) {
543*d6b92ffaSHans Petter Selasky 			if (test_size[i].option > size_option)
544*d6b92ffaSHans Petter Selasky 				continue;
545*d6b92ffaSHans Petter Selasky 			init_bandwidth_test(test_size[i].size);
546*d6b92ffaSHans Petter Selasky 			run_test();
547*d6b92ffaSHans Petter Selasky 		}
548*d6b92ffaSHans Petter Selasky 	} else {
549*d6b92ffaSHans Petter Selasky 		ret = dst_addr ? client_connect() : server_connect();
550*d6b92ffaSHans Petter Selasky 		if (ret)
551*d6b92ffaSHans Petter Selasky 			goto free;
552*d6b92ffaSHans Petter Selasky 
553*d6b92ffaSHans Petter Selasky 		if (!fork_pid)
554*d6b92ffaSHans Petter Selasky 			ret = run_test();
555*d6b92ffaSHans Petter Selasky 	}
556*d6b92ffaSHans Petter Selasky 
557*d6b92ffaSHans Petter Selasky 	if (fork_pid)
558*d6b92ffaSHans Petter Selasky 		waitpid(fork_pid, NULL, 0);
559*d6b92ffaSHans Petter Selasky 	else
560*d6b92ffaSHans Petter Selasky 		rs_shutdown(rs, SHUT_RDWR);
561*d6b92ffaSHans Petter Selasky 	rs_close(rs);
562*d6b92ffaSHans Petter Selasky free:
563*d6b92ffaSHans Petter Selasky 	free(buf);
564*d6b92ffaSHans Petter Selasky 	return ret;
565*d6b92ffaSHans Petter Selasky }
566*d6b92ffaSHans Petter Selasky 
set_test_opt(const char * arg)567*d6b92ffaSHans Petter Selasky static int set_test_opt(const char *arg)
568*d6b92ffaSHans Petter Selasky {
569*d6b92ffaSHans Petter Selasky 	if (strlen(arg) == 1) {
570*d6b92ffaSHans Petter Selasky 		switch (arg[0]) {
571*d6b92ffaSHans Petter Selasky 		case 's':
572*d6b92ffaSHans Petter Selasky 			use_rs = 0;
573*d6b92ffaSHans Petter Selasky 			break;
574*d6b92ffaSHans Petter Selasky 		case 'a':
575*d6b92ffaSHans Petter Selasky 			use_async = 1;
576*d6b92ffaSHans Petter Selasky 			break;
577*d6b92ffaSHans Petter Selasky 		case 'b':
578*d6b92ffaSHans Petter Selasky 			flags = (flags & ~MSG_DONTWAIT) | MSG_WAITALL;
579*d6b92ffaSHans Petter Selasky 			break;
580*d6b92ffaSHans Petter Selasky 		case 'f':
581*d6b92ffaSHans Petter Selasky 			use_fork = 1;
582*d6b92ffaSHans Petter Selasky 			use_rs = 0;
583*d6b92ffaSHans Petter Selasky 			break;
584*d6b92ffaSHans Petter Selasky 		case 'n':
585*d6b92ffaSHans Petter Selasky 			flags |= MSG_DONTWAIT;
586*d6b92ffaSHans Petter Selasky 			break;
587*d6b92ffaSHans Petter Selasky 		case 'r':
588*d6b92ffaSHans Petter Selasky 			use_rgai = 1;
589*d6b92ffaSHans Petter Selasky 			break;
590*d6b92ffaSHans Petter Selasky 		case 'v':
591*d6b92ffaSHans Petter Selasky 			verify = 1;
592*d6b92ffaSHans Petter Selasky 			break;
593*d6b92ffaSHans Petter Selasky 		default:
594*d6b92ffaSHans Petter Selasky 			return -1;
595*d6b92ffaSHans Petter Selasky 		}
596*d6b92ffaSHans Petter Selasky 	} else {
597*d6b92ffaSHans Petter Selasky 		if (!strncasecmp("socket", arg, 6)) {
598*d6b92ffaSHans Petter Selasky 			use_rs = 0;
599*d6b92ffaSHans Petter Selasky 		} else if (!strncasecmp("async", arg, 5)) {
600*d6b92ffaSHans Petter Selasky 			use_async = 1;
601*d6b92ffaSHans Petter Selasky 		} else if (!strncasecmp("block", arg, 5)) {
602*d6b92ffaSHans Petter Selasky 			flags = (flags & ~MSG_DONTWAIT) | MSG_WAITALL;
603*d6b92ffaSHans Petter Selasky 		} else if (!strncasecmp("nonblock", arg, 8)) {
604*d6b92ffaSHans Petter Selasky 			flags |= MSG_DONTWAIT;
605*d6b92ffaSHans Petter Selasky 		} else if (!strncasecmp("resolve", arg, 7)) {
606*d6b92ffaSHans Petter Selasky 			use_rgai = 1;
607*d6b92ffaSHans Petter Selasky 		} else if (!strncasecmp("verify", arg, 6)) {
608*d6b92ffaSHans Petter Selasky 			verify = 1;
609*d6b92ffaSHans Petter Selasky 		} else if (!strncasecmp("fork", arg, 4)) {
610*d6b92ffaSHans Petter Selasky 			use_fork = 1;
611*d6b92ffaSHans Petter Selasky 			use_rs = 0;
612*d6b92ffaSHans Petter Selasky 		} else {
613*d6b92ffaSHans Petter Selasky 			return -1;
614*d6b92ffaSHans Petter Selasky 		}
615*d6b92ffaSHans Petter Selasky 	}
616*d6b92ffaSHans Petter Selasky 	return 0;
617*d6b92ffaSHans Petter Selasky }
618*d6b92ffaSHans Petter Selasky 
main(int argc,char ** argv)619*d6b92ffaSHans Petter Selasky int main(int argc, char **argv)
620*d6b92ffaSHans Petter Selasky {
621*d6b92ffaSHans Petter Selasky 	int op, ret;
622*d6b92ffaSHans Petter Selasky 
623*d6b92ffaSHans Petter Selasky 	ai_hints.ai_socktype = SOCK_STREAM;
624*d6b92ffaSHans Petter Selasky 	rai_hints.ai_port_space = RDMA_PS_TCP;
625*d6b92ffaSHans Petter Selasky 	while ((op = getopt(argc, argv, "s:b:f:B:i:I:C:S:p:k:T:")) != -1) {
626*d6b92ffaSHans Petter Selasky 		switch (op) {
627*d6b92ffaSHans Petter Selasky 		case 's':
628*d6b92ffaSHans Petter Selasky 			dst_addr = optarg;
629*d6b92ffaSHans Petter Selasky 			break;
630*d6b92ffaSHans Petter Selasky 		case 'b':
631*d6b92ffaSHans Petter Selasky 			src_addr = optarg;
632*d6b92ffaSHans Petter Selasky 			break;
633*d6b92ffaSHans Petter Selasky 		case 'f':
634*d6b92ffaSHans Petter Selasky 			if (!strncasecmp("ip", optarg, 2)) {
635*d6b92ffaSHans Petter Selasky 				ai_hints.ai_flags = AI_NUMERICHOST;
636*d6b92ffaSHans Petter Selasky 			} else if (!strncasecmp("gid", optarg, 3)) {
637*d6b92ffaSHans Petter Selasky 				rai_hints.ai_flags = RAI_NUMERICHOST | RAI_FAMILY;
638*d6b92ffaSHans Petter Selasky 				rai_hints.ai_family = AF_IB;
639*d6b92ffaSHans Petter Selasky 				use_rgai = 1;
640*d6b92ffaSHans Petter Selasky 			} else {
641*d6b92ffaSHans Petter Selasky 				fprintf(stderr, "Warning: unknown address format\n");
642*d6b92ffaSHans Petter Selasky 			}
643*d6b92ffaSHans Petter Selasky 			break;
644*d6b92ffaSHans Petter Selasky 		case 'B':
645*d6b92ffaSHans Petter Selasky 			buffer_size = atoi(optarg);
646*d6b92ffaSHans Petter Selasky 			break;
647*d6b92ffaSHans Petter Selasky 		case 'i':
648*d6b92ffaSHans Petter Selasky 			inline_size = atoi(optarg);
649*d6b92ffaSHans Petter Selasky 			break;
650*d6b92ffaSHans Petter Selasky 		case 'I':
651*d6b92ffaSHans Petter Selasky 			custom = 1;
652*d6b92ffaSHans Petter Selasky 			iterations = atoi(optarg);
653*d6b92ffaSHans Petter Selasky 			break;
654*d6b92ffaSHans Petter Selasky 		case 'C':
655*d6b92ffaSHans Petter Selasky 			custom = 1;
656*d6b92ffaSHans Petter Selasky 			transfer_count = atoi(optarg);
657*d6b92ffaSHans Petter Selasky 			break;
658*d6b92ffaSHans Petter Selasky 		case 'S':
659*d6b92ffaSHans Petter Selasky 			if (!strncasecmp("all", optarg, 3)) {
660*d6b92ffaSHans Petter Selasky 				size_option = 1;
661*d6b92ffaSHans Petter Selasky 			} else {
662*d6b92ffaSHans Petter Selasky 				custom = 1;
663*d6b92ffaSHans Petter Selasky 				transfer_size = atoi(optarg);
664*d6b92ffaSHans Petter Selasky 			}
665*d6b92ffaSHans Petter Selasky 			break;
666*d6b92ffaSHans Petter Selasky 		case 'p':
667*d6b92ffaSHans Petter Selasky 			port = optarg;
668*d6b92ffaSHans Petter Selasky 			break;
669*d6b92ffaSHans Petter Selasky 		case 'k':
670*d6b92ffaSHans Petter Selasky 			keepalive = atoi(optarg);
671*d6b92ffaSHans Petter Selasky 			break;
672*d6b92ffaSHans Petter Selasky 		case 'T':
673*d6b92ffaSHans Petter Selasky 			if (!set_test_opt(optarg))
674*d6b92ffaSHans Petter Selasky 				break;
675*d6b92ffaSHans Petter Selasky 			/* invalid option - fall through */
676*d6b92ffaSHans Petter Selasky 			SWITCH_FALLTHROUGH;
677*d6b92ffaSHans Petter Selasky 		default:
678*d6b92ffaSHans Petter Selasky 			printf("usage: %s\n", argv[0]);
679*d6b92ffaSHans Petter Selasky 			printf("\t[-s server_address]\n");
680*d6b92ffaSHans Petter Selasky 			printf("\t[-b bind_address]\n");
681*d6b92ffaSHans Petter Selasky 			printf("\t[-f address_format]\n");
682*d6b92ffaSHans Petter Selasky 			printf("\t    name, ip, ipv6, or gid\n");
683*d6b92ffaSHans Petter Selasky 			printf("\t[-B buffer_size]\n");
684*d6b92ffaSHans Petter Selasky 			printf("\t[-i inline_size]\n");
685*d6b92ffaSHans Petter Selasky 			printf("\t[-I iterations]\n");
686*d6b92ffaSHans Petter Selasky 			printf("\t[-C transfer_count]\n");
687*d6b92ffaSHans Petter Selasky 			printf("\t[-S transfer_size or all]\n");
688*d6b92ffaSHans Petter Selasky 			printf("\t[-p port_number]\n");
689*d6b92ffaSHans Petter Selasky 			printf("\t[-k keepalive_time]\n");
690*d6b92ffaSHans Petter Selasky 			printf("\t[-T test_option]\n");
691*d6b92ffaSHans Petter Selasky 			printf("\t    s|sockets - use standard tcp/ip sockets\n");
692*d6b92ffaSHans Petter Selasky 			printf("\t    a|async - asynchronous operation (use poll)\n");
693*d6b92ffaSHans Petter Selasky 			printf("\t    b|blocking - use blocking calls\n");
694*d6b92ffaSHans Petter Selasky 			printf("\t    f|fork - fork server processing\n");
695*d6b92ffaSHans Petter Selasky 			printf("\t    n|nonblocking - use nonblocking calls\n");
696*d6b92ffaSHans Petter Selasky 			printf("\t    r|resolve - use rdma cm to resolve address\n");
697*d6b92ffaSHans Petter Selasky 			printf("\t    v|verify - verify data\n");
698*d6b92ffaSHans Petter Selasky 			exit(1);
699*d6b92ffaSHans Petter Selasky 		}
700*d6b92ffaSHans Petter Selasky 	}
701*d6b92ffaSHans Petter Selasky 
702*d6b92ffaSHans Petter Selasky 	if (!(flags & MSG_DONTWAIT))
703*d6b92ffaSHans Petter Selasky 		poll_timeout = -1;
704*d6b92ffaSHans Petter Selasky 
705*d6b92ffaSHans Petter Selasky 	ret = run();
706*d6b92ffaSHans Petter Selasky 	return ret;
707*d6b92ffaSHans Petter Selasky }
708