1 /* 2 * Copyright (c) 2014-2016 Oracle and/or its affiliates. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of 7 * the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it would be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 * 17 * Author: Alexey Kodanev <alexey.kodanev (at) oracle.com> 18 * 19 */ 20 21 #include <pthread.h> 22 #include <stdlib.h> 23 #include <limits.h> 24 #include <sys/types.h> 25 #include <sys/socket.h> 26 #include <netdb.h> 27 #include <netinet/in.h> 28 #include <arpa/inet.h> 29 #include <poll.h> 30 #include <time.h> 31 #include <string.h> 32 #include <unistd.h> 33 #include <errno.h> 34 35 #include "lapi/posix_clocks.h" 36 #include "tst_safe_pthread.h" 37 #include "tst_test.h" 38 39 static const int max_msg_len = (1 << 16) - 1; 40 41 /* TCP server requiers */ 42 #ifndef TCP_FASTOPEN 43 #define TCP_FASTOPEN 23 44 #endif 45 46 #ifndef SO_BUSY_POLL 47 #define SO_BUSY_POLL 46 48 #endif 49 50 /* TCP client requiers */ 51 #ifndef MSG_FASTOPEN 52 #define MSG_FASTOPEN 0x20000000 /* Send data in TCP SYN */ 53 #endif 54 55 enum { 56 SERVER_HOST = 0, 57 CLIENT_HOST, 58 }; 59 static char *client_mode; 60 61 enum { 62 TFO_DISABLED = 0, 63 TFO_ENABLED, 64 }; 65 static int tfo_value = -1; 66 static char *fastopen_api; 67 68 static const char tfo_cfg[] = "/proc/sys/net/ipv4/tcp_fastopen"; 69 static const char tcp_tw_reuse[] = "/proc/sys/net/ipv4/tcp_tw_reuse"; 70 static int tw_reuse_changed; 71 static int tfo_cfg_value; 72 static int tfo_cfg_changed; 73 static int tfo_queue_size = 100; 74 static int max_queue_len = 100; 75 static const int client_byte = 0x43; 76 static const int server_byte = 0x53; 77 static const int start_byte = 0x24; 78 static const int start_fin_byte = 0x25; 79 static const int end_byte = 0x0a; 80 static int client_msg_size = 32; 81 static int server_msg_size = 128; 82 static char *client_msg; 83 static char *server_msg; 84 85 /* 86 * The number of requests from client after 87 * which server has to close the connection. 88 */ 89 static int server_max_requests = 3; 90 static int client_max_requests = 10; 91 static int clients_num; 92 static char *tcp_port = "61000"; 93 static char *server_addr = "localhost"; 94 static int busy_poll = -1; 95 static char *use_udp; 96 /* server socket */ 97 static int sfd; 98 99 /* how long a client must wait for the server's reply, microsec */ 100 static long wait_timeout = 60000000L; 101 102 /* in the end test will save time result in this file */ 103 static char *rpath = "tfo_result"; 104 105 static char *verbose; 106 107 static char *narg, *Narg, *qarg, *rarg, *Rarg, *aarg, *Targ, *barg, *targ; 108 109 /* common structure for TCP/UDP server and TCP/UDP client */ 110 struct net_func { 111 void (*init)(void); 112 void (*run)(void); 113 void (*cleanup)(void); 114 }; 115 static struct net_func net; 116 117 #define MAX_THREADS 10000 118 static pthread_attr_t attr; 119 static pthread_t *thread_ids; 120 121 static struct addrinfo *remote_addrinfo; 122 static struct addrinfo *local_addrinfo; 123 static struct sockaddr_storage remote_addr; 124 static socklen_t remote_addr_len; 125 126 static void init_socket_opts(int sd) 127 { 128 if (busy_poll >= 0) { 129 SAFE_SETSOCKOPT(sd, SOL_SOCKET, SO_BUSY_POLL, 130 &busy_poll, sizeof(busy_poll)); 131 } 132 } 133 134 static void do_cleanup(void) 135 { 136 free(client_msg); 137 free(server_msg); 138 139 if (net.cleanup) 140 net.cleanup(); 141 142 if (tfo_cfg_changed) { 143 tst_res(TINFO, "unset '%s' back to '%d'", 144 tfo_cfg, tfo_cfg_value); 145 SAFE_FILE_PRINTF(tfo_cfg, "%d", tfo_cfg_value); 146 } 147 148 if (tw_reuse_changed) { 149 SAFE_FILE_PRINTF(tcp_tw_reuse, "0"); 150 tst_res(TINFO, "unset '%s' back to '0'", tcp_tw_reuse); 151 } 152 } 153 TST_DECLARE_ONCE_FN(cleanup, do_cleanup) 154 155 static int sock_recv_poll(int fd, char *buf, int buf_size, int offset) 156 { 157 struct pollfd pfd; 158 pfd.fd = fd; 159 pfd.events = POLLIN; 160 int len = -1; 161 162 while (1) { 163 errno = 0; 164 int ret = poll(&pfd, 1, wait_timeout / 1000); 165 if (ret == -1) { 166 if (errno == EINTR) 167 continue; 168 break; 169 } 170 171 if (ret == 0) { 172 errno = ETIME; 173 break; 174 } 175 176 if (ret != 1 || !(pfd.revents & POLLIN)) 177 break; 178 179 errno = 0; 180 len = recvfrom(fd, buf + offset, buf_size - offset, 181 MSG_DONTWAIT, (struct sockaddr *)&remote_addr, 182 &remote_addr_len); 183 184 if (len == -1 && errno == EINTR) 185 continue; 186 187 break; 188 } 189 190 return len; 191 } 192 193 static int client_recv(int *fd, char *buf) 194 { 195 int len, offset = 0; 196 197 while (1) { 198 errno = 0; 199 len = sock_recv_poll(*fd, buf, server_msg_size, offset); 200 201 /* socket closed or msg is not valid */ 202 if (len < 1 || (offset + len) > server_msg_size || 203 (buf[0] != start_byte && buf[0] != start_fin_byte)) { 204 if (!errno) 205 errno = ENOMSG; 206 break; 207 } 208 offset += len; 209 if (buf[offset - 1] != end_byte) 210 continue; 211 212 if (verbose) { 213 tst_res_hexd(TINFO, buf, offset, 214 "msg recv from sock %d:", *fd); 215 } 216 217 /* recv last msg, close socket */ 218 if (buf[0] == start_fin_byte) 219 break; 220 return 0; 221 } 222 223 SAFE_CLOSE(*fd); 224 return (errno) ? -1 : 0; 225 } 226 227 static int client_connect_send(const char *msg, int size) 228 { 229 int cfd = SAFE_SOCKET(remote_addrinfo->ai_family, 230 remote_addrinfo->ai_socktype, 0); 231 232 init_socket_opts(cfd); 233 234 if (fastopen_api) { 235 /* Replaces connect() + send()/write() */ 236 SAFE_SENDTO(1, cfd, msg, size, MSG_FASTOPEN | MSG_NOSIGNAL, 237 remote_addrinfo->ai_addr, remote_addrinfo->ai_addrlen); 238 } else { 239 /* old TCP API */ 240 SAFE_CONNECT(cfd, remote_addrinfo->ai_addr, 241 remote_addrinfo->ai_addrlen); 242 SAFE_SEND(1, cfd, msg, size, MSG_NOSIGNAL); 243 } 244 245 return cfd; 246 } 247 248 void *client_fn(LTP_ATTRIBUTE_UNUSED void *arg) 249 { 250 char buf[server_msg_size]; 251 int cfd, i = 0; 252 intptr_t err = 0; 253 254 /* connect & send requests */ 255 cfd = client_connect_send(client_msg, client_msg_size); 256 if (cfd == -1) { 257 err = errno; 258 goto out; 259 } 260 261 if (client_recv(&cfd, buf)) { 262 err = errno; 263 goto out; 264 } 265 266 for (i = 1; i < client_max_requests; ++i) { 267 if (use_udp) 268 goto send; 269 270 if (cfd == -1) { 271 cfd = client_connect_send(client_msg, client_msg_size); 272 if (cfd == -1) { 273 err = errno; 274 goto out; 275 } 276 277 if (client_recv(&cfd, buf)) { 278 err = errno; 279 break; 280 } 281 continue; 282 } 283 284 send: 285 if (verbose) { 286 tst_res_hexd(TINFO, client_msg, client_msg_size, 287 "try to send msg[%d]", i); 288 } 289 290 SAFE_SEND(1, cfd, client_msg, client_msg_size, MSG_NOSIGNAL); 291 292 if (client_recv(&cfd, buf)) { 293 err = errno; 294 break; 295 } 296 } 297 298 if (cfd != -1) 299 SAFE_CLOSE(cfd); 300 301 out: 302 if (i != client_max_requests) 303 tst_res(TWARN, "client exit on '%d' request", i); 304 305 return (void *) err; 306 } 307 308 union net_size_field { 309 char bytes[2]; 310 uint16_t value; 311 }; 312 313 static void make_client_request(void) 314 { 315 client_msg[0] = start_byte; 316 317 /* set size for reply */ 318 union net_size_field net_size; 319 net_size.value = htons(server_msg_size); 320 client_msg[1] = net_size.bytes[0]; 321 client_msg[2] = net_size.bytes[1]; 322 323 client_msg[client_msg_size - 1] = end_byte; 324 } 325 326 static int parse_client_request(const char *msg) 327 { 328 union net_size_field net_size; 329 net_size.bytes[0] = msg[1]; 330 net_size.bytes[1] = msg[2]; 331 int size = ntohs(net_size.value); 332 if (size < 2 || size > max_msg_len) 333 return -1; 334 335 return size; 336 } 337 338 static struct timespec tv_client_start; 339 static struct timespec tv_client_end; 340 341 static void client_init(void) 342 { 343 if (clients_num >= MAX_THREADS) { 344 tst_brk(TBROK, "Unexpected num of clients '%d'", 345 clients_num); 346 } 347 348 thread_ids = SAFE_MALLOC(sizeof(pthread_t) * clients_num); 349 350 client_msg = SAFE_MALLOC(client_msg_size); 351 memset(client_msg, client_byte, client_msg_size); 352 353 make_client_request(); 354 355 struct addrinfo hints; 356 memset(&hints, 0, sizeof(struct addrinfo)); 357 hints.ai_family = AF_UNSPEC; 358 hints.ai_socktype = (use_udp) ? SOCK_DGRAM : SOCK_STREAM; 359 hints.ai_flags = 0; 360 hints.ai_protocol = 0; 361 362 int err = getaddrinfo(server_addr, tcp_port, &hints, &remote_addrinfo); 363 if (err) { 364 tst_brk(TBROK, "getaddrinfo of '%s' failed, %s", 365 server_addr, gai_strerror(err)); 366 } 367 368 tst_res(TINFO, "Running the test over IPv%s", 369 (remote_addrinfo->ai_family == AF_INET6) ? "6" : "4"); 370 371 clock_gettime(CLOCK_MONOTONIC_RAW, &tv_client_start); 372 int i; 373 for (i = 0; i < clients_num; ++i) 374 SAFE_PTHREAD_CREATE(&thread_ids[i], 0, client_fn, NULL); 375 } 376 377 static void client_run(void) 378 { 379 void *res = NULL; 380 long clnt_time = 0; 381 int i; 382 for (i = 0; i < clients_num; ++i) { 383 pthread_join(thread_ids[i], &res); 384 if (res) { 385 tst_brk(TBROK, "client[%d] failed: %s", 386 i, strerror((intptr_t)res)); 387 } 388 } 389 390 clock_gettime(CLOCK_MONOTONIC_RAW, &tv_client_end); 391 clnt_time = (tv_client_end.tv_sec - tv_client_start.tv_sec) * 1000 + 392 (tv_client_end.tv_nsec - tv_client_start.tv_nsec) / 1000000; 393 394 tst_res(TINFO, "total time '%ld' ms", clnt_time); 395 396 /* ask server to terminate */ 397 client_msg[0] = start_fin_byte; 398 int cfd = client_connect_send(client_msg, client_msg_size); 399 if (cfd != -1) { 400 shutdown(cfd, SHUT_WR); 401 SAFE_CLOSE(cfd); 402 } 403 /* the script tcp_fastopen_run.sh will remove it */ 404 SAFE_FILE_PRINTF(rpath, "%ld", clnt_time); 405 406 tst_res(TPASS, "test completed"); 407 } 408 409 static void client_cleanup(void) 410 { 411 free(thread_ids); 412 413 if (remote_addrinfo) 414 freeaddrinfo(remote_addrinfo); 415 } 416 417 static void make_server_reply(char *send_msg, int size) 418 { 419 memset(send_msg, server_byte, size - 1); 420 send_msg[0] = start_byte; 421 send_msg[size - 1] = end_byte; 422 } 423 424 void *server_fn(void *cfd) 425 { 426 int client_fd = (intptr_t) cfd; 427 int num_requests = 0, offset = 0; 428 /* Reply will be constructed from first client request */ 429 char send_msg[max_msg_len]; 430 int send_msg_size = 0; 431 char recv_msg[max_msg_len]; 432 ssize_t recv_len; 433 434 send_msg[0] = '\0'; 435 436 init_socket_opts(client_fd); 437 438 while (1) { 439 recv_len = sock_recv_poll(client_fd, recv_msg, 440 max_msg_len, offset); 441 442 if (recv_len == 0) 443 break; 444 445 if (recv_len < 0 || (offset + recv_len) > max_msg_len || 446 (recv_msg[0] != start_byte && 447 recv_msg[0] != start_fin_byte)) { 448 tst_res(TFAIL, "recv failed, sock '%d'", client_fd); 449 goto out; 450 } 451 452 offset += recv_len; 453 454 if (recv_msg[offset - 1] != end_byte) { 455 /* msg is not complete, continue recv */ 456 continue; 457 } 458 459 /* client asks to terminate */ 460 if (recv_msg[0] == start_fin_byte) 461 goto out; 462 463 if (verbose) { 464 tst_res_hexd(TINFO, recv_msg, offset, 465 "msg recv from sock %d:", client_fd); 466 } 467 468 /* if we send reply for the first time, construct it here */ 469 if (send_msg[0] != start_byte) { 470 send_msg_size = parse_client_request(recv_msg); 471 if (send_msg_size < 0) { 472 tst_res(TFAIL, "wrong msg size '%d'", 473 send_msg_size); 474 goto out; 475 } 476 make_server_reply(send_msg, send_msg_size); 477 } 478 479 offset = 0; 480 481 /* 482 * It will tell client that server is going 483 * to close this connection. 484 */ 485 if (!use_udp && ++num_requests >= server_max_requests) 486 send_msg[0] = start_fin_byte; 487 488 SAFE_SENDTO(1, client_fd, send_msg, send_msg_size, MSG_NOSIGNAL, 489 (struct sockaddr *)&remote_addr, remote_addr_len); 490 491 if (!use_udp && num_requests >= server_max_requests) { 492 /* max reqs, close socket */ 493 shutdown(client_fd, SHUT_WR); 494 break; 495 } 496 } 497 498 SAFE_CLOSE(client_fd); 499 return NULL; 500 501 out: 502 SAFE_CLOSE(client_fd); 503 tst_brk(TBROK, "Server closed"); 504 return NULL; 505 } 506 507 static pthread_t server_thread_add(intptr_t client_fd) 508 { 509 pthread_t id; 510 SAFE_PTHREAD_CREATE(&id, &attr, server_fn, (void *) client_fd); 511 return id; 512 } 513 514 static void server_init(void) 515 { 516 struct addrinfo hints; 517 memset(&hints, 0, sizeof(struct addrinfo)); 518 hints.ai_family = AF_INET6; 519 hints.ai_socktype = (use_udp) ? SOCK_DGRAM : SOCK_STREAM; 520 hints.ai_flags = AI_PASSIVE; 521 522 int err = getaddrinfo(NULL, tcp_port, &hints, &local_addrinfo); 523 524 if (err) 525 tst_brk(TBROK, "getaddrinfo failed, %s", gai_strerror(err)); 526 527 if (!local_addrinfo) 528 tst_brk(TBROK, "failed to get the address"); 529 530 /* IPv6 socket is also able to access IPv4 protocol stack */ 531 sfd = SAFE_SOCKET(AF_INET6, local_addrinfo->ai_socktype, 0); 532 const int flag = 1; 533 SAFE_SETSOCKOPT(sfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); 534 535 tst_res(TINFO, "assigning a name to the server socket..."); 536 SAFE_BIND(sfd, local_addrinfo->ai_addr, local_addrinfo->ai_addrlen); 537 538 freeaddrinfo(local_addrinfo); 539 540 if (use_udp) 541 return; 542 543 init_socket_opts(sfd); 544 545 if (fastopen_api) { 546 SAFE_SETSOCKOPT(sfd, IPPROTO_TCP, TCP_FASTOPEN, 547 &tfo_queue_size, sizeof(tfo_queue_size)); 548 } 549 550 SAFE_LISTEN(sfd, max_queue_len); 551 tst_res(TINFO, "Listen on the socket '%d', port '%s'", sfd, tcp_port); 552 } 553 554 static void server_cleanup(void) 555 { 556 SAFE_CLOSE(sfd); 557 } 558 559 static void server_run_udp(void) 560 { 561 pthread_t p_id = server_thread_add(sfd); 562 563 SAFE_PTHREAD_JOIN(p_id, NULL); 564 } 565 566 static void server_run(void) 567 { 568 /* IPv4 source address will be mapped to IPv6 address */ 569 struct sockaddr_in6 addr6; 570 socklen_t addr_size = sizeof(addr6); 571 572 pthread_attr_init(&attr); 573 574 /* 575 * detaching threads allow to reclaim thread's resources 576 * once a thread finishes its work. 577 */ 578 if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) 579 tst_brk(TBROK | TERRNO, "setdetachstate failed"); 580 581 while (1) { 582 int client_fd = accept(sfd, (struct sockaddr *)&addr6, 583 &addr_size); 584 585 if (client_fd == -1) 586 tst_brk(TBROK, "Can't create client socket"); 587 588 if (verbose) { 589 char addr_buf[INET6_ADDRSTRLEN]; 590 tst_res(TINFO, "conn: port '%d', addr '%s'", 591 addr6.sin6_port, inet_ntop(AF_INET6, 592 &addr6.sin6_addr, addr_buf, INET6_ADDRSTRLEN)); 593 } 594 595 server_thread_add(client_fd); 596 } 597 } 598 599 static void require_root(const char *file) 600 { 601 if (!geteuid()) 602 return; 603 tst_brk(TCONF, "Test needs to be run as root to change %s", file); 604 } 605 606 static void check_tfo_value(void) 607 { 608 /* Check if we can write to tcp_fastopen knob. We might be 609 * inside netns and either have read-only permission or 610 * doesn't have the knob at all. 611 */ 612 if (access(tfo_cfg, W_OK) < 0) { 613 /* TODO check /proc/self/ns/ or TST_USE_NETNS env var */ 614 tst_res(TINFO, "can't read %s, assume server runs in netns", 615 tfo_cfg); 616 return; 617 } 618 619 SAFE_FILE_SCANF(tfo_cfg, "%d", &tfo_cfg_value); 620 tst_res(TINFO, "'%s' is %d", tfo_cfg, tfo_cfg_value); 621 622 /* The check can be the first in this function but set here 623 * to allow to print information about the currently set config 624 */ 625 if (tfo_value < 0) 626 return; 627 628 if (tfo_cfg_value == tfo_value) 629 return; 630 631 require_root(tfo_cfg); 632 633 tst_res(TINFO, "set '%s' to '%d'", tfo_cfg, tfo_value); 634 635 SAFE_FILE_PRINTF(tfo_cfg, "%d", tfo_value); 636 tfo_cfg_changed = 1; 637 } 638 639 static void check_tw_reuse(void) 640 { 641 if (access(tcp_tw_reuse, W_OK) < 0) 642 return; 643 644 int reuse_value = 0; 645 646 SAFE_FILE_SCANF(tcp_tw_reuse, "%d", &reuse_value); 647 if (reuse_value) { 648 tst_res(TINFO, "tcp_tw_reuse is already set"); 649 return; 650 } 651 652 require_root(tfo_cfg); 653 654 SAFE_FILE_PRINTF(tcp_tw_reuse, "1"); 655 tw_reuse_changed = 1; 656 tst_res(TINFO, "set '%s' to '1'", tcp_tw_reuse); 657 } 658 659 static void setup(void) 660 { 661 if (tst_parse_int(aarg, &clients_num, 1, INT_MAX)) 662 tst_brk(TBROK, "Invalid client number '%s'", aarg); 663 if (tst_parse_int(rarg, &client_max_requests, 1, INT_MAX)) 664 tst_brk(TBROK, "Invalid client max requests '%s'", rarg); 665 if (tst_parse_int(Rarg, &server_max_requests, 1, INT_MAX)) 666 tst_brk(TBROK, "Invalid server max requests '%s'", Rarg); 667 if (tst_parse_int(narg, &client_msg_size, 3, max_msg_len)) 668 tst_brk(TBROK, "Invalid client msg size '%s'", narg); 669 if (tst_parse_int(Narg, &server_msg_size, 3, max_msg_len)) 670 tst_brk(TBROK, "Invalid server msg size '%s'", Narg); 671 if (tst_parse_int(qarg, &tfo_queue_size, 1, INT_MAX)) 672 tst_brk(TBROK, "Invalid TFO queue size '%s'", qarg); 673 if (tst_parse_long(Targ, &wait_timeout, 0L, LONG_MAX)) 674 tst_brk(TBROK, "Invalid wait timeout '%s'", Targ); 675 if (tst_parse_int(barg, &busy_poll, 0, INT_MAX)) 676 tst_brk(TBROK, "Invalid busy poll timeout'%s'", barg); 677 if (tst_parse_int(targ, &tfo_value, 0, INT_MAX)) 678 tst_brk(TBROK, "Invalid net.ipv4.tcp_fastopen '%s'", targ); 679 680 /* if client_num is not set, use num of processors */ 681 if (!clients_num) 682 clients_num = sysconf(_SC_NPROCESSORS_ONLN); 683 684 if (tfo_value > 0 && tst_kvercmp(3, 7, 0) < 0) 685 tst_brk(TCONF, "Test must be run with kernel 3.7 or newer"); 686 687 if (busy_poll >= 0 && tst_kvercmp(3, 11, 0) < 0) 688 tst_brk(TCONF, "Test must be run with kernel 3.11 or newer"); 689 690 if (client_mode) { 691 tst_res(TINFO, "connection: addr '%s', port '%s'", 692 server_addr, tcp_port); 693 tst_res(TINFO, "client max req: %d", client_max_requests); 694 tst_res(TINFO, "clients num: %d", clients_num); 695 tst_res(TINFO, "client msg size: %d", client_msg_size); 696 tst_res(TINFO, "server msg size: %d", server_msg_size); 697 net.init = client_init; 698 net.run = client_run; 699 net.cleanup = client_cleanup; 700 701 check_tw_reuse(); 702 } else { 703 tst_res(TINFO, "max requests '%d'", 704 server_max_requests); 705 net.init = server_init; 706 net.run = (use_udp) ? server_run_udp : server_run; 707 net.cleanup = (use_udp) ? NULL : server_cleanup; 708 } 709 710 remote_addr_len = sizeof(struct sockaddr_storage); 711 712 if (use_udp) { 713 tst_res(TINFO, "using UDP"); 714 fastopen_api = NULL; 715 } else { 716 tst_res(TINFO, "TCP %s is using %s TCP API.", 717 (client_mode) ? "client" : "server", 718 (fastopen_api) ? "Fastopen" : "old"); 719 720 check_tfo_value(); 721 } 722 723 net.init(); 724 } 725 726 static void do_test(void) 727 { 728 net.run(); 729 } 730 731 static struct tst_option options[] = { 732 {"v", &verbose, "-v Verbose"}, 733 {"f", &fastopen_api, "-f Use TFO API, default is old API"}, 734 {"t:", &targ, "-t x Set tcp_fastopen value"}, 735 736 {"g:", &tcp_port, "-g x x - server port"}, 737 {"b:", &barg, "-b x x - low latency busy poll timeout"}, 738 {"U", &use_udp, "-U Use UDP\n"}, 739 740 {"H:", &server_addr, "Client:\n-H x Server name or IP address"}, 741 {"l", &client_mode, "-l Become client, default is server"}, 742 {"a:", &aarg, "-a x Number of clients running in parallel"}, 743 {"r:", &rarg, "-r x Number of client requests"}, 744 {"n:", &narg, "-n x Client message size"}, 745 {"N:", &Narg, "-N x Server message size"}, 746 {"T:", &Targ, "-T x Reply timeout in microsec."}, 747 {"d:", &rpath, "-d x x is a path to file where result is saved\n"}, 748 749 {"R:", &Rarg, "Server:\n-R x x requests after which conn.closed"}, 750 {"q:", &qarg, "-q x x - TFO queue"}, 751 {NULL, NULL, NULL} 752 }; 753 754 static struct tst_test test = { 755 .tid = "netstress", 756 .test_all = do_test, 757 .setup = setup, 758 .cleanup = cleanup, 759 .options = options 760 }; 761