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
usage(const char * cmd)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
main(int argc,char * argv[])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
signal_handler(int signum __unused)114 signal_handler(int signum __unused)
115 {
116 global_stopped = 1;
117 }
118
119 static void
mainloop(const struct sockaddr_in * in,long dur,u_long * res)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