19a127286SSepherosa Ziehau #include <sys/types.h>
29a127286SSepherosa Ziehau #include <sys/mman.h>
39a127286SSepherosa Ziehau #include <sys/socket.h>
4a74edad3SSepherosa Ziehau #include <sys/sysctl.h>
59a127286SSepherosa Ziehau #include <sys/time.h>
69a127286SSepherosa Ziehau #include <sys/wait.h>
79a127286SSepherosa Ziehau 
89a127286SSepherosa Ziehau #include <arpa/inet.h>
99a127286SSepherosa Ziehau #include <netinet/in.h>
109a127286SSepherosa Ziehau 
11*9aebb1f1SSepherosa Ziehau #include <err.h>
129a127286SSepherosa Ziehau #include <signal.h>
139a127286SSepherosa Ziehau #include <stdio.h>
149a127286SSepherosa Ziehau #include <stdlib.h>
159a127286SSepherosa Ziehau #include <string.h>
169a127286SSepherosa Ziehau #include <unistd.h>
179a127286SSepherosa Ziehau 
189a127286SSepherosa Ziehau static void	mainloop(const struct sockaddr_in *, long, u_long *);
199a127286SSepherosa Ziehau 
209a127286SSepherosa Ziehau static int	global_stopped;
219a127286SSepherosa Ziehau 
229a127286SSepherosa Ziehau static void
usage(const char * cmd)239a127286SSepherosa Ziehau usage(const char *cmd)
249a127286SSepherosa Ziehau {
259a127286SSepherosa Ziehau 	fprintf(stderr, "%s -4 inet4 -p port "
269a127286SSepherosa Ziehau 	    "[-i n_instance] [-l duration]\n", cmd);
279a127286SSepherosa Ziehau 	exit(1);
289a127286SSepherosa Ziehau }
299a127286SSepherosa Ziehau 
309a127286SSepherosa Ziehau int
main(int argc,char * argv[])319a127286SSepherosa Ziehau main(int argc, char *argv[])
329a127286SSepherosa Ziehau {
339a127286SSepherosa Ziehau 	struct sockaddr_in in;
349a127286SSepherosa Ziehau 	int opt, ninst, i;
359a127286SSepherosa Ziehau 	long dur;
369a127286SSepherosa Ziehau 	u_long *result, sum;
37a74edad3SSepherosa Ziehau 	size_t prm_len;
38a74edad3SSepherosa Ziehau 
39a74edad3SSepherosa Ziehau 	prm_len = sizeof(ninst);
40*9aebb1f1SSepherosa Ziehau 	if (sysctlbyname("hw.ncpu", &ninst, &prm_len, NULL, 0) != 0)
41*9aebb1f1SSepherosa Ziehau 		err(2, "sysctl hw.ncpu failed");
429a127286SSepherosa Ziehau 
439a127286SSepherosa Ziehau 	memset(&in, 0, sizeof(in));
449a127286SSepherosa Ziehau 	in.sin_family = AF_INET;
459a127286SSepherosa Ziehau 
469a127286SSepherosa Ziehau 	dur = 10;
479a127286SSepherosa Ziehau 
489a127286SSepherosa Ziehau 	while ((opt = getopt(argc, argv, "4:p:i:l:")) != -1) {
499a127286SSepherosa Ziehau 		switch (opt) {
509a127286SSepherosa Ziehau 		case '4':
519a127286SSepherosa Ziehau 			if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0) {
529a127286SSepherosa Ziehau 				fprintf(stderr, "invalid inet address %s\n",
539a127286SSepherosa Ziehau 				    optarg);
549a127286SSepherosa Ziehau 				usage(argv[0]);
559a127286SSepherosa Ziehau 			}
569a127286SSepherosa Ziehau 			break;
579a127286SSepherosa Ziehau 
589a127286SSepherosa Ziehau 		case 'p':
599a127286SSepherosa Ziehau 			in.sin_port = htons(atoi(optarg));
609a127286SSepherosa Ziehau 			break;
619a127286SSepherosa Ziehau 
629a127286SSepherosa Ziehau 		case 'i':
639a127286SSepherosa Ziehau 			ninst = atoi(optarg);
649a127286SSepherosa Ziehau 			break;
659a127286SSepherosa Ziehau 
669a127286SSepherosa Ziehau 		case 'l':
679a127286SSepherosa Ziehau 			dur = strtol(optarg, NULL, 10);
689a127286SSepherosa Ziehau 			break;
699a127286SSepherosa Ziehau 
709a127286SSepherosa Ziehau 		default:
719a127286SSepherosa Ziehau 			usage(argv[0]);
729a127286SSepherosa Ziehau 		}
739a127286SSepherosa Ziehau 	}
749a127286SSepherosa Ziehau 
759a127286SSepherosa Ziehau 	if (ninst < 1 || dur < 1 ||
769a127286SSepherosa Ziehau 	    in.sin_port == 0 || in.sin_addr.s_addr == INADDR_ANY)
779a127286SSepherosa Ziehau 		usage(argv[0]);
789a127286SSepherosa Ziehau 
799a127286SSepherosa Ziehau 	result = mmap(NULL, ninst * sizeof(u_long), PROT_READ | PROT_WRITE,
809a127286SSepherosa Ziehau 	    MAP_ANON | MAP_SHARED, -1, 0);
81*9aebb1f1SSepherosa Ziehau 	if (result == MAP_FAILED)
82*9aebb1f1SSepherosa Ziehau 		err(1, "mmap failed");
839a127286SSepherosa Ziehau 	memset(result, 0, ninst * sizeof(u_long));
849a127286SSepherosa Ziehau 
859a127286SSepherosa Ziehau 	for (i = 0; i < ninst; ++i) {
869a127286SSepherosa Ziehau 		pid_t pid;
879a127286SSepherosa Ziehau 
889a127286SSepherosa Ziehau 		pid = fork();
899a127286SSepherosa Ziehau 		if (pid == 0) {
909a127286SSepherosa Ziehau 			mainloop(&in, dur, &result[i]);
919a127286SSepherosa Ziehau 			exit(0);
929a127286SSepherosa Ziehau 		} else if (pid < 0) {
93*9aebb1f1SSepherosa Ziehau 			err(1, "fork failed");
949a127286SSepherosa Ziehau 		}
959a127286SSepherosa Ziehau 	}
969a127286SSepherosa Ziehau 
979a127286SSepherosa Ziehau 	for (i = 0; i < ninst; ++i) {
989a127286SSepherosa Ziehau 		pid_t pid;
999a127286SSepherosa Ziehau 
1009a127286SSepherosa Ziehau 		pid = waitpid(-1, NULL, 0);
101*9aebb1f1SSepherosa Ziehau 		if (pid < 0)
102*9aebb1f1SSepherosa Ziehau 			err(1, "waitpid failed");
1039a127286SSepherosa Ziehau 	}
1049a127286SSepherosa Ziehau 
1059a127286SSepherosa Ziehau 	sum = 0;
1069a127286SSepherosa Ziehau 	for (i = 0; i < ninst; ++i)
1079a127286SSepherosa Ziehau 		sum += result[i];
1089a127286SSepherosa Ziehau 	printf("%.2f\n", (double)sum / (double)dur);
1099a127286SSepherosa Ziehau 
1109a127286SSepherosa Ziehau 	exit(0);
1119a127286SSepherosa Ziehau }
1129a127286SSepherosa Ziehau 
1139a127286SSepherosa Ziehau static void
signal_handler(int signum __unused)1149a127286SSepherosa Ziehau signal_handler(int signum __unused)
1159a127286SSepherosa Ziehau {
1169a127286SSepherosa Ziehau 	global_stopped = 1;
1179a127286SSepherosa Ziehau }
1189a127286SSepherosa Ziehau 
1199a127286SSepherosa Ziehau static void
mainloop(const struct sockaddr_in * in,long dur,u_long * res)1209a127286SSepherosa Ziehau mainloop(const struct sockaddr_in *in, long dur, u_long *res)
1219a127286SSepherosa Ziehau {
1229a127286SSepherosa Ziehau 	struct itimerval it;
1239a127286SSepherosa Ziehau 	u_long count = 0;
1249a127286SSepherosa Ziehau 
125*9aebb1f1SSepherosa Ziehau 	if (signal(SIGALRM, signal_handler) == SIG_ERR)
126*9aebb1f1SSepherosa Ziehau 		err(1, "signal failed");
1279a127286SSepherosa Ziehau 
1289a127286SSepherosa Ziehau 	it.it_interval.tv_sec = 0;
1299a127286SSepherosa Ziehau 	it.it_interval.tv_usec = 0;
1309a127286SSepherosa Ziehau 	it.it_value.tv_sec = dur;
1319a127286SSepherosa Ziehau 	it.it_value.tv_usec = 0;
1329a127286SSepherosa Ziehau 
133*9aebb1f1SSepherosa Ziehau 	if (setitimer(ITIMER_REAL, &it, NULL) < 0)
134*9aebb1f1SSepherosa Ziehau 		err(1, "setitimer failed");
1359a127286SSepherosa Ziehau 
1369a127286SSepherosa Ziehau 	while (!global_stopped) {
1379a127286SSepherosa Ziehau 		int s;
1389a127286SSepherosa Ziehau 
1399a127286SSepherosa Ziehau 		s = socket(AF_INET, SOCK_STREAM, 0);
1409a127286SSepherosa Ziehau 		if (s < 0)
1419a127286SSepherosa Ziehau 			continue;
1429a127286SSepherosa Ziehau 
1439a127286SSepherosa Ziehau 		if (connect(s,
1449a127286SSepherosa Ziehau 		    (const struct sockaddr *)in, sizeof(*in)) == 0)
1459a127286SSepherosa Ziehau 			++count;
1469a127286SSepherosa Ziehau 		close(s);
1479a127286SSepherosa Ziehau 	}
1489a127286SSepherosa Ziehau 	*res = count;
1499a127286SSepherosa Ziehau }
150