tools/netrate: Use ncpus as # of instance by default
[dragonfly.git] / tools / tools / netrate / accept_connect / connect_client / connect_client.c
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 <errno.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                 fprintf(stderr, "sysctl hw.ncpu failed: %d\n", errno);
42                 exit(2);
43         }
44
45         memset(&in, 0, sizeof(in));
46         in.sin_family = AF_INET;
47
48         dur = 10;
49
50         while ((opt = getopt(argc, argv, "4:p:i:l:")) != -1) {
51                 switch (opt) {
52                 case '4':
53                         if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0) {
54                                 fprintf(stderr, "invalid inet address %s\n",
55                                     optarg);
56                                 usage(argv[0]);
57                         }
58                         break;
59
60                 case 'p':
61                         in.sin_port = htons(atoi(optarg));
62                         break;
63
64                 case 'i':
65                         ninst = atoi(optarg);
66                         break;
67
68                 case 'l':
69                         dur = strtol(optarg, NULL, 10);
70                         break;
71
72                 default:
73                         usage(argv[0]);
74                 }
75         }
76
77         if (ninst < 1 || dur < 1 ||
78             in.sin_port == 0 || in.sin_addr.s_addr == INADDR_ANY)
79                 usage(argv[0]);
80
81         result = mmap(NULL, ninst * sizeof(u_long), PROT_READ | PROT_WRITE,
82             MAP_ANON | MAP_SHARED, -1, 0);
83         if (result == MAP_FAILED) {
84                 fprintf(stderr, "mmap failed: %d\n", errno);
85                 exit(1);
86         }
87         memset(result, 0, ninst * sizeof(u_long));
88
89         for (i = 0; i < ninst; ++i) {
90                 pid_t pid;
91
92                 pid = fork();
93                 if (pid == 0) {
94                         mainloop(&in, dur, &result[i]);
95                         exit(0);
96                 } else if (pid < 0) {
97                         fprintf(stderr, "fork failed: %d\n", errno);
98                 }
99         }
100
101         for (i = 0; i < ninst; ++i) {
102                 pid_t pid;
103
104                 pid = waitpid(-1, NULL, 0);
105                 if (pid < 0) {
106                         fprintf(stderr, "waitpid failed: %d\n", errno);
107                         exit(1);
108                 }
109         }
110
111         sum = 0;
112         for (i = 0; i < ninst; ++i)
113                 sum += result[i];
114         printf("%.2f\n", (double)sum / (double)dur);
115
116         exit(0);
117 }
118
119 static void
120 signal_handler(int signum __unused)
121 {
122         global_stopped = 1;
123 }
124
125
126 static void
127 mainloop(const struct sockaddr_in *in, long dur, u_long *res)
128 {
129         struct itimerval it;
130         u_long count = 0;
131
132         if (signal(SIGALRM, signal_handler) == SIG_ERR) {
133                 fprintf(stderr, "signal failed: %d\n", errno);
134                 return;
135         }
136
137         it.it_interval.tv_sec = 0;
138         it.it_interval.tv_usec = 0;
139         it.it_value.tv_sec = dur;
140         it.it_value.tv_usec = 0;
141
142         if (setitimer(ITIMER_REAL, &it, NULL) < 0) {
143                 fprintf(stderr, "setitimer failed: %d\n", errno);
144                 return;
145         }
146
147         while (!global_stopped) {
148                 int s;
149
150                 s = socket(AF_INET, SOCK_STREAM, 0);
151                 if (s < 0)
152                         continue;
153
154                 if (connect(s,
155                     (const struct sockaddr *)in, sizeof(*in)) == 0)
156                         ++count;
157                 close(s);
158         }
159         *res = count;
160 }