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