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 MSGVEC_SIZE (4)
28
29 static const stress_help_t help[] = {
30 { "S N", "sock N", "start N workers exercising socket I/O" },
31 { NULL, "sock-ops N", "stop after N socket bogo operations" },
32 { NULL, NULL, NULL }
33 };
34
35 #define VOID_RET(type, x) \
36 do { \
37 type ret = x; \
38 \
39 (void)ret; \
40 } while(0) \
41
42 /*
43 * stress_sockabuse_fd
44 * exercise and abuse the fd
45 */
stress_sockabuse_fd(const int fd)46 static void stress_sockabuse_fd(const int fd)
47 {
48 const uid_t uid = getuid();
49 const gid_t gid = getgid();
50 struct stat statbuf;
51 void *ptr;
52 int nfd;
53 struct sockaddr addr;
54 socklen_t addrlen;
55 #if defined(HAVE_FUTIMENS)
56 struct timespec timespec[2];
57 #endif
58
59 (void)memset(&addr, 0, sizeof(addr));
60 VOID_RET(int, connect(fd, &addr, sizeof(addr)));
61 VOID_RET(int, shim_fdatasync(fd));
62 VOID_RET(int, shim_fsync(fd));
63 VOID_RET(int, shim_fallocate(fd, 0, 4096, 0));
64 VOID_RET(int, fchdir(fd));
65 VOID_RET(int, fchmod(fd, 0660));
66 VOID_RET(int, fchown(fd, uid, gid));
67 #if defined(F_GETFD)
68 VOID_RET(int, fcntl(fd, F_GETFD));
69 #endif
70 #if defined(HAVE_FLOCK) && \
71 defined(LOCK_UN)
72 VOID_RET(int, flock(fd, LOCK_UN));
73 #endif
74 #if (defined(HAVE_SYS_XATTR_H) || \
75 defined(HAVE_ATTR_XATTR_H)) && \
76 defined(HAVE_SETXATTR) && \
77 defined(XATTR_CREATE)
78 VOID_RET(ssize_t, shim_fsetxattr(fd, "test", "value", 5, XATTR_CREATE));
79 #endif
80 VOID_RET(int, fstat(fd, &statbuf));
81 VOID_RET(int, ftruncate(fd, 0));
82 #if (defined(HAVE_SYS_XATTR_H) || \
83 defined(HAVE_ATTR_XATTR_H)) && \
84 defined(HAVE_FLISTXATTR)
85 {
86 char list[4096];
87
88 VOID_RET(ssize_t, shim_flistxattr(fd, list, sizeof(list)));
89 }
90 #endif
91 #if defined(HAVE_FUTIMENS)
92 {
93 struct timeval now;
94
95 if (gettimeofday(&now, NULL) == 0) {
96 timespec[0].tv_sec = now.tv_sec;
97 timespec[1].tv_sec = now.tv_sec;
98
99 timespec[0].tv_nsec = 1000 * now.tv_usec;
100 timespec[1].tv_nsec = 1000 * now.tv_usec;
101 VOID_RET(int, futimens(fd, timespec));
102 }
103 }
104 #endif
105 addrlen = sizeof(addr);
106 VOID_RET(int, getpeername(fd, &addr, &addrlen));
107 #if defined(FIONREAD)
108 {
109 int n;
110
111 VOID_RET(int, ioctl(fd, FIONREAD, &n));
112 }
113 #endif
114 #if defined(SEEK_SET)
115 VOID_RET(off_t, lseek(fd, 0, SEEK_SET));
116 #endif
117 VOID_RET(int, shim_pidfd_send_signal(fd, SIGUSR1, NULL, 0));
118 ptr = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd, 0);
119 if (ptr != MAP_FAILED)
120 (void)munmap(ptr, 4096);
121 ptr = mmap(NULL, 4096, PROT_READ, MAP_PRIVATE, fd, 0);
122 if (ptr != MAP_FAILED)
123 (void)munmap(ptr, 4096);
124 nfd = dup(fd);
125 VOID_RET(ssize_t, shim_copy_file_range(fd, 0, nfd, 0, 16, 0));
126 if (nfd >= 0)
127 (void)close(nfd);
128 #if defined(HAVE_POSIX_FADVISE) && \
129 defined(POSIX_FADV_RANDOM)
130 VOID_RET(int, posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM));
131 #endif
132 VOID_RET(int, shim_sync_file_range(fd, 0, 1, 0));
133 #if defined(HAVE_FUTIMENS)
134 (void)memset(×pec, 0, sizeof(timespec));
135 #endif
136 }
137
138 /*
139 * stress_sockabuse_client()
140 * client reader
141 */
stress_sockabuse_client(const stress_args_t * args,const pid_t ppid,const int socket_port)142 static void stress_sockabuse_client(
143 const stress_args_t *args,
144 const pid_t ppid,
145 const int socket_port)
146 {
147 struct sockaddr *addr;
148
149 (void)setpgid(0, g_pgrp);
150 stress_parent_died_alarm();
151 (void)sched_settings_apply(true);
152
153 do {
154 char buf[SOCKET_BUF];
155 int fd;
156 ssize_t n;
157 socklen_t addr_len = 0;
158 uint64_t delay = 10000;
159
160 retry:
161 if (!keep_stressing_flag()) {
162 (void)kill(getppid(), SIGALRM);
163 _exit(EXIT_FAILURE);
164 }
165 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
166 pr_fail("%s: socket failed, errno=%d (%s)\n",
167 args->name, errno, strerror(errno));
168 /* failed, kick parent to finish */
169 (void)kill(getppid(), SIGALRM);
170 _exit(EXIT_FAILURE);
171 }
172
173 stress_set_sockaddr(args->name, args->instance, ppid,
174 AF_INET, socket_port,
175 &addr, &addr_len, NET_ADDR_ANY);
176 if (connect(fd, addr, addr_len) < 0) {
177 (void)shutdown(fd, SHUT_RDWR);
178 (void)close(fd);
179 (void)shim_usleep(delay);
180
181 /* Backoff */
182 delay += 10000;
183 if (delay > 250000)
184 delay = 250000;
185 goto retry;
186 }
187
188 n = recv(fd, buf, sizeof(buf), 0);
189 if (n < 0) {
190 if ((errno != EINTR) && (errno != ECONNRESET))
191 pr_fail("%s: recv failed, errno=%d (%s)\n",
192 args->name, errno, strerror(errno));
193 }
194
195 stress_sockabuse_fd(fd);
196
197 (void)shutdown(fd, SHUT_RDWR);
198 (void)close(fd);
199 } while (keep_stressing(args));
200
201 /* Inform parent we're all done */
202 (void)kill(getppid(), SIGALRM);
203 }
204
205 /*
206 * stress_sockabuse_server()
207 * server writer
208 */
stress_sockabuse_server(const stress_args_t * args,const pid_t pid,const pid_t ppid,const int socket_port)209 static int stress_sockabuse_server(
210 const stress_args_t *args,
211 const pid_t pid,
212 const pid_t ppid,
213 const int socket_port)
214 {
215 char buf[SOCKET_BUF];
216 int fd, status;
217 int so_reuseaddr = 1;
218 socklen_t addr_len = 0;
219 struct sockaddr *addr = NULL;
220 uint64_t msgs = 0;
221 int rc = EXIT_SUCCESS;
222 double t1 = 0.0, t2 = 0.0, dt;
223
224 (void)setpgid(pid, g_pgrp);
225
226 if (stress_sig_stop_stressing(args->name, SIGALRM) < 0) {
227 rc = EXIT_FAILURE;
228 goto die;
229 }
230
231 t1 = stress_time_now();
232 do {
233 int i;
234
235 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
236 rc = exit_status(errno);
237 pr_fail("%s: socket failed, errno=%d (%s)\n",
238 args->name, errno, strerror(errno));
239 continue;
240 }
241 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
242 &so_reuseaddr, sizeof(so_reuseaddr)) < 0) {
243 rc = exit_status(errno);
244 pr_fail("%s: setsockopt failed, errno=%d (%s)\n",
245 args->name, errno, strerror(errno));
246 stress_sockabuse_fd(fd);
247 (void)close(fd);
248 continue;
249 }
250
251 stress_set_sockaddr(args->name, args->instance, ppid,
252 AF_INET, socket_port,
253 &addr, &addr_len, NET_ADDR_ANY);
254 if (bind(fd, addr, addr_len) < 0) {
255 if (errno != EADDRINUSE) {
256 rc = exit_status(errno);
257 pr_fail("%s: bind failed, errno=%d (%s)\n",
258 args->name, errno, strerror(errno));
259 }
260 stress_sockabuse_fd(fd);
261 (void)close(fd);
262 continue;
263 }
264 if (listen(fd, 10) < 0) {
265 pr_fail("%s: listen failed, errno=%d (%s)\n",
266 args->name, errno, strerror(errno));
267 rc = EXIT_FAILURE;
268
269 stress_sockabuse_fd(fd);
270 (void)close(fd);
271 continue;
272 }
273
274 for (i = 0; i < 16; i++) {
275 int sfd;
276
277 if (!keep_stressing(args))
278 break;
279
280 sfd = accept(fd, (struct sockaddr *)NULL, NULL);
281 if (sfd >= 0) {
282 struct sockaddr saddr;
283 socklen_t len;
284 int sndbuf;
285 ssize_t n;
286
287 len = sizeof(saddr);
288 if (getsockname(fd, &saddr, &len) < 0) {
289 pr_fail("%s: getsockname failed, errno=%d (%s)\n",
290 args->name, errno, strerror(errno));
291 (void)close(sfd);
292 break;
293 }
294 len = sizeof(sndbuf);
295 if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, &len) < 0) {
296 pr_fail("%s: getsockopt failed, errno=%d (%s)\n",
297 args->name, errno, strerror(errno));
298 (void)close(sfd);
299 break;
300 }
301 (void)memset(buf, 'A' + (get_counter(args) % 26), sizeof(buf));
302
303 n = send(sfd, buf, sizeof(buf), 0);
304 if (n < 0) {
305 if ((errno != EINTR) && (errno != EPIPE))
306 pr_fail("%s: send failed, errno=%d (%s)\n",
307 args->name, errno, strerror(errno));
308 stress_sockabuse_fd(sfd);
309 (void)close(sfd);
310 break;
311 } else {
312 msgs++;
313 }
314 stress_sockabuse_fd(sfd);
315 (void)close(sfd);
316 }
317 }
318 inc_counter(args);
319 stress_sockabuse_fd(fd);
320 (void)close(fd);
321 } while (keep_stressing(args));
322 t2 = stress_time_now();
323
324 die:
325 if (pid) {
326 (void)kill(pid, SIGKILL);
327 (void)shim_waitpid(pid, &status, 0);
328 }
329 pr_dbg("%s: %" PRIu64 " messages sent\n", args->name, msgs);
330 dt = t2 - t1;
331 if (dt > 0.0) {
332 stress_misc_stats_set(args->misc_stats, 0,
333 "messages sent per sec", (double)msgs / dt);
334 }
335
336 return rc;
337 }
338
stress_sockabuse_sigpipe_handler(int signum)339 static void stress_sockabuse_sigpipe_handler(int signum)
340 {
341 (void)signum;
342
343 keep_stressing_set_flag(false);
344 }
345
346 /*
347 * stress_sockabuse
348 * stress by heavy socket I/O
349 */
stress_sockabuse(const stress_args_t * args)350 static int stress_sockabuse(const stress_args_t *args)
351 {
352 pid_t pid, ppid = getppid();
353 int socket_port = DEFAULT_SOCKABUSE_PORT + (int)args->instance;
354 int rc = EXIT_SUCCESS;
355
356 pr_dbg("%s: process [%d] using socket port %d\n",
357 args->name, (int)args->pid, socket_port);
358
359 if (stress_sighandler(args->name, SIGPIPE, stress_sockabuse_sigpipe_handler, NULL) < 0)
360 return EXIT_NO_RESOURCE;
361
362 stress_set_proc_state(args->name, STRESS_STATE_RUN);
363 again:
364 pid = fork();
365 if (pid < 0) {
366 if (stress_redo_fork(errno))
367 goto again;
368 if (!keep_stressing(args)) {
369 rc = EXIT_SUCCESS;
370 goto finish;
371 }
372 pr_fail("%s: fork failed, errno=%d (%s)\n",
373 args->name, errno, strerror(errno));
374 return EXIT_FAILURE;
375 } else if (pid == 0) {
376 stress_sockabuse_client(args, ppid,
377 socket_port);
378 _exit(rc);
379 } else {
380 rc = stress_sockabuse_server(args, pid, ppid,
381 socket_port);
382 }
383 finish:
384 stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
385
386 return rc;
387 }
388
389 stressor_info_t stress_sockabuse_info = {
390 .stressor = stress_sockabuse,
391 .class = CLASS_NETWORK | CLASS_OS,
392 .help = help
393 };
394