1 1.9 christos /* $NetBSD: h_stresscli.c,v 1.9 2011/06/26 13:17:36 christos Exp $ */ 2 1.1 pooka 3 1.1 pooka #include <sys/types.h> 4 1.1 pooka #include <sys/atomic.h> 5 1.1 pooka #include <sys/sysctl.h> 6 1.1 pooka #include <sys/wait.h> 7 1.8 pooka #include <sys/socket.h> 8 1.8 pooka 9 1.8 pooka #include <netinet/in.h> 10 1.1 pooka 11 1.1 pooka #include <err.h> 12 1.8 pooka #include <fcntl.h> 13 1.1 pooka #include <pthread.h> 14 1.1 pooka #include <stdio.h> 15 1.1 pooka #include <stdlib.h> 16 1.1 pooka #include <string.h> 17 1.1 pooka #include <unistd.h> 18 1.9 christos #include <signal.h> 19 1.1 pooka 20 1.1 pooka #include <rump/rump_syscalls.h> 21 1.1 pooka #include <rump/rumpclient.h> 22 1.1 pooka 23 1.8 pooka static unsigned int syscalls, bindcalls; 24 1.1 pooka static pid_t mypid; 25 1.4 pooka static volatile sig_atomic_t doquit; 26 1.1 pooka 27 1.1 pooka static void 28 1.1 pooka signaali(int sig) 29 1.1 pooka { 30 1.1 pooka 31 1.4 pooka doquit = 1; 32 1.1 pooka } 33 1.1 pooka 34 1.1 pooka static const int hostnamemib[] = { CTL_KERN, KERN_HOSTNAME }; 35 1.1 pooka static char hostnamebuf[128]; 36 1.1 pooka #define HOSTNAMEBASE "rumpclient" 37 1.1 pooka 38 1.8 pooka static int iskiller; 39 1.8 pooka 40 1.1 pooka static void * 41 1.1 pooka client(void *arg) 42 1.1 pooka { 43 1.1 pooka char buf[256]; 44 1.8 pooka struct sockaddr_in sin; 45 1.1 pooka size_t blen; 46 1.8 pooka int port = (int)(uintptr_t)arg; 47 1.8 pooka int s, fd, x; 48 1.8 pooka 49 1.8 pooka memset(&sin, 0, sizeof(sin)); 50 1.8 pooka sin.sin_family = AF_INET; 51 1.8 pooka sin.sin_len = sizeof(sin); 52 1.8 pooka sin.sin_port = htons(port); 53 1.1 pooka 54 1.4 pooka while (!doquit) { 55 1.1 pooka pid_t pidi; 56 1.1 pooka blen = sizeof(buf); 57 1.8 pooka s = rump_sys_socket(PF_INET, SOCK_STREAM, 0); 58 1.8 pooka if (s == -1) 59 1.8 pooka err(1, "socket"); 60 1.8 pooka atomic_inc_uint(&syscalls); 61 1.8 pooka 62 1.8 pooka fd = rump_sys_open("/dev/null", O_RDWR); 63 1.8 pooka atomic_inc_uint(&syscalls); 64 1.8 pooka 65 1.8 pooka if (doquit) 66 1.8 pooka goto out; 67 1.8 pooka 68 1.8 pooka x = 1; 69 1.8 pooka if (rump_sys_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 70 1.8 pooka &x, sizeof(x)) == -1) 71 1.8 pooka err(1, "reuseaddr"); 72 1.8 pooka 73 1.8 pooka /* 74 1.8 pooka * we don't really know when the kernel handles our disconnect, 75 1.8 pooka * so be soft about about the failure in case of a killer client 76 1.8 pooka */ 77 1.8 pooka if (rump_sys_bind(s, (struct sockaddr*)&sin, sizeof(sin))==-1) { 78 1.8 pooka if (!iskiller) 79 1.8 pooka err(1, "bind to port %d failed", 80 1.8 pooka ntohs(sin.sin_port)); 81 1.8 pooka } else { 82 1.8 pooka atomic_inc_uint(&bindcalls); 83 1.8 pooka } 84 1.8 pooka atomic_inc_uint(&syscalls); 85 1.8 pooka 86 1.8 pooka if (doquit) 87 1.8 pooka goto out; 88 1.8 pooka 89 1.1 pooka if (rump_sys___sysctl(hostnamemib, __arraycount(hostnamemib), 90 1.1 pooka buf, &blen, NULL, 0) == -1) 91 1.1 pooka err(1, "sysctl"); 92 1.1 pooka if (strncmp(buf, hostnamebuf, sizeof(HOSTNAMEBASE)-1) != 0) 93 1.1 pooka errx(1, "hostname (%s/%s) mismatch", buf, hostnamebuf); 94 1.1 pooka atomic_inc_uint(&syscalls); 95 1.1 pooka 96 1.8 pooka if (doquit) 97 1.8 pooka goto out; 98 1.8 pooka 99 1.1 pooka pidi = rump_sys_getpid(); 100 1.1 pooka if (pidi == -1) 101 1.1 pooka err(1, "getpid"); 102 1.1 pooka if (pidi != mypid) 103 1.1 pooka errx(1, "mypid mismatch"); 104 1.1 pooka atomic_inc_uint(&syscalls); 105 1.8 pooka 106 1.8 pooka if (doquit) 107 1.8 pooka goto out; 108 1.8 pooka 109 1.8 pooka if (rump_sys_write(fd, buf, 16) != 16) 110 1.8 pooka err(1, "write /dev/null"); 111 1.8 pooka atomic_inc_uint(&syscalls); 112 1.8 pooka 113 1.8 pooka out: 114 1.8 pooka rump_sys_close(fd); 115 1.8 pooka atomic_inc_uint(&syscalls); 116 1.8 pooka rump_sys_close(s); 117 1.8 pooka atomic_inc_uint(&syscalls); 118 1.1 pooka } 119 1.1 pooka 120 1.1 pooka return NULL; 121 1.1 pooka } 122 1.1 pooka 123 1.1 pooka /* Stress with max 32 clients, 8 threads each (256 concurrent threads) */ 124 1.1 pooka #define NCLI 32 125 1.1 pooka #define NTHR 8 126 1.1 pooka 127 1.1 pooka int 128 1.1 pooka main(int argc, char *argv[]) 129 1.1 pooka { 130 1.4 pooka pthread_t pt[NTHR-1]; 131 1.1 pooka pid_t clis[NCLI]; 132 1.1 pooka pid_t apid; 133 1.1 pooka int ncli = 0; 134 1.1 pooka int i = 0, j; 135 1.7 pooka int status, thesig; 136 1.8 pooka int rounds, myport; 137 1.1 pooka 138 1.7 pooka if (argc != 2 && argc != 3) 139 1.1 pooka errx(1, "need roundcount"); 140 1.1 pooka 141 1.7 pooka if (argc == 3) { 142 1.7 pooka if (strcmp(argv[2], "kill") != 0) 143 1.7 pooka errx(1, "optional 3rd param must be kill"); 144 1.7 pooka thesig = SIGKILL; 145 1.8 pooka iskiller = 1; 146 1.7 pooka } else { 147 1.7 pooka thesig = SIGUSR1; 148 1.7 pooka } 149 1.7 pooka 150 1.6 pooka signal(SIGUSR1, signaali); 151 1.6 pooka 152 1.1 pooka memset(clis, 0, sizeof(clis)); 153 1.1 pooka for (rounds = 1; rounds < atoi(argv[1])*10; rounds++) { 154 1.1 pooka while (ncli < NCLI) { 155 1.1 pooka switch ((apid = fork())) { 156 1.1 pooka case -1: 157 1.1 pooka err(1, "fork failed"); 158 1.1 pooka case 0: 159 1.1 pooka if (rumpclient_init() == -1) 160 1.1 pooka err(1, "rumpclient init"); 161 1.1 pooka 162 1.1 pooka mypid = rump_sys_getpid(); 163 1.1 pooka sprintf(hostnamebuf, HOSTNAMEBASE "%d", mypid); 164 1.1 pooka if (rump_sys___sysctl(hostnamemib, 165 1.1 pooka __arraycount(hostnamemib), NULL, NULL, 166 1.1 pooka hostnamebuf, strlen(hostnamebuf)+1) == -1) 167 1.1 pooka err(1, "sethostname"); 168 1.1 pooka 169 1.8 pooka for (j = 0; j < NTHR-1; j++) { 170 1.8 pooka myport = i*NCLI + j+2; 171 1.4 pooka if (pthread_create(&pt[j], NULL, 172 1.8 pooka client, 173 1.8 pooka (void*)(uintptr_t)myport) !=0 ) 174 1.1 pooka err(1, "pthread create"); 175 1.8 pooka } 176 1.8 pooka myport = i*NCLI+1; 177 1.8 pooka client((void *)(uintptr_t)myport); 178 1.4 pooka for (j = 0; j < NTHR-1; j++) 179 1.4 pooka pthread_join(pt[j], NULL); 180 1.4 pooka membar_consumer(); 181 1.4 pooka fprintf(stderr, "done %d\n", syscalls); 182 1.4 pooka exit(0); 183 1.1 pooka /* NOTREACHED */ 184 1.1 pooka default: 185 1.1 pooka ncli++; 186 1.1 pooka clis[i] = apid; 187 1.1 pooka break; 188 1.1 pooka } 189 1.1 pooka 190 1.1 pooka i = (i + 1) % NCLI; 191 1.1 pooka } 192 1.1 pooka 193 1.1 pooka usleep(100000); 194 1.7 pooka kill(clis[i], thesig); 195 1.1 pooka 196 1.1 pooka apid = wait(&status); 197 1.1 pooka if (apid != clis[i]) 198 1.1 pooka errx(1, "wanted pid %d, got %d\n", clis[i], apid); 199 1.1 pooka clis[i] = 0; 200 1.1 pooka ncli--; 201 1.7 pooka if (thesig == SIGUSR1) { 202 1.7 pooka if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { 203 1.7 pooka fprintf(stderr, "child died with 0x%x\n", 204 1.7 pooka status); 205 1.7 pooka exit(1); 206 1.7 pooka } 207 1.7 pooka } else { 208 1.7 pooka if (!WIFSIGNALED(status) || WTERMSIG(status) != thesig){ 209 1.7 pooka fprintf(stderr, "child died with 0x%x\n", 210 1.7 pooka status); 211 1.7 pooka exit(1); 212 1.7 pooka } 213 1.5 pooka } 214 1.1 pooka } 215 1.1 pooka 216 1.1 pooka for (i = 0; i < NCLI; i++) 217 1.1 pooka if (clis[i]) 218 1.1 pooka kill(clis[i], SIGKILL); 219 1.1 pooka } 220