5 #include <sys/socket.h>
6 #include <sys/sysctl.h>
10 #include <arpa/inet.h>
11 #include <netinet/in.h>
21 static void mainloop(const struct sockaddr_in *, int, int, long, u_long *,
25 usage(const char *cmd)
27 fprintf(stderr, "%s -4 inet4 [-4 inet4_1] -p port "
28 "[-i n_instance] [-c conn_max] [-l duration] [-u]\n", cmd);
33 main(int argc, char *argv[])
35 struct sockaddr_in *in, *tmp;
36 int opt, ninst, nconn, i, in_max, in_cnt, do_udp;
42 prm_len = sizeof(ninst);
43 if (sysctlbyname("hw.ncpu", &ninst, &prm_len, NULL, 0) != 0)
44 err(2, "sysctl hw.ncpu failed");
52 in = calloc(in_max, sizeof(struct sockaddr_in));
54 err(1, "calloc failed");
57 while ((opt = getopt(argc, argv, "4:p:i:l:c:u")) != -1) {
60 if (in_cnt >= in_max) {
61 struct sockaddr_in *old_in = in;
62 int old_in_max = in_max;
65 in = calloc(in_max, sizeof(struct sockaddr_in));
67 err(1, "calloc failed");
70 old_in_max * sizeof(struct sockaddr_in));
75 if (inet_pton(AF_INET, optarg, &tmp->sin_addr) <= 0) {
76 fprintf(stderr, "invalid inet address %s\n",
84 port = htons(atoi(optarg));
96 dur = strtol(optarg, NULL, 10);
108 if (ninst < 1 || dur < 1 || nconn < 1 || port == 0 || in_cnt == 0)
111 for (i = 0; i < in_cnt; ++i) {
113 tmp->sin_family = AF_INET;
114 tmp->sin_port = port;
117 result = mmap(NULL, ninst * sizeof(u_long), PROT_READ | PROT_WRITE,
118 MAP_ANON | MAP_SHARED, -1, 0);
119 if (result == MAP_FAILED)
120 err(1, "mmap failed");
121 memset(result, 0, ninst * sizeof(u_long));
123 for (i = 0; i < ninst; ++i) {
128 mainloop(in, in_cnt, nconn, dur, &result[i], do_udp);
130 } else if (pid < 0) {
131 err(1, "fork failed");
135 for (i = 0; i < ninst; ++i) {
138 pid = waitpid(-1, NULL, 0);
140 err(1, "waitpid failed");
144 for (i = 0; i < ninst; ++i)
146 printf("%.2f\n", (double)sum / (double)dur);
152 udp_send(const struct sockaddr_in *in)
157 s = socket(AF_INET, SOCK_DGRAM, 0);
159 warn("socket DGRAM failed");
163 if (connect(s, (const struct sockaddr *)in, sizeof(*in)) < 0) {
164 warn("connect DGRAM failed");
168 write(s, d, sizeof(d));
174 mainloop(const struct sockaddr_in *in, int in_cnt, int nconn_max,
175 long dur, u_long *res, int do_udp)
177 struct kevent *evt_change0, *evt;
178 int kq, nchange = 0, nconn = 0, nevt_max;
185 err(1, "kqueue failed");
187 nevt_max = nconn_max + 1; /* timer */
189 evt_change0 = malloc(nevt_max * sizeof(struct kevent));
190 if (evt_change0 == NULL)
191 err(1, "malloc evt_change failed");
193 evt = malloc(nevt_max * sizeof(struct kevent));
195 err(1, "malloc evt failed");
197 EV_SET(&evt_change0[0], 0, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0,
202 struct kevent *evt_change = NULL;
205 while (nconn < nconn_max) {
206 const struct sockaddr_in *tmp;
209 tmp = &in[in_idx % in_cnt];
215 s = socket(AF_INET, SOCK_STREAM, 0);
217 err(1, "socket failed");
219 if (ioctl(s, FIONBIO, &nblock, sizeof(nblock)) < 0)
220 err(1, "ioctl failed");
222 n = connect(s, (const struct sockaddr *)tmp,
231 if (error != EINPROGRESS)
232 errc(1, error, "connect failed");
236 if (nchange >= nevt_max) {
237 fprintf(stderr, "invalid nchange %d, max %d\n",
241 EV_SET(&evt_change0[nchange], s, EVFILT_WRITE, EV_ADD,
247 evt_change = evt_change0;
249 n = kevent(kq, evt_change, nchange, evt, nevt_max, NULL);
251 err(1, "kevent failed");
254 for (i = 0; i < n; ++i) {
255 struct kevent *e = &evt[i];
257 if (e->filter == EVFILT_TIMER) {
262 if ((e->flags & EV_EOF) && e->fflags) {
263 /* Error, don't count */