1 #include <sys/types.h> 2 #include <sys/mman.h> 3 #include <sys/socket.h> 4 #include <sys/sysctl.h> 5 #include <sys/time.h> 6 #include <sys/wait.h> 7 8 #include <arpa/inet.h> 9 #include <netinet/in.h> 10 11 #include <err.h> 12 #include <signal.h> 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <unistd.h> 17 18 static void mainloop(const struct sockaddr_in *, long, u_long *); 19 20 static int global_stopped; 21 22 static void 23 usage(const char *cmd) 24 { 25 fprintf(stderr, "%s -4 inet4 -p port " 26 "[-i n_instance] [-l duration]\n", cmd); 27 exit(1); 28 } 29 30 int 31 main(int argc, char *argv[]) 32 { 33 struct sockaddr_in in; 34 int opt, ninst, i; 35 long dur; 36 u_long *result, sum; 37 size_t prm_len; 38 39 prm_len = sizeof(ninst); 40 if (sysctlbyname("hw.ncpu", &ninst, &prm_len, NULL, 0) != 0) 41 err(2, "sysctl hw.ncpu failed"); 42 43 memset(&in, 0, sizeof(in)); 44 in.sin_family = AF_INET; 45 46 dur = 10; 47 48 while ((opt = getopt(argc, argv, "4:p:i:l:")) != -1) { 49 switch (opt) { 50 case '4': 51 if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0) { 52 fprintf(stderr, "invalid inet address %s\n", 53 optarg); 54 usage(argv[0]); 55 } 56 break; 57 58 case 'p': 59 in.sin_port = htons(atoi(optarg)); 60 break; 61 62 case 'i': 63 ninst = atoi(optarg); 64 break; 65 66 case 'l': 67 dur = strtol(optarg, NULL, 10); 68 break; 69 70 default: 71 usage(argv[0]); 72 } 73 } 74 75 if (ninst < 1 || dur < 1 || 76 in.sin_port == 0 || in.sin_addr.s_addr == INADDR_ANY) 77 usage(argv[0]); 78 79 result = mmap(NULL, ninst * sizeof(u_long), PROT_READ | PROT_WRITE, 80 MAP_ANON | MAP_SHARED, -1, 0); 81 if (result == MAP_FAILED) 82 err(1, "mmap failed"); 83 memset(result, 0, ninst * sizeof(u_long)); 84 85 for (i = 0; i < ninst; ++i) { 86 pid_t pid; 87 88 pid = fork(); 89 if (pid == 0) { 90 mainloop(&in, dur, &result[i]); 91 exit(0); 92 } else if (pid < 0) { 93 err(1, "fork failed"); 94 } 95 } 96 97 for (i = 0; i < ninst; ++i) { 98 pid_t pid; 99 100 pid = waitpid(-1, NULL, 0); 101 if (pid < 0) 102 err(1, "waitpid failed"); 103 } 104 105 sum = 0; 106 for (i = 0; i < ninst; ++i) 107 sum += result[i]; 108 printf("%.2f\n", (double)sum / (double)dur); 109 110 exit(0); 111 } 112 113 static void 114 signal_handler(int signum __unused) 115 { 116 global_stopped = 1; 117 } 118 119 static void 120 mainloop(const struct sockaddr_in *in, long dur, u_long *res) 121 { 122 struct itimerval it; 123 u_long count = 0; 124 125 if (signal(SIGALRM, signal_handler) == SIG_ERR) 126 err(1, "signal failed"); 127 128 it.it_interval.tv_sec = 0; 129 it.it_interval.tv_usec = 0; 130 it.it_value.tv_sec = dur; 131 it.it_value.tv_usec = 0; 132 133 if (setitimer(ITIMER_REAL, &it, NULL) < 0) 134 err(1, "setitimer failed"); 135 136 while (!global_stopped) { 137 int s; 138 139 s = socket(AF_INET, SOCK_STREAM, 0); 140 if (s < 0) 141 continue; 142 143 if (connect(s, 144 (const struct sockaddr *)in, sizeof(*in)) == 0) 145 ++count; 146 close(s); 147 } 148 *res = count; 149 } 150