1#!/bin/sh 2 3# 4# SPDX-License-Identifier: BSD-2-Clause 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, *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 if ((buf = malloc(bufsize)) == NULL) 103 err(1, "malloc(%d), %s:%d", bufsize, __FILE__, __LINE__); 104 for (;;) { 105 if ((n = read(msgsock, buf, bufsize)) < 0) 106 err(1, "read(), %s:%d", __FILE__, __LINE__); 107 if (n == 0) break; 108 } 109 close(msgsock); 110 return; 111} 112 113static void 114writer(void) { 115 struct sockaddr_in inetaddr; 116 struct hostent *hostent; 117 time_t start; 118 int i, *buf, r; 119 int tcpsock, on; 120 121 on = 1; 122 setproctitle("%s", __func__); 123 for (i = 1; i < 5; i++) { 124 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 125 err(1, "socket(), %s:%d", __FILE__, __LINE__); 126 127 if (setsockopt(tcpsock, 128 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 129 err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); 130 131 hostent = gethostbyname ("localhost"); 132 bzero((char *) &inetaddr, sizeof(inetaddr)); 133 memcpy (&inetaddr.sin_addr.s_addr, hostent->h_addr, 134 sizeof (struct in_addr)); 135 136 inetaddr.sin_family = AF_INET; 137 inetaddr.sin_port = htons(port); 138 inetaddr.sin_len = sizeof(inetaddr); 139 140 r = connect(tcpsock, (struct sockaddr *) &inetaddr, 141 sizeof(inetaddr)); 142 if (r == 0) 143 break; 144 sleep(1); 145 close(tcpsock); 146 } 147 if (r < 0) 148 err(1, "connect(), %s:%d", __FILE__, __LINE__); 149 150 if ((buf = malloc(bufsize)) == NULL) 151 err(1, "malloc(%d), %s:%d", bufsize, __FILE__, __LINE__); 152 for (i = 0; i < bufsize / (int)sizeof(int); i++) 153 buf[i] = i; 154 155 start = time(NULL); 156 while (time(NULL) - start < 60) { 157 for (i = 0; i < NB; i+= bufsize) { 158 if (write(tcpsock, buf, bufsize) < 0) { 159 if (errno == EPIPE) 160 return; 161 if (errno != ECONNRESET) 162 err(1, "write(%d), %s:%d", tcpsock, 163 __FILE__, __LINE__); 164 _exit(EXIT_SUCCESS); 165 } 166 } 167 } 168 return; 169} 170 171int 172setup(int nb) 173{ 174 port = 12340 + nb; 175 bufsize = 2 << random_int(1, 12); 176 return (0); 177} 178 179int 180test(void) 181{ 182 pid_t pid; 183 184 sleep(1); 185 if ((pid = fork()) == 0) { 186 alarm(180); 187 writer(); 188 _exit(EXIT_SUCCESS); 189 190 } else if (pid > 0) { 191 alarm(180); 192 reader(); 193 kill(pid, SIGINT); 194 if (waitpid(pid, NULL, 0) != pid) 195 err(1, "waitpid(%d)", pid); 196 } else 197 err(1, "fork(), %s:%d", __FILE__, __LINE__); 198 199 return (0); 200} 201 202int 203main(int argc, char *argv[]) 204{ 205 pid_t *pid; 206 time_t start; 207 int i, n; 208 209 if (argc != 2) { 210 fprintf(stderr, "Usage: %s <threads>\n", argv[0]); 211 exit(1); 212 } 213 n = atoi(argv[1]); 214 pid = calloc(sizeof(pid_t *), n); 215 216 start = time(NULL); 217 while (time(NULL) - start < RUNTIME) { 218 for (i = 0; i < n; i++) { 219 if ((pid[i] = fork()) == 0) { 220 setup(i); 221 test(); 222 _exit(0); 223 } 224 } 225 for (i = 0; i < n; i++) 226 if (waitpid(pid[i], NULL, 0) != pid[i]) 227 err(1, "waitpid(%d) l%d", pid[i], __LINE__); 228 fprintf(stderr, "*** Done loop\n"); 229 } 230 231 return (0); 232} 233EOF 234 235mycc -o tcp4 -Wall -Wextra -O2 tcp4.c || exit 1 236rm tcp4.c 237 238n=`sysctl -n kern.maxprocperuid` 239n=$((n / 2 / 10 * 8)) 240./tcp4 $n > /dev/null 2>&1 & 241sleep 30 242while pgrep -q tcp4; do 243 pkill tcp4 244done 245wait 246rm -f tcp4 247exit 0 248