From b69ae5072bbf6779d7dbfd01392b8db6ee4f78a6 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Wed, 5 Dec 2012 15:58:03 -0800 Subject: [PATCH] examples/udpong: Add test program for rsocket datagrams Signed-off-by: Sean Hefty --- examples/common.c | 91 +++++++ examples/common.h | 15 +- examples/riostream.c | 103 +------- examples/rstream.c | 101 +------- examples/udpong.c | 565 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 681 insertions(+), 194 deletions(-) create mode 100644 examples/udpong.c diff --git a/examples/common.c b/examples/common.c index 3eeb1e9b..43bfb6b0 100644 --- a/examples/common.c +++ b/examples/common.c @@ -72,3 +72,94 @@ int get_rdma_addr(char *src, char *dst, char *port, return ret; } + +void size_str(char *str, size_t ssize, long long size) +{ + long long base, fraction = 0; + char mag; + + if (size >= (1 << 30)) { + base = 1 << 30; + mag = 'g'; + } else if (size >= (1 << 20)) { + base = 1 << 20; + mag = 'm'; + } else if (size >= (1 << 10)) { + base = 1 << 10; + mag = 'k'; + } else { + base = 1; + mag = '\0'; + } + + if (size / base < 10) + fraction = (size % base) * 10 / base; + if (fraction) { + snprintf(str, ssize, "%lld.%lld%c", size / base, fraction, mag); + } else { + snprintf(str, ssize, "%lld%c", size / base, mag); + } +} + +void cnt_str(char *str, size_t ssize, long long cnt) +{ + if (cnt >= 1000000000) + snprintf(str, ssize, "%lldb", cnt / 1000000000); + else if (cnt >= 1000000) + snprintf(str, ssize, "%lldm", cnt / 1000000); + else if (cnt >= 1000) + snprintf(str, ssize, "%lldk", cnt / 1000); + else + snprintf(str, ssize, "%lld", cnt); +} + +int size_to_count(int size) +{ + if (size >= 1000000) + return 100; + else if (size >= 100000) + return 1000; + else if (size >= 10000) + return 10000; + else if (size >= 1000) + return 100000; + else + return 1000000; +} + +void format_buf(void *buf, int size) +{ + uint8_t *array = buf; + static uint8_t data; + int i; + + for (i = 0; i < size; i++) + array[i] = data++; +} + +int verify_buf(void *buf, int size) +{ + static long long total_bytes; + uint8_t *array = buf; + static uint8_t data; + int i; + + for (i = 0; i < size; i++, total_bytes++) { + if (array[i] != data++) { + printf("data verification failed byte %lld\n", total_bytes); + return -1; + } + } + return 0; +} + +int do_poll(struct pollfd *fds, int timeout) +{ + int ret; + + do { + ret = rs_poll(fds, 1, timeout); + } while (!ret); + + return ret == 1 ? 0 : ret; +} diff --git a/examples/common.h b/examples/common.h index 8d9fea02..ef0ea7b5 100644 --- a/examples/common.h +++ b/examples/common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2011 Intel Corporation. All rights reserved. + * Copyright (c) 2005-2012 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -46,5 +46,18 @@ static inline uint64_t cpu_to_be64(uint64_t x) { return bswap_64(x); } static inline uint32_t cpu_to_be32(uint32_t x) { return bswap_32(x); } #endif +union socket_addr { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; +}; + int get_rdma_addr(char *src, char *dst, char *port, struct rdma_addrinfo *hints, struct rdma_addrinfo **rai); + +void size_str(char *str, size_t ssize, long long size); +void cnt_str(char *str, size_t ssize, long long cnt); +int size_to_count(int size); +void format_buf(void *buf, int size); +int verify_buf(void *buf, int size); +int do_poll(struct pollfd *fds, int timeout); diff --git a/examples/riostream.c b/examples/riostream.c index dfb03e50..d73a43fa 100644 --- a/examples/riostream.c +++ b/examples/riostream.c @@ -98,46 +98,6 @@ static struct timeval start, end; static void *buf; static volatile uint8_t *poll_byte; -static void size_str(char *str, size_t ssize, long long size) -{ - long long base, fraction = 0; - char mag; - - if (size >= (1 << 30)) { - base = 1 << 30; - mag = 'g'; - } else if (size >= (1 << 20)) { - base = 1 << 20; - mag = 'm'; - } else if (size >= (1 << 10)) { - base = 1 << 10; - mag = 'k'; - } else { - base = 1; - mag = '\0'; - } - - if (size / base < 10) - fraction = (size % base) * 10 / base; - if (fraction) { - snprintf(str, ssize, "%lld.%lld%c", size / base, fraction, mag); - } else { - snprintf(str, ssize, "%lld%c", size / base, mag); - } -} - -static void cnt_str(char *str, size_t ssize, long long cnt) -{ - if (cnt >= 1000000000) - snprintf(str, ssize, "%lldb", cnt / 1000000000); - else if (cnt >= 1000000) - snprintf(str, ssize, "%lldm", cnt / 1000000); - else if (cnt >= 1000) - snprintf(str, ssize, "%lldk", cnt / 1000); - else - snprintf(str, ssize, "%lld", cnt); -} - static void show_perf(void) { char str[32]; @@ -162,20 +122,6 @@ static void show_perf(void) (usec / iterations) / (transfer_count * 2)); } -static int size_to_count(int size) -{ - if (size >= 1000000) - return 100; - else if (size >= 100000) - return 1000; - else if (size >= 10000) - return 10000; - else if (size >= 1000) - return 100000; - else - return 1000000; -} - static void init_latency_test(int size) { char sstr[5]; @@ -198,43 +144,6 @@ static void init_bandwidth_test(int size) transfer_count = size_to_count(transfer_size); } -static void format_buf(void *buf, int size) -{ - uint8_t *array = buf; - static uint8_t data; - int i; - - for (i = 0; i < size; i++) - array[i] = data++; -} - -static int verify_buf(void *buf, int size) -{ - static long long total_bytes; - uint8_t *array = buf; - static uint8_t data; - int i; - - for (i = 0; i < size; i++, total_bytes++) { - if (array[i] != data++) { - printf("data verification failed byte %lld\n", total_bytes); - return -1; - } - } - return 0; -} - -static int do_poll(struct pollfd *fds) -{ - int ret; - - do { - ret = rpoll(fds, 1, poll_timeout); - } while (!ret); - - return ret == 1 ? 0 : ret; -} - static int send_msg(int size) { struct pollfd fds; @@ -250,7 +159,7 @@ static int send_msg(int size) for (offset = 0; offset < size; ) { if (use_async) { - ret = do_poll(&fds); + ret = do_poll(&fds, poll_timeout); if (ret) return ret; } @@ -282,7 +191,7 @@ static int send_xfer(int size) for (offset = 0; offset < size; ) { if (use_async) { - ret = do_poll(&fds); + ret = do_poll(&fds, poll_timeout); if (ret) return ret; } @@ -311,7 +220,7 @@ static int recv_msg(int size) for (offset = 0; offset < size; ) { if (use_async) { - ret = do_poll(&fds); + ret = do_poll(&fds, poll_timeout); if (ret) return ret; } @@ -455,7 +364,7 @@ static int server_listen(void) int val, ret; memset(&hints, 0, sizeof hints); - hints.ai_flags = RAI_PASSIVE; + hints.ai_flags = AI_PASSIVE; ret = getaddrinfo(src_addr, port, &hints, &res); if (ret) { perror("getaddrinfo"); @@ -505,7 +414,7 @@ static int server_connect(void) fds.fd = lrs; fds.events = POLLIN; - ret = do_poll(&fds); + ret = do_poll(&fds, poll_timeout); if (ret) { perror("rpoll"); return ret; @@ -555,7 +464,7 @@ static int client_connect(void) if (ret && (errno == EINPROGRESS)) { fds.fd = rs; fds.events = POLLOUT; - ret = do_poll(&fds); + ret = do_poll(&fds, poll_timeout); if (ret) goto close; diff --git a/examples/rstream.c b/examples/rstream.c index 069b7c9f..ae3b8ad8 100644 --- a/examples/rstream.c +++ b/examples/rstream.c @@ -116,46 +116,6 @@ static void *buf; #define rs_getsockopt(s,l,n,v,ol) \ use_rs ? rgetsockopt(s,l,n,v,ol) : getsockopt(s,l,n,v,ol) -static void size_str(char *str, size_t ssize, long long size) -{ - long long base, fraction = 0; - char mag; - - if (size >= (1 << 30)) { - base = 1 << 30; - mag = 'g'; - } else if (size >= (1 << 20)) { - base = 1 << 20; - mag = 'm'; - } else if (size >= (1 << 10)) { - base = 1 << 10; - mag = 'k'; - } else { - base = 1; - mag = '\0'; - } - - if (size / base < 10) - fraction = (size % base) * 10 / base; - if (fraction) { - snprintf(str, ssize, "%lld.%lld%c", size / base, fraction, mag); - } else { - snprintf(str, ssize, "%lld%c", size / base, mag); - } -} - -static void cnt_str(char *str, size_t ssize, long long cnt) -{ - if (cnt >= 1000000000) - snprintf(str, ssize, "%lldb", cnt / 1000000000); - else if (cnt >= 1000000) - snprintf(str, ssize, "%lldm", cnt / 1000000); - else if (cnt >= 1000) - snprintf(str, ssize, "%lldk", cnt / 1000); - else - snprintf(str, ssize, "%lld", cnt); -} - static void show_perf(void) { char str[32]; @@ -180,20 +140,6 @@ static void show_perf(void) (usec / iterations) / (transfer_count * 2)); } -static int size_to_count(int size) -{ - if (size >= 1000000) - return 100; - else if (size >= 100000) - return 1000; - else if (size >= 10000) - return 10000; - else if (size >= 1000) - return 100000; - else - return 1000000; -} - static void init_latency_test(int size) { char sstr[5]; @@ -216,43 +162,6 @@ static void init_bandwidth_test(int size) transfer_count = size_to_count(transfer_size); } -static void format_buf(void *buf, int size) -{ - uint8_t *array = buf; - static uint8_t data; - int i; - - for (i = 0; i < size; i++) - array[i] = data++; -} - -static int verify_buf(void *buf, int size) -{ - static long long total_bytes; - uint8_t *array = buf; - static uint8_t data; - int i; - - for (i = 0; i < size; i++, total_bytes++) { - if (array[i] != data++) { - printf("data verification failed byte %lld\n", total_bytes); - return -1; - } - } - return 0; -} - -static int do_poll(struct pollfd *fds) -{ - int ret; - - do { - ret = rs_poll(fds, 1, poll_timeout); - } while (!ret); - - return ret == 1 ? 0 : ret; -} - static int send_xfer(int size) { struct pollfd fds; @@ -268,7 +177,7 @@ static int send_xfer(int size) for (offset = 0; offset < size; ) { if (use_async) { - ret = do_poll(&fds); + ret = do_poll(&fds, poll_timeout); if (ret) return ret; } @@ -297,7 +206,7 @@ static int recv_xfer(int size) for (offset = 0; offset < size; ) { if (use_async) { - ret = do_poll(&fds); + ret = do_poll(&fds, poll_timeout); if (ret) return ret; } @@ -402,7 +311,7 @@ static int server_listen(void) int val, ret; memset(&hints, 0, sizeof hints); - hints.ai_flags = RAI_PASSIVE; + hints.ai_flags = AI_PASSIVE; ret = getaddrinfo(src_addr, port, &hints, &res); if (ret) { perror("getaddrinfo"); @@ -452,7 +361,7 @@ static int server_connect(void) fds.fd = lrs; fds.events = POLLIN; - ret = do_poll(&fds); + ret = do_poll(&fds, poll_timeout); if (ret) { perror("rpoll"); return ret; @@ -505,7 +414,7 @@ static int client_connect(void) if (ret && (errno == EINPROGRESS)) { fds.fd = rs; fds.events = POLLOUT; - ret = do_poll(&fds); + ret = do_poll(&fds, poll_timeout); if (ret) goto close; diff --git a/examples/udpong.c b/examples/udpong.c new file mode 100644 index 00000000..d29e5848 --- /dev/null +++ b/examples/udpong.c @@ -0,0 +1,565 @@ +/* + * Copyright (c) 2012 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static int test_size[] = { + { 1 << 6 }, + { 1 << 7 }, { (1 << 7) + (1 << 6) }, + { 1 << 8 }, { (1 << 8) + (1 << 7) }, + { 1 << 9 }, { (1 << 9) + (1 << 8) }, + { 1 << 10 }, { (1 << 10) + (1 << 9) }, +}; +#define TEST_CNT (sizeof test_size / sizeof test_size[0]) + +enum { + msg_op_start, + msg_op_data, + msg_op_echo, + msg_op_end +}; + +struct message { + uint8_t op; + uint8_t id; + uint16_t reserved; + uint32_t data; + uint8_t buf[2048]; +}; + +#define CTRL_MSG_SIZE 16 + +struct client { + uint64_t recvcnt; +}; + +static struct client clients[256]; +static int id; + +static int rs; +static int use_rs = 1; +static int use_async; +static int flags = MSG_DONTWAIT; +static int poll_timeout; +static int custom; +static int echo; +static int transfer_size = 1000; +static int transfer_count = 1000; +static int buffer_size; +static char test_name[10] = "custom"; +static char *port = "7174"; +static char *dst_addr; +static char *src_addr; +static union socket_addr addr; +static socklen_t addrlen; +static struct timeval start, end; +static struct message msg; + +#define rs_socket(f,t,p) use_rs ? rsocket(f,t,p) : socket(f,t,p) +#define rs_bind(s,a,l) use_rs ? rbind(s,a,l) : bind(s,a,l) +#define rs_connect(s,a,l) use_rs ? rconnect(s,a,l) : connect(s,a,l) +#define rs_close(s) use_rs ? rclose(s) : close(s) +#define rs_recvfrom(s,b,l,f,a,al) \ + use_rs ? rrecvfrom(s,b,l,f,a,al) : recvfrom(s,b,l,f,a,al) +#define rs_sendto(s,b,l,f,a,al) \ + use_rs ? rsendto(s,b,l,f,a,al) : sendto(s,b,l,fa,al) +#define rs_poll(f,n,t) use_rs ? rpoll(f,n,t) : poll(f,n,t) +#define rs_fcntl(s,c,p) use_rs ? rfcntl(s,c,p) : fcntl(s,c,p) +#define rs_setsockopt(s,l,n,v,ol) \ + use_rs ? rsetsockopt(s,l,n,v,ol) : setsockopt(s,l,n,v,ol) +#define rs_getsockopt(s,l,n,v,ol) \ + use_rs ? rgetsockopt(s,l,n,v,ol) : getsockopt(s,l,n,v,ol) + +static void show_perf(void) +{ + char str[32]; + float usec; + long long bytes; + int transfers; + + usec = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); + if (echo) { + transfers = transfer_count; + bytes = (long long) transfer_count * transfer_size * 2; + } else { + transfers = ntohl(msg.data); + bytes = (long long) transfers * transfer_size; + } + + /* name size transfers bytes seconds Gb/sec usec/xfer */ + printf("%-10s", test_name); + size_str(str, sizeof str, transfer_size); + printf("%-8s", str); + cnt_str(str, sizeof str, transfers); + printf("%-8s", str); + size_str(str, sizeof str, bytes); + printf("%-8s", str); + printf("%8.2fs%10.2f%11.2f\n", + usec / 1000000., (bytes * 8) / (1000. * usec), + (usec / iterations) / (transfers * 2)); +} + +static void init_latency_test(int size) +{ + char sstr[5]; + + size_str(sstr, sizeof sstr, size); + snprintf(test_name, sizeof test_name, "%s_lat", sstr); + transfer_size = size; + transfer_count = size_to_count(transfer_size) / 10; + echo = 1; +} + +static void init_bandwidth_test(int size) +{ + char sstr[5]; + + size_str(sstr, sizeof sstr, size); + snprintf(test_name, sizeof test_name, "%s_bw", sstr); + transfer_size = size; + transfer_count = size_to_count(transfer_size); + echo = 0; +} + +static void set_options(int rs) +{ + int val; + + if (buffer_size) { + rs_setsockopt(rs, SOL_SOCKET, SO_SNDBUF, (void *) &buffer_size, + sizeof buffer_size); + rs_setsockopt(rs, SOL_SOCKET, SO_RCVBUF, (void *) &buffer_size, + sizeof buffer_size); + } else { + val = 1 << 19; + rs_setsockopt(rs, SOL_SOCKET, SO_SNDBUF, (void *) &val, sizeof val); + rs_setsockopt(rs, SOL_SOCKET, SO_RCVBUF, (void *) &val, sizeof val); + } + + if (flags & MSG_DONTWAIT) + rs_fcntl(rs, F_SETFL, O_NONBLOCK); +} + +static ssize_t svr_send(struct message *msg, size_t size, + union socket_addr *addr, socklen_t addrlen) +{ + struct pollfd fds; + ssize_t ret; + + if (use_async) { + fds.fd = rs; + fds.events = POLLOUT; + } + + do { + if (use_async) { + ret = do_poll(&fds, poll_timeout); + if (ret) + return ret; + } + + ret = rs_sendto(rs, msg, size, flags, &addr->sa, addrlen); + } while (ret < 0 && (errno == EWOULDBLOCK || errno == EAGAIN)); + + if (ret < 0) + perror("rsend"); + + return ret; +} + +static ssize_t svr_recv(struct message *msg, size_t size, + union socket_addr *addr, socklen_t *addrlen) +{ + struct pollfd fds; + ssize_t ret; + + if (use_async) { + fds.fd = rs; + fds.events = POLLIN; + } + + do { + if (use_async) { + ret = do_poll(fds, poll_timeout); + if (ret) + return ret; + } + + ret = rs_recvfrom(rs, msg, size, flags, &addr->sa, addrlen); + } while (ret < 0 && (errno == EWOULDBLOCK || errno == EAGAIN)); + + if (ret < 0) + perror("rrecv"); + + return ret; +} + +static int svr_process(struct message *msg, size_t size, + union socket_addr *addr, socklen_t addrlen) +{ + ssize_t ret; + + switch (msg->op) { + case msg_op_start: + memset(&clients[id], 0, sizeof clients[id]); + msg.id = id++; + break; + case msg_op_echo: + clients[msg->id].recvcnt++; + break; + case msg_op_end: + msg->data = htonl(clients[msg->id].recvcnt); + break; + default: + clients[msg->id].recvcnt++; + return 0; + } + + ret = svr_send(msg, size, addr, addrlen); + return (ret == size) ? 0 : (int) ret; +} + +static int svr_bind(void) +{ + struct addrinfo hints, *res; + int ret; + + memset(&hints, 0, sizeof hints); + hints.ai_socktype = SOCK_DGRAM; + ret = getaddrinfo(src_addr, port, &hints, &res); + if (ret) { + perror("getaddrinfo"); + return ret; + } + + rs = rs_socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (rs < 0) { + perror("rsocket"); + ret = rs; + goto out; + } + + set_options(rs); + ret = rs_bind(rs, res->ai_addr, res->ai_addrlen); + if (ret) { + perror("rbind"); + rs_close(rs); + } + +out: + free(res); + return ret; +} + +static int svr_run(void) +{ + size_t len; + int ret; + + ret = svr_bind(); + while (!ret) { + addrlen = sizeof addr; + len = svr_recv(&msg, sizeof msg, &addr, &addrlen); + if (len < 0) + return len; + + ret = svr_process(&msg, len, &addr, addrlen); + } + return ret; +} + +static ssize_t client_send(struct message *msg, size_t size) +{ + struct pollfd fds; + int ret; + + if (use_async) { + fds.fd = rs; + fds.events = POLLOUT; + } + + do { + if (use_async) { + ret = do_poll(&fds, poll_timeout); + if (ret) + return ret; + } + + ret = rs_send(rs, msg, size, flags); + } while (ret < 0 && (errno == EWOULDBLOCK || errno == EAGAIN)); + + if (ret < 0) + perror("rsend"); + + return ret; +} + +static ssize_t client_recv(struct message *msg, size_t size, int timeout) +{ + struct pollfd fds; + int ret; + + if (timeout) { + fds.fd = rs; + fds.events = POLLIN; + + ret = rs_poll(fds, 1, timeout); + if (ret <= 0) + return ret; + } + + ret = rs_recv(rs, msg, size, flags); + if (ret < 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) + perror("rrecv"); + + return ret; +} + +static int client_send_recv(struct message *msg, size_t size) +{ + int ret; + + do { + ret = client_send(msg, size); + if (ret != size) + return ret; + + ret = client_recv(msg, size, 1); + } while (ret <= 0); + + return ret; +} + +static int run_test(void) +{ + int ret, i, t; + + msg.op = msg_op_start; + ret = client_send_recv(&msg, CTRL_MSG_SIZE); + if (ret != CTRL_MSG_SIZE) + goto out; + + msg.op = echo ? htonl(msg_op_echo) : htonl(msg_op_data); + gettimeofday(&start, NULL); + for (i = 0; i < transfer_count; i++) { + ret = echo ? client_send_recv(&msg, transfer_size) : + client_send(&msg, transfer_size); + if (ret != transfer_size) + goto out; + } + + msg.op = msg_op_end; + ret = client_send_recv(&msg, CTRL_MSG_SIZE); + if (ret != CTRL_MSG_SIZE) + goto out; + + gettimeofday(&end, NULL); + show_perf(); + ret = 0; + +out: + return ret; +} + +static int client_connect(void) +{ + struct addrinfo hints, *res; + int ret; + + memset(&hints, 0, sizeof hints); + hints.ai_socktype = SOCK_DGRAM; + ret = getaddrinfo(dst_addr, port, hints, &res); + if (ret) { + perror("getaddrinfo"); + return ret; + } + + rs = rs_socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (rs < 0) { + perror("rsocket"); + ret = rs; + goto out; + } + + set_options(rs); + ret = rs_connect(rs, res->ai_addr, res->ai_addrlen); + if (ret) { + perror("rconnect"); + rs_close(rs); + } + +out: + freeaddrinfo(res); + return ret; +} + +static int client_run(void) +{ + int i, ret; + + printf("%-10s%-8s%-8s%-8s%8s %10s%13s\n", + "name", "bytes", "xfers", "total", "time", "Gb/sec", "usec/xfer"); + + ret = client_connect(); + if (ret) + return ret; + + if (!custom) { + for (i = 0; i < TEST_CNT; i++) { + init_latency_test(test_size[i]); + run_test(); + } + for (i = 0; i < TEST_CNT; i++) { + init_bandwidth_test(test_size[i]); + run_test(); + } + } else { + run_test(); + } + rs_close(rs); + + return ret; +} + +static int set_test_opt(char *optarg) +{ + if (strlen(optarg) == 1) { + switch (optarg[0]) { + case 's': + use_rs = 0; + break; + case 'a': + use_async = 1; + break; + case 'b': + flags = 0; + break; + case 'n': + flags = MSG_DONTWAIT; + break; + case 'e': + echo = 1; + break; + default: + return -1; + } + } else { + if (!strncasecmp("socket", optarg, 6)) { + use_rs = 0; + } else if (!strncasecmp("async", optarg, 5)) { + use_async = 1; + } else if (!strncasecmp("block", optarg, 5)) { + flags = 0; + } else if (!strncasecmp("nonblock", optarg, 8)) { + flags = MSG_DONTWAIT; + } else if (!strncasecmp("echo", optarg, 4)) { + echo = 1; + } else { + return -1; + } + } + return 0; +} + +int main(int argc, char **argv) +{ + int op, ret; + + while ((op = getopt(argc, argv, "s:b:B:C:S:p:T:")) != -1) { + switch (op) { + case 's': + dst_addr = optarg; + break; + case 'b': + src_addr = optarg; + break; + case 'B': + buffer_size = atoi(optarg); + break; + case 'C': + custom = 1; + transfer_count = atoi(optarg); + break; + case 'S': + custom = 1; + transfer_size = atoi(optarg); + if (transfer_size < CTRL_MSG_SIZE) { + printf("size must be at least %d bytes\n", + CTRL_MSG_SIZE); + exit(1); + } + break; + case 'p': + port = optarg; + break; + case 'T': + if (!set_test_opt(optarg)) + break; + /* invalid option - fall through */ + default: + printf("usage: %s\n", argv[0]); + printf("\t[-s server_address]\n"); + printf("\t[-b bind_address]\n"); + printf("\t[-B buffer_size]\n"); + printf("\t[-C transfer_count]\n"); + printf("\t[-S transfer_size]\n"); + printf("\t[-p port_number]\n"); + printf("\t[-T test_option]\n"); + printf("\t s|sockets - use standard tcp/ip sockets\n"); + printf("\t a|async - asynchronous operation (use poll)\n"); + printf("\t b|blocking - use blocking calls\n"); + printf("\t n|nonblocking - use nonblocking calls\n"); + printf("\t e|echo - server echoes all messages\n"); + exit(1); + } + } + + if (flags) + poll_timeout = -1; + + ret = dst_addr ? client_run() : svr_run(); + return ret; +} -- 2.41.0