• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 
init_socket_opts(int sd)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 
do_cleanup(void)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 }
TST_DECLARE_ONCE_FN(cleanup,do_cleanup)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 
client_recv(int * fd,char * buf)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 
client_connect_send(const char * msg,int size)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 
client_fn(LTP_ATTRIBUTE_UNUSED void * arg)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 
make_client_request(void)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 
parse_client_request(const char * msg)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 
client_init(void)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 
client_run(void)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 
client_cleanup(void)409 static void client_cleanup(void)
410 {
411 	free(thread_ids);
412 
413 	if (remote_addrinfo)
414 		freeaddrinfo(remote_addrinfo);
415 }
416 
make_server_reply(char * send_msg,int size)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 
server_fn(void * cfd)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 
server_thread_add(intptr_t client_fd)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 
server_init(void)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 
server_cleanup(void)554 static void server_cleanup(void)
555 {
556 	SAFE_CLOSE(sfd);
557 }
558 
server_run_udp(void)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 
server_run(void)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 
require_root(const char * file)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 
check_tfo_value(void)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 
check_tw_reuse(void)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 
setup(void)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 
do_test(void)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