1#!/bin/sh 2 3# 4# Copyright (c) 2016 EMC Corp. 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28 29# No problems seen 30# Stand alone version of testcases/tcp 31 32. ../default.cfg 33 34dir=/tmp 35odir=`pwd` 36cd $dir 37sed '1,/^EOF/d' < $odir/$0 > $dir/tcp3.c 38mycc -o tcp3 -Wall -Wextra -O0 -g tcp3.c || exit 1 39rm -f tcp3.c 40 41daemon sh -c "(cd $odir/../testcases/swap; ./swap -t 5m)" > /dev/null 2>&1 42timeout 2m /tmp/tcp3 43s=$? 44while pgrep -q swap; do 45 pkill -9 swap 46done 47 48if pgrep -q tcp3; then 49 echo FAIL 50 pgrep tcp3 | while read pid; do 51 ps -lp$pid 52 procstat -kk $pid 53 done 54 exit 1 55fi 56rm -rf /tmp/tcp3 /tmp/tcp3.c 57exit $s 58 59EOF 60#include <sys/param.h> 61#include <sys/mman.h> 62#include <sys/socket.h> 63#include <sys/stat.h> 64#include <sys/wait.h> 65 66#include <netinet/in.h> 67 68#include <machine/atomic.h> 69 70#include <err.h> 71#include <errno.h> 72#include <fcntl.h> 73#include <netdb.h> 74#include <signal.h> 75#include <stdio.h> 76#include <stdlib.h> 77#include <string.h> 78#include <time.h> 79#include <unistd.h> 80 81#define NB (400 * 1024 * 1024) 82#define SYNC 0 83#define PARALLEL 8 84#define RUNTIME (1 * 60) 85 86static sig_atomic_t done_testing; 87static volatile u_int *share; 88static int bufsize; 89static int port; 90 91static void 92alarm_handler(int i __unused) 93{ 94 95 done_testing++; 96} 97 98static void 99exit_handler(int i __unused) 100{ 101 102 _exit(1); 103} 104 105static void 106callcleanup(void) 107{ 108} 109 110static int 111random_int(int mi, int ma) 112{ 113 return (arc4random() % (ma - mi + 1) + mi); 114} 115 116static void 117reader(void) { 118 struct sockaddr_in inetaddr, inetpeer; 119 socklen_t len; 120 int n, t, *buf; 121 int on; 122 int tcpsock, msgsock; 123 124 on = 1; 125 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 126 err(1, "socket(), %s:%d", __FILE__, __LINE__); 127 128 if (setsockopt(tcpsock, 129 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 130 err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); 131 132 inetaddr.sin_family = AF_INET; 133 inetaddr.sin_addr.s_addr = INADDR_ANY; 134 inetaddr.sin_port = htons(port); 135 inetaddr.sin_len = sizeof(inetaddr); 136 137 if (bind(tcpsock, 138 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) 139 err(1, "bind(), %s:%d", __FILE__, __LINE__); 140 141 if (listen(tcpsock, 5) < 0) 142 err(1, "listen(), %s:%d", __FILE__, __LINE__); 143 144 if (random_int(1,100) > 60) 145 sleep(6); 146 147 len = sizeof(inetpeer); 148 if ((msgsock = accept(tcpsock, 149 (struct sockaddr *)&inetpeer, &len)) < 0) 150 err(1, "accept(), %s:%d", __FILE__, __LINE__); 151 152 t = 0; 153 if ((buf = malloc(bufsize)) == NULL) 154 err(1, "malloc(%d), %s:%d", bufsize, __FILE__, 155 __LINE__); 156 while (done_testing == 0) { 157 if ((n = read(msgsock, buf, bufsize)) < 0) 158 err(1, "read(), %s:%d", __FILE__, __LINE__); 159 t += n; 160 if (n == 0) break; 161 } 162 close(msgsock); 163 return; 164} 165 166static void 167writer(void) { 168 struct hostent *hostent; 169 struct sockaddr_in inetaddr; 170 int i, *buf, r; 171 int tcpsock, on; 172 173 on = 1; 174 for (i = 1; i < 5; i++) { 175 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 176 err(1, "socket(), %s:%d", __FILE__, __LINE__); 177 178 if (setsockopt(tcpsock, 179 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 180 err(1, "setsockopt(), %s:%d", __FILE__, __LINE__); 181 182 hostent = gethostbyname ("localhost"); 183 bzero((char *) &inetaddr, sizeof(inetaddr)); 184 memcpy (&inetaddr.sin_addr.s_addr, hostent->h_addr, 185 sizeof (struct in_addr)); 186 187 inetaddr.sin_family = AF_INET; 188 inetaddr.sin_port = htons(port); 189 inetaddr.sin_len = sizeof(inetaddr); 190 191 r = connect(tcpsock, (struct sockaddr *) &inetaddr, 192 sizeof(inetaddr)); 193 if (r == 0) 194 break; 195 sleep(1); 196 close(tcpsock); 197 } 198 if (r < 0) 199 err(1, "connect(), %s:%d", __FILE__, __LINE__); 200 201 if ((buf = malloc(bufsize)) == NULL) 202 err(1, "malloc(%d), %s:%d", bufsize, __FILE__, 203 __LINE__); 204 for (i = 0; i < bufsize / (int)sizeof(int); i++) 205 buf[i] = i; 206 207 for (;;) { 208 for (i = 0; i < NB; i+= bufsize) { 209 if (write(tcpsock, buf, bufsize) < 0) { 210 if (errno == EPIPE) 211 return; 212 if (errno != ECONNRESET) 213 err(1, "write(%d), %s:%d", tcpsock, 214 __FILE__, __LINE__); 215 _exit(EXIT_SUCCESS); 216 } 217 } 218 } 219 return; 220} 221 222static int 223test2(void) 224{ 225 pid_t pid; 226 227 if ((pid = fork()) == 0) { 228 writer(); 229 _exit(EXIT_SUCCESS); 230 231 } else if (pid > 0) { 232 reader(); 233 kill(pid, SIGINT); 234 waitpid(pid, NULL, 0); 235 } else 236 err(1, "fork(), %s:%d", __FILE__, __LINE__); 237 238 return (0); 239} 240 241static void 242test(int nb) 243{ 244 atomic_add_int(&share[SYNC], 1); 245 while (share[SYNC] != PARALLEL) 246 ; 247 248 port = 12340 + nb; 249 bufsize = 2 << random_int(1, 12); 250 signal(SIGALRM, alarm_handler); 251 signal(SIGINT, exit_handler); 252 atexit(callcleanup); 253 254 alarm(2); 255 test2(); 256 257 _exit(0); 258} 259 260int 261main(void) 262{ 263 size_t len; 264 time_t start; 265 int e, i, pids[PARALLEL], status; 266 267 e = 0; 268 len = PAGE_SIZE; 269 if ((share = mmap(NULL, len, PROT_READ | PROT_WRITE, 270 MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED) 271 err(1, "mmap"); 272 273 start = time(NULL); 274 while ((time(NULL) - start) < RUNTIME && e == 0) { 275 share[SYNC] = 0; 276 for (i = 0; i < PARALLEL; i++) { 277 if ((pids[i] = fork()) == 0) 278 test(i); 279 } 280 for (i = 0; i < PARALLEL; i++) { 281 if (waitpid(pids[i], &status, 0) == -1) 282 err(1, "waitpid(%d)", pids[i]); 283 e += status == 0 ? 0 : 1; 284 } 285 } 286 287 return (e); 288} 289