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