1 /*
2 * Copyright (C) 2013-2021 Canonical, Ltd.
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
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will 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 to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 * This code is a complete clean re-write of the stress tool by
19 * Colin Ian King <colin.king@canonical.com> and attempts to be
20 * backwardly compatible with the stress tool by Amos Waterland
21 * <apw@rossby.metr.ou.edu> but has more stress tests and more
22 * functionality.
23 *
24 */
25 #include "stress-ng.h"
26
27 #define MMAP_BUF_SIZE (65536)
28 #define MMAP_IO_SIZE (8192) /* Must be less or equal to 8192 */
29
30 #define SOCKET_OPT_SEND (0x00)
31 #define SOCKET_OPT_SENDMSG (0x01)
32 #define SOCKET_OPT_SENDMMSG (0x02)
33 #define SOCKET_OPT_RANDOM (0x03)
34
35 #define SOCKET_OPT_RECV (SOCKET_OPT_SEND)
36 #define SOCKET_OPT_RECVMSG (SOCKET_OPT_SENDMSG)
37 #define SOCKET_OPT_RECVMMSG (SOCKET_OPT_SENDMMSG)
38
39 #if !defined(IPPROTO_TCP)
40 #define IPPROTO_TCP (0)
41 #endif
42
43 #define MSGVEC_SIZE (4)
44
45 #define PROC_CONG_CTRLS "/proc/sys/net/ipv4/tcp_allowed_congestion_control"
46
47 typedef struct {
48 const char *optname;
49 const int optval;
50 } stress_socket_options_t;
51
52 static const stress_help_t help[] = {
53 { "S N", "sock N", "start N workers exercising socket I/O" },
54 { NULL, "sock-domain D", "specify socket domain, default is ipv4" },
55 { NULL, "sock-nodelay", "disable Nagle algorithm, send data immediately" },
56 { NULL, "sock-ops N", "stop after N socket bogo operations" },
57 { NULL, "sock-opts option", "socket options [send|sendmsg|sendmmsg]" },
58 { NULL, "sock-port P", "use socket ports P to P + number of workers - 1" },
59 { NULL, "sock-protocol", "use socket protocol P, default is tcp, can be mptcp" },
60 { NULL, "sock-type T", "socket type (stream, seqpacket)" },
61 { NULL, "sock-zerocopy", "enable zero copy sends" },
62 { NULL, NULL, NULL }
63 };
64
65 /*
66 * stress_set_socket_option()
67 * generic helper to set an option
68 */
stress_set_socket_option(const char * setting,const stress_socket_options_t options[],const char * opt)69 static int stress_set_socket_option(
70 const char *setting,
71 const stress_socket_options_t options[],
72 const char *opt)
73 {
74 size_t i;
75
76 for (i = 0; options[i].optname; i++) {
77 if (!strcmp(opt, options[i].optname)) {
78 int type = options[i].optval;
79
80 stress_set_setting(setting, TYPE_ID_INT, &type);
81 return 0;
82 }
83 }
84 (void)fprintf(stderr, "%s option '%s' not known, options are:", setting, opt);
85 for (i = 0; options[i].optname; i++) {
86 (void)fprintf(stderr, "%s %s",
87 i == 0 ? "" : ",", options[i].optname);
88 }
89 (void)fprintf(stderr, "\n");
90 return -1;
91 }
92
93 /*
94 * stress_set_socket_opts()
95 * parse --sock-opts
96 */
stress_set_socket_opts(const char * opt)97 static int stress_set_socket_opts(const char *opt)
98 {
99 static const stress_socket_options_t socket_opts[] = {
100 { "random", SOCKET_OPT_RANDOM },
101 { "send", SOCKET_OPT_SEND },
102 { "sendmsg", SOCKET_OPT_SENDMSG },
103 #if defined(HAVE_SENDMMSG)
104 { "sendmmsg", SOCKET_OPT_SENDMMSG },
105 #endif
106 { NULL, 0 }
107 };
108
109 return stress_set_socket_option("sock-opts", socket_opts, opt);
110 }
111
112 /*
113 * stress_set_socket_type()
114 * parse --sock-type
115 */
stress_set_socket_type(const char * opt)116 static int stress_set_socket_type(const char *opt)
117 {
118 static const stress_socket_options_t socket_types[] = {
119 #if defined(SOCK_STREAM)
120 { "stream", SOCK_STREAM },
121 #endif
122 #if defined(SOCK_SEQPACKET)
123 { "seqpacket", SOCK_SEQPACKET },
124 #endif
125 { NULL, 0 }
126 };
127
128 return stress_set_socket_option("sock-type", socket_types, opt);
129 }
130
131 /*
132 * stress_set_socket_port()
133 * set port to use
134 */
stress_set_socket_port(const char * opt)135 static int stress_set_socket_port(const char *opt)
136 {
137 int socket_port;
138
139 stress_set_net_port("sock-port", opt,
140 MIN_SOCKET_PORT, MAX_SOCKET_PORT - STRESS_PROCS_MAX,
141 &socket_port);
142 return stress_set_setting("sock-port", TYPE_ID_INT, &socket_port);
143 }
144
145 /*
146 * stress_set_socket_protocol()
147 * parse --sock-protocol
148 */
stress_set_socket_protocol(const char * opt)149 static int stress_set_socket_protocol(const char *opt)
150 {
151 static const stress_socket_options_t socket_protocols[] = {
152 { "tcp", IPPROTO_TCP},
153 #if defined(IPPROTO_MPTCP)
154 { "mptcp", IPPROTO_MPTCP},
155 #endif
156 { NULL, 0 }
157 };
158
159 return stress_set_socket_option("sock-protocol", socket_protocols, opt);
160 }
161
162
163 /*
164 * stress_set_socket_domain()
165 * set the socket domain option
166 */
stress_set_socket_domain(const char * name)167 static int stress_set_socket_domain(const char *name)
168 {
169 int ret, socket_domain;
170
171 ret = stress_set_net_domain(DOMAIN_ALL, "sock-domain",
172 name, &socket_domain);
173 stress_set_setting("sock-domain", TYPE_ID_INT, &socket_domain);
174
175 return ret;
176 }
177
178 /*
179 * stress_set_socket_zerocopy()
180 * set the socket zerocopy option
181 */
stress_set_socket_zerocopy(const char * opt)182 static int stress_set_socket_zerocopy(const char *opt)
183 {
184 #if defined(MSG_ZEROCOPY)
185 bool socket_zerocopy = true;
186
187 (void)opt;
188 return stress_set_setting("sock-zerocopy", TYPE_ID_BOOL, &socket_zerocopy);
189 #else
190 (void)opt;
191 pr_inf("sock: cannot enable sock-zerocopy, MSG_ZEROCOPY is not available\n");
192 return 0;
193 #endif
194 }
195
196 /*
197 * stress_free_congestion_controls()
198 * free congestion controls array
199 */
stress_free_congestion_controls(char * ctrls[],const size_t n)200 static void stress_free_congestion_controls(char *ctrls[], const size_t n)
201 {
202 size_t i;
203
204 if (!ctrls)
205 return;
206
207 for (i = 0; i < n; i++)
208 free(ctrls[i]);
209
210 free(ctrls); /* cppcheck-suppress autovarInvalidDeallocation */
211 }
212
213 /*
214 * stress_get_congestion_controls()
215 * get congestion controls, currently only for AF_INET. ctrls is a
216 * pointer to an array of pointers to available congestion control names -
217 * the array is allocated by this function, or NULL if it fails. Returns
218 * the number of congestion controls, 0 if none found.
219 */
stress_get_congestion_controls(const int socket_domain,char ** ctrls[])220 static size_t stress_get_congestion_controls(const int socket_domain, char **ctrls[])
221 {
222 char buf[4096], *ptr, *ctrl;
223 char **array = NULL;
224 size_t n_ctrls;
225
226 *ctrls = NULL;
227
228 if (socket_domain != AF_INET)
229 return 0;
230
231 if (system_read(PROC_CONG_CTRLS, buf, sizeof(buf)) < 0)
232 return 0;
233
234 for (n_ctrls = 0, ptr = buf; (ctrl = strtok(ptr, " ")) != NULL; ptr = NULL) {
235 char **tmp, *newline = strchr(ctrl, '\n');
236
237 if (newline)
238 *newline = '\0';
239
240 tmp = realloc(array , (sizeof(*array)) * (n_ctrls + 1));
241 if (!tmp) {
242 stress_free_congestion_controls(array, n_ctrls);
243 return 0;
244 }
245 array = tmp;
246 array[n_ctrls] = strdup(ctrl);
247 if (!array[n_ctrls]) {
248 stress_free_congestion_controls(array, n_ctrls);
249 return 0;
250 }
251 n_ctrls++;
252 }
253
254 *ctrls = array;
255 return n_ctrls;
256 }
257
258 /*
259 * stress_sock_ioctl()
260 * exercise various ioctl commands
261 */
stress_sock_ioctl(const int fd,const int socket_domain,const bool rt)262 static void stress_sock_ioctl(
263 const int fd,
264 const int socket_domain,
265 const bool rt)
266 {
267 (void)fd;
268 (void)socket_domain;
269 (void)rt;
270
271 #if defined(FIOGETOWN)
272 if (!rt) {
273 int ret, own;
274
275 ret = ioctl(fd, FIOGETOWN, &own);
276 #if defined(FIOSETOWN)
277 if (ret == 0)
278 ret = ioctl(fd, FIOSETOWN, &own);
279 (void)ret;
280 #endif
281 }
282 #endif
283
284 #if defined(SIOCGPGRP)
285 if (!rt) {
286 int ret, own;
287
288 ret = ioctl(fd, SIOCGPGRP, &own);
289 #if defined(SIOCSPGRP)
290 if (ret == 0)
291 ret = ioctl(fd, SIOCSPGRP, &own);
292 #endif
293 (void)ret;
294 }
295 #endif
296 #if defined(SIOCGIFCONF) && \
297 defined(HAVE_IFCONF)
298 if (!rt) {
299 int ret;
300 struct ifconf ifc;
301
302 (void)memset(&ifc, 0, sizeof(ifc));
303 ret = ioctl(fd, SIOCGIFCONF, &ifc);
304 (void)ret;
305 }
306 #endif
307
308 /*
309 * On some 32 bit arches on some kernels/libc flavours
310 * struct __kernel_old_timeval is not defined and causes
311 * this ioctl to break the build. So only build it for
312 * 64 bit arches as a workaround.
313 */
314 #if defined(SIOCGSTAMP) && \
315 (ULONG_MAX > 4294967295UL)
316 {
317 int ret;
318 struct timeval tv;
319
320 ret = ioctl(fd, SIOCGSTAMP, &tv);
321 (void)ret;
322 }
323 #endif
324
325 #if defined(SIOCGSTAMP_NEW) && \
326 (ULONG_MAX > 4294967295UL)
327 {
328 int ret;
329 struct timeval tv;
330
331 ret = ioctl(fd, SIOCGSTAMP_NEW, &tv);
332 (void)ret;
333 }
334 #endif
335
336 #if defined(SIOCGSKNS)
337 {
338 int ns_fd;
339
340 ns_fd = ioctl(fd, SIOCGSKNS);
341 if (ns_fd >= 0)
342 (void)close(ns_fd);
343 }
344 #endif
345
346 #if defined(__linux__) && \
347 !defined(SIOCUNIXFILE)
348 #define SIOCUNIXFILE (SIOCPROTOPRIVATE + 0)
349 #endif
350
351 #if defined(SIOCUNIXFILE)
352 if (socket_domain == AF_UNIX) {
353 int fd_unixfile;
354
355 fd_unixfile = ioctl(fd, SIOCUNIXFILE, 0);
356 if (fd_unixfile >= 0)
357 (void)close(fd_unixfile);
358 }
359 #endif
360 }
361
362 /*
363 * stress_sock_invalid_recv()
364 * exercise invalid recv* calls
365 */
stress_sock_invalid_recv(const int fd,const int opt)366 static void stress_sock_invalid_recv(const int fd, const int opt)
367 {
368 ssize_t n;
369 char buf[16];
370 struct iovec vec[1];
371 struct msghdr msg;
372 #if defined(HAVE_RECVMMSG)
373 struct mmsghdr msgvec[MSGVEC_SIZE];
374 struct timespec ts;
375 #endif
376
377 switch (opt) {
378 case SOCKET_OPT_RECV:
379 /* exercise invalid flags */
380 n = recv(fd, buf, sizeof(buf), ~0);
381 (void)n;
382
383 /* exercise invalid fd */
384 n = recv(~0, buf, sizeof(buf), 0);
385 (void)n;
386 break;
387 case SOCKET_OPT_RECVMSG:
388 vec[0].iov_base = buf;
389 vec[0].iov_len = sizeof(buf);
390 (void)memset(&msg, 0, sizeof(msg));
391 msg.msg_iov = vec;
392 msg.msg_iovlen = 1;
393
394 /* exercise invalid flags */
395 n = recvmsg(fd, &msg, ~0);
396 (void)n;
397
398 /* exercise invalid fd */
399 n = recvmsg(~0, &msg, 0);
400 (void)n;
401 break;
402 #if defined(HAVE_RECVMMSG)
403 case SOCKET_OPT_RECVMMSG:
404 (void)memset(msgvec, 0, sizeof(msgvec));
405 vec[0].iov_base = buf;
406 vec[0].iov_len = sizeof(buf);
407 msgvec[0].msg_hdr.msg_iov = vec;
408 msgvec[0].msg_hdr.msg_iovlen = 1;
409
410 /* exercise invalid flags */
411 n = recvmmsg(fd, msgvec, MSGVEC_SIZE, ~0, NULL);
412 (void)n;
413
414 /* exercise invalid fd */
415 n = recvmmsg(~0, msgvec, MSGVEC_SIZE, 0, NULL);
416 (void)n;
417
418 /* exercise invalid timespec */
419 ts.tv_sec = 0;
420 ts.tv_nsec = 0;
421 n = recvmmsg(~0, msgvec, MSGVEC_SIZE, 0, &ts);
422 (void)n;
423 break;
424 #endif
425 }
426 }
427
428 /*
429 * stress_sock_client()
430 * client reader
431 */
stress_sock_client(const stress_args_t * args,char * buf,const pid_t ppid,const int socket_opts,const int socket_domain,const int socket_type,const int socket_protocol,const int socket_port,const bool rt,const bool socket_zerocopy)432 static void stress_sock_client(
433 const stress_args_t *args,
434 char *buf,
435 const pid_t ppid,
436 const int socket_opts,
437 const int socket_domain,
438 const int socket_type,
439 const int socket_protocol,
440 const int socket_port,
441 const bool rt,
442 const bool socket_zerocopy)
443 {
444 struct sockaddr *addr;
445 size_t n_ctrls;
446 char **ctrls;
447 int recvflag = 0;
448
449 (void)setpgid(0, g_pgrp);
450 stress_parent_died_alarm();
451 (void)sched_settings_apply(true);
452
453 n_ctrls = stress_get_congestion_controls(socket_domain, &ctrls);
454
455 #if defined(MSG_ZEROCOPY)
456 if (socket_zerocopy)
457 recvflag |= MSG_ZEROCOPY;
458 #else
459 (void)socket_zerocopy;
460 #endif
461
462 do {
463 int fd;
464 int retries = 0;
465 static int count = 0;
466 socklen_t addr_len = 0;
467 retry:
468 if (!keep_stressing_flag()) {
469 (void)kill(getppid(), SIGALRM);
470 _exit(EXIT_FAILURE);
471 }
472
473 /* Exercise illegal socket family */
474 fd = socket(~0, socket_type, socket_protocol);
475 if (fd >= 0)
476 (void)close(fd);
477
478 /* Exercise illegal socket type */
479 fd = socket(socket_domain, ~0, socket_protocol);
480 if (fd >= 0)
481 (void)close(fd);
482
483 /* Exercise illegal socket protocol */
484 fd = socket(socket_domain, socket_type, ~0);
485 if (fd >= 0)
486 (void)close(fd);
487
488 fd = socket(socket_domain, socket_type, socket_protocol);
489 if (fd < 0) {
490 pr_fail("%s: socket failed, errno=%d (%s)\n",
491 args->name, errno, strerror(errno));
492 /* failed, kick parent to finish */
493 (void)kill(getppid(), SIGALRM);
494 _exit(EXIT_FAILURE);
495 }
496
497 stress_set_sockaddr(args->name, args->instance, ppid,
498 socket_domain, socket_port,
499 &addr, &addr_len, NET_ADDR_ANY);
500 if (connect(fd, addr, addr_len) < 0) {
501 int errno_tmp = errno;
502
503 (void)close(fd);
504 (void)shim_usleep(10000);
505 retries++;
506 if (retries > 100) {
507 /* Give up.. */
508 pr_fail("%s: connect failed, errno=%d (%s)\n",
509 args->name, errno_tmp, strerror(errno_tmp));
510 (void)kill(getppid(), SIGALRM);
511 _exit(EXIT_FAILURE);
512 }
513 goto retry;
514 }
515
516 #if defined(TCP_CONGESTION)
517 /*
518 * Randomly set congestion control
519 */
520 if (n_ctrls > 0) {
521 const int idx = stress_mwc16() % n_ctrls;
522 const char *control = ctrls[idx];
523 char name[256];
524 socklen_t len;
525
526 len = (socklen_t)strlen(ctrls[idx]);
527 (void)setsockopt(fd, IPPROTO_TCP, TCP_CONGESTION, control, len);
528 len = (socklen_t)sizeof(name);
529 (void)getsockopt(fd, IPPROTO_TCP, TCP_CONGESTION, name, &len);
530 }
531 #endif
532 #if defined(IP_MTU)
533 {
534 int ret, mtu;
535 socklen_t optlen;
536
537 optlen = sizeof(mtu);
538 ret = getsockopt(fd, IPPROTO_IP, IP_MTU,
539 &mtu, &optlen);
540 if (ret == 0) {
541 optlen = sizeof(mtu);
542 ret = setsockopt(fd, IPPROTO_IP, IP_MTU,
543 &mtu, optlen);
544 }
545 (void)ret;
546 }
547 #endif
548 #if defined(IP_TOS) && \
549 defined(IPTOS_THROUGHPUT)
550 {
551 char tos = IPTOS_THROUGHPUT;
552 socklen_t optlen = sizeof(tos);
553
554 (void)setsockopt(fd, IPPROTO_IP, IP_TOS,
555 &tos, optlen);
556 (void)getsockopt(fd, IPPROTO_IP, IP_TOS,
557 &tos, &optlen);
558 }
559 #endif
560 #if defined(SO_INCOMING_CPU)
561 {
562 int cpu;
563 socklen_t optlen = sizeof(cpu);
564
565 (void)getsockopt(fd, SOL_SOCKET, SO_INCOMING_CPU,
566 &cpu, &optlen);
567 }
568 #endif
569 if ((socket_domain == AF_INET) || (socket_domain == AF_INET6)) {
570 #if defined(TCP_NODELAY)
571 {
572 int val = 0, ret;
573 socklen_t optlen = sizeof(val);
574
575 ret = getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, &optlen);
576 if (ret == 0) {
577 optlen = sizeof(val);
578 ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, optlen);
579 }
580 (void)ret;
581 }
582 #endif
583 #if defined(TCP_CORK)
584 {
585 int val = 0, ret;
586 socklen_t optlen = sizeof(val);
587
588 ret = getsockopt(fd, IPPROTO_TCP, TCP_CORK, &val, &optlen);
589 if (ret == 0) {
590 optlen = sizeof(val);
591 ret = setsockopt(fd, IPPROTO_TCP, TCP_CORK, &val, optlen);
592 }
593 (void)ret;
594 }
595 #endif
596 #if defined(TCP_DEFER_ACCEPT)
597 {
598 int val = 0, ret;
599 socklen_t optlen = sizeof(val);
600
601 ret = getsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &val, &optlen);
602 if (ret == 0) {
603 optlen = sizeof(val);
604 ret = setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &val, optlen);
605 }
606 (void)ret;
607 }
608 #endif
609 #if defined(TCP_KEEPCNT)
610 {
611 int val = 0, ret;
612 socklen_t optlen = sizeof(val);
613
614 ret = getsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, &optlen);
615 if (ret == 0) {
616 optlen = sizeof(val);
617 ret = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, optlen);
618 }
619 (void)ret;
620 }
621 #endif
622 #if defined(TCP_KEEPIDLE)
623 {
624 int val = 0, ret;
625 socklen_t optlen = sizeof(val);
626
627 ret = getsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, &optlen);
628 if (ret == 0) {
629 optlen = sizeof(val);
630 ret = setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, optlen);
631 }
632 (void)ret;
633 }
634 #endif
635 #if defined(TCP_KEEPINTVL)
636 {
637 int val = 0, ret;
638 socklen_t optlen = sizeof(val);
639
640 ret = getsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, &optlen);
641 if (ret == 0) {
642 optlen = sizeof(val);
643 ret = setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, optlen);
644 }
645 (void)ret;
646 }
647 #endif
648 #if defined(TCP_LINGER2)
649 {
650 int val = 0, ret;
651 socklen_t optlen = sizeof(val);
652
653 ret = getsockopt(fd, IPPROTO_TCP, TCP_LINGER2, &val, &optlen);
654 if (ret == 0) {
655 optlen = sizeof(val);
656 ret = setsockopt(fd, IPPROTO_TCP, TCP_LINGER2, &val, optlen);
657 }
658 (void)ret;
659 }
660 #endif
661 #if defined(TCP_MAXSEG)
662 {
663 int val = 0, ret;
664 socklen_t optlen = sizeof(val);
665
666 ret = getsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, &val, &optlen);
667 if (ret == 0) {
668 optlen = sizeof(val);
669 ret = setsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, &val, optlen);
670 }
671 (void)ret;
672 }
673 #endif
674 #if defined(TCP_SYNCNT)
675 {
676 int val = 0, ret;
677 socklen_t optlen = sizeof(val);
678
679 ret = getsockopt(fd, IPPROTO_TCP, TCP_SYNCNT, &val, &optlen);
680 if (ret == 0) {
681 optlen = sizeof(val);
682 ret = setsockopt(fd, IPPROTO_TCP, TCP_SYNCNT, &val, optlen);
683 }
684 (void)ret;
685 }
686 #endif
687 #if defined(TCP_USER_TIMEOUT)
688 {
689 int val = 0, ret;
690 socklen_t optlen = sizeof(val);
691
692 ret = getsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &val, &optlen);
693 if (ret == 0) {
694 optlen = sizeof(val);
695 ret = setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &val, optlen);
696 }
697 (void)ret;
698 }
699 #endif
700 #if defined(TCP_WINDOW_CLAMP)
701 {
702 int val = 0, ret;
703 socklen_t optlen = sizeof(val);
704
705 ret = getsockopt(fd, IPPROTO_TCP, TCP_WINDOW_CLAMP, &val, &optlen);
706 if (ret == 0) {
707 optlen = sizeof(val);
708 ret = setsockopt(fd, IPPROTO_TCP, TCP_WINDOW_CLAMP, &val, optlen);
709 }
710 (void)ret;
711 }
712 #endif
713 }
714
715 do {
716 ssize_t n = 0;
717 size_t i, j;
718 char *recvfunc = "recv";
719 struct msghdr msg;
720 struct iovec vec[MMAP_IO_SIZE / 16];
721 #if defined(HAVE_RECVMMSG)
722 struct mmsghdr msgvec[MSGVEC_SIZE];
723 const int max_opt = 3;
724 #else
725 const int max_opt = 2;
726 #endif
727 const int opt = (socket_opts == SOCKET_OPT_RANDOM) ?
728 stress_mwc8() % max_opt: socket_opts;
729
730 #if defined(FIONREAD)
731 /*
732 * Exercise FIONREAD ioctl. Linux supports
733 * this also with SIOCINQ but lets try and
734 * do the more standard way of peeking the
735 * pending data size. Do this infrequently
736 * to ensure we exercise it without impacting
737 * performance.
738 */
739 if ((count & 0x3ff) == 0) {
740 int ret;
741 size_t bytes = MMAP_IO_SIZE;
742
743 ret = ioctl(fd, FIONREAD, &bytes);
744 (void)ret;
745 count = 0;
746
747 if (bytes > MMAP_IO_SIZE)
748 bytes = MMAP_IO_SIZE;
749
750 }
751 #endif
752 /* Periodically exercise invalid recv calls */
753 if ((count & 0x7ff) == 0)
754 stress_sock_invalid_recv(fd, opt);
755 #if defined(SIOCINQ)
756 {
757 int pending;
758
759 (void)ioctl(fd, SIOCINQ, &pending);
760 }
761 #endif
762
763 /*
764 * Receive using equivalent receive method
765 * as the send
766 */
767 switch (opt) {
768 case SOCKET_OPT_RECV:
769 recvfunc = "recv";
770 n = recv(fd, buf, MMAP_IO_SIZE, recvflag);
771 break;
772 case SOCKET_OPT_RECVMSG:
773 recvfunc = "recvmsg";
774 for (j = 0, i = 16; i < MMAP_IO_SIZE; i += 16, j++) {
775 vec[j].iov_base = buf;
776 vec[j].iov_len = i;
777 }
778 (void)memset(&msg, 0, sizeof(msg));
779 msg.msg_iov = vec;
780 msg.msg_iovlen = j;
781 n = recvmsg(fd, &msg, 0);
782 break;
783 #if defined(HAVE_RECVMMSG)
784 case SOCKET_OPT_RECVMMSG:
785 recvfunc = "recvmmsg";
786 (void)memset(msgvec, 0, sizeof(msgvec));
787 for (j = 0, i = 16; i < MMAP_IO_SIZE; i += 16, j++) {
788 vec[j].iov_base = buf;
789 vec[j].iov_len = i;
790 }
791 for (i = 0; i < MSGVEC_SIZE; i++) {
792 msgvec[i].msg_hdr.msg_iov = vec;
793 msgvec[i].msg_hdr.msg_iovlen = j;
794 }
795 n = recvmmsg(fd, msgvec, MSGVEC_SIZE, 0, NULL);
796 if (n > 0) {
797 for (n = 0, i = 0; i < MSGVEC_SIZE; i++)
798 n += msgvec[i].msg_len;
799 }
800 break;
801 #endif
802 }
803 if (n == 0)
804 break;
805 if (n < 0) {
806 if ((errno != EINTR) && (errno != ECONNRESET))
807 pr_fail("%s: %s failed, errno=%d (%s)\n",
808 recvfunc, args->name,
809 errno, strerror(errno));
810 break;
811 }
812 count++;
813 } while (keep_stressing(args));
814
815 stress_sock_ioctl(fd, socket_domain, rt);
816 #if defined(AF_INET) && \
817 defined(IPPROTO_IP) && \
818 defined(IP_MTU)
819 /* Exercise IP_MTU */
820 if (socket_domain == AF_INET) {
821 int ret, mtu;
822 socklen_t mtu_len = sizeof(mtu);
823
824 ret = getsockopt(fd, IPPROTO_IP, IP_MTU, &mtu, &mtu_len);
825 (void)ret;
826 }
827 #endif
828
829 (void)shutdown(fd, SHUT_RDWR);
830 (void)close(fd);
831 } while (keep_stressing(args));
832
833 #if defined(AF_UNIX) && \
834 defined(HAVE_SOCKADDR_UN)
835 if (socket_domain == AF_UNIX) {
836 struct sockaddr_un *addr_un = (struct sockaddr_un *)addr;
837
838 (void)unlink(addr_un->sun_path);
839 }
840 #endif
841 /* Inform parent we're all done */
842 stress_free_congestion_controls(ctrls, n_ctrls);
843
844 (void)kill(getppid(), SIGALRM);
845 }
846
847 /*
848 * stress_sock_server()
849 * server writer
850 */
stress_sock_server(const stress_args_t * args,char * buf,const pid_t pid,const pid_t ppid,const int socket_opts,const int socket_domain,const int socket_type,const int socket_protocol,const int socket_port,const bool rt,const bool socket_zerocopy)851 static int stress_sock_server(
852 const stress_args_t *args,
853 char *buf,
854 const pid_t pid,
855 const pid_t ppid,
856 const int socket_opts,
857 const int socket_domain,
858 const int socket_type,
859 const int socket_protocol,
860 const int socket_port,
861 const bool rt,
862 const bool socket_zerocopy)
863 {
864 int fd, status;
865 int so_reuseaddr = 1;
866 socklen_t addr_len = 0;
867 struct sockaddr *addr = NULL;
868 uint64_t msgs = 0;
869 int rc = EXIT_SUCCESS;
870 const size_t page_size = args->page_size;
871 void *ptr = MAP_FAILED;
872 const pid_t self = getpid();
873 int sendflag = 0;
874
875 #if defined(MSG_ZEROCOPY)
876 if (socket_zerocopy)
877 sendflag |= MSG_ZEROCOPY;
878 #else
879 (void)socket_zerocopy;
880 #endif
881
882 (void)setpgid(pid, g_pgrp);
883
884 if (stress_sig_stop_stressing(args->name, SIGALRM) < 0) {
885 rc = EXIT_FAILURE;
886 goto die;
887 }
888
889 if ((fd = socket(socket_domain, socket_type, socket_protocol)) < 0) {
890 rc = exit_status(errno);
891 pr_fail("%s: socket failed, errno=%d (%s)\n",
892 args->name, errno, strerror(errno));
893 goto die;
894 }
895 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
896 &so_reuseaddr, sizeof(so_reuseaddr)) < 0) {
897 pr_fail("%s: setsockopt failed, errno=%d (%s)\n",
898 args->name, errno, strerror(errno));
899 rc = EXIT_FAILURE;
900 goto die_close;
901 }
902 /* exercise invalid setsockopt lengths */
903 (void)setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, 0);
904 (void)setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, -1);
905
906 /* exercise invalid setsockopt fd */
907 (void)setsockopt(-1, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, sizeof(so_reuseaddr));
908
909 /* exercise invalid level */
910 (void)setsockopt(fd, -1, SO_REUSEADDR, &so_reuseaddr, sizeof(so_reuseaddr));
911
912 /* exercise invalid optname */
913 (void)setsockopt(fd, SOL_SOCKET, -1, &so_reuseaddr, sizeof(so_reuseaddr));
914
915 stress_set_sockaddr(args->name, args->instance, ppid,
916 socket_domain, socket_port,
917 &addr, &addr_len, NET_ADDR_ANY);
918 if (bind(fd, addr, addr_len) < 0) {
919 rc = exit_status(errno);
920 pr_fail("%s: bind failed, errno=%d (%s)\n",
921 args->name, errno, strerror(errno));
922 goto die_close;
923 }
924 if (listen(fd, 10) < 0) {
925 pr_fail("%s: listen failed, errno=%d (%s)\n",
926 args->name, errno, strerror(errno));
927 rc = EXIT_FAILURE;
928 goto die_close;
929 }
930
931 /*
932 * Some systems allow us to mmap onto the fd
933 * so try and do this just because we can
934 */
935 ptr = mmap(NULL, page_size, PROT_READ, MAP_PRIVATE, fd, 0);
936
937 do {
938 int sfd;
939
940 if (!keep_stressing(args))
941 break;
942
943 #if defined(HAVE_ACCEPT4)
944 /* Randomly use accept or accept4 to exercise both */
945 if (stress_mwc1()) {
946 sfd = accept4(fd, (struct sockaddr *)NULL, NULL, SOCK_CLOEXEC);
947 } else {
948 sfd = accept(fd, (struct sockaddr *)NULL, NULL);
949 }
950 #else
951 sfd = accept(fd, (struct sockaddr *)NULL, NULL);
952 #endif
953 if (sfd >= 0) {
954 size_t i, j;
955 struct sockaddr saddr;
956 socklen_t len;
957 int sndbuf, opt;
958 struct msghdr msg;
959 struct iovec vec[MMAP_IO_SIZE / 16];
960 #if defined(HAVE_SENDMMSG)
961 struct mmsghdr msgvec[MSGVEC_SIZE];
962 #endif
963
964 len = sizeof(saddr);
965 if (getsockname(fd, &saddr, &len) < 0) {
966 pr_fail("%s: getsockname failed, errno=%d (%s)\n",
967 args->name, errno, strerror(errno));
968 (void)close(sfd);
969 break;
970 }
971 /*
972 * Exercise illegal sockname lengths
973 */
974 {
975 int ret;
976
977 len = 0;
978 ret = getsockname(fd, &saddr, &len);
979 (void)ret;
980
981 len = 1;
982 ret = getsockname(fd, &saddr, &len);
983 (void)ret;
984 }
985
986 len = sizeof(sndbuf);
987 if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, &len) < 0) {
988 pr_fail("%s: getsockopt failed, errno=%d (%s)\n",
989 args->name, errno, strerror(errno));
990 (void)close(sfd);
991 break;
992 }
993 #if defined(SOL_TCP) && \
994 defined(TCP_QUICKACK)
995 {
996 int ret, one = 1;
997 /*
998 * We try do to a TCP_QUICKACK, failing is OK as
999 * it's just a faster optimization option
1000 */
1001 ret = setsockopt(fd, SOL_TCP, TCP_QUICKACK, &one, sizeof(one));
1002 (void)ret;
1003 }
1004 #endif
1005
1006 #if defined(SOL_TCP) && \
1007 defined(HAVE_NETINET_TCP_H)
1008 if (g_opt_flags & OPT_FLAGS_SOCKET_NODELAY) {
1009 int one = 1;
1010
1011 if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)) < 0) {
1012 pr_inf("%s: setsockopt TCP_NODELAY "
1013 "failed and disabled, errno=%d (%s)\n",
1014 args->name, errno, strerror(errno));
1015 g_opt_flags &= ~OPT_FLAGS_SOCKET_NODELAY;
1016 }
1017 }
1018 #endif
1019 (void)memset(buf, 'A' + (get_counter(args) % 26), MMAP_IO_SIZE);
1020
1021 if (socket_opts == SOCKET_OPT_RANDOM)
1022 opt = stress_mwc8() % 3;
1023 else
1024 opt = socket_opts;
1025
1026 switch (opt) {
1027 case SOCKET_OPT_SEND:
1028 for (i = 16; i < MMAP_IO_SIZE; i += 16) {
1029 ssize_t ret = send(sfd, buf, i, sendflag);
1030 if (ret < 0) {
1031 if ((errno != EINTR) && (errno != EPIPE))
1032 pr_fail("%s: send failed, errno=%d (%s)\n",
1033 args->name, errno, strerror(errno));
1034 break;
1035 } else
1036 msgs++;
1037 }
1038 break;
1039 case SOCKET_OPT_SENDMSG:
1040 for (j = 0, i = 16; i < MMAP_IO_SIZE; i += 16, j++) {
1041 vec[j].iov_base = buf;
1042 vec[j].iov_len = i;
1043 }
1044 (void)memset(&msg, 0, sizeof(msg));
1045 msg.msg_iov = vec;
1046 msg.msg_iovlen = j;
1047 if (sendmsg(sfd, &msg, 0) < 0) {
1048 if ((errno != EINTR) && (errno != EPIPE))
1049 pr_fail("%s: sendmsg failed, errno=%d (%s)\n",
1050 args->name, errno, strerror(errno));
1051 } else
1052 msgs += j;
1053 break;
1054 #if defined(HAVE_SENDMMSG)
1055 case SOCKET_OPT_SENDMMSG:
1056 (void)memset(msgvec, 0, sizeof(msgvec));
1057 for (j = 0, i = 16; i < MMAP_IO_SIZE; i += 16, j++) {
1058 vec[j].iov_base = buf;
1059 vec[j].iov_len = i;
1060 }
1061 for (i = 0; i < MSGVEC_SIZE; i++) {
1062 msgvec[i].msg_hdr.msg_iov = vec;
1063 msgvec[i].msg_hdr.msg_iovlen = j;
1064 }
1065 if (sendmmsg(sfd, msgvec, MSGVEC_SIZE, 0) < 0) {
1066 if ((errno != EINTR) && (errno != EPIPE))
1067 pr_fail("%s: sendmmsg failed, errno=%d (%s)\n",
1068 args->name, errno, strerror(errno));
1069 } else
1070 msgs += (MSGVEC_SIZE * j);
1071 break;
1072 #endif
1073 default:
1074 /* Should never happen */
1075 pr_err("%s: bad option %d\n", args->name, socket_opts);
1076 (void)close(sfd);
1077 goto die_close;
1078 }
1079 if (getpeername(sfd, &saddr, &len) < 0) {
1080 if (errno != ENOTCONN)
1081 pr_fail("%s: getpeername failed, errno=%d (%s)\n",
1082 args->name, errno, strerror(errno));
1083 }
1084 #if defined(SIOCOUTQ)
1085 {
1086 int pending;
1087
1088 (void)ioctl(sfd, SIOCOUTQ, &pending);
1089 }
1090 #endif
1091 stress_sock_ioctl(fd, socket_domain, rt);
1092 stress_read_fdinfo(self, sfd);
1093
1094 (void)close(sfd);
1095 }
1096
1097 #if defined(HAVE_ACCEPT4)
1098 /*
1099 * Exercise accept4 with invalid flags
1100 */
1101 sfd = accept4(fd, (struct sockaddr *)NULL, NULL, ~0);
1102 if (sfd)
1103 (void)close(sfd);
1104 #endif
1105 inc_counter(args);
1106 } while (keep_stressing(args));
1107
1108 die_close:
1109 (void)close(fd);
1110 die:
1111 if (ptr != MAP_FAILED)
1112 (void)munmap(ptr, page_size);
1113 #if defined(AF_UNIX) && \
1114 defined(HAVE_SOCKADDR_UN)
1115 if (addr && (socket_domain == AF_UNIX)) {
1116 struct sockaddr_un *addr_un = (struct sockaddr_un *)addr;
1117
1118 (void)unlink(addr_un->sun_path);
1119 }
1120 #endif
1121 if (pid) {
1122 (void)kill(pid, SIGKILL);
1123 (void)shim_waitpid(pid, &status, 0);
1124 }
1125 pr_dbg("%s: %" PRIu64 " messages sent\n", args->name, msgs);
1126
1127 return rc;
1128 }
1129
stress_sock_sigpipe_handler(int signum)1130 static void stress_sock_sigpipe_handler(int signum)
1131 {
1132 (void)signum;
1133
1134 keep_stressing_set_flag(false);
1135 }
1136
1137 /*
1138 * stress_sock_kernel_rt()
1139 * return true if kernel is PREEMPT_RT, true if
1140 * not sure, false if definitely not PREEMPT_RT.
1141 */
stress_sock_kernel_rt(void)1142 static bool stress_sock_kernel_rt(void)
1143 {
1144 #if defined(HAVE_UNAME) && \
1145 defined(HAVE_SYS_UTSNAME_H)
1146 struct utsname buf;
1147
1148 if (uname(&buf) < 0)
1149 return true; /* Not sure, assume rt */
1150
1151 if (strstr(buf.version, "PREEMPT_RT"))
1152 return true; /* Definitely rt */
1153
1154 /* probably not RT */
1155 return false;
1156 #else
1157 return true; /* Not sure, assume rt */
1158 #endif
1159 }
1160
1161 /*
1162 * stress_sock
1163 * stress by heavy socket I/O
1164 */
stress_sock(const stress_args_t * args)1165 static int stress_sock(const stress_args_t *args)
1166 {
1167 pid_t pid, ppid = getppid();
1168 int socket_opts = SOCKET_OPT_SEND;
1169 int socket_domain = AF_INET;
1170 int socket_type = SOCK_STREAM;
1171 int socket_port = DEFAULT_SOCKET_PORT;
1172 #if defined(IPPROTO_TCP)
1173 int socket_protocol = IPPROTO_TCP;
1174 #else
1175 int socket_protocol = 0;
1176 #endif
1177 int socket_zerocopy = false;
1178 int rc = EXIT_SUCCESS;
1179 const bool rt = stress_sock_kernel_rt();
1180 char *mmap_buffer;
1181
1182 (void)stress_get_setting("sock-domain", &socket_domain);
1183 (void)stress_get_setting("sock-type", &socket_type);
1184 (void)stress_get_setting("sock-protocol", &socket_protocol);
1185 (void)stress_get_setting("sock-port", &socket_port);
1186 (void)stress_get_setting("sock-opts", &socket_opts);
1187 (void)stress_get_setting("sock-zerocopy", &socket_zerocopy);
1188
1189 pr_dbg("%s: process [%d] using socket port %d\n",
1190 args->name, (int)args->pid, socket_port + (int)args->instance);
1191
1192 if (stress_sighandler(args->name, SIGPIPE, stress_sock_sigpipe_handler, NULL) < 0)
1193 return EXIT_NO_RESOURCE;
1194
1195 mmap_buffer = (char *)mmap(NULL, MMAP_BUF_SIZE, PROT_READ | PROT_WRITE,
1196 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
1197 if (mmap_buffer == MAP_FAILED) {
1198 pr_inf("%s: cannot mmap I/O buffer, errno=%d (%s)\n",
1199 args->name, errno, strerror(errno));
1200 return EXIT_NO_RESOURCE;
1201 }
1202
1203 stress_set_proc_state(args->name, STRESS_STATE_RUN);
1204 again:
1205 pid = fork();
1206 if (pid < 0) {
1207 if (stress_redo_fork(errno))
1208 goto again;
1209 if (!keep_stressing(args)) {
1210 rc = EXIT_SUCCESS;
1211 goto finish;
1212 }
1213 pr_fail("%s: fork failed, errno=%d (%s)\n",
1214 args->name, errno, strerror(errno));
1215 return EXIT_FAILURE;
1216 } else if (pid == 0) {
1217 stress_sock_client(args, mmap_buffer, ppid, socket_opts,
1218 socket_domain, socket_type, socket_protocol,
1219 socket_port, rt, socket_zerocopy);
1220 (void)munmap((void *)mmap_buffer, MMAP_BUF_SIZE);
1221 _exit(rc);
1222 } else {
1223 rc = stress_sock_server(args, mmap_buffer, pid, ppid, socket_opts,
1224 socket_domain, socket_type, socket_protocol,
1225 socket_port, rt, socket_zerocopy);
1226 (void)munmap((void *)mmap_buffer, MMAP_BUF_SIZE);
1227
1228 }
1229 finish:
1230 stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
1231
1232 return rc;
1233 }
1234
1235 static const stress_opt_set_func_t opt_set_funcs[] = {
1236 { OPT_sock_domain, stress_set_socket_domain },
1237 { OPT_sock_opts, stress_set_socket_opts },
1238 { OPT_sock_type, stress_set_socket_type },
1239 { OPT_sock_port, stress_set_socket_port },
1240 { OPT_sock_protocol, stress_set_socket_protocol },
1241 { OPT_sock_zerocopy, stress_set_socket_zerocopy },
1242 { 0, NULL }
1243 };
1244
1245 stressor_info_t stress_sock_info = {
1246 .stressor = stress_sock,
1247 .class = CLASS_NETWORK | CLASS_OS,
1248 .opt_set_funcs = opt_set_funcs,
1249 .help = help
1250 };
1251