xref: /linux/tools/testing/selftests/net/reuseport_bpf.c (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
1 /*
2  * Test functionality of BPF filters for SO_REUSEPORT.  The tests below will use
3  * a BPF program (both classic and extended) to read the first word from an
4  * incoming packet (expected to be in network byte-order), calculate a modulus
5  * of that number, and then dispatch the packet to the Nth socket using the
6  * result.  These tests are run for each supported address family and protocol.
7  * Additionally, a few edge cases in the implementation are tested.
8  */
9 
10 #include <errno.h>
11 #include <error.h>
12 #include <fcntl.h>
13 #include <linux/bpf.h>
14 #include <linux/filter.h>
15 #include <linux/unistd.h>
16 #include <netinet/in.h>
17 #include <netinet/tcp.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sys/epoll.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/resource.h>
25 #include <unistd.h>
26 #include <sched.h>
27 
28 #include "kselftest.h"
29 
30 struct test_params {
31 	int recv_family;
32 	int send_family;
33 	int protocol;
34 	size_t recv_socks;
35 	uint16_t recv_port;
36 	uint16_t send_port_min;
37 };
38 
39 static size_t sockaddr_size(void)
40 {
41 	return sizeof(struct sockaddr_storage);
42 }
43 
44 static struct sockaddr *new_any_sockaddr(int family, uint16_t port)
45 {
46 	struct sockaddr_storage *addr;
47 	struct sockaddr_in *addr4;
48 	struct sockaddr_in6 *addr6;
49 
50 	addr = malloc(sizeof(struct sockaddr_storage));
51 	memset(addr, 0, sizeof(struct sockaddr_storage));
52 
53 	switch (family) {
54 	case AF_INET:
55 		addr4 = (struct sockaddr_in *)addr;
56 		addr4->sin_family = AF_INET;
57 		addr4->sin_addr.s_addr = htonl(INADDR_ANY);
58 		addr4->sin_port = htons(port);
59 		break;
60 	case AF_INET6:
61 		addr6 = (struct sockaddr_in6 *)addr;
62 		addr6->sin6_family = AF_INET6;
63 		addr6->sin6_addr = in6addr_any;
64 		addr6->sin6_port = htons(port);
65 		break;
66 	default:
67 		error(1, 0, "Unsupported family %d", family);
68 	}
69 	return (struct sockaddr *)addr;
70 }
71 
72 static struct sockaddr *new_loopback_sockaddr(int family, uint16_t port)
73 {
74 	struct sockaddr *addr = new_any_sockaddr(family, port);
75 	struct sockaddr_in *addr4;
76 	struct sockaddr_in6 *addr6;
77 
78 	switch (family) {
79 	case AF_INET:
80 		addr4 = (struct sockaddr_in *)addr;
81 		addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
82 		break;
83 	case AF_INET6:
84 		addr6 = (struct sockaddr_in6 *)addr;
85 		addr6->sin6_addr = in6addr_loopback;
86 		break;
87 	default:
88 		error(1, 0, "Unsupported family %d", family);
89 	}
90 	return addr;
91 }
92 
93 static void attach_ebpf(int fd, uint16_t mod)
94 {
95 	static char bpf_log_buf[65536];
96 	static const char bpf_license[] = "GPL";
97 
98 	int bpf_fd;
99 	const struct bpf_insn prog[] = {
100 		/* BPF_MOV64_REG(BPF_REG_6, BPF_REG_1) */
101 		{ BPF_ALU64 | BPF_MOV | BPF_X, BPF_REG_6, BPF_REG_1, 0, 0 },
102 		/* BPF_LD_ABS(BPF_W, 0) R0 = (uint32_t)skb[0] */
103 		{ BPF_LD | BPF_ABS | BPF_W, 0, 0, 0, 0 },
104 		/* BPF_ALU64_IMM(BPF_MOD, BPF_REG_0, mod) */
105 		{ BPF_ALU64 | BPF_MOD | BPF_K, BPF_REG_0, 0, 0, mod },
106 		/* BPF_EXIT_INSN() */
107 		{ BPF_JMP | BPF_EXIT, 0, 0, 0, 0 }
108 	};
109 	union bpf_attr attr;
110 
111 	memset(&attr, 0, sizeof(attr));
112 	attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
113 	attr.insn_cnt = ARRAY_SIZE(prog);
114 	attr.insns = (unsigned long) &prog;
115 	attr.license = (unsigned long) &bpf_license;
116 	attr.log_buf = (unsigned long) &bpf_log_buf;
117 	attr.log_size = sizeof(bpf_log_buf);
118 	attr.log_level = 1;
119 	attr.kern_version = 0;
120 
121 	bpf_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
122 	if (bpf_fd < 0)
123 		error(1, errno, "ebpf error. log:\n%s\n", bpf_log_buf);
124 
125 	if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &bpf_fd,
126 			sizeof(bpf_fd)))
127 		error(1, errno, "failed to set SO_ATTACH_REUSEPORT_EBPF");
128 
129 	close(bpf_fd);
130 }
131 
132 static void attach_cbpf(int fd, uint16_t mod)
133 {
134 	struct sock_filter code[] = {
135 		/* A = (uint32_t)skb[0] */
136 		{ BPF_LD  | BPF_W | BPF_ABS, 0, 0, 0 },
137 		/* A = A % mod */
138 		{ BPF_ALU | BPF_MOD, 0, 0, mod },
139 		/* return A */
140 		{ BPF_RET | BPF_A, 0, 0, 0 },
141 	};
142 	struct sock_fprog p = {
143 		.len = ARRAY_SIZE(code),
144 		.filter = code,
145 	};
146 
147 	if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, &p, sizeof(p)))
148 		error(1, errno, "failed to set SO_ATTACH_REUSEPORT_CBPF");
149 }
150 
151 static void build_recv_group(const struct test_params p, int fd[], uint16_t mod,
152 			     void (*attach_bpf)(int, uint16_t))
153 {
154 	struct sockaddr * const addr =
155 		new_any_sockaddr(p.recv_family, p.recv_port);
156 	int i, opt;
157 
158 	for (i = 0; i < p.recv_socks; ++i) {
159 		fd[i] = socket(p.recv_family, p.protocol, 0);
160 		if (fd[i] < 0)
161 			error(1, errno, "failed to create recv %d", i);
162 
163 		opt = 1;
164 		if (setsockopt(fd[i], SOL_SOCKET, SO_REUSEPORT, &opt,
165 			       sizeof(opt)))
166 			error(1, errno, "failed to set SO_REUSEPORT on %d", i);
167 
168 		if (i == 0)
169 			attach_bpf(fd[i], mod);
170 
171 		if (bind(fd[i], addr, sockaddr_size()))
172 			error(1, errno, "failed to bind recv socket %d", i);
173 
174 		if (p.protocol == SOCK_STREAM) {
175 			opt = 4;
176 			if (setsockopt(fd[i], SOL_TCP, TCP_FASTOPEN, &opt,
177 				       sizeof(opt)))
178 				error(1, errno,
179 				      "failed to set TCP_FASTOPEN on %d", i);
180 			if (listen(fd[i], p.recv_socks * 10))
181 				error(1, errno, "failed to listen on socket");
182 		}
183 	}
184 	free(addr);
185 }
186 
187 static void send_from(struct test_params p, uint16_t sport, char *buf,
188 		      size_t len)
189 {
190 	struct sockaddr * const saddr = new_any_sockaddr(p.send_family, sport);
191 	struct sockaddr * const daddr =
192 		new_loopback_sockaddr(p.send_family, p.recv_port);
193 	const int fd = socket(p.send_family, p.protocol, 0), one = 1;
194 
195 	if (fd < 0)
196 		error(1, errno, "failed to create send socket");
197 
198 	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)))
199 		error(1, errno, "failed to set reuseaddr");
200 
201 	if (bind(fd, saddr, sockaddr_size()))
202 		error(1, errno, "failed to bind send socket");
203 
204 	if (sendto(fd, buf, len, MSG_FASTOPEN, daddr, sockaddr_size()) < 0)
205 		error(1, errno, "failed to send message");
206 
207 	close(fd);
208 	free(saddr);
209 	free(daddr);
210 }
211 
212 static void test_recv_order(const struct test_params p, int fd[], int mod)
213 {
214 	char recv_buf[8], send_buf[8];
215 	struct msghdr msg;
216 	struct iovec recv_io = { recv_buf, 8 };
217 	struct epoll_event ev;
218 	int epfd, conn, i, sport, expected;
219 	uint32_t data, ndata;
220 
221 	epfd = epoll_create(1);
222 	if (epfd < 0)
223 		error(1, errno, "failed to create epoll");
224 	for (i = 0; i < p.recv_socks; ++i) {
225 		ev.events = EPOLLIN;
226 		ev.data.fd = fd[i];
227 		if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd[i], &ev))
228 			error(1, errno, "failed to register sock %d epoll", i);
229 	}
230 
231 	memset(&msg, 0, sizeof(msg));
232 	msg.msg_iov = &recv_io;
233 	msg.msg_iovlen = 1;
234 
235 	for (data = 0; data < p.recv_socks * 2; ++data) {
236 		sport = p.send_port_min + data;
237 		ndata = htonl(data);
238 		memcpy(send_buf, &ndata, sizeof(ndata));
239 		send_from(p, sport, send_buf, sizeof(ndata));
240 
241 		i = epoll_wait(epfd, &ev, 1, -1);
242 		if (i < 0)
243 			error(1, errno, "epoll wait failed");
244 
245 		if (p.protocol == SOCK_STREAM) {
246 			conn = accept(ev.data.fd, NULL, NULL);
247 			if (conn < 0)
248 				error(1, errno, "error accepting");
249 			i = recvmsg(conn, &msg, 0);
250 			close(conn);
251 		} else {
252 			i = recvmsg(ev.data.fd, &msg, 0);
253 		}
254 		if (i < 0)
255 			error(1, errno, "recvmsg error");
256 		if (i != sizeof(ndata))
257 			error(1, 0, "expected size %zd got %d",
258 			      sizeof(ndata), i);
259 
260 		for (i = 0; i < p.recv_socks; ++i)
261 			if (ev.data.fd == fd[i])
262 				break;
263 		memcpy(&ndata, recv_buf, sizeof(ndata));
264 		fprintf(stderr, "Socket %d: %d\n", i, ntohl(ndata));
265 
266 		expected = (sport % mod);
267 		if (i != expected)
268 			error(1, 0, "expected socket %d", expected);
269 	}
270 }
271 
272 static void test_reuseport_ebpf(struct test_params p)
273 {
274 	int i, fd[p.recv_socks];
275 
276 	fprintf(stderr, "Testing EBPF mod %zd...\n", p.recv_socks);
277 	build_recv_group(p, fd, p.recv_socks, attach_ebpf);
278 	test_recv_order(p, fd, p.recv_socks);
279 
280 	p.send_port_min += p.recv_socks * 2;
281 	fprintf(stderr, "Reprograming, testing mod %zd...\n", p.recv_socks / 2);
282 	attach_ebpf(fd[0], p.recv_socks / 2);
283 	test_recv_order(p, fd, p.recv_socks / 2);
284 
285 	for (i = 0; i < p.recv_socks; ++i)
286 		close(fd[i]);
287 }
288 
289 static void test_reuseport_cbpf(struct test_params p)
290 {
291 	int i, fd[p.recv_socks];
292 
293 	fprintf(stderr, "Testing CBPF mod %zd...\n", p.recv_socks);
294 	build_recv_group(p, fd, p.recv_socks, attach_cbpf);
295 	test_recv_order(p, fd, p.recv_socks);
296 
297 	p.send_port_min += p.recv_socks * 2;
298 	fprintf(stderr, "Reprograming, testing mod %zd...\n", p.recv_socks / 2);
299 	attach_cbpf(fd[0], p.recv_socks / 2);
300 	test_recv_order(p, fd, p.recv_socks / 2);
301 
302 	for (i = 0; i < p.recv_socks; ++i)
303 		close(fd[i]);
304 }
305 
306 static void test_extra_filter(const struct test_params p)
307 {
308 	struct sockaddr * const addr =
309 		new_any_sockaddr(p.recv_family, p.recv_port);
310 	int fd1, fd2, opt;
311 
312 	fprintf(stderr, "Testing too many filters...\n");
313 	fd1 = socket(p.recv_family, p.protocol, 0);
314 	if (fd1 < 0)
315 		error(1, errno, "failed to create socket 1");
316 	fd2 = socket(p.recv_family, p.protocol, 0);
317 	if (fd2 < 0)
318 		error(1, errno, "failed to create socket 2");
319 
320 	opt = 1;
321 	if (setsockopt(fd1, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
322 		error(1, errno, "failed to set SO_REUSEPORT on socket 1");
323 	if (setsockopt(fd2, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
324 		error(1, errno, "failed to set SO_REUSEPORT on socket 2");
325 
326 	attach_ebpf(fd1, 10);
327 	attach_ebpf(fd2, 10);
328 
329 	if (bind(fd1, addr, sockaddr_size()))
330 		error(1, errno, "failed to bind recv socket 1");
331 
332 	if (!bind(fd2, addr, sockaddr_size()) || errno != EADDRINUSE)
333 		error(1, errno, "bind socket 2 should fail with EADDRINUSE");
334 
335 	free(addr);
336 }
337 
338 static void test_filter_no_reuseport(const struct test_params p)
339 {
340 	struct sockaddr * const addr =
341 		new_any_sockaddr(p.recv_family, p.recv_port);
342 	const char bpf_license[] = "GPL";
343 	struct bpf_insn ecode[] = {
344 		{ BPF_ALU64 | BPF_MOV | BPF_K, BPF_REG_0, 0, 0, 10 },
345 		{ BPF_JMP | BPF_EXIT, 0, 0, 0, 0 }
346 	};
347 	struct sock_filter ccode[] = {{ BPF_RET | BPF_A, 0, 0, 0 }};
348 	union bpf_attr eprog;
349 	struct sock_fprog cprog;
350 	int fd, bpf_fd;
351 
352 	fprintf(stderr, "Testing filters on non-SO_REUSEPORT socket...\n");
353 
354 	memset(&eprog, 0, sizeof(eprog));
355 	eprog.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
356 	eprog.insn_cnt = ARRAY_SIZE(ecode);
357 	eprog.insns = (unsigned long) &ecode;
358 	eprog.license = (unsigned long) &bpf_license;
359 	eprog.kern_version = 0;
360 
361 	memset(&cprog, 0, sizeof(cprog));
362 	cprog.len = ARRAY_SIZE(ccode);
363 	cprog.filter = ccode;
364 
365 
366 	bpf_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &eprog, sizeof(eprog));
367 	if (bpf_fd < 0)
368 		error(1, errno, "ebpf error");
369 	fd = socket(p.recv_family, p.protocol, 0);
370 	if (fd < 0)
371 		error(1, errno, "failed to create socket 1");
372 
373 	if (bind(fd, addr, sockaddr_size()))
374 		error(1, errno, "failed to bind recv socket 1");
375 
376 	errno = 0;
377 	if (!setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &bpf_fd,
378 			sizeof(bpf_fd)) || errno != EINVAL)
379 		error(1, errno, "setsockopt should have returned EINVAL");
380 
381 	errno = 0;
382 	if (!setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, &cprog,
383 		       sizeof(cprog)) || errno != EINVAL)
384 		error(1, errno, "setsockopt should have returned EINVAL");
385 
386 	free(addr);
387 }
388 
389 static void test_filter_without_bind(void)
390 {
391 	int fd1, fd2, opt = 1;
392 
393 	fprintf(stderr, "Testing filter add without bind...\n");
394 	fd1 = socket(AF_INET, SOCK_DGRAM, 0);
395 	if (fd1 < 0)
396 		error(1, errno, "failed to create socket 1");
397 	fd2 = socket(AF_INET, SOCK_DGRAM, 0);
398 	if (fd2 < 0)
399 		error(1, errno, "failed to create socket 2");
400 	if (setsockopt(fd1, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
401 		error(1, errno, "failed to set SO_REUSEPORT on socket 1");
402 	if (setsockopt(fd2, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
403 		error(1, errno, "failed to set SO_REUSEPORT on socket 2");
404 
405 	attach_ebpf(fd1, 10);
406 	attach_cbpf(fd2, 10);
407 
408 	close(fd1);
409 	close(fd2);
410 }
411 
412 void enable_fastopen(void)
413 {
414 	int fd = open("/proc/sys/net/ipv4/tcp_fastopen", 0);
415 	int rw_mask = 3;  /* bit 1: client side; bit-2 server side */
416 	int val, size;
417 	char buf[16];
418 
419 	if (fd < 0)
420 		error(1, errno, "Unable to open tcp_fastopen sysctl");
421 	if (read(fd, buf, sizeof(buf)) <= 0)
422 		error(1, errno, "Unable to read tcp_fastopen sysctl");
423 	val = atoi(buf);
424 	close(fd);
425 
426 	if ((val & rw_mask) != rw_mask) {
427 		fd = open("/proc/sys/net/ipv4/tcp_fastopen", O_RDWR);
428 		if (fd < 0)
429 			error(1, errno,
430 			      "Unable to open tcp_fastopen sysctl for writing");
431 		val |= rw_mask;
432 		size = snprintf(buf, 16, "%d", val);
433 		if (write(fd, buf, size) <= 0)
434 			error(1, errno, "Unable to write tcp_fastopen sysctl");
435 		close(fd);
436 	}
437 }
438 
439 static struct rlimit rlim_old;
440 
441 static  __attribute__((constructor)) void main_ctor(void)
442 {
443 	getrlimit(RLIMIT_MEMLOCK, &rlim_old);
444 
445 	if (rlim_old.rlim_cur != RLIM_INFINITY) {
446 		struct rlimit rlim_new;
447 
448 		rlim_new.rlim_cur = rlim_old.rlim_cur + (1UL << 20);
449 		rlim_new.rlim_max = rlim_old.rlim_max + (1UL << 20);
450 		setrlimit(RLIMIT_MEMLOCK, &rlim_new);
451 	}
452 }
453 
454 static __attribute__((destructor)) void main_dtor(void)
455 {
456 	setrlimit(RLIMIT_MEMLOCK, &rlim_old);
457 }
458 
459 static void setup_netns(void)
460 {
461 	if (unshare(CLONE_NEWNET))
462 		error(1, errno, "failed to unshare netns");
463 	if (system("ip link set lo up"))
464 		error(1, 0, "failed to bring up lo interface in netns");
465 }
466 
467 int main(void)
468 {
469 	setup_netns();
470 
471 	fprintf(stderr, "---- IPv4 UDP ----\n");
472 	/* NOTE: UDP socket lookups traverse a different code path when there
473 	 * are > 10 sockets in a group.  Run the bpf test through both paths.
474 	 */
475 	test_reuseport_ebpf((struct test_params) {
476 		.recv_family = AF_INET,
477 		.send_family = AF_INET,
478 		.protocol = SOCK_DGRAM,
479 		.recv_socks = 10,
480 		.recv_port = 8000,
481 		.send_port_min = 9000});
482 	test_reuseport_ebpf((struct test_params) {
483 		.recv_family = AF_INET,
484 		.send_family = AF_INET,
485 		.protocol = SOCK_DGRAM,
486 		.recv_socks = 20,
487 		.recv_port = 8000,
488 		.send_port_min = 9000});
489 	test_reuseport_cbpf((struct test_params) {
490 		.recv_family = AF_INET,
491 		.send_family = AF_INET,
492 		.protocol = SOCK_DGRAM,
493 		.recv_socks = 10,
494 		.recv_port = 8001,
495 		.send_port_min = 9020});
496 	test_reuseport_cbpf((struct test_params) {
497 		.recv_family = AF_INET,
498 		.send_family = AF_INET,
499 		.protocol = SOCK_DGRAM,
500 		.recv_socks = 20,
501 		.recv_port = 8001,
502 		.send_port_min = 9020});
503 	test_extra_filter((struct test_params) {
504 		.recv_family = AF_INET,
505 		.protocol = SOCK_DGRAM,
506 		.recv_port = 8002});
507 	test_filter_no_reuseport((struct test_params) {
508 		.recv_family = AF_INET,
509 		.protocol = SOCK_DGRAM,
510 		.recv_port = 8008});
511 
512 	fprintf(stderr, "---- IPv6 UDP ----\n");
513 	test_reuseport_ebpf((struct test_params) {
514 		.recv_family = AF_INET6,
515 		.send_family = AF_INET6,
516 		.protocol = SOCK_DGRAM,
517 		.recv_socks = 10,
518 		.recv_port = 8003,
519 		.send_port_min = 9040});
520 	test_reuseport_ebpf((struct test_params) {
521 		.recv_family = AF_INET6,
522 		.send_family = AF_INET6,
523 		.protocol = SOCK_DGRAM,
524 		.recv_socks = 20,
525 		.recv_port = 8003,
526 		.send_port_min = 9040});
527 	test_reuseport_cbpf((struct test_params) {
528 		.recv_family = AF_INET6,
529 		.send_family = AF_INET6,
530 		.protocol = SOCK_DGRAM,
531 		.recv_socks = 10,
532 		.recv_port = 8004,
533 		.send_port_min = 9060});
534 	test_reuseport_cbpf((struct test_params) {
535 		.recv_family = AF_INET6,
536 		.send_family = AF_INET6,
537 		.protocol = SOCK_DGRAM,
538 		.recv_socks = 20,
539 		.recv_port = 8004,
540 		.send_port_min = 9060});
541 	test_extra_filter((struct test_params) {
542 		.recv_family = AF_INET6,
543 		.protocol = SOCK_DGRAM,
544 		.recv_port = 8005});
545 	test_filter_no_reuseport((struct test_params) {
546 		.recv_family = AF_INET6,
547 		.protocol = SOCK_DGRAM,
548 		.recv_port = 8009});
549 
550 	fprintf(stderr, "---- IPv6 UDP w/ mapped IPv4 ----\n");
551 	test_reuseport_ebpf((struct test_params) {
552 		.recv_family = AF_INET6,
553 		.send_family = AF_INET,
554 		.protocol = SOCK_DGRAM,
555 		.recv_socks = 20,
556 		.recv_port = 8006,
557 		.send_port_min = 9080});
558 	test_reuseport_ebpf((struct test_params) {
559 		.recv_family = AF_INET6,
560 		.send_family = AF_INET,
561 		.protocol = SOCK_DGRAM,
562 		.recv_socks = 10,
563 		.recv_port = 8006,
564 		.send_port_min = 9080});
565 	test_reuseport_cbpf((struct test_params) {
566 		.recv_family = AF_INET6,
567 		.send_family = AF_INET,
568 		.protocol = SOCK_DGRAM,
569 		.recv_socks = 10,
570 		.recv_port = 8007,
571 		.send_port_min = 9100});
572 	test_reuseport_cbpf((struct test_params) {
573 		.recv_family = AF_INET6,
574 		.send_family = AF_INET,
575 		.protocol = SOCK_DGRAM,
576 		.recv_socks = 20,
577 		.recv_port = 8007,
578 		.send_port_min = 9100});
579 
580 	/* TCP fastopen is required for the TCP tests */
581 	enable_fastopen();
582 	fprintf(stderr, "---- IPv4 TCP ----\n");
583 	test_reuseport_ebpf((struct test_params) {
584 		.recv_family = AF_INET,
585 		.send_family = AF_INET,
586 		.protocol = SOCK_STREAM,
587 		.recv_socks = 10,
588 		.recv_port = 8008,
589 		.send_port_min = 9120});
590 	test_reuseport_cbpf((struct test_params) {
591 		.recv_family = AF_INET,
592 		.send_family = AF_INET,
593 		.protocol = SOCK_STREAM,
594 		.recv_socks = 10,
595 		.recv_port = 8009,
596 		.send_port_min = 9160});
597 	test_extra_filter((struct test_params) {
598 		.recv_family = AF_INET,
599 		.protocol = SOCK_STREAM,
600 		.recv_port = 8010});
601 	test_filter_no_reuseport((struct test_params) {
602 		.recv_family = AF_INET,
603 		.protocol = SOCK_STREAM,
604 		.recv_port = 8011});
605 
606 	fprintf(stderr, "---- IPv6 TCP ----\n");
607 	test_reuseport_ebpf((struct test_params) {
608 		.recv_family = AF_INET6,
609 		.send_family = AF_INET6,
610 		.protocol = SOCK_STREAM,
611 		.recv_socks = 10,
612 		.recv_port = 8012,
613 		.send_port_min = 9200});
614 	test_reuseport_cbpf((struct test_params) {
615 		.recv_family = AF_INET6,
616 		.send_family = AF_INET6,
617 		.protocol = SOCK_STREAM,
618 		.recv_socks = 10,
619 		.recv_port = 8013,
620 		.send_port_min = 9240});
621 	test_extra_filter((struct test_params) {
622 		.recv_family = AF_INET6,
623 		.protocol = SOCK_STREAM,
624 		.recv_port = 8014});
625 	test_filter_no_reuseport((struct test_params) {
626 		.recv_family = AF_INET6,
627 		.protocol = SOCK_STREAM,
628 		.recv_port = 8015});
629 
630 	fprintf(stderr, "---- IPv6 TCP w/ mapped IPv4 ----\n");
631 	test_reuseport_ebpf((struct test_params) {
632 		.recv_family = AF_INET6,
633 		.send_family = AF_INET,
634 		.protocol = SOCK_STREAM,
635 		.recv_socks = 10,
636 		.recv_port = 8016,
637 		.send_port_min = 9320});
638 	test_reuseport_cbpf((struct test_params) {
639 		.recv_family = AF_INET6,
640 		.send_family = AF_INET,
641 		.protocol = SOCK_STREAM,
642 		.recv_socks = 10,
643 		.recv_port = 8017,
644 		.send_port_min = 9360});
645 
646 	test_filter_without_bind();
647 
648 	fprintf(stderr, "SUCCESS\n");
649 	return 0;
650 }
651