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