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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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