2 #include <sys/socket.h>
3 #include <sys/sysctl.h>
4 #include <sys/usched.h>
7 #include <netinet/in.h>
16 #define RCVBUF_SIZE (256 * 1024)
19 #define FLAG_NOREPLY 0x0001
20 #define FLAG_BINDCPU 0x0002
22 static void mainloop(struct sockaddr_in *, int, int, uint32_t);
25 usage(const char *cmd)
27 fprintf(stderr, "%s -4 addr4 -p port [-i ninst] [-r rcvbuf] "
33 main(int argc, char *argv[])
35 struct sockaddr_in in;
36 int opt, ninst, i, s, rcvbuf, flags;
39 prm_len = sizeof(ninst);
40 if (sysctlbyname("hw.ncpu", &ninst, &prm_len, NULL, 0) != 0)
41 err(2, "sysctl hw.ncpu failed");
43 memset(&in, 0, sizeof(in));
44 in.sin_family = AF_INET;
49 while ((opt = getopt(argc, argv, "4:p:i:r:NB")) != -1) {
52 if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0)
53 errx(1, "invalid -4 %s\n", optarg);
57 in.sin_port = strtoul(optarg, NULL, 10);
58 in.sin_port = htons(in.sin_port);
62 ninst = strtoul(optarg, NULL, 10);
66 rcvbuf = strtoul(optarg, NULL, 10);
71 flags |= FLAG_NOREPLY;
75 flags |= FLAG_BINDCPU;
83 if (in.sin_port == 0 || in.sin_addr.s_addr == INADDR_ANY)
88 for (i = 0; i < ninst - 1; ++i) {
93 mainloop(&in, s, rcvbuf, flags);
95 err(1, "fork %d failed", i);
98 mainloop(&in, s, rcvbuf, flags);
103 mainloop(struct sockaddr_in *in, int s, int rcvbuf, uint32_t flags)
109 s = socket(AF_INET, SOCK_DGRAM, 0);
111 err(1, "socket(INET, DGRAM) failed");
114 buf = malloc(BUFLEN);
116 err(1, "malloc buf failed");
119 if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0)
120 err(1, "setsockopt(SOCK, REUSEPORT) failed");
122 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) < 0)
123 err(1, "setsockopt(SOCK, RCVBUF) failed");
125 if (bind(s, (const struct sockaddr *)in, sizeof(*in)) < 0)
126 err(1, "bind failed");
128 if (flags & FLAG_BINDCPU) {
132 cpu_len = sizeof(cpu);
133 if (getsockopt(s, SOL_SOCKET, SO_CPUHINT, &cpu, &cpu_len) < 0)
134 err(1, "getsockopt(SOCK, CPUHINT) failed");
136 usched_set(getpid(), USCHED_SET_CPU, &cpu, sizeof(cpu));
140 struct sockaddr_in cli;
144 cli_len = sizeof(cli);
145 n = recvfrom(s, buf, BUFLEN, 0,
146 (struct sockaddr *)&cli, &cli_len);
147 if (n > 0 && (flags & FLAG_NOREPLY) == 0) {
149 (const struct sockaddr *)&cli, cli_len);