Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Test functionality of BPF filters for SO_REUSEPORT.  The tests below will use
0003  * a BPF program (both classic and extended) to read the first word from an
0004  * incoming packet (expected to be in network byte-order), calculate a modulus
0005  * of that number, and then dispatch the packet to the Nth socket using the
0006  * result.  These tests are run for each supported address family and protocol.
0007  * Additionally, a few edge cases in the implementation are tested.
0008  */
0009 
0010 #include <errno.h>
0011 #include <error.h>
0012 #include <fcntl.h>
0013 #include <linux/bpf.h>
0014 #include <linux/filter.h>
0015 #include <linux/unistd.h>
0016 #include <netinet/in.h>
0017 #include <netinet/tcp.h>
0018 #include <stdio.h>
0019 #include <stdlib.h>
0020 #include <string.h>
0021 #include <sys/epoll.h>
0022 #include <sys/types.h>
0023 #include <sys/socket.h>
0024 #include <sys/resource.h>
0025 #include <unistd.h>
0026 
0027 #include "../kselftest.h"
0028 
0029 struct test_params {
0030     int recv_family;
0031     int send_family;
0032     int protocol;
0033     size_t recv_socks;
0034     uint16_t recv_port;
0035     uint16_t send_port_min;
0036 };
0037 
0038 static size_t sockaddr_size(void)
0039 {
0040     return sizeof(struct sockaddr_storage);
0041 }
0042 
0043 static struct sockaddr *new_any_sockaddr(int family, uint16_t port)
0044 {
0045     struct sockaddr_storage *addr;
0046     struct sockaddr_in *addr4;
0047     struct sockaddr_in6 *addr6;
0048 
0049     addr = malloc(sizeof(struct sockaddr_storage));
0050     memset(addr, 0, sizeof(struct sockaddr_storage));
0051 
0052     switch (family) {
0053     case AF_INET:
0054         addr4 = (struct sockaddr_in *)addr;
0055         addr4->sin_family = AF_INET;
0056         addr4->sin_addr.s_addr = htonl(INADDR_ANY);
0057         addr4->sin_port = htons(port);
0058         break;
0059     case AF_INET6:
0060         addr6 = (struct sockaddr_in6 *)addr;
0061         addr6->sin6_family = AF_INET6;
0062         addr6->sin6_addr = in6addr_any;
0063         addr6->sin6_port = htons(port);
0064         break;
0065     default:
0066         error(1, 0, "Unsupported family %d", family);
0067     }
0068     return (struct sockaddr *)addr;
0069 }
0070 
0071 static struct sockaddr *new_loopback_sockaddr(int family, uint16_t port)
0072 {
0073     struct sockaddr *addr = new_any_sockaddr(family, port);
0074     struct sockaddr_in *addr4;
0075     struct sockaddr_in6 *addr6;
0076 
0077     switch (family) {
0078     case AF_INET:
0079         addr4 = (struct sockaddr_in *)addr;
0080         addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
0081         break;
0082     case AF_INET6:
0083         addr6 = (struct sockaddr_in6 *)addr;
0084         addr6->sin6_addr = in6addr_loopback;
0085         break;
0086     default:
0087         error(1, 0, "Unsupported family %d", family);
0088     }
0089     return addr;
0090 }
0091 
0092 static void attach_ebpf(int fd, uint16_t mod)
0093 {
0094     static char bpf_log_buf[65536];
0095     static const char bpf_license[] = "GPL";
0096 
0097     int bpf_fd;
0098     const struct bpf_insn prog[] = {
0099         /* BPF_MOV64_REG(BPF_REG_6, BPF_REG_1) */
0100         { BPF_ALU64 | BPF_MOV | BPF_X, BPF_REG_6, BPF_REG_1, 0, 0 },
0101         /* BPF_LD_ABS(BPF_W, 0) R0 = (uint32_t)skb[0] */
0102         { BPF_LD | BPF_ABS | BPF_W, 0, 0, 0, 0 },
0103         /* BPF_ALU64_IMM(BPF_MOD, BPF_REG_0, mod) */
0104         { BPF_ALU64 | BPF_MOD | BPF_K, BPF_REG_0, 0, 0, mod },
0105         /* BPF_EXIT_INSN() */
0106         { BPF_JMP | BPF_EXIT, 0, 0, 0, 0 }
0107     };
0108     union bpf_attr attr;
0109 
0110     memset(&attr, 0, sizeof(attr));
0111     attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
0112     attr.insn_cnt = ARRAY_SIZE(prog);
0113     attr.insns = (unsigned long) &prog;
0114     attr.license = (unsigned long) &bpf_license;
0115     attr.log_buf = (unsigned long) &bpf_log_buf;
0116     attr.log_size = sizeof(bpf_log_buf);
0117     attr.log_level = 1;
0118     attr.kern_version = 0;
0119 
0120     bpf_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
0121     if (bpf_fd < 0)
0122         error(1, errno, "ebpf error. log:\n%s\n", bpf_log_buf);
0123 
0124     if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &bpf_fd,
0125             sizeof(bpf_fd)))
0126         error(1, errno, "failed to set SO_ATTACH_REUSEPORT_EBPF");
0127 
0128     close(bpf_fd);
0129 }
0130 
0131 static void attach_cbpf(int fd, uint16_t mod)
0132 {
0133     struct sock_filter code[] = {
0134         /* A = (uint32_t)skb[0] */
0135         { BPF_LD  | BPF_W | BPF_ABS, 0, 0, 0 },
0136         /* A = A % mod */
0137         { BPF_ALU | BPF_MOD, 0, 0, mod },
0138         /* return A */
0139         { BPF_RET | BPF_A, 0, 0, 0 },
0140     };
0141     struct sock_fprog p = {
0142         .len = ARRAY_SIZE(code),
0143         .filter = code,
0144     };
0145 
0146     if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, &p, sizeof(p)))
0147         error(1, errno, "failed to set SO_ATTACH_REUSEPORT_CBPF");
0148 }
0149 
0150 static void build_recv_group(const struct test_params p, int fd[], uint16_t mod,
0151                  void (*attach_bpf)(int, uint16_t))
0152 {
0153     struct sockaddr * const addr =
0154         new_any_sockaddr(p.recv_family, p.recv_port);
0155     int i, opt;
0156 
0157     for (i = 0; i < p.recv_socks; ++i) {
0158         fd[i] = socket(p.recv_family, p.protocol, 0);
0159         if (fd[i] < 0)
0160             error(1, errno, "failed to create recv %d", i);
0161 
0162         opt = 1;
0163         if (setsockopt(fd[i], SOL_SOCKET, SO_REUSEPORT, &opt,
0164                    sizeof(opt)))
0165             error(1, errno, "failed to set SO_REUSEPORT on %d", i);
0166 
0167         if (i == 0)
0168             attach_bpf(fd[i], mod);
0169 
0170         if (bind(fd[i], addr, sockaddr_size()))
0171             error(1, errno, "failed to bind recv socket %d", i);
0172 
0173         if (p.protocol == SOCK_STREAM) {
0174             opt = 4;
0175             if (setsockopt(fd[i], SOL_TCP, TCP_FASTOPEN, &opt,
0176                        sizeof(opt)))
0177                 error(1, errno,
0178                       "failed to set TCP_FASTOPEN on %d", i);
0179             if (listen(fd[i], p.recv_socks * 10))
0180                 error(1, errno, "failed to listen on socket");
0181         }
0182     }
0183     free(addr);
0184 }
0185 
0186 static void send_from(struct test_params p, uint16_t sport, char *buf,
0187               size_t len)
0188 {
0189     struct sockaddr * const saddr = new_any_sockaddr(p.send_family, sport);
0190     struct sockaddr * const daddr =
0191         new_loopback_sockaddr(p.send_family, p.recv_port);
0192     const int fd = socket(p.send_family, p.protocol, 0), one = 1;
0193 
0194     if (fd < 0)
0195         error(1, errno, "failed to create send socket");
0196 
0197     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)))
0198         error(1, errno, "failed to set reuseaddr");
0199 
0200     if (bind(fd, saddr, sockaddr_size()))
0201         error(1, errno, "failed to bind send socket");
0202 
0203     if (sendto(fd, buf, len, MSG_FASTOPEN, daddr, sockaddr_size()) < 0)
0204         error(1, errno, "failed to send message");
0205 
0206     close(fd);
0207     free(saddr);
0208     free(daddr);
0209 }
0210 
0211 static void test_recv_order(const struct test_params p, int fd[], int mod)
0212 {
0213     char recv_buf[8], send_buf[8];
0214     struct msghdr msg;
0215     struct iovec recv_io = { recv_buf, 8 };
0216     struct epoll_event ev;
0217     int epfd, conn, i, sport, expected;
0218     uint32_t data, ndata;
0219 
0220     epfd = epoll_create(1);
0221     if (epfd < 0)
0222         error(1, errno, "failed to create epoll");
0223     for (i = 0; i < p.recv_socks; ++i) {
0224         ev.events = EPOLLIN;
0225         ev.data.fd = fd[i];
0226         if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd[i], &ev))
0227             error(1, errno, "failed to register sock %d epoll", i);
0228     }
0229 
0230     memset(&msg, 0, sizeof(msg));
0231     msg.msg_iov = &recv_io;
0232     msg.msg_iovlen = 1;
0233 
0234     for (data = 0; data < p.recv_socks * 2; ++data) {
0235         sport = p.send_port_min + data;
0236         ndata = htonl(data);
0237         memcpy(send_buf, &ndata, sizeof(ndata));
0238         send_from(p, sport, send_buf, sizeof(ndata));
0239 
0240         i = epoll_wait(epfd, &ev, 1, -1);
0241         if (i < 0)
0242             error(1, errno, "epoll wait failed");
0243 
0244         if (p.protocol == SOCK_STREAM) {
0245             conn = accept(ev.data.fd, NULL, NULL);
0246             if (conn < 0)
0247                 error(1, errno, "error accepting");
0248             i = recvmsg(conn, &msg, 0);
0249             close(conn);
0250         } else {
0251             i = recvmsg(ev.data.fd, &msg, 0);
0252         }
0253         if (i < 0)
0254             error(1, errno, "recvmsg error");
0255         if (i != sizeof(ndata))
0256             error(1, 0, "expected size %zd got %d",
0257                   sizeof(ndata), i);
0258 
0259         for (i = 0; i < p.recv_socks; ++i)
0260             if (ev.data.fd == fd[i])
0261                 break;
0262         memcpy(&ndata, recv_buf, sizeof(ndata));
0263         fprintf(stderr, "Socket %d: %d\n", i, ntohl(ndata));
0264 
0265         expected = (sport % mod);
0266         if (i != expected)
0267             error(1, 0, "expected socket %d", expected);
0268     }
0269 }
0270 
0271 static void test_reuseport_ebpf(struct test_params p)
0272 {
0273     int i, fd[p.recv_socks];
0274 
0275     fprintf(stderr, "Testing EBPF mod %zd...\n", p.recv_socks);
0276     build_recv_group(p, fd, p.recv_socks, attach_ebpf);
0277     test_recv_order(p, fd, p.recv_socks);
0278 
0279     p.send_port_min += p.recv_socks * 2;
0280     fprintf(stderr, "Reprograming, testing mod %zd...\n", p.recv_socks / 2);
0281     attach_ebpf(fd[0], p.recv_socks / 2);
0282     test_recv_order(p, fd, p.recv_socks / 2);
0283 
0284     for (i = 0; i < p.recv_socks; ++i)
0285         close(fd[i]);
0286 }
0287 
0288 static void test_reuseport_cbpf(struct test_params p)
0289 {
0290     int i, fd[p.recv_socks];
0291 
0292     fprintf(stderr, "Testing CBPF mod %zd...\n", p.recv_socks);
0293     build_recv_group(p, fd, p.recv_socks, attach_cbpf);
0294     test_recv_order(p, fd, p.recv_socks);
0295 
0296     p.send_port_min += p.recv_socks * 2;
0297     fprintf(stderr, "Reprograming, testing mod %zd...\n", p.recv_socks / 2);
0298     attach_cbpf(fd[0], p.recv_socks / 2);
0299     test_recv_order(p, fd, p.recv_socks / 2);
0300 
0301     for (i = 0; i < p.recv_socks; ++i)
0302         close(fd[i]);
0303 }
0304 
0305 static void test_extra_filter(const struct test_params p)
0306 {
0307     struct sockaddr * const addr =
0308         new_any_sockaddr(p.recv_family, p.recv_port);
0309     int fd1, fd2, opt;
0310 
0311     fprintf(stderr, "Testing too many filters...\n");
0312     fd1 = socket(p.recv_family, p.protocol, 0);
0313     if (fd1 < 0)
0314         error(1, errno, "failed to create socket 1");
0315     fd2 = socket(p.recv_family, p.protocol, 0);
0316     if (fd2 < 0)
0317         error(1, errno, "failed to create socket 2");
0318 
0319     opt = 1;
0320     if (setsockopt(fd1, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
0321         error(1, errno, "failed to set SO_REUSEPORT on socket 1");
0322     if (setsockopt(fd2, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
0323         error(1, errno, "failed to set SO_REUSEPORT on socket 2");
0324 
0325     attach_ebpf(fd1, 10);
0326     attach_ebpf(fd2, 10);
0327 
0328     if (bind(fd1, addr, sockaddr_size()))
0329         error(1, errno, "failed to bind recv socket 1");
0330 
0331     if (!bind(fd2, addr, sockaddr_size()) || errno != EADDRINUSE)
0332         error(1, errno, "bind socket 2 should fail with EADDRINUSE");
0333 
0334     free(addr);
0335 }
0336 
0337 static void test_filter_no_reuseport(const struct test_params p)
0338 {
0339     struct sockaddr * const addr =
0340         new_any_sockaddr(p.recv_family, p.recv_port);
0341     const char bpf_license[] = "GPL";
0342     struct bpf_insn ecode[] = {
0343         { BPF_ALU64 | BPF_MOV | BPF_K, BPF_REG_0, 0, 0, 10 },
0344         { BPF_JMP | BPF_EXIT, 0, 0, 0, 0 }
0345     };
0346     struct sock_filter ccode[] = {{ BPF_RET | BPF_A, 0, 0, 0 }};
0347     union bpf_attr eprog;
0348     struct sock_fprog cprog;
0349     int fd, bpf_fd;
0350 
0351     fprintf(stderr, "Testing filters on non-SO_REUSEPORT socket...\n");
0352 
0353     memset(&eprog, 0, sizeof(eprog));
0354     eprog.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
0355     eprog.insn_cnt = ARRAY_SIZE(ecode);
0356     eprog.insns = (unsigned long) &ecode;
0357     eprog.license = (unsigned long) &bpf_license;
0358     eprog.kern_version = 0;
0359 
0360     memset(&cprog, 0, sizeof(cprog));
0361     cprog.len = ARRAY_SIZE(ccode);
0362     cprog.filter = ccode;
0363 
0364 
0365     bpf_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &eprog, sizeof(eprog));
0366     if (bpf_fd < 0)
0367         error(1, errno, "ebpf error");
0368     fd = socket(p.recv_family, p.protocol, 0);
0369     if (fd < 0)
0370         error(1, errno, "failed to create socket 1");
0371 
0372     if (bind(fd, addr, sockaddr_size()))
0373         error(1, errno, "failed to bind recv socket 1");
0374 
0375     errno = 0;
0376     if (!setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &bpf_fd,
0377             sizeof(bpf_fd)) || errno != EINVAL)
0378         error(1, errno, "setsockopt should have returned EINVAL");
0379 
0380     errno = 0;
0381     if (!setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, &cprog,
0382                sizeof(cprog)) || errno != EINVAL)
0383         error(1, errno, "setsockopt should have returned EINVAL");
0384 
0385     free(addr);
0386 }
0387 
0388 static void test_filter_without_bind(void)
0389 {
0390     int fd1, fd2, opt = 1;
0391 
0392     fprintf(stderr, "Testing filter add without bind...\n");
0393     fd1 = socket(AF_INET, SOCK_DGRAM, 0);
0394     if (fd1 < 0)
0395         error(1, errno, "failed to create socket 1");
0396     fd2 = socket(AF_INET, SOCK_DGRAM, 0);
0397     if (fd2 < 0)
0398         error(1, errno, "failed to create socket 2");
0399     if (setsockopt(fd1, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
0400         error(1, errno, "failed to set SO_REUSEPORT on socket 1");
0401     if (setsockopt(fd2, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
0402         error(1, errno, "failed to set SO_REUSEPORT on socket 2");
0403 
0404     attach_ebpf(fd1, 10);
0405     attach_cbpf(fd2, 10);
0406 
0407     close(fd1);
0408     close(fd2);
0409 }
0410 
0411 void enable_fastopen(void)
0412 {
0413     int fd = open("/proc/sys/net/ipv4/tcp_fastopen", 0);
0414     int rw_mask = 3;  /* bit 1: client side; bit-2 server side */
0415     int val, size;
0416     char buf[16];
0417 
0418     if (fd < 0)
0419         error(1, errno, "Unable to open tcp_fastopen sysctl");
0420     if (read(fd, buf, sizeof(buf)) <= 0)
0421         error(1, errno, "Unable to read tcp_fastopen sysctl");
0422     val = atoi(buf);
0423     close(fd);
0424 
0425     if ((val & rw_mask) != rw_mask) {
0426         fd = open("/proc/sys/net/ipv4/tcp_fastopen", O_RDWR);
0427         if (fd < 0)
0428             error(1, errno,
0429                   "Unable to open tcp_fastopen sysctl for writing");
0430         val |= rw_mask;
0431         size = snprintf(buf, 16, "%d", val);
0432         if (write(fd, buf, size) <= 0)
0433             error(1, errno, "Unable to write tcp_fastopen sysctl");
0434         close(fd);
0435     }
0436 }
0437 
0438 static struct rlimit rlim_old;
0439 
0440 static  __attribute__((constructor)) void main_ctor(void)
0441 {
0442     getrlimit(RLIMIT_MEMLOCK, &rlim_old);
0443 
0444     if (rlim_old.rlim_cur != RLIM_INFINITY) {
0445         struct rlimit rlim_new;
0446 
0447         rlim_new.rlim_cur = rlim_old.rlim_cur + (1UL << 20);
0448         rlim_new.rlim_max = rlim_old.rlim_max + (1UL << 20);
0449         setrlimit(RLIMIT_MEMLOCK, &rlim_new);
0450     }
0451 }
0452 
0453 static __attribute__((destructor)) void main_dtor(void)
0454 {
0455     setrlimit(RLIMIT_MEMLOCK, &rlim_old);
0456 }
0457 
0458 int main(void)
0459 {
0460     fprintf(stderr, "---- IPv4 UDP ----\n");
0461     /* NOTE: UDP socket lookups traverse a different code path when there
0462      * are > 10 sockets in a group.  Run the bpf test through both paths.
0463      */
0464     test_reuseport_ebpf((struct test_params) {
0465         .recv_family = AF_INET,
0466         .send_family = AF_INET,
0467         .protocol = SOCK_DGRAM,
0468         .recv_socks = 10,
0469         .recv_port = 8000,
0470         .send_port_min = 9000});
0471     test_reuseport_ebpf((struct test_params) {
0472         .recv_family = AF_INET,
0473         .send_family = AF_INET,
0474         .protocol = SOCK_DGRAM,
0475         .recv_socks = 20,
0476         .recv_port = 8000,
0477         .send_port_min = 9000});
0478     test_reuseport_cbpf((struct test_params) {
0479         .recv_family = AF_INET,
0480         .send_family = AF_INET,
0481         .protocol = SOCK_DGRAM,
0482         .recv_socks = 10,
0483         .recv_port = 8001,
0484         .send_port_min = 9020});
0485     test_reuseport_cbpf((struct test_params) {
0486         .recv_family = AF_INET,
0487         .send_family = AF_INET,
0488         .protocol = SOCK_DGRAM,
0489         .recv_socks = 20,
0490         .recv_port = 8001,
0491         .send_port_min = 9020});
0492     test_extra_filter((struct test_params) {
0493         .recv_family = AF_INET,
0494         .protocol = SOCK_DGRAM,
0495         .recv_port = 8002});
0496     test_filter_no_reuseport((struct test_params) {
0497         .recv_family = AF_INET,
0498         .protocol = SOCK_DGRAM,
0499         .recv_port = 8008});
0500 
0501     fprintf(stderr, "---- IPv6 UDP ----\n");
0502     test_reuseport_ebpf((struct test_params) {
0503         .recv_family = AF_INET6,
0504         .send_family = AF_INET6,
0505         .protocol = SOCK_DGRAM,
0506         .recv_socks = 10,
0507         .recv_port = 8003,
0508         .send_port_min = 9040});
0509     test_reuseport_ebpf((struct test_params) {
0510         .recv_family = AF_INET6,
0511         .send_family = AF_INET6,
0512         .protocol = SOCK_DGRAM,
0513         .recv_socks = 20,
0514         .recv_port = 8003,
0515         .send_port_min = 9040});
0516     test_reuseport_cbpf((struct test_params) {
0517         .recv_family = AF_INET6,
0518         .send_family = AF_INET6,
0519         .protocol = SOCK_DGRAM,
0520         .recv_socks = 10,
0521         .recv_port = 8004,
0522         .send_port_min = 9060});
0523     test_reuseport_cbpf((struct test_params) {
0524         .recv_family = AF_INET6,
0525         .send_family = AF_INET6,
0526         .protocol = SOCK_DGRAM,
0527         .recv_socks = 20,
0528         .recv_port = 8004,
0529         .send_port_min = 9060});
0530     test_extra_filter((struct test_params) {
0531         .recv_family = AF_INET6,
0532         .protocol = SOCK_DGRAM,
0533         .recv_port = 8005});
0534     test_filter_no_reuseport((struct test_params) {
0535         .recv_family = AF_INET6,
0536         .protocol = SOCK_DGRAM,
0537         .recv_port = 8009});
0538 
0539     fprintf(stderr, "---- IPv6 UDP w/ mapped IPv4 ----\n");
0540     test_reuseport_ebpf((struct test_params) {
0541         .recv_family = AF_INET6,
0542         .send_family = AF_INET,
0543         .protocol = SOCK_DGRAM,
0544         .recv_socks = 20,
0545         .recv_port = 8006,
0546         .send_port_min = 9080});
0547     test_reuseport_ebpf((struct test_params) {
0548         .recv_family = AF_INET6,
0549         .send_family = AF_INET,
0550         .protocol = SOCK_DGRAM,
0551         .recv_socks = 10,
0552         .recv_port = 8006,
0553         .send_port_min = 9080});
0554     test_reuseport_cbpf((struct test_params) {
0555         .recv_family = AF_INET6,
0556         .send_family = AF_INET,
0557         .protocol = SOCK_DGRAM,
0558         .recv_socks = 10,
0559         .recv_port = 8007,
0560         .send_port_min = 9100});
0561     test_reuseport_cbpf((struct test_params) {
0562         .recv_family = AF_INET6,
0563         .send_family = AF_INET,
0564         .protocol = SOCK_DGRAM,
0565         .recv_socks = 20,
0566         .recv_port = 8007,
0567         .send_port_min = 9100});
0568 
0569     /* TCP fastopen is required for the TCP tests */
0570     enable_fastopen();
0571     fprintf(stderr, "---- IPv4 TCP ----\n");
0572     test_reuseport_ebpf((struct test_params) {
0573         .recv_family = AF_INET,
0574         .send_family = AF_INET,
0575         .protocol = SOCK_STREAM,
0576         .recv_socks = 10,
0577         .recv_port = 8008,
0578         .send_port_min = 9120});
0579     test_reuseport_cbpf((struct test_params) {
0580         .recv_family = AF_INET,
0581         .send_family = AF_INET,
0582         .protocol = SOCK_STREAM,
0583         .recv_socks = 10,
0584         .recv_port = 8009,
0585         .send_port_min = 9160});
0586     test_extra_filter((struct test_params) {
0587         .recv_family = AF_INET,
0588         .protocol = SOCK_STREAM,
0589         .recv_port = 8010});
0590     test_filter_no_reuseport((struct test_params) {
0591         .recv_family = AF_INET,
0592         .protocol = SOCK_STREAM,
0593         .recv_port = 8011});
0594 
0595     fprintf(stderr, "---- IPv6 TCP ----\n");
0596     test_reuseport_ebpf((struct test_params) {
0597         .recv_family = AF_INET6,
0598         .send_family = AF_INET6,
0599         .protocol = SOCK_STREAM,
0600         .recv_socks = 10,
0601         .recv_port = 8012,
0602         .send_port_min = 9200});
0603     test_reuseport_cbpf((struct test_params) {
0604         .recv_family = AF_INET6,
0605         .send_family = AF_INET6,
0606         .protocol = SOCK_STREAM,
0607         .recv_socks = 10,
0608         .recv_port = 8013,
0609         .send_port_min = 9240});
0610     test_extra_filter((struct test_params) {
0611         .recv_family = AF_INET6,
0612         .protocol = SOCK_STREAM,
0613         .recv_port = 8014});
0614     test_filter_no_reuseport((struct test_params) {
0615         .recv_family = AF_INET6,
0616         .protocol = SOCK_STREAM,
0617         .recv_port = 8015});
0618 
0619     fprintf(stderr, "---- IPv6 TCP w/ mapped IPv4 ----\n");
0620     test_reuseport_ebpf((struct test_params) {
0621         .recv_family = AF_INET6,
0622         .send_family = AF_INET,
0623         .protocol = SOCK_STREAM,
0624         .recv_socks = 10,
0625         .recv_port = 8016,
0626         .send_port_min = 9320});
0627     test_reuseport_cbpf((struct test_params) {
0628         .recv_family = AF_INET6,
0629         .send_family = AF_INET,
0630         .protocol = SOCK_STREAM,
0631         .recv_socks = 10,
0632         .recv_port = 8017,
0633         .send_port_min = 9360});
0634 
0635     test_filter_without_bind();
0636 
0637     fprintf(stderr, "SUCCESS\n");
0638     return 0;
0639 }