1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2014-2016 Oracle and/or its affiliates. All Rights Reserved.
4*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2014-2023 Petr Vorel <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker * Author: Alexey Kodanev <[email protected]>
6*49cdfc7eSAndroid Build Coastguard Worker */
7*49cdfc7eSAndroid Build Coastguard Worker
8*49cdfc7eSAndroid Build Coastguard Worker #include <pthread.h>
9*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
10*49cdfc7eSAndroid Build Coastguard Worker #include <limits.h>
11*49cdfc7eSAndroid Build Coastguard Worker #include <linux/dccp.h>
12*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
13*49cdfc7eSAndroid Build Coastguard Worker #include <sys/socket.h>
14*49cdfc7eSAndroid Build Coastguard Worker #include <netdb.h>
15*49cdfc7eSAndroid Build Coastguard Worker #include <netinet/in.h>
16*49cdfc7eSAndroid Build Coastguard Worker #include <netinet/tcp.h>
17*49cdfc7eSAndroid Build Coastguard Worker #include <arpa/inet.h>
18*49cdfc7eSAndroid Build Coastguard Worker #include <poll.h>
19*49cdfc7eSAndroid Build Coastguard Worker #include <time.h>
20*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
21*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
22*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
23*49cdfc7eSAndroid Build Coastguard Worker
24*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/udp.h"
25*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/dccp.h"
26*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/netinet_in.h"
27*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/posix_clocks.h"
28*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/socket.h"
29*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/tcp.h"
30*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_stdio.h"
31*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_pthread.h"
32*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
33*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_net.h"
34*49cdfc7eSAndroid Build Coastguard Worker
35*49cdfc7eSAndroid Build Coastguard Worker #if !defined(HAVE_RAND_R)
rand_r(LTP_ATTRIBUTE_UNUSED unsigned int * seed)36*49cdfc7eSAndroid Build Coastguard Worker static int rand_r(LTP_ATTRIBUTE_UNUSED unsigned int *seed)
37*49cdfc7eSAndroid Build Coastguard Worker {
38*49cdfc7eSAndroid Build Coastguard Worker return rand();
39*49cdfc7eSAndroid Build Coastguard Worker }
40*49cdfc7eSAndroid Build Coastguard Worker #endif
41*49cdfc7eSAndroid Build Coastguard Worker
42*49cdfc7eSAndroid Build Coastguard Worker static const int max_msg_len = (1 << 16) - 1;
43*49cdfc7eSAndroid Build Coastguard Worker static const int min_msg_len = 5;
44*49cdfc7eSAndroid Build Coastguard Worker
45*49cdfc7eSAndroid Build Coastguard Worker enum {
46*49cdfc7eSAndroid Build Coastguard Worker SERVER_HOST = 0,
47*49cdfc7eSAndroid Build Coastguard Worker CLIENT_HOST,
48*49cdfc7eSAndroid Build Coastguard Worker };
49*49cdfc7eSAndroid Build Coastguard Worker static char *client_mode;
50*49cdfc7eSAndroid Build Coastguard Worker
51*49cdfc7eSAndroid Build Coastguard Worker enum {
52*49cdfc7eSAndroid Build Coastguard Worker TFO_DISABLED = 0,
53*49cdfc7eSAndroid Build Coastguard Worker TFO_ENABLED,
54*49cdfc7eSAndroid Build Coastguard Worker };
55*49cdfc7eSAndroid Build Coastguard Worker static int tfo_value = -1;
56*49cdfc7eSAndroid Build Coastguard Worker static char *fastopen_api, *fastopen_sapi;
57*49cdfc7eSAndroid Build Coastguard Worker
58*49cdfc7eSAndroid Build Coastguard Worker static const char tfo_cfg[] = "/proc/sys/net/ipv4/tcp_fastopen";
59*49cdfc7eSAndroid Build Coastguard Worker static const char tcp_tw_reuse[] = "/proc/sys/net/ipv4/tcp_tw_reuse";
60*49cdfc7eSAndroid Build Coastguard Worker static int tw_reuse_changed;
61*49cdfc7eSAndroid Build Coastguard Worker static int tfo_cfg_value;
62*49cdfc7eSAndroid Build Coastguard Worker static int tfo_cfg_changed;
63*49cdfc7eSAndroid Build Coastguard Worker static int tfo_queue_size = 100;
64*49cdfc7eSAndroid Build Coastguard Worker static int max_queue_len = 100;
65*49cdfc7eSAndroid Build Coastguard Worker static const int client_byte = 0x43;
66*49cdfc7eSAndroid Build Coastguard Worker static const int server_byte = 0x53;
67*49cdfc7eSAndroid Build Coastguard Worker static const int start_byte = 0x24;
68*49cdfc7eSAndroid Build Coastguard Worker static const int start_fin_byte = 0x25;
69*49cdfc7eSAndroid Build Coastguard Worker static const int end_byte = 0x0a;
70*49cdfc7eSAndroid Build Coastguard Worker static int init_cln_msg_len = 32;
71*49cdfc7eSAndroid Build Coastguard Worker static int init_srv_msg_len = 128;
72*49cdfc7eSAndroid Build Coastguard Worker static int max_rand_msg_len;
73*49cdfc7eSAndroid Build Coastguard Worker static int init_seed;
74*49cdfc7eSAndroid Build Coastguard Worker
75*49cdfc7eSAndroid Build Coastguard Worker /*
76*49cdfc7eSAndroid Build Coastguard Worker * The number of requests from client after
77*49cdfc7eSAndroid Build Coastguard Worker * which server has to close the connection.
78*49cdfc7eSAndroid Build Coastguard Worker */
79*49cdfc7eSAndroid Build Coastguard Worker static int server_max_requests = 3;
80*49cdfc7eSAndroid Build Coastguard Worker static int client_max_requests = 10;
81*49cdfc7eSAndroid Build Coastguard Worker static int clients_num;
82*49cdfc7eSAndroid Build Coastguard Worker static char *tcp_port;
83*49cdfc7eSAndroid Build Coastguard Worker static char *server_addr;
84*49cdfc7eSAndroid Build Coastguard Worker static char *source_addr;
85*49cdfc7eSAndroid Build Coastguard Worker static char *server_bg;
86*49cdfc7eSAndroid Build Coastguard Worker static int busy_poll = -1;
87*49cdfc7eSAndroid Build Coastguard Worker static int max_etime_cnt = 21; /* ~60 sec max timeout if no connection */
88*49cdfc7eSAndroid Build Coastguard Worker static int max_eshutdown_cnt = 10;
89*49cdfc7eSAndroid Build Coastguard Worker static int max_pmtu_err = 10;
90*49cdfc7eSAndroid Build Coastguard Worker
91*49cdfc7eSAndroid Build Coastguard Worker enum {
92*49cdfc7eSAndroid Build Coastguard Worker TYPE_TCP = 0,
93*49cdfc7eSAndroid Build Coastguard Worker TYPE_UDP,
94*49cdfc7eSAndroid Build Coastguard Worker TYPE_UDP_LITE,
95*49cdfc7eSAndroid Build Coastguard Worker TYPE_DCCP,
96*49cdfc7eSAndroid Build Coastguard Worker TYPE_SCTP
97*49cdfc7eSAndroid Build Coastguard Worker };
98*49cdfc7eSAndroid Build Coastguard Worker static uint proto_type;
99*49cdfc7eSAndroid Build Coastguard Worker static char *type;
100*49cdfc7eSAndroid Build Coastguard Worker static char *dev;
101*49cdfc7eSAndroid Build Coastguard Worker static int sock_type = SOCK_STREAM;
102*49cdfc7eSAndroid Build Coastguard Worker static int protocol;
103*49cdfc7eSAndroid Build Coastguard Worker static int family = AF_INET6;
104*49cdfc7eSAndroid Build Coastguard Worker
105*49cdfc7eSAndroid Build Coastguard Worker static uint32_t service_code = 0xffff;
106*49cdfc7eSAndroid Build Coastguard Worker
107*49cdfc7eSAndroid Build Coastguard Worker /* server socket */
108*49cdfc7eSAndroid Build Coastguard Worker static int sfd;
109*49cdfc7eSAndroid Build Coastguard Worker
110*49cdfc7eSAndroid Build Coastguard Worker /* how long a client must wait for the server's reply */
111*49cdfc7eSAndroid Build Coastguard Worker static int wait_timeout = 60000;
112*49cdfc7eSAndroid Build Coastguard Worker
113*49cdfc7eSAndroid Build Coastguard Worker /* in the end test will save time result in this file */
114*49cdfc7eSAndroid Build Coastguard Worker static char *rpath;
115*49cdfc7eSAndroid Build Coastguard Worker static char *port_path = "netstress_port";
116*49cdfc7eSAndroid Build Coastguard Worker static char *log_path = "netstress.log";
117*49cdfc7eSAndroid Build Coastguard Worker
118*49cdfc7eSAndroid Build Coastguard Worker static char *narg, *Narg, *qarg, *rarg, *Rarg, *aarg, *Targ, *barg, *targ,
119*49cdfc7eSAndroid Build Coastguard Worker *Aarg;
120*49cdfc7eSAndroid Build Coastguard Worker
121*49cdfc7eSAndroid Build Coastguard Worker /* common structure for TCP/UDP server and TCP/UDP client */
122*49cdfc7eSAndroid Build Coastguard Worker struct net_func {
123*49cdfc7eSAndroid Build Coastguard Worker void (*init)(void);
124*49cdfc7eSAndroid Build Coastguard Worker void (*run)(void);
125*49cdfc7eSAndroid Build Coastguard Worker void (*cleanup)(void);
126*49cdfc7eSAndroid Build Coastguard Worker };
127*49cdfc7eSAndroid Build Coastguard Worker static struct net_func net;
128*49cdfc7eSAndroid Build Coastguard Worker
129*49cdfc7eSAndroid Build Coastguard Worker #define MAX_THREADS 10000
130*49cdfc7eSAndroid Build Coastguard Worker static pthread_attr_t attr;
131*49cdfc7eSAndroid Build Coastguard Worker static pthread_t *thread_ids;
132*49cdfc7eSAndroid Build Coastguard Worker
133*49cdfc7eSAndroid Build Coastguard Worker static struct addrinfo *remote_addrinfo;
134*49cdfc7eSAndroid Build Coastguard Worker static struct addrinfo *local_addrinfo;
135*49cdfc7eSAndroid Build Coastguard Worker
136*49cdfc7eSAndroid Build Coastguard Worker struct sock_info {
137*49cdfc7eSAndroid Build Coastguard Worker int fd;
138*49cdfc7eSAndroid Build Coastguard Worker struct sockaddr_storage raddr;
139*49cdfc7eSAndroid Build Coastguard Worker socklen_t raddr_len;
140*49cdfc7eSAndroid Build Coastguard Worker int etime_cnt;
141*49cdfc7eSAndroid Build Coastguard Worker int pmtu_err_cnt;
142*49cdfc7eSAndroid Build Coastguard Worker int eshutdown_cnt;
143*49cdfc7eSAndroid Build Coastguard Worker int timeout;
144*49cdfc7eSAndroid Build Coastguard Worker };
145*49cdfc7eSAndroid Build Coastguard Worker
146*49cdfc7eSAndroid Build Coastguard Worker static char *zcopy;
147*49cdfc7eSAndroid Build Coastguard Worker static int send_flags = MSG_NOSIGNAL;
148*49cdfc7eSAndroid Build Coastguard Worker static char *reuse_port;
149*49cdfc7eSAndroid Build Coastguard Worker
init_socket_opts(int sd)150*49cdfc7eSAndroid Build Coastguard Worker static void init_socket_opts(int sd)
151*49cdfc7eSAndroid Build Coastguard Worker {
152*49cdfc7eSAndroid Build Coastguard Worker if (busy_poll >= 0)
153*49cdfc7eSAndroid Build Coastguard Worker SAFE_SETSOCKOPT_INT(sd, SOL_SOCKET, SO_BUSY_POLL, busy_poll);
154*49cdfc7eSAndroid Build Coastguard Worker
155*49cdfc7eSAndroid Build Coastguard Worker if (dev)
156*49cdfc7eSAndroid Build Coastguard Worker SAFE_SETSOCKOPT(sd, SOL_SOCKET, SO_BINDTODEVICE, dev,
157*49cdfc7eSAndroid Build Coastguard Worker strlen(dev) + 1);
158*49cdfc7eSAndroid Build Coastguard Worker
159*49cdfc7eSAndroid Build Coastguard Worker switch (proto_type) {
160*49cdfc7eSAndroid Build Coastguard Worker case TYPE_TCP:
161*49cdfc7eSAndroid Build Coastguard Worker if (client_mode && fastopen_sapi) {
162*49cdfc7eSAndroid Build Coastguard Worker SAFE_SETSOCKOPT_INT(sd, IPPROTO_TCP,
163*49cdfc7eSAndroid Build Coastguard Worker TCP_FASTOPEN_CONNECT, 1);
164*49cdfc7eSAndroid Build Coastguard Worker }
165*49cdfc7eSAndroid Build Coastguard Worker if (client_mode && zcopy)
166*49cdfc7eSAndroid Build Coastguard Worker SAFE_SETSOCKOPT_INT(sd, SOL_SOCKET, SO_ZEROCOPY, 1);
167*49cdfc7eSAndroid Build Coastguard Worker break;
168*49cdfc7eSAndroid Build Coastguard Worker case TYPE_DCCP:
169*49cdfc7eSAndroid Build Coastguard Worker SAFE_SETSOCKOPT_INT(sd, SOL_DCCP, DCCP_SOCKOPT_SERVICE,
170*49cdfc7eSAndroid Build Coastguard Worker service_code);
171*49cdfc7eSAndroid Build Coastguard Worker break;
172*49cdfc7eSAndroid Build Coastguard Worker case TYPE_UDP_LITE: {
173*49cdfc7eSAndroid Build Coastguard Worker int cscov = init_srv_msg_len >> 1;
174*49cdfc7eSAndroid Build Coastguard Worker
175*49cdfc7eSAndroid Build Coastguard Worker if (cscov < 8)
176*49cdfc7eSAndroid Build Coastguard Worker cscov = 8;
177*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "UDP-Lite send cscov is %d", cscov);
178*49cdfc7eSAndroid Build Coastguard Worker /* set checksum for header and partially for payload */
179*49cdfc7eSAndroid Build Coastguard Worker SAFE_SETSOCKOPT_INT(sd, SOL_UDPLITE, UDPLITE_SEND_CSCOV, cscov);
180*49cdfc7eSAndroid Build Coastguard Worker SAFE_SETSOCKOPT_INT(sd, SOL_UDPLITE, UDPLITE_RECV_CSCOV, 8);
181*49cdfc7eSAndroid Build Coastguard Worker } break;
182*49cdfc7eSAndroid Build Coastguard Worker }
183*49cdfc7eSAndroid Build Coastguard Worker }
184*49cdfc7eSAndroid Build Coastguard Worker
do_cleanup(void)185*49cdfc7eSAndroid Build Coastguard Worker static void do_cleanup(void)
186*49cdfc7eSAndroid Build Coastguard Worker {
187*49cdfc7eSAndroid Build Coastguard Worker if (net.cleanup)
188*49cdfc7eSAndroid Build Coastguard Worker net.cleanup();
189*49cdfc7eSAndroid Build Coastguard Worker
190*49cdfc7eSAndroid Build Coastguard Worker if (tfo_cfg_changed) {
191*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "unset '%s' back to '%d'",
192*49cdfc7eSAndroid Build Coastguard Worker tfo_cfg, tfo_cfg_value);
193*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTF(tfo_cfg, "%d", tfo_cfg_value);
194*49cdfc7eSAndroid Build Coastguard Worker }
195*49cdfc7eSAndroid Build Coastguard Worker
196*49cdfc7eSAndroid Build Coastguard Worker if (tw_reuse_changed) {
197*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTF(tcp_tw_reuse, "0");
198*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "unset '%s' back to '0'", tcp_tw_reuse);
199*49cdfc7eSAndroid Build Coastguard Worker }
200*49cdfc7eSAndroid Build Coastguard Worker }
TST_DECLARE_ONCE_FN(cleanup,do_cleanup)201*49cdfc7eSAndroid Build Coastguard Worker TST_DECLARE_ONCE_FN(cleanup, do_cleanup)
202*49cdfc7eSAndroid Build Coastguard Worker
203*49cdfc7eSAndroid Build Coastguard Worker static int sock_recv_poll(char *buf, int size, struct sock_info *i)
204*49cdfc7eSAndroid Build Coastguard Worker {
205*49cdfc7eSAndroid Build Coastguard Worker struct pollfd pfd;
206*49cdfc7eSAndroid Build Coastguard Worker pfd.fd = i->fd;
207*49cdfc7eSAndroid Build Coastguard Worker pfd.events = POLLIN;
208*49cdfc7eSAndroid Build Coastguard Worker int len = -1;
209*49cdfc7eSAndroid Build Coastguard Worker
210*49cdfc7eSAndroid Build Coastguard Worker while (1) {
211*49cdfc7eSAndroid Build Coastguard Worker errno = 0;
212*49cdfc7eSAndroid Build Coastguard Worker int ret = poll(&pfd, 1, i->timeout);
213*49cdfc7eSAndroid Build Coastguard Worker if (ret == -1) {
214*49cdfc7eSAndroid Build Coastguard Worker if (errno == EINTR)
215*49cdfc7eSAndroid Build Coastguard Worker continue;
216*49cdfc7eSAndroid Build Coastguard Worker break;
217*49cdfc7eSAndroid Build Coastguard Worker }
218*49cdfc7eSAndroid Build Coastguard Worker
219*49cdfc7eSAndroid Build Coastguard Worker if (ret != 1) {
220*49cdfc7eSAndroid Build Coastguard Worker if (!errno)
221*49cdfc7eSAndroid Build Coastguard Worker errno = ETIME;
222*49cdfc7eSAndroid Build Coastguard Worker break;
223*49cdfc7eSAndroid Build Coastguard Worker }
224*49cdfc7eSAndroid Build Coastguard Worker
225*49cdfc7eSAndroid Build Coastguard Worker if (!(pfd.revents & POLLIN)) {
226*49cdfc7eSAndroid Build Coastguard Worker if (pfd.revents & POLLERR) {
227*49cdfc7eSAndroid Build Coastguard Worker int err = 0;
228*49cdfc7eSAndroid Build Coastguard Worker socklen_t err_len = sizeof(err);
229*49cdfc7eSAndroid Build Coastguard Worker
230*49cdfc7eSAndroid Build Coastguard Worker getsockopt(i->fd, SOL_SOCKET, SO_ERROR,
231*49cdfc7eSAndroid Build Coastguard Worker &err, &err_len);
232*49cdfc7eSAndroid Build Coastguard Worker if (!err)
233*49cdfc7eSAndroid Build Coastguard Worker continue;
234*49cdfc7eSAndroid Build Coastguard Worker errno = err;
235*49cdfc7eSAndroid Build Coastguard Worker }
236*49cdfc7eSAndroid Build Coastguard Worker break;
237*49cdfc7eSAndroid Build Coastguard Worker }
238*49cdfc7eSAndroid Build Coastguard Worker
239*49cdfc7eSAndroid Build Coastguard Worker errno = 0;
240*49cdfc7eSAndroid Build Coastguard Worker len = recvfrom(i->fd, buf, size, MSG_DONTWAIT,
241*49cdfc7eSAndroid Build Coastguard Worker (struct sockaddr *)&i->raddr,
242*49cdfc7eSAndroid Build Coastguard Worker &i->raddr_len);
243*49cdfc7eSAndroid Build Coastguard Worker
244*49cdfc7eSAndroid Build Coastguard Worker if (len == -1 && errno == EINTR)
245*49cdfc7eSAndroid Build Coastguard Worker continue;
246*49cdfc7eSAndroid Build Coastguard Worker
247*49cdfc7eSAndroid Build Coastguard Worker if (len == 0)
248*49cdfc7eSAndroid Build Coastguard Worker errno = ESHUTDOWN;
249*49cdfc7eSAndroid Build Coastguard Worker
250*49cdfc7eSAndroid Build Coastguard Worker break;
251*49cdfc7eSAndroid Build Coastguard Worker }
252*49cdfc7eSAndroid Build Coastguard Worker
253*49cdfc7eSAndroid Build Coastguard Worker return len;
254*49cdfc7eSAndroid Build Coastguard Worker }
255*49cdfc7eSAndroid Build Coastguard Worker
client_recv(char * buf,int srv_msg_len,struct sock_info * i)256*49cdfc7eSAndroid Build Coastguard Worker static int client_recv(char *buf, int srv_msg_len, struct sock_info *i)
257*49cdfc7eSAndroid Build Coastguard Worker {
258*49cdfc7eSAndroid Build Coastguard Worker int len, offset = 0;
259*49cdfc7eSAndroid Build Coastguard Worker
260*49cdfc7eSAndroid Build Coastguard Worker while (1) {
261*49cdfc7eSAndroid Build Coastguard Worker errno = 0;
262*49cdfc7eSAndroid Build Coastguard Worker len = sock_recv_poll(buf + offset, srv_msg_len - offset, i);
263*49cdfc7eSAndroid Build Coastguard Worker
264*49cdfc7eSAndroid Build Coastguard Worker /* socket closed or msg is not valid */
265*49cdfc7eSAndroid Build Coastguard Worker if (len < 1 || (offset + len) > srv_msg_len ||
266*49cdfc7eSAndroid Build Coastguard Worker (buf[0] != start_byte && buf[0] != start_fin_byte)) {
267*49cdfc7eSAndroid Build Coastguard Worker /* packet too big message, resend with new pmtu */
268*49cdfc7eSAndroid Build Coastguard Worker if (errno == EMSGSIZE) {
269*49cdfc7eSAndroid Build Coastguard Worker if (++(i->pmtu_err_cnt) < max_pmtu_err)
270*49cdfc7eSAndroid Build Coastguard Worker return 0;
271*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TFAIL, "too many pmtu errors %d",
272*49cdfc7eSAndroid Build Coastguard Worker i->pmtu_err_cnt);
273*49cdfc7eSAndroid Build Coastguard Worker } else if (!errno) {
274*49cdfc7eSAndroid Build Coastguard Worker errno = ENOMSG;
275*49cdfc7eSAndroid Build Coastguard Worker }
276*49cdfc7eSAndroid Build Coastguard Worker break;
277*49cdfc7eSAndroid Build Coastguard Worker }
278*49cdfc7eSAndroid Build Coastguard Worker offset += len;
279*49cdfc7eSAndroid Build Coastguard Worker if (buf[offset - 1] != end_byte)
280*49cdfc7eSAndroid Build Coastguard Worker continue;
281*49cdfc7eSAndroid Build Coastguard Worker
282*49cdfc7eSAndroid Build Coastguard Worker /* recv last msg, close socket */
283*49cdfc7eSAndroid Build Coastguard Worker if (buf[0] == start_fin_byte)
284*49cdfc7eSAndroid Build Coastguard Worker break;
285*49cdfc7eSAndroid Build Coastguard Worker return 0;
286*49cdfc7eSAndroid Build Coastguard Worker }
287*49cdfc7eSAndroid Build Coastguard Worker
288*49cdfc7eSAndroid Build Coastguard Worker if (sock_type != SOCK_STREAM) {
289*49cdfc7eSAndroid Build Coastguard Worker if (errno == ETIME) {
290*49cdfc7eSAndroid Build Coastguard Worker if (++(i->etime_cnt) > max_etime_cnt)
291*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TFAIL, "client requests timeout %d times, last timeout %dms",
292*49cdfc7eSAndroid Build Coastguard Worker i->etime_cnt, i->timeout);
293*49cdfc7eSAndroid Build Coastguard Worker /* Increase timeout in poll up to 3.2 sec */
294*49cdfc7eSAndroid Build Coastguard Worker if (i->timeout < 3000)
295*49cdfc7eSAndroid Build Coastguard Worker i->timeout <<= 1;
296*49cdfc7eSAndroid Build Coastguard Worker return 0;
297*49cdfc7eSAndroid Build Coastguard Worker }
298*49cdfc7eSAndroid Build Coastguard Worker if (errno == ESHUTDOWN) {
299*49cdfc7eSAndroid Build Coastguard Worker if (++(i->eshutdown_cnt) > max_eshutdown_cnt)
300*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TFAIL, "too many zero-length msgs");
301*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "%d-length msg on sock %d", len, i->fd);
302*49cdfc7eSAndroid Build Coastguard Worker return 0;
303*49cdfc7eSAndroid Build Coastguard Worker }
304*49cdfc7eSAndroid Build Coastguard Worker }
305*49cdfc7eSAndroid Build Coastguard Worker
306*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(i->fd);
307*49cdfc7eSAndroid Build Coastguard Worker return (errno) ? -1 : 0;
308*49cdfc7eSAndroid Build Coastguard Worker }
309*49cdfc7eSAndroid Build Coastguard Worker
310*49cdfc7eSAndroid Build Coastguard Worker static int bind_no_port;
bind_before_connect(int sd)311*49cdfc7eSAndroid Build Coastguard Worker static void bind_before_connect(int sd)
312*49cdfc7eSAndroid Build Coastguard Worker {
313*49cdfc7eSAndroid Build Coastguard Worker if (!local_addrinfo)
314*49cdfc7eSAndroid Build Coastguard Worker return;
315*49cdfc7eSAndroid Build Coastguard Worker
316*49cdfc7eSAndroid Build Coastguard Worker if (bind_no_port)
317*49cdfc7eSAndroid Build Coastguard Worker SAFE_SETSOCKOPT_INT(sd, SOL_IP, IP_BIND_ADDRESS_NO_PORT, 1);
318*49cdfc7eSAndroid Build Coastguard Worker if (reuse_port)
319*49cdfc7eSAndroid Build Coastguard Worker SAFE_SETSOCKOPT_INT(sd, SOL_SOCKET, SO_REUSEPORT, 1);
320*49cdfc7eSAndroid Build Coastguard Worker
321*49cdfc7eSAndroid Build Coastguard Worker SAFE_BIND(sd, local_addrinfo->ai_addr, local_addrinfo->ai_addrlen);
322*49cdfc7eSAndroid Build Coastguard Worker
323*49cdfc7eSAndroid Build Coastguard Worker if (bind_no_port && proto_type != TYPE_SCTP) {
324*49cdfc7eSAndroid Build Coastguard Worker int port = TST_GETSOCKPORT(sd);
325*49cdfc7eSAndroid Build Coastguard Worker
326*49cdfc7eSAndroid Build Coastguard Worker if (port)
327*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TFAIL, "port not zero after bind(): %d", port);
328*49cdfc7eSAndroid Build Coastguard Worker }
329*49cdfc7eSAndroid Build Coastguard Worker }
330*49cdfc7eSAndroid Build Coastguard Worker
client_connect_send(const char * msg,int size)331*49cdfc7eSAndroid Build Coastguard Worker static int client_connect_send(const char *msg, int size)
332*49cdfc7eSAndroid Build Coastguard Worker {
333*49cdfc7eSAndroid Build Coastguard Worker int cfd = SAFE_SOCKET(family, sock_type, protocol);
334*49cdfc7eSAndroid Build Coastguard Worker
335*49cdfc7eSAndroid Build Coastguard Worker init_socket_opts(cfd);
336*49cdfc7eSAndroid Build Coastguard Worker
337*49cdfc7eSAndroid Build Coastguard Worker if (fastopen_api) {
338*49cdfc7eSAndroid Build Coastguard Worker /* Replaces connect() + send()/write() */
339*49cdfc7eSAndroid Build Coastguard Worker SAFE_SENDTO(1, cfd, msg, size, send_flags | MSG_FASTOPEN,
340*49cdfc7eSAndroid Build Coastguard Worker remote_addrinfo->ai_addr, remote_addrinfo->ai_addrlen);
341*49cdfc7eSAndroid Build Coastguard Worker } else {
342*49cdfc7eSAndroid Build Coastguard Worker bind_before_connect(cfd);
343*49cdfc7eSAndroid Build Coastguard Worker /* old TCP API */
344*49cdfc7eSAndroid Build Coastguard Worker SAFE_CONNECT(cfd, remote_addrinfo->ai_addr,
345*49cdfc7eSAndroid Build Coastguard Worker remote_addrinfo->ai_addrlen);
346*49cdfc7eSAndroid Build Coastguard Worker SAFE_SEND(1, cfd, msg, size, send_flags);
347*49cdfc7eSAndroid Build Coastguard Worker }
348*49cdfc7eSAndroid Build Coastguard Worker return cfd;
349*49cdfc7eSAndroid Build Coastguard Worker }
350*49cdfc7eSAndroid Build Coastguard Worker
351*49cdfc7eSAndroid Build Coastguard Worker union net_size_field {
352*49cdfc7eSAndroid Build Coastguard Worker char bytes[2];
353*49cdfc7eSAndroid Build Coastguard Worker uint16_t value;
354*49cdfc7eSAndroid Build Coastguard Worker };
355*49cdfc7eSAndroid Build Coastguard Worker
make_client_request(char client_msg[],int * cln_len,int * srv_len,unsigned int * seed)356*49cdfc7eSAndroid Build Coastguard Worker static void make_client_request(char client_msg[], int *cln_len, int *srv_len,
357*49cdfc7eSAndroid Build Coastguard Worker unsigned int *seed)
358*49cdfc7eSAndroid Build Coastguard Worker {
359*49cdfc7eSAndroid Build Coastguard Worker if (max_rand_msg_len)
360*49cdfc7eSAndroid Build Coastguard Worker *cln_len = *srv_len = min_msg_len + rand_r(seed) % max_rand_msg_len;
361*49cdfc7eSAndroid Build Coastguard Worker
362*49cdfc7eSAndroid Build Coastguard Worker memset(client_msg, client_byte, *cln_len);
363*49cdfc7eSAndroid Build Coastguard Worker client_msg[0] = start_byte;
364*49cdfc7eSAndroid Build Coastguard Worker
365*49cdfc7eSAndroid Build Coastguard Worker /* set size for reply */
366*49cdfc7eSAndroid Build Coastguard Worker union net_size_field net_size;
367*49cdfc7eSAndroid Build Coastguard Worker
368*49cdfc7eSAndroid Build Coastguard Worker net_size.value = htons(*srv_len);
369*49cdfc7eSAndroid Build Coastguard Worker client_msg[1] = net_size.bytes[0];
370*49cdfc7eSAndroid Build Coastguard Worker client_msg[2] = net_size.bytes[1];
371*49cdfc7eSAndroid Build Coastguard Worker
372*49cdfc7eSAndroid Build Coastguard Worker client_msg[*cln_len - 1] = end_byte;
373*49cdfc7eSAndroid Build Coastguard Worker }
374*49cdfc7eSAndroid Build Coastguard Worker
client_fn(void * id)375*49cdfc7eSAndroid Build Coastguard Worker void *client_fn(void *id)
376*49cdfc7eSAndroid Build Coastguard Worker {
377*49cdfc7eSAndroid Build Coastguard Worker int cln_len = init_cln_msg_len,
378*49cdfc7eSAndroid Build Coastguard Worker srv_len = init_srv_msg_len;
379*49cdfc7eSAndroid Build Coastguard Worker struct sock_info inf;
380*49cdfc7eSAndroid Build Coastguard Worker char buf[max_msg_len];
381*49cdfc7eSAndroid Build Coastguard Worker char client_msg[max_msg_len];
382*49cdfc7eSAndroid Build Coastguard Worker int i = 0;
383*49cdfc7eSAndroid Build Coastguard Worker intptr_t err = 0;
384*49cdfc7eSAndroid Build Coastguard Worker unsigned int seed = init_seed ^ (intptr_t)id;
385*49cdfc7eSAndroid Build Coastguard Worker
386*49cdfc7eSAndroid Build Coastguard Worker inf.raddr_len = sizeof(inf.raddr);
387*49cdfc7eSAndroid Build Coastguard Worker inf.etime_cnt = 0;
388*49cdfc7eSAndroid Build Coastguard Worker inf.eshutdown_cnt = 0;
389*49cdfc7eSAndroid Build Coastguard Worker inf.timeout = wait_timeout;
390*49cdfc7eSAndroid Build Coastguard Worker inf.pmtu_err_cnt = 0;
391*49cdfc7eSAndroid Build Coastguard Worker
392*49cdfc7eSAndroid Build Coastguard Worker make_client_request(client_msg, &cln_len, &srv_len, &seed);
393*49cdfc7eSAndroid Build Coastguard Worker
394*49cdfc7eSAndroid Build Coastguard Worker /* connect & send requests */
395*49cdfc7eSAndroid Build Coastguard Worker inf.fd = client_connect_send(client_msg, cln_len);
396*49cdfc7eSAndroid Build Coastguard Worker if (inf.fd == -1) {
397*49cdfc7eSAndroid Build Coastguard Worker err = errno;
398*49cdfc7eSAndroid Build Coastguard Worker goto out;
399*49cdfc7eSAndroid Build Coastguard Worker }
400*49cdfc7eSAndroid Build Coastguard Worker
401*49cdfc7eSAndroid Build Coastguard Worker if (client_recv(buf, srv_len, &inf)) {
402*49cdfc7eSAndroid Build Coastguard Worker err = errno;
403*49cdfc7eSAndroid Build Coastguard Worker goto out;
404*49cdfc7eSAndroid Build Coastguard Worker }
405*49cdfc7eSAndroid Build Coastguard Worker
406*49cdfc7eSAndroid Build Coastguard Worker for (i = 1; i < client_max_requests; ++i) {
407*49cdfc7eSAndroid Build Coastguard Worker if (inf.fd == -1) {
408*49cdfc7eSAndroid Build Coastguard Worker inf.fd = client_connect_send(client_msg, cln_len);
409*49cdfc7eSAndroid Build Coastguard Worker if (inf.fd == -1) {
410*49cdfc7eSAndroid Build Coastguard Worker err = errno;
411*49cdfc7eSAndroid Build Coastguard Worker goto out;
412*49cdfc7eSAndroid Build Coastguard Worker }
413*49cdfc7eSAndroid Build Coastguard Worker
414*49cdfc7eSAndroid Build Coastguard Worker if (client_recv(buf, srv_len, &inf)) {
415*49cdfc7eSAndroid Build Coastguard Worker err = errno;
416*49cdfc7eSAndroid Build Coastguard Worker break;
417*49cdfc7eSAndroid Build Coastguard Worker }
418*49cdfc7eSAndroid Build Coastguard Worker continue;
419*49cdfc7eSAndroid Build Coastguard Worker }
420*49cdfc7eSAndroid Build Coastguard Worker
421*49cdfc7eSAndroid Build Coastguard Worker if (max_rand_msg_len)
422*49cdfc7eSAndroid Build Coastguard Worker make_client_request(client_msg, &cln_len, &srv_len, &seed);
423*49cdfc7eSAndroid Build Coastguard Worker
424*49cdfc7eSAndroid Build Coastguard Worker SAFE_SEND(1, inf.fd, client_msg, cln_len, send_flags);
425*49cdfc7eSAndroid Build Coastguard Worker
426*49cdfc7eSAndroid Build Coastguard Worker if (client_recv(buf, srv_len, &inf)) {
427*49cdfc7eSAndroid Build Coastguard Worker err = errno;
428*49cdfc7eSAndroid Build Coastguard Worker break;
429*49cdfc7eSAndroid Build Coastguard Worker }
430*49cdfc7eSAndroid Build Coastguard Worker }
431*49cdfc7eSAndroid Build Coastguard Worker
432*49cdfc7eSAndroid Build Coastguard Worker if (inf.fd != -1)
433*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(inf.fd);
434*49cdfc7eSAndroid Build Coastguard Worker
435*49cdfc7eSAndroid Build Coastguard Worker out:
436*49cdfc7eSAndroid Build Coastguard Worker if (i != client_max_requests)
437*49cdfc7eSAndroid Build Coastguard Worker tst_res(TWARN, "client exit on '%d' request", i);
438*49cdfc7eSAndroid Build Coastguard Worker
439*49cdfc7eSAndroid Build Coastguard Worker return (void *) err;
440*49cdfc7eSAndroid Build Coastguard Worker }
441*49cdfc7eSAndroid Build Coastguard Worker
parse_client_request(const char * msg)442*49cdfc7eSAndroid Build Coastguard Worker static int parse_client_request(const char *msg)
443*49cdfc7eSAndroid Build Coastguard Worker {
444*49cdfc7eSAndroid Build Coastguard Worker union net_size_field net_size;
445*49cdfc7eSAndroid Build Coastguard Worker net_size.bytes[0] = msg[1];
446*49cdfc7eSAndroid Build Coastguard Worker net_size.bytes[1] = msg[2];
447*49cdfc7eSAndroid Build Coastguard Worker int size = ntohs(net_size.value);
448*49cdfc7eSAndroid Build Coastguard Worker if (size < 2 || size > max_msg_len)
449*49cdfc7eSAndroid Build Coastguard Worker return -1;
450*49cdfc7eSAndroid Build Coastguard Worker
451*49cdfc7eSAndroid Build Coastguard Worker return size;
452*49cdfc7eSAndroid Build Coastguard Worker }
453*49cdfc7eSAndroid Build Coastguard Worker
454*49cdfc7eSAndroid Build Coastguard Worker static struct timespec tv_client_start;
455*49cdfc7eSAndroid Build Coastguard Worker static struct timespec tv_client_end;
456*49cdfc7eSAndroid Build Coastguard Worker
client_init(void)457*49cdfc7eSAndroid Build Coastguard Worker static void client_init(void)
458*49cdfc7eSAndroid Build Coastguard Worker {
459*49cdfc7eSAndroid Build Coastguard Worker if (clients_num >= MAX_THREADS) {
460*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Unexpected num of clients '%d'",
461*49cdfc7eSAndroid Build Coastguard Worker clients_num);
462*49cdfc7eSAndroid Build Coastguard Worker }
463*49cdfc7eSAndroid Build Coastguard Worker
464*49cdfc7eSAndroid Build Coastguard Worker thread_ids = SAFE_MALLOC(sizeof(pthread_t) * clients_num);
465*49cdfc7eSAndroid Build Coastguard Worker
466*49cdfc7eSAndroid Build Coastguard Worker struct addrinfo hints;
467*49cdfc7eSAndroid Build Coastguard Worker memset(&hints, 0, sizeof(struct addrinfo));
468*49cdfc7eSAndroid Build Coastguard Worker hints.ai_family = AF_UNSPEC;
469*49cdfc7eSAndroid Build Coastguard Worker hints.ai_socktype = sock_type;
470*49cdfc7eSAndroid Build Coastguard Worker hints.ai_flags = 0;
471*49cdfc7eSAndroid Build Coastguard Worker hints.ai_protocol = 0;
472*49cdfc7eSAndroid Build Coastguard Worker
473*49cdfc7eSAndroid Build Coastguard Worker if (source_addr)
474*49cdfc7eSAndroid Build Coastguard Worker SAFE_GETADDRINFO(source_addr, NULL, &hints, &local_addrinfo);
475*49cdfc7eSAndroid Build Coastguard Worker SAFE_GETADDRINFO(server_addr, tcp_port, &hints, &remote_addrinfo);
476*49cdfc7eSAndroid Build Coastguard Worker
477*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "Running the test over IPv%s",
478*49cdfc7eSAndroid Build Coastguard Worker (remote_addrinfo->ai_family == AF_INET6) ? "6" : "4");
479*49cdfc7eSAndroid Build Coastguard Worker
480*49cdfc7eSAndroid Build Coastguard Worker family = remote_addrinfo->ai_family;
481*49cdfc7eSAndroid Build Coastguard Worker
482*49cdfc7eSAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC_RAW, &tv_client_start);
483*49cdfc7eSAndroid Build Coastguard Worker intptr_t i;
484*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < clients_num; ++i)
485*49cdfc7eSAndroid Build Coastguard Worker SAFE_PTHREAD_CREATE(&thread_ids[i], &attr, client_fn, (void *)i);
486*49cdfc7eSAndroid Build Coastguard Worker }
487*49cdfc7eSAndroid Build Coastguard Worker
client_run(void)488*49cdfc7eSAndroid Build Coastguard Worker static void client_run(void)
489*49cdfc7eSAndroid Build Coastguard Worker {
490*49cdfc7eSAndroid Build Coastguard Worker void *res = NULL;
491*49cdfc7eSAndroid Build Coastguard Worker long clnt_time = 0;
492*49cdfc7eSAndroid Build Coastguard Worker int i;
493*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < clients_num; ++i) {
494*49cdfc7eSAndroid Build Coastguard Worker pthread_join(thread_ids[i], &res);
495*49cdfc7eSAndroid Build Coastguard Worker if (res) {
496*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "client[%d] failed: %s",
497*49cdfc7eSAndroid Build Coastguard Worker i, strerror((intptr_t)res));
498*49cdfc7eSAndroid Build Coastguard Worker }
499*49cdfc7eSAndroid Build Coastguard Worker }
500*49cdfc7eSAndroid Build Coastguard Worker
501*49cdfc7eSAndroid Build Coastguard Worker clock_gettime(CLOCK_MONOTONIC_RAW, &tv_client_end);
502*49cdfc7eSAndroid Build Coastguard Worker clnt_time = (tv_client_end.tv_sec - tv_client_start.tv_sec) * 1000 +
503*49cdfc7eSAndroid Build Coastguard Worker (tv_client_end.tv_nsec - tv_client_start.tv_nsec) / 1000000;
504*49cdfc7eSAndroid Build Coastguard Worker
505*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "total time '%ld' ms", clnt_time);
506*49cdfc7eSAndroid Build Coastguard Worker
507*49cdfc7eSAndroid Build Coastguard Worker char client_msg[min_msg_len];
508*49cdfc7eSAndroid Build Coastguard Worker int msg_len = min_msg_len;
509*49cdfc7eSAndroid Build Coastguard Worker
510*49cdfc7eSAndroid Build Coastguard Worker max_rand_msg_len = 0;
511*49cdfc7eSAndroid Build Coastguard Worker make_client_request(client_msg, &msg_len, &msg_len, NULL);
512*49cdfc7eSAndroid Build Coastguard Worker /* ask server to terminate */
513*49cdfc7eSAndroid Build Coastguard Worker client_msg[0] = start_fin_byte;
514*49cdfc7eSAndroid Build Coastguard Worker int cfd = client_connect_send(client_msg, msg_len);
515*49cdfc7eSAndroid Build Coastguard Worker if (cfd != -1) {
516*49cdfc7eSAndroid Build Coastguard Worker shutdown(cfd, SHUT_WR);
517*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(cfd);
518*49cdfc7eSAndroid Build Coastguard Worker }
519*49cdfc7eSAndroid Build Coastguard Worker /* the script tcp_fastopen_run.sh will remove it */
520*49cdfc7eSAndroid Build Coastguard Worker if (rpath)
521*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTF(rpath, "%ld", clnt_time);
522*49cdfc7eSAndroid Build Coastguard Worker
523*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "test completed");
524*49cdfc7eSAndroid Build Coastguard Worker }
525*49cdfc7eSAndroid Build Coastguard Worker
client_cleanup(void)526*49cdfc7eSAndroid Build Coastguard Worker static void client_cleanup(void)
527*49cdfc7eSAndroid Build Coastguard Worker {
528*49cdfc7eSAndroid Build Coastguard Worker free(thread_ids);
529*49cdfc7eSAndroid Build Coastguard Worker
530*49cdfc7eSAndroid Build Coastguard Worker if (remote_addrinfo)
531*49cdfc7eSAndroid Build Coastguard Worker freeaddrinfo(remote_addrinfo);
532*49cdfc7eSAndroid Build Coastguard Worker }
533*49cdfc7eSAndroid Build Coastguard Worker
make_server_reply(char * send_msg,int size)534*49cdfc7eSAndroid Build Coastguard Worker static void make_server_reply(char *send_msg, int size)
535*49cdfc7eSAndroid Build Coastguard Worker {
536*49cdfc7eSAndroid Build Coastguard Worker memset(send_msg, server_byte, size - 1);
537*49cdfc7eSAndroid Build Coastguard Worker send_msg[0] = start_byte;
538*49cdfc7eSAndroid Build Coastguard Worker send_msg[size - 1] = end_byte;
539*49cdfc7eSAndroid Build Coastguard Worker }
540*49cdfc7eSAndroid Build Coastguard Worker
server_fn(void * cfd)541*49cdfc7eSAndroid Build Coastguard Worker void *server_fn(void *cfd)
542*49cdfc7eSAndroid Build Coastguard Worker {
543*49cdfc7eSAndroid Build Coastguard Worker int num_requests = 0, offset = 0;
544*49cdfc7eSAndroid Build Coastguard Worker char send_msg[max_msg_len], end[] = { end_byte };
545*49cdfc7eSAndroid Build Coastguard Worker int start_send_type = (sock_type == SOCK_DGRAM) ? 1 : 0;
546*49cdfc7eSAndroid Build Coastguard Worker int send_msg_len, send_type = start_send_type;
547*49cdfc7eSAndroid Build Coastguard Worker char recv_msg[max_msg_len];
548*49cdfc7eSAndroid Build Coastguard Worker struct sock_info inf;
549*49cdfc7eSAndroid Build Coastguard Worker ssize_t recv_len;
550*49cdfc7eSAndroid Build Coastguard Worker struct iovec iov[2];
551*49cdfc7eSAndroid Build Coastguard Worker struct msghdr msg;
552*49cdfc7eSAndroid Build Coastguard Worker
553*49cdfc7eSAndroid Build Coastguard Worker inf.fd = (intptr_t) cfd;
554*49cdfc7eSAndroid Build Coastguard Worker inf.raddr_len = sizeof(inf.raddr);
555*49cdfc7eSAndroid Build Coastguard Worker inf.timeout = wait_timeout;
556*49cdfc7eSAndroid Build Coastguard Worker
557*49cdfc7eSAndroid Build Coastguard Worker iov[0].iov_base = send_msg;
558*49cdfc7eSAndroid Build Coastguard Worker iov[1].iov_base = end;
559*49cdfc7eSAndroid Build Coastguard Worker iov[1].iov_len = 1;
560*49cdfc7eSAndroid Build Coastguard Worker memset(&msg, 0, sizeof(msg));
561*49cdfc7eSAndroid Build Coastguard Worker msg.msg_name = &inf.raddr;
562*49cdfc7eSAndroid Build Coastguard Worker msg.msg_iov = iov;
563*49cdfc7eSAndroid Build Coastguard Worker msg.msg_iovlen = 2;
564*49cdfc7eSAndroid Build Coastguard Worker
565*49cdfc7eSAndroid Build Coastguard Worker init_socket_opts(inf.fd);
566*49cdfc7eSAndroid Build Coastguard Worker
567*49cdfc7eSAndroid Build Coastguard Worker while (1) {
568*49cdfc7eSAndroid Build Coastguard Worker recv_len = sock_recv_poll(recv_msg + offset,
569*49cdfc7eSAndroid Build Coastguard Worker max_msg_len - offset, &inf);
570*49cdfc7eSAndroid Build Coastguard Worker
571*49cdfc7eSAndroid Build Coastguard Worker if (recv_len == 0)
572*49cdfc7eSAndroid Build Coastguard Worker break;
573*49cdfc7eSAndroid Build Coastguard Worker
574*49cdfc7eSAndroid Build Coastguard Worker if (recv_len < 0 || (offset + recv_len) > max_msg_len ||
575*49cdfc7eSAndroid Build Coastguard Worker (recv_msg[0] != start_byte &&
576*49cdfc7eSAndroid Build Coastguard Worker recv_msg[0] != start_fin_byte)) {
577*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "recv failed, sock '%d'", inf.fd);
578*49cdfc7eSAndroid Build Coastguard Worker goto out;
579*49cdfc7eSAndroid Build Coastguard Worker }
580*49cdfc7eSAndroid Build Coastguard Worker
581*49cdfc7eSAndroid Build Coastguard Worker offset += recv_len;
582*49cdfc7eSAndroid Build Coastguard Worker
583*49cdfc7eSAndroid Build Coastguard Worker if (recv_msg[offset - 1] != end_byte) {
584*49cdfc7eSAndroid Build Coastguard Worker /* msg is not complete, continue recv */
585*49cdfc7eSAndroid Build Coastguard Worker continue;
586*49cdfc7eSAndroid Build Coastguard Worker }
587*49cdfc7eSAndroid Build Coastguard Worker
588*49cdfc7eSAndroid Build Coastguard Worker /* client asks to terminate */
589*49cdfc7eSAndroid Build Coastguard Worker if (recv_msg[0] == start_fin_byte)
590*49cdfc7eSAndroid Build Coastguard Worker goto out;
591*49cdfc7eSAndroid Build Coastguard Worker
592*49cdfc7eSAndroid Build Coastguard Worker send_msg_len = parse_client_request(recv_msg);
593*49cdfc7eSAndroid Build Coastguard Worker if (send_msg_len < 0) {
594*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "wrong msg size '%d'",
595*49cdfc7eSAndroid Build Coastguard Worker send_msg_len);
596*49cdfc7eSAndroid Build Coastguard Worker goto out;
597*49cdfc7eSAndroid Build Coastguard Worker }
598*49cdfc7eSAndroid Build Coastguard Worker make_server_reply(send_msg, send_msg_len);
599*49cdfc7eSAndroid Build Coastguard Worker
600*49cdfc7eSAndroid Build Coastguard Worker offset = 0;
601*49cdfc7eSAndroid Build Coastguard Worker
602*49cdfc7eSAndroid Build Coastguard Worker /*
603*49cdfc7eSAndroid Build Coastguard Worker * It will tell client that server is going
604*49cdfc7eSAndroid Build Coastguard Worker * to close this connection.
605*49cdfc7eSAndroid Build Coastguard Worker */
606*49cdfc7eSAndroid Build Coastguard Worker if (sock_type == SOCK_STREAM &&
607*49cdfc7eSAndroid Build Coastguard Worker ++num_requests >= server_max_requests)
608*49cdfc7eSAndroid Build Coastguard Worker send_msg[0] = start_fin_byte;
609*49cdfc7eSAndroid Build Coastguard Worker
610*49cdfc7eSAndroid Build Coastguard Worker switch (send_type) {
611*49cdfc7eSAndroid Build Coastguard Worker case 0:
612*49cdfc7eSAndroid Build Coastguard Worker SAFE_SEND(1, inf.fd, send_msg, send_msg_len,
613*49cdfc7eSAndroid Build Coastguard Worker send_flags);
614*49cdfc7eSAndroid Build Coastguard Worker if (proto_type != TYPE_SCTP)
615*49cdfc7eSAndroid Build Coastguard Worker ++send_type;
616*49cdfc7eSAndroid Build Coastguard Worker break;
617*49cdfc7eSAndroid Build Coastguard Worker case 1:
618*49cdfc7eSAndroid Build Coastguard Worker SAFE_SENDTO(1, inf.fd, send_msg, send_msg_len,
619*49cdfc7eSAndroid Build Coastguard Worker send_flags, (struct sockaddr *)&inf.raddr,
620*49cdfc7eSAndroid Build Coastguard Worker inf.raddr_len);
621*49cdfc7eSAndroid Build Coastguard Worker ++send_type;
622*49cdfc7eSAndroid Build Coastguard Worker break;
623*49cdfc7eSAndroid Build Coastguard Worker default:
624*49cdfc7eSAndroid Build Coastguard Worker iov[0].iov_len = send_msg_len - 1;
625*49cdfc7eSAndroid Build Coastguard Worker msg.msg_namelen = inf.raddr_len;
626*49cdfc7eSAndroid Build Coastguard Worker SAFE_SENDMSG(send_msg_len, inf.fd, &msg, send_flags);
627*49cdfc7eSAndroid Build Coastguard Worker send_type = start_send_type;
628*49cdfc7eSAndroid Build Coastguard Worker break;
629*49cdfc7eSAndroid Build Coastguard Worker }
630*49cdfc7eSAndroid Build Coastguard Worker
631*49cdfc7eSAndroid Build Coastguard Worker if (sock_type == SOCK_STREAM &&
632*49cdfc7eSAndroid Build Coastguard Worker num_requests >= server_max_requests) {
633*49cdfc7eSAndroid Build Coastguard Worker /* max reqs, close socket */
634*49cdfc7eSAndroid Build Coastguard Worker shutdown(inf.fd, SHUT_WR);
635*49cdfc7eSAndroid Build Coastguard Worker break;
636*49cdfc7eSAndroid Build Coastguard Worker }
637*49cdfc7eSAndroid Build Coastguard Worker }
638*49cdfc7eSAndroid Build Coastguard Worker
639*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(inf.fd);
640*49cdfc7eSAndroid Build Coastguard Worker return NULL;
641*49cdfc7eSAndroid Build Coastguard Worker
642*49cdfc7eSAndroid Build Coastguard Worker out:
643*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(inf.fd);
644*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Server closed");
645*49cdfc7eSAndroid Build Coastguard Worker return NULL;
646*49cdfc7eSAndroid Build Coastguard Worker }
647*49cdfc7eSAndroid Build Coastguard Worker
server_thread_add(intptr_t client_fd)648*49cdfc7eSAndroid Build Coastguard Worker static pthread_t server_thread_add(intptr_t client_fd)
649*49cdfc7eSAndroid Build Coastguard Worker {
650*49cdfc7eSAndroid Build Coastguard Worker pthread_t id;
651*49cdfc7eSAndroid Build Coastguard Worker SAFE_PTHREAD_CREATE(&id, &attr, server_fn, (void *) client_fd);
652*49cdfc7eSAndroid Build Coastguard Worker return id;
653*49cdfc7eSAndroid Build Coastguard Worker }
654*49cdfc7eSAndroid Build Coastguard Worker
server_init(void)655*49cdfc7eSAndroid Build Coastguard Worker static void server_init(void)
656*49cdfc7eSAndroid Build Coastguard Worker {
657*49cdfc7eSAndroid Build Coastguard Worker char *src_addr = NULL;
658*49cdfc7eSAndroid Build Coastguard Worker struct addrinfo hints;
659*49cdfc7eSAndroid Build Coastguard Worker
660*49cdfc7eSAndroid Build Coastguard Worker memset(&hints, 0, sizeof(struct addrinfo));
661*49cdfc7eSAndroid Build Coastguard Worker hints.ai_family = AF_INET6;
662*49cdfc7eSAndroid Build Coastguard Worker hints.ai_socktype = sock_type;
663*49cdfc7eSAndroid Build Coastguard Worker hints.ai_flags = AI_PASSIVE;
664*49cdfc7eSAndroid Build Coastguard Worker
665*49cdfc7eSAndroid Build Coastguard Worker if (!source_addr && !tcp_port)
666*49cdfc7eSAndroid Build Coastguard Worker tcp_port = "0";
667*49cdfc7eSAndroid Build Coastguard Worker
668*49cdfc7eSAndroid Build Coastguard Worker if (source_addr && !strchr(source_addr, ':'))
669*49cdfc7eSAndroid Build Coastguard Worker SAFE_ASPRINTF(&src_addr, "::ffff:%s", source_addr);
670*49cdfc7eSAndroid Build Coastguard Worker SAFE_GETADDRINFO(src_addr ? src_addr : source_addr, tcp_port,
671*49cdfc7eSAndroid Build Coastguard Worker &hints, &local_addrinfo);
672*49cdfc7eSAndroid Build Coastguard Worker free(src_addr);
673*49cdfc7eSAndroid Build Coastguard Worker
674*49cdfc7eSAndroid Build Coastguard Worker /* IPv6 socket is also able to access IPv4 protocol stack */
675*49cdfc7eSAndroid Build Coastguard Worker sfd = SAFE_SOCKET(family, sock_type, protocol);
676*49cdfc7eSAndroid Build Coastguard Worker SAFE_SETSOCKOPT_INT(sfd, SOL_SOCKET, SO_REUSEADDR, 1);
677*49cdfc7eSAndroid Build Coastguard Worker if (reuse_port)
678*49cdfc7eSAndroid Build Coastguard Worker SAFE_SETSOCKOPT_INT(sfd, SOL_SOCKET, SO_REUSEPORT, 1);
679*49cdfc7eSAndroid Build Coastguard Worker
680*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "assigning a name to the server socket...");
681*49cdfc7eSAndroid Build Coastguard Worker SAFE_BIND(sfd, local_addrinfo->ai_addr, local_addrinfo->ai_addrlen);
682*49cdfc7eSAndroid Build Coastguard Worker
683*49cdfc7eSAndroid Build Coastguard Worker freeaddrinfo(local_addrinfo);
684*49cdfc7eSAndroid Build Coastguard Worker
685*49cdfc7eSAndroid Build Coastguard Worker int port = TST_GETSOCKPORT(sfd);
686*49cdfc7eSAndroid Build Coastguard Worker
687*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "bind to port %d", port);
688*49cdfc7eSAndroid Build Coastguard Worker if (server_bg) {
689*49cdfc7eSAndroid Build Coastguard Worker SAFE_CHDIR(server_bg);
690*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTF(port_path, "%d", port);
691*49cdfc7eSAndroid Build Coastguard Worker }
692*49cdfc7eSAndroid Build Coastguard Worker
693*49cdfc7eSAndroid Build Coastguard Worker if (sock_type == SOCK_DGRAM)
694*49cdfc7eSAndroid Build Coastguard Worker return;
695*49cdfc7eSAndroid Build Coastguard Worker
696*49cdfc7eSAndroid Build Coastguard Worker init_socket_opts(sfd);
697*49cdfc7eSAndroid Build Coastguard Worker
698*49cdfc7eSAndroid Build Coastguard Worker if (fastopen_api || fastopen_sapi) {
699*49cdfc7eSAndroid Build Coastguard Worker SAFE_SETSOCKOPT_INT(sfd, IPPROTO_TCP, TCP_FASTOPEN,
700*49cdfc7eSAndroid Build Coastguard Worker tfo_queue_size);
701*49cdfc7eSAndroid Build Coastguard Worker }
702*49cdfc7eSAndroid Build Coastguard Worker
703*49cdfc7eSAndroid Build Coastguard Worker if (zcopy)
704*49cdfc7eSAndroid Build Coastguard Worker SAFE_SETSOCKOPT_INT(sfd, SOL_SOCKET, SO_ZEROCOPY, 1);
705*49cdfc7eSAndroid Build Coastguard Worker
706*49cdfc7eSAndroid Build Coastguard Worker SAFE_LISTEN(sfd, max_queue_len);
707*49cdfc7eSAndroid Build Coastguard Worker
708*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "Listen on the socket '%d'", sfd);
709*49cdfc7eSAndroid Build Coastguard Worker }
710*49cdfc7eSAndroid Build Coastguard Worker
server_cleanup(void)711*49cdfc7eSAndroid Build Coastguard Worker static void server_cleanup(void)
712*49cdfc7eSAndroid Build Coastguard Worker {
713*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(sfd);
714*49cdfc7eSAndroid Build Coastguard Worker }
715*49cdfc7eSAndroid Build Coastguard Worker
move_to_background(void)716*49cdfc7eSAndroid Build Coastguard Worker static void move_to_background(void)
717*49cdfc7eSAndroid Build Coastguard Worker {
718*49cdfc7eSAndroid Build Coastguard Worker if (SAFE_FORK()) {
719*49cdfc7eSAndroid Build Coastguard Worker TST_CHECKPOINT_WAIT(0);
720*49cdfc7eSAndroid Build Coastguard Worker exit(0);
721*49cdfc7eSAndroid Build Coastguard Worker }
722*49cdfc7eSAndroid Build Coastguard Worker
723*49cdfc7eSAndroid Build Coastguard Worker SAFE_SETSID();
724*49cdfc7eSAndroid Build Coastguard Worker
725*49cdfc7eSAndroid Build Coastguard Worker TST_CHECKPOINT_WAKE(0);
726*49cdfc7eSAndroid Build Coastguard Worker
727*49cdfc7eSAndroid Build Coastguard Worker close(STDIN_FILENO);
728*49cdfc7eSAndroid Build Coastguard Worker SAFE_OPEN("/dev/null", O_RDONLY);
729*49cdfc7eSAndroid Build Coastguard Worker close(STDOUT_FILENO);
730*49cdfc7eSAndroid Build Coastguard Worker close(STDERR_FILENO);
731*49cdfc7eSAndroid Build Coastguard Worker
732*49cdfc7eSAndroid Build Coastguard Worker int fd = SAFE_OPEN(log_path, O_CREAT | O_TRUNC | O_WRONLY, 0644);
733*49cdfc7eSAndroid Build Coastguard Worker
734*49cdfc7eSAndroid Build Coastguard Worker SAFE_DUP(fd);
735*49cdfc7eSAndroid Build Coastguard Worker }
736*49cdfc7eSAndroid Build Coastguard Worker
server_run_udp(void)737*49cdfc7eSAndroid Build Coastguard Worker static void server_run_udp(void)
738*49cdfc7eSAndroid Build Coastguard Worker {
739*49cdfc7eSAndroid Build Coastguard Worker if (server_bg)
740*49cdfc7eSAndroid Build Coastguard Worker move_to_background();
741*49cdfc7eSAndroid Build Coastguard Worker
742*49cdfc7eSAndroid Build Coastguard Worker pthread_t p_id = server_thread_add(sfd);
743*49cdfc7eSAndroid Build Coastguard Worker
744*49cdfc7eSAndroid Build Coastguard Worker SAFE_PTHREAD_JOIN(p_id, NULL);
745*49cdfc7eSAndroid Build Coastguard Worker }
746*49cdfc7eSAndroid Build Coastguard Worker
server_run(void)747*49cdfc7eSAndroid Build Coastguard Worker static void server_run(void)
748*49cdfc7eSAndroid Build Coastguard Worker {
749*49cdfc7eSAndroid Build Coastguard Worker if (server_bg)
750*49cdfc7eSAndroid Build Coastguard Worker move_to_background();
751*49cdfc7eSAndroid Build Coastguard Worker
752*49cdfc7eSAndroid Build Coastguard Worker /* IPv4 source address will be mapped to IPv6 address */
753*49cdfc7eSAndroid Build Coastguard Worker struct sockaddr_in6 addr6;
754*49cdfc7eSAndroid Build Coastguard Worker socklen_t addr_size = sizeof(addr6);
755*49cdfc7eSAndroid Build Coastguard Worker
756*49cdfc7eSAndroid Build Coastguard Worker /*
757*49cdfc7eSAndroid Build Coastguard Worker * detaching threads allow to reclaim thread's resources
758*49cdfc7eSAndroid Build Coastguard Worker * once a thread finishes its work.
759*49cdfc7eSAndroid Build Coastguard Worker */
760*49cdfc7eSAndroid Build Coastguard Worker if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
761*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TERRNO, "setdetachstate failed");
762*49cdfc7eSAndroid Build Coastguard Worker
763*49cdfc7eSAndroid Build Coastguard Worker while (1) {
764*49cdfc7eSAndroid Build Coastguard Worker int client_fd = accept(sfd, (struct sockaddr *)&addr6,
765*49cdfc7eSAndroid Build Coastguard Worker &addr_size);
766*49cdfc7eSAndroid Build Coastguard Worker
767*49cdfc7eSAndroid Build Coastguard Worker if (client_fd == -1)
768*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Can't create client socket");
769*49cdfc7eSAndroid Build Coastguard Worker
770*49cdfc7eSAndroid Build Coastguard Worker server_thread_add(client_fd);
771*49cdfc7eSAndroid Build Coastguard Worker }
772*49cdfc7eSAndroid Build Coastguard Worker }
773*49cdfc7eSAndroid Build Coastguard Worker
require_root(const char * file)774*49cdfc7eSAndroid Build Coastguard Worker static void require_root(const char *file)
775*49cdfc7eSAndroid Build Coastguard Worker {
776*49cdfc7eSAndroid Build Coastguard Worker if (!geteuid())
777*49cdfc7eSAndroid Build Coastguard Worker return;
778*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TCONF, "Test needs to be run as root to change %s", file);
779*49cdfc7eSAndroid Build Coastguard Worker }
780*49cdfc7eSAndroid Build Coastguard Worker
check_tfo_value(void)781*49cdfc7eSAndroid Build Coastguard Worker static void check_tfo_value(void)
782*49cdfc7eSAndroid Build Coastguard Worker {
783*49cdfc7eSAndroid Build Coastguard Worker /* Check if we can write to tcp_fastopen knob. We might be
784*49cdfc7eSAndroid Build Coastguard Worker * inside netns and either have read-only permission or
785*49cdfc7eSAndroid Build Coastguard Worker * doesn't have the knob at all.
786*49cdfc7eSAndroid Build Coastguard Worker */
787*49cdfc7eSAndroid Build Coastguard Worker if (access(tfo_cfg, W_OK) < 0) {
788*49cdfc7eSAndroid Build Coastguard Worker /* TODO check /proc/self/ns/ or TST_USE_NETNS env var */
789*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "can't read %s, assume server runs in netns",
790*49cdfc7eSAndroid Build Coastguard Worker tfo_cfg);
791*49cdfc7eSAndroid Build Coastguard Worker return;
792*49cdfc7eSAndroid Build Coastguard Worker }
793*49cdfc7eSAndroid Build Coastguard Worker
794*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_SCANF(tfo_cfg, "%d", &tfo_cfg_value);
795*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "'%s' is %d", tfo_cfg, tfo_cfg_value);
796*49cdfc7eSAndroid Build Coastguard Worker
797*49cdfc7eSAndroid Build Coastguard Worker /* The check can be the first in this function but set here
798*49cdfc7eSAndroid Build Coastguard Worker * to allow to print information about the currently set config
799*49cdfc7eSAndroid Build Coastguard Worker */
800*49cdfc7eSAndroid Build Coastguard Worker if (tfo_value < 0)
801*49cdfc7eSAndroid Build Coastguard Worker return;
802*49cdfc7eSAndroid Build Coastguard Worker
803*49cdfc7eSAndroid Build Coastguard Worker if (tfo_cfg_value == tfo_value)
804*49cdfc7eSAndroid Build Coastguard Worker return;
805*49cdfc7eSAndroid Build Coastguard Worker
806*49cdfc7eSAndroid Build Coastguard Worker require_root(tfo_cfg);
807*49cdfc7eSAndroid Build Coastguard Worker
808*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "set '%s' to '%d'", tfo_cfg, tfo_value);
809*49cdfc7eSAndroid Build Coastguard Worker
810*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTF(tfo_cfg, "%d", tfo_value);
811*49cdfc7eSAndroid Build Coastguard Worker tfo_cfg_changed = 1;
812*49cdfc7eSAndroid Build Coastguard Worker }
813*49cdfc7eSAndroid Build Coastguard Worker
check_tw_reuse(void)814*49cdfc7eSAndroid Build Coastguard Worker static void check_tw_reuse(void)
815*49cdfc7eSAndroid Build Coastguard Worker {
816*49cdfc7eSAndroid Build Coastguard Worker if (access(tcp_tw_reuse, W_OK) < 0)
817*49cdfc7eSAndroid Build Coastguard Worker return;
818*49cdfc7eSAndroid Build Coastguard Worker
819*49cdfc7eSAndroid Build Coastguard Worker int reuse_value = 0;
820*49cdfc7eSAndroid Build Coastguard Worker
821*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_SCANF(tcp_tw_reuse, "%d", &reuse_value);
822*49cdfc7eSAndroid Build Coastguard Worker if (reuse_value) {
823*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "tcp_tw_reuse is already set");
824*49cdfc7eSAndroid Build Coastguard Worker return;
825*49cdfc7eSAndroid Build Coastguard Worker }
826*49cdfc7eSAndroid Build Coastguard Worker
827*49cdfc7eSAndroid Build Coastguard Worker require_root(tfo_cfg);
828*49cdfc7eSAndroid Build Coastguard Worker
829*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTF(tcp_tw_reuse, "1");
830*49cdfc7eSAndroid Build Coastguard Worker tw_reuse_changed = 1;
831*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "set '%s' to '1'", tcp_tw_reuse);
832*49cdfc7eSAndroid Build Coastguard Worker }
833*49cdfc7eSAndroid Build Coastguard Worker
set_protocol_type(void)834*49cdfc7eSAndroid Build Coastguard Worker static void set_protocol_type(void)
835*49cdfc7eSAndroid Build Coastguard Worker {
836*49cdfc7eSAndroid Build Coastguard Worker if (!type || !strcmp(type, "tcp"))
837*49cdfc7eSAndroid Build Coastguard Worker proto_type = TYPE_TCP;
838*49cdfc7eSAndroid Build Coastguard Worker else if (!strcmp(type, "udp"))
839*49cdfc7eSAndroid Build Coastguard Worker proto_type = TYPE_UDP;
840*49cdfc7eSAndroid Build Coastguard Worker else if (!strcmp(type, "udp_lite"))
841*49cdfc7eSAndroid Build Coastguard Worker proto_type = TYPE_UDP_LITE;
842*49cdfc7eSAndroid Build Coastguard Worker else if (!strcmp(type, "dccp"))
843*49cdfc7eSAndroid Build Coastguard Worker proto_type = TYPE_DCCP;
844*49cdfc7eSAndroid Build Coastguard Worker else if (!strcmp(type, "sctp"))
845*49cdfc7eSAndroid Build Coastguard Worker proto_type = TYPE_SCTP;
846*49cdfc7eSAndroid Build Coastguard Worker else
847*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Invalid proto_type: '%s'", type);
848*49cdfc7eSAndroid Build Coastguard Worker }
849*49cdfc7eSAndroid Build Coastguard Worker
setup(void)850*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
851*49cdfc7eSAndroid Build Coastguard Worker {
852*49cdfc7eSAndroid Build Coastguard Worker if (tst_parse_int(aarg, &clients_num, 1, INT_MAX))
853*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Invalid client number '%s'", aarg);
854*49cdfc7eSAndroid Build Coastguard Worker if (tst_parse_int(rarg, &client_max_requests, 1, INT_MAX))
855*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Invalid client max requests '%s'", rarg);
856*49cdfc7eSAndroid Build Coastguard Worker if (tst_parse_int(Rarg, &server_max_requests, 1, INT_MAX))
857*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Invalid server max requests '%s'", Rarg);
858*49cdfc7eSAndroid Build Coastguard Worker if (tst_parse_int(narg, &init_cln_msg_len, min_msg_len, max_msg_len))
859*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Invalid client msg size '%s'", narg);
860*49cdfc7eSAndroid Build Coastguard Worker if (tst_parse_int(Narg, &init_srv_msg_len, min_msg_len, max_msg_len))
861*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Invalid server msg size '%s'", Narg);
862*49cdfc7eSAndroid Build Coastguard Worker if (tst_parse_int(qarg, &tfo_queue_size, 1, INT_MAX))
863*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Invalid TFO queue size '%s'", qarg);
864*49cdfc7eSAndroid Build Coastguard Worker if (tst_parse_int(Targ, &wait_timeout, 0, INT_MAX))
865*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Invalid wait timeout '%s'", Targ);
866*49cdfc7eSAndroid Build Coastguard Worker if (tst_parse_int(barg, &busy_poll, 0, INT_MAX))
867*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Invalid busy poll timeout'%s'", barg);
868*49cdfc7eSAndroid Build Coastguard Worker if (tst_parse_int(targ, &tfo_value, 0, INT_MAX))
869*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Invalid net.ipv4.tcp_fastopen '%s'", targ);
870*49cdfc7eSAndroid Build Coastguard Worker if (tst_parse_int(Aarg, &max_rand_msg_len, 10, max_msg_len))
871*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Invalid max random payload size '%s'", Aarg);
872*49cdfc7eSAndroid Build Coastguard Worker
873*49cdfc7eSAndroid Build Coastguard Worker if (!server_addr)
874*49cdfc7eSAndroid Build Coastguard Worker server_addr = "localhost";
875*49cdfc7eSAndroid Build Coastguard Worker
876*49cdfc7eSAndroid Build Coastguard Worker if (max_rand_msg_len) {
877*49cdfc7eSAndroid Build Coastguard Worker max_rand_msg_len -= min_msg_len;
878*49cdfc7eSAndroid Build Coastguard Worker init_seed = max_rand_msg_len ^ client_max_requests;
879*49cdfc7eSAndroid Build Coastguard Worker srand(init_seed); /* in case rand_r() is missing */
880*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "rand start seed 0x%x", init_seed);
881*49cdfc7eSAndroid Build Coastguard Worker }
882*49cdfc7eSAndroid Build Coastguard Worker
883*49cdfc7eSAndroid Build Coastguard Worker /* if client_num is not set, use num of processors */
884*49cdfc7eSAndroid Build Coastguard Worker if (!clients_num)
885*49cdfc7eSAndroid Build Coastguard Worker clients_num = sysconf(_SC_NPROCESSORS_ONLN);
886*49cdfc7eSAndroid Build Coastguard Worker
887*49cdfc7eSAndroid Build Coastguard Worker if (busy_poll >= 0 && tst_kvercmp(3, 11, 0) < 0)
888*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TCONF, "Test must be run with kernel 3.11 or newer");
889*49cdfc7eSAndroid Build Coastguard Worker
890*49cdfc7eSAndroid Build Coastguard Worker set_protocol_type();
891*49cdfc7eSAndroid Build Coastguard Worker
892*49cdfc7eSAndroid Build Coastguard Worker if (client_mode) {
893*49cdfc7eSAndroid Build Coastguard Worker if (source_addr && tst_kvercmp(4, 2, 0) >= 0) {
894*49cdfc7eSAndroid Build Coastguard Worker bind_no_port = 1;
895*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "IP_BIND_ADDRESS_NO_PORT is used");
896*49cdfc7eSAndroid Build Coastguard Worker }
897*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "connection: addr '%s', port '%s'",
898*49cdfc7eSAndroid Build Coastguard Worker server_addr, tcp_port);
899*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "client max req: %d", client_max_requests);
900*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "clients num: %d", clients_num);
901*49cdfc7eSAndroid Build Coastguard Worker if (max_rand_msg_len) {
902*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "random msg size [%d %d]",
903*49cdfc7eSAndroid Build Coastguard Worker min_msg_len, max_rand_msg_len);
904*49cdfc7eSAndroid Build Coastguard Worker } else {
905*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "client msg size: %d", init_cln_msg_len);
906*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "server msg size: %d", init_srv_msg_len);
907*49cdfc7eSAndroid Build Coastguard Worker }
908*49cdfc7eSAndroid Build Coastguard Worker net.init = client_init;
909*49cdfc7eSAndroid Build Coastguard Worker net.run = client_run;
910*49cdfc7eSAndroid Build Coastguard Worker net.cleanup = client_cleanup;
911*49cdfc7eSAndroid Build Coastguard Worker
912*49cdfc7eSAndroid Build Coastguard Worker switch (proto_type) {
913*49cdfc7eSAndroid Build Coastguard Worker case TYPE_TCP:
914*49cdfc7eSAndroid Build Coastguard Worker check_tw_reuse();
915*49cdfc7eSAndroid Build Coastguard Worker break;
916*49cdfc7eSAndroid Build Coastguard Worker case TYPE_DCCP:
917*49cdfc7eSAndroid Build Coastguard Worker case TYPE_UDP:
918*49cdfc7eSAndroid Build Coastguard Worker case TYPE_UDP_LITE:
919*49cdfc7eSAndroid Build Coastguard Worker if (max_etime_cnt >= client_max_requests)
920*49cdfc7eSAndroid Build Coastguard Worker max_etime_cnt = client_max_requests - 1;
921*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "maximum allowed timeout errors %d", max_etime_cnt);
922*49cdfc7eSAndroid Build Coastguard Worker wait_timeout = 100;
923*49cdfc7eSAndroid Build Coastguard Worker }
924*49cdfc7eSAndroid Build Coastguard Worker } else {
925*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "max requests '%d'",
926*49cdfc7eSAndroid Build Coastguard Worker server_max_requests);
927*49cdfc7eSAndroid Build Coastguard Worker net.init = server_init;
928*49cdfc7eSAndroid Build Coastguard Worker switch (proto_type) {
929*49cdfc7eSAndroid Build Coastguard Worker case TYPE_TCP:
930*49cdfc7eSAndroid Build Coastguard Worker case TYPE_DCCP:
931*49cdfc7eSAndroid Build Coastguard Worker case TYPE_SCTP:
932*49cdfc7eSAndroid Build Coastguard Worker net.run = server_run;
933*49cdfc7eSAndroid Build Coastguard Worker net.cleanup = server_cleanup;
934*49cdfc7eSAndroid Build Coastguard Worker break;
935*49cdfc7eSAndroid Build Coastguard Worker case TYPE_UDP:
936*49cdfc7eSAndroid Build Coastguard Worker case TYPE_UDP_LITE:
937*49cdfc7eSAndroid Build Coastguard Worker net.run = server_run_udp;
938*49cdfc7eSAndroid Build Coastguard Worker net.cleanup = NULL;
939*49cdfc7eSAndroid Build Coastguard Worker break;
940*49cdfc7eSAndroid Build Coastguard Worker }
941*49cdfc7eSAndroid Build Coastguard Worker }
942*49cdfc7eSAndroid Build Coastguard Worker
943*49cdfc7eSAndroid Build Coastguard Worker if (zcopy)
944*49cdfc7eSAndroid Build Coastguard Worker send_flags |= MSG_ZEROCOPY;
945*49cdfc7eSAndroid Build Coastguard Worker
946*49cdfc7eSAndroid Build Coastguard Worker switch (proto_type) {
947*49cdfc7eSAndroid Build Coastguard Worker case TYPE_TCP:
948*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "TCP %s is using %s TCP API.",
949*49cdfc7eSAndroid Build Coastguard Worker (client_mode) ? "client" : "server",
950*49cdfc7eSAndroid Build Coastguard Worker (fastopen_api) ? "Fastopen" : "old");
951*49cdfc7eSAndroid Build Coastguard Worker check_tfo_value();
952*49cdfc7eSAndroid Build Coastguard Worker break;
953*49cdfc7eSAndroid Build Coastguard Worker case TYPE_UDP:
954*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "using UDP");
955*49cdfc7eSAndroid Build Coastguard Worker fastopen_api = fastopen_sapi = NULL;
956*49cdfc7eSAndroid Build Coastguard Worker sock_type = SOCK_DGRAM;
957*49cdfc7eSAndroid Build Coastguard Worker break;
958*49cdfc7eSAndroid Build Coastguard Worker case TYPE_UDP_LITE:
959*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "using UDP Lite");
960*49cdfc7eSAndroid Build Coastguard Worker fastopen_api = fastopen_sapi = NULL;
961*49cdfc7eSAndroid Build Coastguard Worker sock_type = SOCK_DGRAM;
962*49cdfc7eSAndroid Build Coastguard Worker protocol = IPPROTO_UDPLITE;
963*49cdfc7eSAndroid Build Coastguard Worker break;
964*49cdfc7eSAndroid Build Coastguard Worker case TYPE_DCCP: {
965*49cdfc7eSAndroid Build Coastguard Worker /* dccp* modules can be blacklisted, load them manually */
966*49cdfc7eSAndroid Build Coastguard Worker const char * const argv[] = {"modprobe", "dccp_ipv6", NULL};
967*49cdfc7eSAndroid Build Coastguard Worker
968*49cdfc7eSAndroid Build Coastguard Worker if (tst_cmd(argv, NULL, NULL, TST_CMD_PASS_RETVAL))
969*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TCONF, "Failed to load dccp_ipv6 module");
970*49cdfc7eSAndroid Build Coastguard Worker
971*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "DCCP %s", (client_mode) ? "client" : "server");
972*49cdfc7eSAndroid Build Coastguard Worker fastopen_api = fastopen_sapi = NULL;
973*49cdfc7eSAndroid Build Coastguard Worker sock_type = SOCK_DCCP;
974*49cdfc7eSAndroid Build Coastguard Worker protocol = IPPROTO_DCCP;
975*49cdfc7eSAndroid Build Coastguard Worker service_code = htonl(service_code);
976*49cdfc7eSAndroid Build Coastguard Worker } break;
977*49cdfc7eSAndroid Build Coastguard Worker case TYPE_SCTP:
978*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "SCTP %s", (client_mode) ? "client" : "server");
979*49cdfc7eSAndroid Build Coastguard Worker fastopen_api = fastopen_sapi = NULL;
980*49cdfc7eSAndroid Build Coastguard Worker protocol = IPPROTO_SCTP;
981*49cdfc7eSAndroid Build Coastguard Worker break;
982*49cdfc7eSAndroid Build Coastguard Worker }
983*49cdfc7eSAndroid Build Coastguard Worker
984*49cdfc7eSAndroid Build Coastguard Worker if ((errno = pthread_attr_init(&attr)))
985*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TERRNO, "pthread_attr_init failed");
986*49cdfc7eSAndroid Build Coastguard Worker
987*49cdfc7eSAndroid Build Coastguard Worker if ((errno = pthread_attr_setstacksize(&attr, 256*1024)))
988*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TERRNO, "pthread_attr_setstacksize(256*1024) failed");
989*49cdfc7eSAndroid Build Coastguard Worker
990*49cdfc7eSAndroid Build Coastguard Worker net.init();
991*49cdfc7eSAndroid Build Coastguard Worker }
992*49cdfc7eSAndroid Build Coastguard Worker
do_test(void)993*49cdfc7eSAndroid Build Coastguard Worker static void do_test(void)
994*49cdfc7eSAndroid Build Coastguard Worker {
995*49cdfc7eSAndroid Build Coastguard Worker net.run();
996*49cdfc7eSAndroid Build Coastguard Worker }
997*49cdfc7eSAndroid Build Coastguard Worker
998*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
999*49cdfc7eSAndroid Build Coastguard Worker .test_all = do_test,
1000*49cdfc7eSAndroid Build Coastguard Worker .forks_child = 1,
1001*49cdfc7eSAndroid Build Coastguard Worker .setup = setup,
1002*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup,
1003*49cdfc7eSAndroid Build Coastguard Worker .options = (struct tst_option[]) {
1004*49cdfc7eSAndroid Build Coastguard Worker {"f", &fastopen_api, "Use TFO API, default is old API"},
1005*49cdfc7eSAndroid Build Coastguard Worker {"F", &fastopen_sapi, "TCP_FASTOPEN_CONNECT socket option and standard API"},
1006*49cdfc7eSAndroid Build Coastguard Worker {"t:", &targ, "Set tcp_fastopen value"},
1007*49cdfc7eSAndroid Build Coastguard Worker {"S:", &source_addr, "Source address to bind"},
1008*49cdfc7eSAndroid Build Coastguard Worker {"g:", &tcp_port, "Server port"},
1009*49cdfc7eSAndroid Build Coastguard Worker {"b:", &barg, "Low latency busy poll timeout"},
1010*49cdfc7eSAndroid Build Coastguard Worker {"T:", &type, "Tcp (default), udp, udp_lite, dccp, sctp"},
1011*49cdfc7eSAndroid Build Coastguard Worker {"z", &zcopy, "Enable SO_ZEROCOPY"},
1012*49cdfc7eSAndroid Build Coastguard Worker {"P:", &reuse_port, "Enable SO_REUSEPORT"},
1013*49cdfc7eSAndroid Build Coastguard Worker {"d:", &dev, "Bind to device x"},
1014*49cdfc7eSAndroid Build Coastguard Worker
1015*49cdfc7eSAndroid Build Coastguard Worker {"H:", &server_addr, "Server name or IP address"},
1016*49cdfc7eSAndroid Build Coastguard Worker {"l", &client_mode, "Become client, default is server"},
1017*49cdfc7eSAndroid Build Coastguard Worker {"a:", &aarg, "Number of clients running in parallel"},
1018*49cdfc7eSAndroid Build Coastguard Worker {"r:", &rarg, "Number of client requests"},
1019*49cdfc7eSAndroid Build Coastguard Worker {"n:", &narg, "Client message size"},
1020*49cdfc7eSAndroid Build Coastguard Worker {"N:", &Narg, "Server message size"},
1021*49cdfc7eSAndroid Build Coastguard Worker {"m:", &Targ, "Receive timeout in milliseconds (not used by UDP/DCCP client)"},
1022*49cdfc7eSAndroid Build Coastguard Worker {"c:", &rpath, "Path to file where result is saved"},
1023*49cdfc7eSAndroid Build Coastguard Worker {"A:", &Aarg, "Max payload length (generated randomly)"},
1024*49cdfc7eSAndroid Build Coastguard Worker
1025*49cdfc7eSAndroid Build Coastguard Worker {"R:", &Rarg, "Server requests after which conn.closed"},
1026*49cdfc7eSAndroid Build Coastguard Worker {"q:", &qarg, "TFO queue"},
1027*49cdfc7eSAndroid Build Coastguard Worker {"B:", &server_bg, "Run in background, arg is the process directory"},
1028*49cdfc7eSAndroid Build Coastguard Worker {}
1029*49cdfc7eSAndroid Build Coastguard Worker },
1030*49cdfc7eSAndroid Build Coastguard Worker .max_runtime = 300,
1031*49cdfc7eSAndroid Build Coastguard Worker .needs_checkpoints = 1,
1032*49cdfc7eSAndroid Build Coastguard Worker };
1033