1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky * Copyright (c) 2012 Intel Corporation. All rights reserved.
3*d6b92ffaSHans Petter Selasky *
4*d6b92ffaSHans Petter Selasky * This software is available to you under the OpenIB.org BSD license
5*d6b92ffaSHans Petter Selasky * below:
6*d6b92ffaSHans Petter Selasky *
7*d6b92ffaSHans Petter Selasky * Redistribution and use in source and binary forms, with or
8*d6b92ffaSHans Petter Selasky * without modification, are permitted provided that the following
9*d6b92ffaSHans Petter Selasky * conditions are met:
10*d6b92ffaSHans Petter Selasky *
11*d6b92ffaSHans Petter Selasky * - Redistributions of source code must retain the above
12*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
13*d6b92ffaSHans Petter Selasky * disclaimer.
14*d6b92ffaSHans Petter Selasky *
15*d6b92ffaSHans Petter Selasky * - Redistributions in binary form must reproduce the above
16*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
17*d6b92ffaSHans Petter Selasky * disclaimer in the documentation and/or other materials
18*d6b92ffaSHans Petter Selasky * provided with the distribution.
19*d6b92ffaSHans Petter Selasky *
20*d6b92ffaSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21*d6b92ffaSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22*d6b92ffaSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
23*d6b92ffaSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24*d6b92ffaSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25*d6b92ffaSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26*d6b92ffaSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27*d6b92ffaSHans Petter Selasky * SOFTWARE.
28*d6b92ffaSHans Petter Selasky */
29*d6b92ffaSHans Petter Selasky
30*d6b92ffaSHans Petter Selasky #include <stdio.h>
31*d6b92ffaSHans Petter Selasky #include <stdlib.h>
32*d6b92ffaSHans Petter Selasky #include <string.h>
33*d6b92ffaSHans Petter Selasky #include <strings.h>
34*d6b92ffaSHans Petter Selasky #include <errno.h>
35*d6b92ffaSHans Petter Selasky #include <getopt.h>
36*d6b92ffaSHans Petter Selasky #include <sys/types.h>
37*d6b92ffaSHans Petter Selasky #include <sys/socket.h>
38*d6b92ffaSHans Petter Selasky #include <sys/time.h>
39*d6b92ffaSHans Petter Selasky #include <sys/wait.h>
40*d6b92ffaSHans Petter Selasky #include <netdb.h>
41*d6b92ffaSHans Petter Selasky #include <fcntl.h>
42*d6b92ffaSHans Petter Selasky #include <unistd.h>
43*d6b92ffaSHans Petter Selasky #include <netinet/tcp.h>
44*d6b92ffaSHans Petter Selasky #include <arpa/inet.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 static int test_size[] = {
52*d6b92ffaSHans Petter Selasky (1 << 6),
53*d6b92ffaSHans Petter Selasky (1 << 7), ((1 << 7) + (1 << 6)),
54*d6b92ffaSHans Petter Selasky (1 << 8), ((1 << 8) + (1 << 7)),
55*d6b92ffaSHans Petter Selasky (1 << 9), ((1 << 9) + (1 << 8)),
56*d6b92ffaSHans Petter Selasky (1 << 10), ((1 << 10) + (1 << 9)),
57*d6b92ffaSHans Petter Selasky };
58*d6b92ffaSHans Petter Selasky #define TEST_CNT (sizeof test_size / sizeof test_size[0])
59*d6b92ffaSHans Petter Selasky
60*d6b92ffaSHans Petter Selasky enum {
61*d6b92ffaSHans Petter Selasky msg_op_login,
62*d6b92ffaSHans Petter Selasky msg_op_start,
63*d6b92ffaSHans Petter Selasky msg_op_data,
64*d6b92ffaSHans Petter Selasky msg_op_echo,
65*d6b92ffaSHans Petter Selasky msg_op_end
66*d6b92ffaSHans Petter Selasky };
67*d6b92ffaSHans Petter Selasky
68*d6b92ffaSHans Petter Selasky struct message {
69*d6b92ffaSHans Petter Selasky uint8_t op;
70*d6b92ffaSHans Petter Selasky uint8_t id;
71*d6b92ffaSHans Petter Selasky uint8_t seqno;
72*d6b92ffaSHans Petter Selasky uint8_t reserved;
73*d6b92ffaSHans Petter Selasky __be32 data;
74*d6b92ffaSHans Petter Selasky uint8_t buf[2048];
75*d6b92ffaSHans Petter Selasky };
76*d6b92ffaSHans Petter Selasky
77*d6b92ffaSHans Petter Selasky #define CTRL_MSG_SIZE 16
78*d6b92ffaSHans Petter Selasky
79*d6b92ffaSHans Petter Selasky struct client {
80*d6b92ffaSHans Petter Selasky uint64_t recvcnt;
81*d6b92ffaSHans Petter Selasky };
82*d6b92ffaSHans Petter Selasky
83*d6b92ffaSHans Petter Selasky static struct client clients[256];
84*d6b92ffaSHans Petter Selasky static uint8_t id;
85*d6b92ffaSHans Petter Selasky
86*d6b92ffaSHans Petter Selasky static int rs;
87*d6b92ffaSHans Petter Selasky static int use_async;
88*d6b92ffaSHans Petter Selasky static int flags = MSG_DONTWAIT;
89*d6b92ffaSHans Petter Selasky static int poll_timeout;
90*d6b92ffaSHans Petter Selasky static int custom;
91*d6b92ffaSHans Petter Selasky static int echo;
92*d6b92ffaSHans Petter Selasky static int transfer_size = 1000;
93*d6b92ffaSHans Petter Selasky static int transfer_count = 1000;
94*d6b92ffaSHans Petter Selasky static int buffer_size;
95*d6b92ffaSHans Petter Selasky static char test_name[10] = "custom";
96*d6b92ffaSHans Petter Selasky static const char *port = "7174";
97*d6b92ffaSHans Petter Selasky static char *dst_addr;
98*d6b92ffaSHans Petter Selasky static char *src_addr;
99*d6b92ffaSHans Petter Selasky static union socket_addr g_addr;
100*d6b92ffaSHans Petter Selasky static socklen_t g_addrlen;
101*d6b92ffaSHans Petter Selasky static struct timeval start, end;
102*d6b92ffaSHans Petter Selasky static struct message g_msg;
103*d6b92ffaSHans Petter Selasky
show_perf(void)104*d6b92ffaSHans Petter Selasky static void show_perf(void)
105*d6b92ffaSHans Petter Selasky {
106*d6b92ffaSHans Petter Selasky char str[32];
107*d6b92ffaSHans Petter Selasky float usec;
108*d6b92ffaSHans Petter Selasky long long bytes;
109*d6b92ffaSHans Petter Selasky int transfers;
110*d6b92ffaSHans Petter Selasky
111*d6b92ffaSHans Petter Selasky usec = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
112*d6b92ffaSHans Petter Selasky transfers = echo ? transfer_count * 2 : be32toh(g_msg.data);
113*d6b92ffaSHans Petter Selasky bytes = (long long) transfers * transfer_size;
114*d6b92ffaSHans Petter Selasky
115*d6b92ffaSHans Petter Selasky /* name size transfers bytes seconds Gb/sec usec/xfer */
116*d6b92ffaSHans Petter Selasky printf("%-10s", test_name);
117*d6b92ffaSHans Petter Selasky size_str(str, sizeof str, transfer_size);
118*d6b92ffaSHans Petter Selasky printf("%-8s", str);
119*d6b92ffaSHans Petter Selasky cnt_str(str, sizeof str, transfers);
120*d6b92ffaSHans Petter Selasky printf("%-8s", str);
121*d6b92ffaSHans Petter Selasky size_str(str, sizeof str, bytes);
122*d6b92ffaSHans Petter Selasky printf("%-8s", str);
123*d6b92ffaSHans Petter Selasky printf("%8.2fs%10.2f%11.2f\n",
124*d6b92ffaSHans Petter Selasky usec / 1000000., (bytes * 8) / (1000. * usec),
125*d6b92ffaSHans Petter Selasky (usec / transfers));
126*d6b92ffaSHans Petter Selasky }
127*d6b92ffaSHans Petter Selasky
init_latency_test(int size)128*d6b92ffaSHans Petter Selasky static void init_latency_test(int size)
129*d6b92ffaSHans Petter Selasky {
130*d6b92ffaSHans Petter Selasky char sstr[5];
131*d6b92ffaSHans Petter Selasky
132*d6b92ffaSHans Petter Selasky size_str(sstr, sizeof sstr, size);
133*d6b92ffaSHans Petter Selasky snprintf(test_name, sizeof test_name, "%s_lat", sstr);
134*d6b92ffaSHans Petter Selasky transfer_size = size;
135*d6b92ffaSHans Petter Selasky transfer_count = size_to_count(transfer_size) / 10;
136*d6b92ffaSHans Petter Selasky echo = 1;
137*d6b92ffaSHans Petter Selasky }
138*d6b92ffaSHans Petter Selasky
init_bandwidth_test(int size)139*d6b92ffaSHans Petter Selasky static void init_bandwidth_test(int size)
140*d6b92ffaSHans Petter Selasky {
141*d6b92ffaSHans Petter Selasky char sstr[5];
142*d6b92ffaSHans Petter Selasky
143*d6b92ffaSHans Petter Selasky size_str(sstr, sizeof sstr, size);
144*d6b92ffaSHans Petter Selasky snprintf(test_name, sizeof test_name, "%s_bw", sstr);
145*d6b92ffaSHans Petter Selasky transfer_size = size;
146*d6b92ffaSHans Petter Selasky transfer_count = size_to_count(transfer_size);
147*d6b92ffaSHans Petter Selasky echo = 0;
148*d6b92ffaSHans Petter Selasky }
149*d6b92ffaSHans Petter Selasky
set_options(int fd)150*d6b92ffaSHans Petter Selasky static void set_options(int fd)
151*d6b92ffaSHans Petter Selasky {
152*d6b92ffaSHans Petter Selasky int val;
153*d6b92ffaSHans Petter Selasky
154*d6b92ffaSHans Petter Selasky if (buffer_size) {
155*d6b92ffaSHans Petter Selasky rs_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void *) &buffer_size,
156*d6b92ffaSHans Petter Selasky sizeof buffer_size);
157*d6b92ffaSHans Petter Selasky rs_setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *) &buffer_size,
158*d6b92ffaSHans Petter Selasky sizeof buffer_size);
159*d6b92ffaSHans Petter Selasky } else {
160*d6b92ffaSHans Petter Selasky val = 1 << 19;
161*d6b92ffaSHans Petter Selasky rs_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void *) &val, sizeof val);
162*d6b92ffaSHans Petter Selasky rs_setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *) &val, sizeof val);
163*d6b92ffaSHans Petter Selasky }
164*d6b92ffaSHans Petter Selasky
165*d6b92ffaSHans Petter Selasky if (flags & MSG_DONTWAIT)
166*d6b92ffaSHans Petter Selasky rs_fcntl(fd, F_SETFL, O_NONBLOCK);
167*d6b92ffaSHans Petter Selasky }
168*d6b92ffaSHans Petter Selasky
svr_send(struct message * msg,size_t size,union socket_addr * addr,socklen_t addrlen)169*d6b92ffaSHans Petter Selasky static ssize_t svr_send(struct message *msg, size_t size,
170*d6b92ffaSHans Petter Selasky union socket_addr *addr, socklen_t addrlen)
171*d6b92ffaSHans Petter Selasky {
172*d6b92ffaSHans Petter Selasky struct pollfd fds;
173*d6b92ffaSHans Petter Selasky ssize_t ret;
174*d6b92ffaSHans Petter Selasky
175*d6b92ffaSHans Petter Selasky if (use_async) {
176*d6b92ffaSHans Petter Selasky fds.fd = rs;
177*d6b92ffaSHans Petter Selasky fds.events = POLLOUT;
178*d6b92ffaSHans Petter Selasky }
179*d6b92ffaSHans Petter Selasky
180*d6b92ffaSHans Petter Selasky do {
181*d6b92ffaSHans Petter Selasky if (use_async) {
182*d6b92ffaSHans Petter Selasky ret = do_poll(&fds, poll_timeout);
183*d6b92ffaSHans Petter Selasky if (ret)
184*d6b92ffaSHans Petter Selasky return ret;
185*d6b92ffaSHans Petter Selasky }
186*d6b92ffaSHans Petter Selasky
187*d6b92ffaSHans Petter Selasky ret = rs_sendto(rs, msg, size, flags, &addr->sa, addrlen);
188*d6b92ffaSHans Petter Selasky } while (ret < 0 && (errno == EWOULDBLOCK || errno == EAGAIN));
189*d6b92ffaSHans Petter Selasky
190*d6b92ffaSHans Petter Selasky if (ret < 0)
191*d6b92ffaSHans Petter Selasky perror("rsend");
192*d6b92ffaSHans Petter Selasky
193*d6b92ffaSHans Petter Selasky return ret;
194*d6b92ffaSHans Petter Selasky }
195*d6b92ffaSHans Petter Selasky
svr_recv(struct message * msg,size_t size,union socket_addr * addr,socklen_t * addrlen)196*d6b92ffaSHans Petter Selasky static ssize_t svr_recv(struct message *msg, size_t size,
197*d6b92ffaSHans Petter Selasky union socket_addr *addr, socklen_t *addrlen)
198*d6b92ffaSHans Petter Selasky {
199*d6b92ffaSHans Petter Selasky struct pollfd fds;
200*d6b92ffaSHans Petter Selasky ssize_t ret;
201*d6b92ffaSHans Petter Selasky
202*d6b92ffaSHans Petter Selasky if (use_async) {
203*d6b92ffaSHans Petter Selasky fds.fd = rs;
204*d6b92ffaSHans Petter Selasky fds.events = POLLIN;
205*d6b92ffaSHans Petter Selasky }
206*d6b92ffaSHans Petter Selasky
207*d6b92ffaSHans Petter Selasky do {
208*d6b92ffaSHans Petter Selasky if (use_async) {
209*d6b92ffaSHans Petter Selasky ret = do_poll(&fds, poll_timeout);
210*d6b92ffaSHans Petter Selasky if (ret)
211*d6b92ffaSHans Petter Selasky return ret;
212*d6b92ffaSHans Petter Selasky }
213*d6b92ffaSHans Petter Selasky
214*d6b92ffaSHans Petter Selasky ret = rs_recvfrom(rs, msg, size, flags, &addr->sa, addrlen);
215*d6b92ffaSHans Petter Selasky } while (ret < 0 && (errno == EWOULDBLOCK || errno == EAGAIN));
216*d6b92ffaSHans Petter Selasky
217*d6b92ffaSHans Petter Selasky if (ret < 0)
218*d6b92ffaSHans Petter Selasky perror("rrecv");
219*d6b92ffaSHans Petter Selasky
220*d6b92ffaSHans Petter Selasky return ret;
221*d6b92ffaSHans Petter Selasky }
222*d6b92ffaSHans Petter Selasky
svr_process(struct message * msg,size_t size,union socket_addr * addr,socklen_t addrlen)223*d6b92ffaSHans Petter Selasky static int svr_process(struct message *msg, size_t size,
224*d6b92ffaSHans Petter Selasky union socket_addr *addr, socklen_t addrlen)
225*d6b92ffaSHans Petter Selasky {
226*d6b92ffaSHans Petter Selasky char str[64];
227*d6b92ffaSHans Petter Selasky ssize_t ret;
228*d6b92ffaSHans Petter Selasky
229*d6b92ffaSHans Petter Selasky switch (msg->op) {
230*d6b92ffaSHans Petter Selasky case msg_op_login:
231*d6b92ffaSHans Petter Selasky if (addr->sa.sa_family == AF_INET) {
232*d6b92ffaSHans Petter Selasky printf("client login from %s\n",
233*d6b92ffaSHans Petter Selasky inet_ntop(AF_INET, &addr->sin.sin_addr.s_addr,
234*d6b92ffaSHans Petter Selasky str, sizeof str));
235*d6b92ffaSHans Petter Selasky } else {
236*d6b92ffaSHans Petter Selasky printf("client login from %s\n",
237*d6b92ffaSHans Petter Selasky inet_ntop(AF_INET6, &addr->sin6.sin6_addr.s6_addr,
238*d6b92ffaSHans Petter Selasky str, sizeof str));
239*d6b92ffaSHans Petter Selasky }
240*d6b92ffaSHans Petter Selasky msg->id = id++;
241*d6b92ffaSHans Petter Selasky /* fall through */
242*d6b92ffaSHans Petter Selasky case msg_op_start:
243*d6b92ffaSHans Petter Selasky memset(&clients[msg->id], 0, sizeof clients[msg->id]);
244*d6b92ffaSHans Petter Selasky break;
245*d6b92ffaSHans Petter Selasky case msg_op_echo:
246*d6b92ffaSHans Petter Selasky clients[msg->id].recvcnt++;
247*d6b92ffaSHans Petter Selasky break;
248*d6b92ffaSHans Petter Selasky case msg_op_end:
249*d6b92ffaSHans Petter Selasky msg->data = htobe32(clients[msg->id].recvcnt);
250*d6b92ffaSHans Petter Selasky break;
251*d6b92ffaSHans Petter Selasky default:
252*d6b92ffaSHans Petter Selasky clients[msg->id].recvcnt++;
253*d6b92ffaSHans Petter Selasky return 0;
254*d6b92ffaSHans Petter Selasky }
255*d6b92ffaSHans Petter Selasky
256*d6b92ffaSHans Petter Selasky ret = svr_send(msg, size, addr, addrlen);
257*d6b92ffaSHans Petter Selasky return (ret == size) ? 0 : (int) ret;
258*d6b92ffaSHans Petter Selasky }
259*d6b92ffaSHans Petter Selasky
svr_bind(void)260*d6b92ffaSHans Petter Selasky static int svr_bind(void)
261*d6b92ffaSHans Petter Selasky {
262*d6b92ffaSHans Petter Selasky struct addrinfo hints, *res;
263*d6b92ffaSHans Petter Selasky int ret;
264*d6b92ffaSHans Petter Selasky
265*d6b92ffaSHans Petter Selasky memset(&hints, 0, sizeof hints);
266*d6b92ffaSHans Petter Selasky hints.ai_socktype = SOCK_DGRAM;
267*d6b92ffaSHans Petter Selasky ret = getaddrinfo(src_addr, port, &hints, &res);
268*d6b92ffaSHans Petter Selasky if (ret) {
269*d6b92ffaSHans Petter Selasky printf("getaddrinfo: %s\n", gai_strerror(ret));
270*d6b92ffaSHans Petter Selasky return ret;
271*d6b92ffaSHans Petter Selasky }
272*d6b92ffaSHans Petter Selasky
273*d6b92ffaSHans Petter Selasky rs = rs_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
274*d6b92ffaSHans Petter Selasky if (rs < 0) {
275*d6b92ffaSHans Petter Selasky perror("rsocket");
276*d6b92ffaSHans Petter Selasky ret = rs;
277*d6b92ffaSHans Petter Selasky goto out;
278*d6b92ffaSHans Petter Selasky }
279*d6b92ffaSHans Petter Selasky
280*d6b92ffaSHans Petter Selasky set_options(rs);
281*d6b92ffaSHans Petter Selasky ret = rs_bind(rs, res->ai_addr, res->ai_addrlen);
282*d6b92ffaSHans Petter Selasky if (ret) {
283*d6b92ffaSHans Petter Selasky perror("rbind");
284*d6b92ffaSHans Petter Selasky rs_close(rs);
285*d6b92ffaSHans Petter Selasky }
286*d6b92ffaSHans Petter Selasky
287*d6b92ffaSHans Petter Selasky out:
288*d6b92ffaSHans Petter Selasky free(res);
289*d6b92ffaSHans Petter Selasky return ret;
290*d6b92ffaSHans Petter Selasky }
291*d6b92ffaSHans Petter Selasky
svr_run(void)292*d6b92ffaSHans Petter Selasky static int svr_run(void)
293*d6b92ffaSHans Petter Selasky {
294*d6b92ffaSHans Petter Selasky ssize_t len;
295*d6b92ffaSHans Petter Selasky int ret;
296*d6b92ffaSHans Petter Selasky
297*d6b92ffaSHans Petter Selasky ret = svr_bind();
298*d6b92ffaSHans Petter Selasky while (!ret) {
299*d6b92ffaSHans Petter Selasky g_addrlen = sizeof g_addr;
300*d6b92ffaSHans Petter Selasky len = svr_recv(&g_msg, sizeof g_msg, &g_addr, &g_addrlen);
301*d6b92ffaSHans Petter Selasky if (len < 0)
302*d6b92ffaSHans Petter Selasky return len;
303*d6b92ffaSHans Petter Selasky
304*d6b92ffaSHans Petter Selasky ret = svr_process(&g_msg, len, &g_addr, g_addrlen);
305*d6b92ffaSHans Petter Selasky }
306*d6b92ffaSHans Petter Selasky return ret;
307*d6b92ffaSHans Petter Selasky }
308*d6b92ffaSHans Petter Selasky
client_send(struct message * msg,size_t size)309*d6b92ffaSHans Petter Selasky static ssize_t client_send(struct message *msg, size_t size)
310*d6b92ffaSHans Petter Selasky {
311*d6b92ffaSHans Petter Selasky struct pollfd fds;
312*d6b92ffaSHans Petter Selasky int ret;
313*d6b92ffaSHans Petter Selasky
314*d6b92ffaSHans Petter Selasky if (use_async) {
315*d6b92ffaSHans Petter Selasky fds.fd = rs;
316*d6b92ffaSHans Petter Selasky fds.events = POLLOUT;
317*d6b92ffaSHans Petter Selasky }
318*d6b92ffaSHans Petter Selasky
319*d6b92ffaSHans Petter Selasky do {
320*d6b92ffaSHans Petter Selasky if (use_async) {
321*d6b92ffaSHans Petter Selasky ret = do_poll(&fds, poll_timeout);
322*d6b92ffaSHans Petter Selasky if (ret)
323*d6b92ffaSHans Petter Selasky return ret;
324*d6b92ffaSHans Petter Selasky }
325*d6b92ffaSHans Petter Selasky
326*d6b92ffaSHans Petter Selasky ret = rs_send(rs, msg, size, flags);
327*d6b92ffaSHans Petter Selasky } while (ret < 0 && (errno == EWOULDBLOCK || errno == EAGAIN));
328*d6b92ffaSHans Petter Selasky
329*d6b92ffaSHans Petter Selasky if (ret < 0)
330*d6b92ffaSHans Petter Selasky perror("rsend");
331*d6b92ffaSHans Petter Selasky
332*d6b92ffaSHans Petter Selasky return ret;
333*d6b92ffaSHans Petter Selasky }
334*d6b92ffaSHans Petter Selasky
client_recv(struct message * msg,size_t size,int timeout)335*d6b92ffaSHans Petter Selasky static ssize_t client_recv(struct message *msg, size_t size, int timeout)
336*d6b92ffaSHans Petter Selasky {
337*d6b92ffaSHans Petter Selasky struct pollfd fds;
338*d6b92ffaSHans Petter Selasky int ret;
339*d6b92ffaSHans Petter Selasky
340*d6b92ffaSHans Petter Selasky if (timeout) {
341*d6b92ffaSHans Petter Selasky fds.fd = rs;
342*d6b92ffaSHans Petter Selasky fds.events = POLLIN;
343*d6b92ffaSHans Petter Selasky
344*d6b92ffaSHans Petter Selasky ret = rs_poll(&fds, 1, timeout);
345*d6b92ffaSHans Petter Selasky if (ret <= 0)
346*d6b92ffaSHans Petter Selasky return ret;
347*d6b92ffaSHans Petter Selasky }
348*d6b92ffaSHans Petter Selasky
349*d6b92ffaSHans Petter Selasky ret = rs_recv(rs, msg, size, flags | MSG_DONTWAIT);
350*d6b92ffaSHans Petter Selasky if (ret < 0 && errno != EWOULDBLOCK && errno != EAGAIN)
351*d6b92ffaSHans Petter Selasky perror("rrecv");
352*d6b92ffaSHans Petter Selasky
353*d6b92ffaSHans Petter Selasky return ret;
354*d6b92ffaSHans Petter Selasky }
355*d6b92ffaSHans Petter Selasky
client_send_recv(struct message * msg,size_t size,int timeout)356*d6b92ffaSHans Petter Selasky static int client_send_recv(struct message *msg, size_t size, int timeout)
357*d6b92ffaSHans Petter Selasky {
358*d6b92ffaSHans Petter Selasky static uint8_t seqno;
359*d6b92ffaSHans Petter Selasky int ret;
360*d6b92ffaSHans Petter Selasky
361*d6b92ffaSHans Petter Selasky msg->seqno = seqno;
362*d6b92ffaSHans Petter Selasky do {
363*d6b92ffaSHans Petter Selasky ret = client_send(msg, size);
364*d6b92ffaSHans Petter Selasky if (ret != size)
365*d6b92ffaSHans Petter Selasky return ret;
366*d6b92ffaSHans Petter Selasky
367*d6b92ffaSHans Petter Selasky ret = client_recv(msg, size, timeout);
368*d6b92ffaSHans Petter Selasky } while (ret <= 0 || msg->seqno != seqno);
369*d6b92ffaSHans Petter Selasky
370*d6b92ffaSHans Petter Selasky seqno++;
371*d6b92ffaSHans Petter Selasky return ret;
372*d6b92ffaSHans Petter Selasky }
373*d6b92ffaSHans Petter Selasky
run_test(void)374*d6b92ffaSHans Petter Selasky static int run_test(void)
375*d6b92ffaSHans Petter Selasky {
376*d6b92ffaSHans Petter Selasky int ret, i;
377*d6b92ffaSHans Petter Selasky
378*d6b92ffaSHans Petter Selasky g_msg.op = msg_op_start;
379*d6b92ffaSHans Petter Selasky ret = client_send_recv(&g_msg, CTRL_MSG_SIZE, 1000);
380*d6b92ffaSHans Petter Selasky if (ret != CTRL_MSG_SIZE)
381*d6b92ffaSHans Petter Selasky goto out;
382*d6b92ffaSHans Petter Selasky
383*d6b92ffaSHans Petter Selasky g_msg.op = echo ? msg_op_echo : msg_op_data;
384*d6b92ffaSHans Petter Selasky gettimeofday(&start, NULL);
385*d6b92ffaSHans Petter Selasky for (i = 0; i < transfer_count; i++) {
386*d6b92ffaSHans Petter Selasky ret = echo ? client_send_recv(&g_msg, transfer_size, 1) :
387*d6b92ffaSHans Petter Selasky client_send(&g_msg, transfer_size);
388*d6b92ffaSHans Petter Selasky if (ret != transfer_size)
389*d6b92ffaSHans Petter Selasky goto out;
390*d6b92ffaSHans Petter Selasky }
391*d6b92ffaSHans Petter Selasky
392*d6b92ffaSHans Petter Selasky g_msg.op = msg_op_end;
393*d6b92ffaSHans Petter Selasky ret = client_send_recv(&g_msg, CTRL_MSG_SIZE, 1);
394*d6b92ffaSHans Petter Selasky if (ret != CTRL_MSG_SIZE)
395*d6b92ffaSHans Petter Selasky goto out;
396*d6b92ffaSHans Petter Selasky
397*d6b92ffaSHans Petter Selasky gettimeofday(&end, NULL);
398*d6b92ffaSHans Petter Selasky show_perf();
399*d6b92ffaSHans Petter Selasky ret = 0;
400*d6b92ffaSHans Petter Selasky
401*d6b92ffaSHans Petter Selasky out:
402*d6b92ffaSHans Petter Selasky return ret;
403*d6b92ffaSHans Petter Selasky }
404*d6b92ffaSHans Petter Selasky
client_connect(void)405*d6b92ffaSHans Petter Selasky static int client_connect(void)
406*d6b92ffaSHans Petter Selasky {
407*d6b92ffaSHans Petter Selasky struct addrinfo hints, *res;
408*d6b92ffaSHans Petter Selasky int ret;
409*d6b92ffaSHans Petter Selasky
410*d6b92ffaSHans Petter Selasky memset(&hints, 0, sizeof hints);
411*d6b92ffaSHans Petter Selasky hints.ai_socktype = SOCK_DGRAM;
412*d6b92ffaSHans Petter Selasky ret = getaddrinfo(dst_addr, port, &hints, &res);
413*d6b92ffaSHans Petter Selasky if (ret) {
414*d6b92ffaSHans Petter Selasky printf("getaddrinfo: %s\n", gai_strerror(ret));
415*d6b92ffaSHans Petter Selasky return ret;
416*d6b92ffaSHans Petter Selasky }
417*d6b92ffaSHans Petter Selasky
418*d6b92ffaSHans Petter Selasky rs = rs_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
419*d6b92ffaSHans Petter Selasky if (rs < 0) {
420*d6b92ffaSHans Petter Selasky perror("rsocket");
421*d6b92ffaSHans Petter Selasky ret = rs;
422*d6b92ffaSHans Petter Selasky goto out;
423*d6b92ffaSHans Petter Selasky }
424*d6b92ffaSHans Petter Selasky
425*d6b92ffaSHans Petter Selasky set_options(rs);
426*d6b92ffaSHans Petter Selasky ret = rs_connect(rs, res->ai_addr, res->ai_addrlen);
427*d6b92ffaSHans Petter Selasky if (ret) {
428*d6b92ffaSHans Petter Selasky perror("rconnect");
429*d6b92ffaSHans Petter Selasky rs_close(rs);
430*d6b92ffaSHans Petter Selasky goto out;
431*d6b92ffaSHans Petter Selasky }
432*d6b92ffaSHans Petter Selasky
433*d6b92ffaSHans Petter Selasky g_msg.op = msg_op_login;
434*d6b92ffaSHans Petter Selasky ret = client_send_recv(&g_msg, CTRL_MSG_SIZE, 1000);
435*d6b92ffaSHans Petter Selasky if (ret == CTRL_MSG_SIZE)
436*d6b92ffaSHans Petter Selasky ret = 0;
437*d6b92ffaSHans Petter Selasky
438*d6b92ffaSHans Petter Selasky out:
439*d6b92ffaSHans Petter Selasky freeaddrinfo(res);
440*d6b92ffaSHans Petter Selasky return ret;
441*d6b92ffaSHans Petter Selasky }
442*d6b92ffaSHans Petter Selasky
client_run(void)443*d6b92ffaSHans Petter Selasky static int client_run(void)
444*d6b92ffaSHans Petter Selasky {
445*d6b92ffaSHans Petter Selasky int i, ret;
446*d6b92ffaSHans Petter Selasky
447*d6b92ffaSHans Petter Selasky printf("%-10s%-8s%-8s%-8s%8s %10s%13s\n",
448*d6b92ffaSHans Petter Selasky "name", "bytes", "xfers", "total", "time", "Gb/sec", "usec/xfer");
449*d6b92ffaSHans Petter Selasky
450*d6b92ffaSHans Petter Selasky ret = client_connect();
451*d6b92ffaSHans Petter Selasky if (ret)
452*d6b92ffaSHans Petter Selasky return ret;
453*d6b92ffaSHans Petter Selasky
454*d6b92ffaSHans Petter Selasky if (!custom) {
455*d6b92ffaSHans Petter Selasky for (i = 0; i < TEST_CNT; i++) {
456*d6b92ffaSHans Petter Selasky init_latency_test(test_size[i]);
457*d6b92ffaSHans Petter Selasky run_test();
458*d6b92ffaSHans Petter Selasky }
459*d6b92ffaSHans Petter Selasky for (i = 0; i < TEST_CNT; i++) {
460*d6b92ffaSHans Petter Selasky init_bandwidth_test(test_size[i]);
461*d6b92ffaSHans Petter Selasky run_test();
462*d6b92ffaSHans Petter Selasky }
463*d6b92ffaSHans Petter Selasky } else {
464*d6b92ffaSHans Petter Selasky run_test();
465*d6b92ffaSHans Petter Selasky }
466*d6b92ffaSHans Petter Selasky rs_close(rs);
467*d6b92ffaSHans Petter Selasky
468*d6b92ffaSHans Petter Selasky return ret;
469*d6b92ffaSHans Petter Selasky }
470*d6b92ffaSHans Petter Selasky
set_test_opt(const char * arg)471*d6b92ffaSHans Petter Selasky static int set_test_opt(const char *arg)
472*d6b92ffaSHans Petter Selasky {
473*d6b92ffaSHans Petter Selasky if (strlen(arg) == 1) {
474*d6b92ffaSHans Petter Selasky switch (arg[0]) {
475*d6b92ffaSHans Petter Selasky case 's':
476*d6b92ffaSHans Petter Selasky use_rs = 0;
477*d6b92ffaSHans Petter Selasky break;
478*d6b92ffaSHans Petter Selasky case 'a':
479*d6b92ffaSHans Petter Selasky use_async = 1;
480*d6b92ffaSHans Petter Selasky break;
481*d6b92ffaSHans Petter Selasky case 'b':
482*d6b92ffaSHans Petter Selasky flags = 0;
483*d6b92ffaSHans Petter Selasky break;
484*d6b92ffaSHans Petter Selasky case 'n':
485*d6b92ffaSHans Petter Selasky flags = MSG_DONTWAIT;
486*d6b92ffaSHans Petter Selasky break;
487*d6b92ffaSHans Petter Selasky case 'e':
488*d6b92ffaSHans Petter Selasky echo = 1;
489*d6b92ffaSHans Petter Selasky break;
490*d6b92ffaSHans Petter Selasky default:
491*d6b92ffaSHans Petter Selasky return -1;
492*d6b92ffaSHans Petter Selasky }
493*d6b92ffaSHans Petter Selasky } else {
494*d6b92ffaSHans Petter Selasky if (!strncasecmp("socket", arg, 6)) {
495*d6b92ffaSHans Petter Selasky use_rs = 0;
496*d6b92ffaSHans Petter Selasky } else if (!strncasecmp("async", arg, 5)) {
497*d6b92ffaSHans Petter Selasky use_async = 1;
498*d6b92ffaSHans Petter Selasky } else if (!strncasecmp("block", arg, 5)) {
499*d6b92ffaSHans Petter Selasky flags = 0;
500*d6b92ffaSHans Petter Selasky } else if (!strncasecmp("nonblock", arg, 8)) {
501*d6b92ffaSHans Petter Selasky flags = MSG_DONTWAIT;
502*d6b92ffaSHans Petter Selasky } else if (!strncasecmp("echo", arg, 4)) {
503*d6b92ffaSHans Petter Selasky echo = 1;
504*d6b92ffaSHans Petter Selasky } else {
505*d6b92ffaSHans Petter Selasky return -1;
506*d6b92ffaSHans Petter Selasky }
507*d6b92ffaSHans Petter Selasky }
508*d6b92ffaSHans Petter Selasky return 0;
509*d6b92ffaSHans Petter Selasky }
510*d6b92ffaSHans Petter Selasky
main(int argc,char ** argv)511*d6b92ffaSHans Petter Selasky int main(int argc, char **argv)
512*d6b92ffaSHans Petter Selasky {
513*d6b92ffaSHans Petter Selasky int op, ret;
514*d6b92ffaSHans Petter Selasky
515*d6b92ffaSHans Petter Selasky while ((op = getopt(argc, argv, "s:b:B:C:S:p:T:")) != -1) {
516*d6b92ffaSHans Petter Selasky switch (op) {
517*d6b92ffaSHans Petter Selasky case 's':
518*d6b92ffaSHans Petter Selasky dst_addr = optarg;
519*d6b92ffaSHans Petter Selasky break;
520*d6b92ffaSHans Petter Selasky case 'b':
521*d6b92ffaSHans Petter Selasky src_addr = optarg;
522*d6b92ffaSHans Petter Selasky break;
523*d6b92ffaSHans Petter Selasky case 'B':
524*d6b92ffaSHans Petter Selasky buffer_size = atoi(optarg);
525*d6b92ffaSHans Petter Selasky break;
526*d6b92ffaSHans Petter Selasky case 'C':
527*d6b92ffaSHans Petter Selasky custom = 1;
528*d6b92ffaSHans Petter Selasky transfer_count = atoi(optarg);
529*d6b92ffaSHans Petter Selasky break;
530*d6b92ffaSHans Petter Selasky case 'S':
531*d6b92ffaSHans Petter Selasky custom = 1;
532*d6b92ffaSHans Petter Selasky transfer_size = atoi(optarg);
533*d6b92ffaSHans Petter Selasky if (transfer_size < CTRL_MSG_SIZE) {
534*d6b92ffaSHans Petter Selasky printf("size must be at least %d bytes\n",
535*d6b92ffaSHans Petter Selasky CTRL_MSG_SIZE);
536*d6b92ffaSHans Petter Selasky exit(1);
537*d6b92ffaSHans Petter Selasky }
538*d6b92ffaSHans Petter Selasky break;
539*d6b92ffaSHans Petter Selasky case 'p':
540*d6b92ffaSHans Petter Selasky port = optarg;
541*d6b92ffaSHans Petter Selasky break;
542*d6b92ffaSHans Petter Selasky case 'T':
543*d6b92ffaSHans Petter Selasky if (!set_test_opt(optarg))
544*d6b92ffaSHans Petter Selasky break;
545*d6b92ffaSHans Petter Selasky /* invalid option - fall through */
546*d6b92ffaSHans Petter Selasky SWITCH_FALLTHROUGH;
547*d6b92ffaSHans Petter Selasky default:
548*d6b92ffaSHans Petter Selasky printf("usage: %s\n", argv[0]);
549*d6b92ffaSHans Petter Selasky printf("\t[-s server_address]\n");
550*d6b92ffaSHans Petter Selasky printf("\t[-b bind_address]\n");
551*d6b92ffaSHans Petter Selasky printf("\t[-B buffer_size]\n");
552*d6b92ffaSHans Petter Selasky printf("\t[-C transfer_count]\n");
553*d6b92ffaSHans Petter Selasky printf("\t[-S transfer_size]\n");
554*d6b92ffaSHans Petter Selasky printf("\t[-p port_number]\n");
555*d6b92ffaSHans Petter Selasky printf("\t[-T test_option]\n");
556*d6b92ffaSHans Petter Selasky printf("\t s|sockets - use standard tcp/ip sockets\n");
557*d6b92ffaSHans Petter Selasky printf("\t a|async - asynchronous operation (use poll)\n");
558*d6b92ffaSHans Petter Selasky printf("\t b|blocking - use blocking calls\n");
559*d6b92ffaSHans Petter Selasky printf("\t n|nonblocking - use nonblocking calls\n");
560*d6b92ffaSHans Petter Selasky printf("\t e|echo - server echoes all messages\n");
561*d6b92ffaSHans Petter Selasky exit(1);
562*d6b92ffaSHans Petter Selasky }
563*d6b92ffaSHans Petter Selasky }
564*d6b92ffaSHans Petter Selasky
565*d6b92ffaSHans Petter Selasky if (flags)
566*d6b92ffaSHans Petter Selasky poll_timeout = -1;
567*d6b92ffaSHans Petter Selasky
568*d6b92ffaSHans Petter Selasky ret = dst_addr ? client_run() : svr_run();
569*d6b92ffaSHans Petter Selasky return ret;
570*d6b92ffaSHans Petter Selasky }
571