1#!/bin/sh 2 3# 4# SPDX-License-Identifier: BSD-2-Clause-FreeBSD 5# 6# Copyright (c) 2018 Dell EMC Isilon 7# 8# Redistribution and use in source and binary forms, with or without 9# modification, are permitted provided that the following conditions 10# are met: 11# 1. Redistributions of source code must retain the above copyright 12# notice, this list of conditions and the following disclaimer. 13# 2. Redistributions in binary form must reproduce the above copyright 14# notice, this list of conditions and the following disclaimer in the 15# documentation and/or other materials provided with the distribution. 16# 17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27# SUCH DAMAGE. 28# 29 30# "panic: in_pcbrele_wlocked: refcount 0" seen in WiP kernel code. 31 32. ../default.cfg 33[ `id -u` -ne 0 ] && echo "Must be root!" && exit 1 34 35cd /tmp 36 37cat > /tmp/tcp4.c <<EOF 38#include <sys/param.h> 39#include <sys/socket.h> 40#include <sys/wait.h> 41 42#include <netinet/in.h> 43 44#include <err.h> 45#include <errno.h> 46#include <netdb.h> 47#include <signal.h> 48#include <stdio.h> 49#include <stdlib.h> 50#include <string.h> 51#include <time.h> 52#include <unistd.h> 53 54#define NB (400 * 1024 * 1024) 55#define RUNTIME (16 * 60) 56 57static int port; 58static int bufsize; 59 60static int 61random_int(int mi, int ma) 62{ 63 return (arc4random() % (ma - mi + 1) + mi); 64} 65 66static void 67reader(void) { 68 socklen_t len; 69 struct sockaddr_in inetaddr, inetpeer; 70 int tcpsock, msgsock ,on, n, t, *buf; 71 72 on = 1; 73 setproctitle("%s", __func__); 74 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 75 err(1, "socket(), %s:%d", __FILE__, __LINE__); 76 77 if (setsockopt(tcpsock, 78 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 79 err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); 80 81 inetaddr.sin_family = AF_INET; 82 inetaddr.sin_addr.s_addr = INADDR_ANY; 83 inetaddr.sin_port = htons(port); 84 inetaddr.sin_len = sizeof(inetaddr); 85 86 if (bind(tcpsock, 87 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) 88 err(1, "bind(), %s:%d", __FILE__, __LINE__); 89 90 if (listen(tcpsock, 5) < 0) 91 err(1, "listen(), %s:%d", __FILE__, __LINE__); 92 93 if ((random_int(1,100) > 60)) { 94 usleep(random_int(1000000,1000000) * 60); 95 } 96 97 len = sizeof(inetpeer); 98 if ((msgsock = accept(tcpsock, 99 (struct sockaddr *)&inetpeer, &len)) < 0) 100 err(1, "accept(), %s:%d", __FILE__, __LINE__); 101 102 t = 0; 103 if ((buf = malloc(bufsize)) == NULL) 104 err(1, "malloc(%d), %s:%d", bufsize, __FILE__, __LINE__); 105 for (;;) { 106 if ((n = read(msgsock, buf, bufsize)) < 0) 107 err(1, "read(), %s:%d", __FILE__, __LINE__); 108 t += n; 109 if (n == 0) break; 110 } 111 close(msgsock); 112 return; 113} 114 115static void 116writer(void) { 117 struct sockaddr_in inetaddr; 118 struct hostent *hostent; 119 time_t start; 120 int i, *buf, r; 121 int tcpsock, on; 122 123 on = 1; 124 setproctitle("%s", __func__); 125 for (i = 1; i < 5; i++) { 126 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 127 err(1, "socket(), %s:%d", __FILE__, __LINE__); 128 129 if (setsockopt(tcpsock, 130 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 131 err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); 132 133 hostent = gethostbyname ("localhost"); 134 bzero((char *) &inetaddr, sizeof(inetaddr)); 135 memcpy (&inetaddr.sin_addr.s_addr, hostent->h_addr, 136 sizeof (struct in_addr)); 137 138 inetaddr.sin_family = AF_INET; 139 inetaddr.sin_port = htons(port); 140 inetaddr.sin_len = sizeof(inetaddr); 141 142 r = connect(tcpsock, (struct sockaddr *) &inetaddr, 143 sizeof(inetaddr)); 144 if (r == 0) 145 break; 146 sleep(1); 147 close(tcpsock); 148 } 149 if (r < 0) 150 err(1, "connect(), %s:%d", __FILE__, __LINE__); 151 152 if ((buf = malloc(bufsize)) == NULL) 153 err(1, "malloc(%d), %s:%d", bufsize, __FILE__, __LINE__); 154 for (i = 0; i < bufsize / (int)sizeof(int); i++) 155 buf[i] = i; 156 157 start = time(NULL); 158 while (time(NULL) - start < 60) { 159 for (i = 0; i < NB; i+= bufsize) { 160 if (write(tcpsock, buf, bufsize) < 0) { 161 if (errno == EPIPE) 162 return; 163 if (errno != ECONNRESET) 164 err(1, "write(%d), %s:%d", tcpsock, 165 __FILE__, __LINE__); 166 _exit(EXIT_SUCCESS); 167 } 168 } 169 } 170 return; 171} 172 173int 174setup(int nb) 175{ 176 port = 12340 + nb; 177 bufsize = 2 << random_int(1, 12); 178 return (0); 179} 180 181int 182test(void) 183{ 184 pid_t pid; 185 186 sleep(1); 187 if ((pid = fork()) == 0) { 188 alarm(180); 189 writer(); 190 _exit(EXIT_SUCCESS); 191 192 } else if (pid > 0) { 193 alarm(180); 194 reader(); 195 kill(pid, SIGINT); 196 if (waitpid(pid, NULL, 0) != pid) 197 err(1, "waitpid(%d)", pid); 198 } else 199 err(1, "fork(), %s:%d", __FILE__, __LINE__); 200 201 return (0); 202} 203 204int 205main(int argc, char *argv[]) 206{ 207 pid_t *pid; 208 time_t start; 209 int i, n; 210 211 if (argc != 2) { 212 fprintf(stderr, "Usage: %s <threads>\n", argv[0]); 213 exit(1); 214 } 215 n = atoi(argv[1]); 216 pid = calloc(sizeof(pid_t *), n); 217 218 start = time(NULL); 219 while (time(NULL) - start < RUNTIME) { 220 for (i = 0; i < n; i++) { 221 if ((pid[i] = fork()) == 0) { 222 setup(i); 223 test(); 224 _exit(0); 225 } 226 } 227 for (i = 0; i < n; i++) 228 if (waitpid(pid[i], NULL, 0) != pid[i]) 229 err(1, "waitpid(%d) l%d", pid[i], __LINE__); 230 fprintf(stderr, "*** Done loop\n"); 231 } 232 233 return (0); 234} 235EOF 236 237mycc -o tcp4 -Wall -Wextra -O2 tcp4.c || exit 1 238rm tcp4.c 239 240n=`sysctl -n kern.maxprocperuid` 241n=$((n / 2 / 10 * 8)) 242./tcp4 $n > /dev/null 2>&1 & 243sleep 30 244while pgrep -q tcp4; do 245 pkill tcp4 246done 247wait 248rm -f tcp4 249exit 0 250