soreuseport: BPF selection functional test
[cascardo/linux.git] / tools / testing / selftests / net / reuseport_bpf.c
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 <linux/bpf.h>
13 #include <linux/filter.h>
14 #include <linux/unistd.h>
15 #include <netinet/in.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <sys/epoll.h>
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <unistd.h>
23
24 #ifndef ARRAY_SIZE
25 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
26 #endif
27
28 struct test_params {
29         int recv_family;
30         int send_family;
31         int protocol;
32         size_t recv_socks;
33         uint16_t recv_port;
34         uint16_t send_port_min;
35 };
36
37 static size_t sockaddr_size(void)
38 {
39         return sizeof(struct sockaddr_storage);
40 }
41
42 static struct sockaddr *new_any_sockaddr(int family, uint16_t port)
43 {
44         struct sockaddr_storage *addr;
45         struct sockaddr_in *addr4;
46         struct sockaddr_in6 *addr6;
47
48         addr = malloc(sizeof(struct sockaddr_storage));
49         memset(addr, 0, sizeof(struct sockaddr_storage));
50
51         switch (family) {
52         case AF_INET:
53                 addr4 = (struct sockaddr_in *)addr;
54                 addr4->sin_family = AF_INET;
55                 addr4->sin_addr.s_addr = htonl(INADDR_ANY);
56                 addr4->sin_port = htons(port);
57                 break;
58         case AF_INET6:
59                 addr6 = (struct sockaddr_in6 *)addr;
60                 addr6->sin6_family = AF_INET6;
61                 addr6->sin6_addr = in6addr_any;
62                 addr6->sin6_port = htons(port);
63                 break;
64         default:
65                 error(1, 0, "Unsupported family %d", family);
66         }
67         return (struct sockaddr *)addr;
68 }
69
70 static struct sockaddr *new_loopback_sockaddr(int family, uint16_t port)
71 {
72         struct sockaddr *addr = new_any_sockaddr(family, port);
73         struct sockaddr_in *addr4;
74         struct sockaddr_in6 *addr6;
75
76         switch (family) {
77         case AF_INET:
78                 addr4 = (struct sockaddr_in *)addr;
79                 addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
80                 break;
81         case AF_INET6:
82                 addr6 = (struct sockaddr_in6 *)addr;
83                 addr6->sin6_addr = in6addr_loopback;
84                 break;
85         default:
86                 error(1, 0, "Unsupported family %d", family);
87         }
88         return addr;
89 }
90
91 static void attach_ebpf(int fd, uint16_t mod)
92 {
93         static char bpf_log_buf[65536];
94         static const char bpf_license[] = "GPL";
95
96         int bpf_fd;
97         const struct bpf_insn prog[] = {
98                 /* BPF_MOV64_REG(BPF_REG_6, BPF_REG_1) */
99                 { BPF_ALU64 | BPF_MOV | BPF_X, BPF_REG_6, BPF_REG_1, 0, 0 },
100                 /* BPF_LD_ABS(BPF_W, 0) R0 = (uint32_t)skb[0] */
101                 { BPF_LD | BPF_ABS | BPF_W, 0, 0, 0, 0 },
102                 /* BPF_ALU64_IMM(BPF_MOD, BPF_REG_0, mod) */
103                 { BPF_ALU64 | BPF_MOD | BPF_K, BPF_REG_0, 0, 0, mod },
104                 /* BPF_EXIT_INSN() */
105                 { BPF_JMP | BPF_EXIT, 0, 0, 0, 0 }
106         };
107         union bpf_attr attr;
108
109         memset(&attr, 0, sizeof(attr));
110         attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
111         attr.insn_cnt = ARRAY_SIZE(prog);
112         attr.insns = (uint64_t)prog;
113         attr.license = (uint64_t)bpf_license;
114         attr.log_buf = (uint64_t)bpf_log_buf;
115         attr.log_size = sizeof(bpf_log_buf);
116         attr.log_level = 1;
117         attr.kern_version = 0;
118
119         bpf_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
120         if (bpf_fd < 0)
121                 error(1, errno, "ebpf error. log:\n%s\n", bpf_log_buf);
122
123         if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &bpf_fd,
124                         sizeof(bpf_fd)))
125                 error(1, errno, "failed to set SO_ATTACH_REUSEPORT_EBPF");
126 }
127
128 static void attach_cbpf(int fd, uint16_t mod)
129 {
130         struct sock_filter code[] = {
131                 /* A = (uint32_t)skb[0] */
132                 { BPF_LD  | BPF_W | BPF_ABS, 0, 0, 0 },
133                 /* A = A % mod */
134                 { BPF_ALU | BPF_MOD, 0, 0, mod },
135                 /* return A */
136                 { BPF_RET | BPF_A, 0, 0, 0 },
137         };
138         struct sock_fprog p = {
139                 .len = ARRAY_SIZE(code),
140                 .filter = code,
141         };
142
143         if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, &p, sizeof(p)))
144                 error(1, errno, "failed to set SO_ATTACH_REUSEPORT_CBPF");
145 }
146
147 static void build_recv_group(const struct test_params p, int fd[], uint16_t mod,
148                              void (*attach_bpf)(int, uint16_t))
149 {
150         struct sockaddr * const addr =
151                 new_any_sockaddr(p.recv_family, p.recv_port);
152         int i, opt;
153
154         for (i = 0; i < p.recv_socks; ++i) {
155                 fd[i] = socket(p.recv_family, p.protocol, 0);
156                 if (fd[i] < 0)
157                         error(1, errno, "failed to create recv %d", i);
158
159                 opt = 1;
160                 if (setsockopt(fd[i], SOL_SOCKET, SO_REUSEPORT, &opt,
161                                sizeof(opt)))
162                         error(1, errno, "failed to set SO_REUSEPORT on %d", i);
163
164                 if (i == 0)
165                         attach_bpf(fd[i], mod);
166
167                 if (bind(fd[i], addr, sockaddr_size()))
168                         error(1, errno, "failed to bind recv socket %d", i);
169
170                 if (p.protocol == SOCK_STREAM)
171                         if (listen(fd[i], p.recv_socks * 10))
172                                 error(1, errno, "failed to listen on socket");
173         }
174         free(addr);
175 }
176
177 static void send_from(struct test_params p, uint16_t sport, char *buf,
178                       size_t len)
179 {
180         struct sockaddr * const saddr = new_any_sockaddr(p.send_family, sport);
181         struct sockaddr * const daddr =
182                 new_loopback_sockaddr(p.send_family, p.recv_port);
183         const int fd = socket(p.send_family, p.protocol, 0);
184
185         if (fd < 0)
186                 error(1, errno, "failed to create send socket");
187
188         if (bind(fd, saddr, sockaddr_size()))
189                 error(1, errno, "failed to bind send socket");
190         if (connect(fd, daddr, sockaddr_size()))
191                 error(1, errno, "failed to connect");
192
193         if (send(fd, buf, len, 0) < 0)
194                 error(1, errno, "failed to send message");
195
196         close(fd);
197         free(saddr);
198         free(daddr);
199 }
200
201 static void test_recv_order(const struct test_params p, int fd[], int mod)
202 {
203         char recv_buf[8], send_buf[8];
204         struct msghdr msg;
205         struct iovec recv_io = { recv_buf, 8 };
206         struct epoll_event ev;
207         int epfd, conn, i, sport, expected;
208         uint32_t data, ndata;
209
210         epfd = epoll_create(1);
211         if (epfd < 0)
212                 error(1, errno, "failed to create epoll");
213         for (i = 0; i < p.recv_socks; ++i) {
214                 ev.events = EPOLLIN;
215                 ev.data.fd = fd[i];
216                 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd[i], &ev))
217                         error(1, errno, "failed to register sock %d epoll", i);
218         }
219
220         memset(&msg, 0, sizeof(msg));
221         msg.msg_iov = &recv_io;
222         msg.msg_iovlen = 1;
223
224         for (data = 0; data < p.recv_socks * 2; ++data) {
225                 sport = p.send_port_min + data;
226                 ndata = htonl(data);
227                 memcpy(send_buf, &ndata, sizeof(ndata));
228                 send_from(p, sport, send_buf, sizeof(ndata));
229
230                 i = epoll_wait(epfd, &ev, 1, -1);
231                 if (i < 0)
232                         error(1, errno, "epoll wait failed");
233
234                 if (p.protocol == SOCK_STREAM) {
235                         conn = accept(ev.data.fd, NULL, NULL);
236                         if (conn < 0)
237                                 error(1, errno, "error accepting");
238                         i = recvmsg(conn, &msg, 0);
239                         close(conn);
240                 } else {
241                         i = recvmsg(ev.data.fd, &msg, 0);
242                 }
243                 if (i < 0)
244                         error(1, errno, "recvmsg error");
245                 if (i != sizeof(ndata))
246                         error(1, 0, "expected size %zd got %d",
247                               sizeof(ndata), i);
248
249                 for (i = 0; i < p.recv_socks; ++i)
250                         if (ev.data.fd == fd[i])
251                                 break;
252                 memcpy(&ndata, recv_buf, sizeof(ndata));
253                 fprintf(stderr, "Socket %d: %d\n", i, ntohl(ndata));
254
255                 expected = (sport % mod);
256                 if (i != expected)
257                         error(1, 0, "expected socket %d", expected);
258         }
259 }
260
261 static void test_reuseport_ebpf(const struct test_params p)
262 {
263         int i, fd[p.recv_socks];
264
265         fprintf(stderr, "Testing EBPF mod %zd...\n", p.recv_socks);
266         build_recv_group(p, fd, p.recv_socks, attach_ebpf);
267         test_recv_order(p, fd, p.recv_socks);
268
269         fprintf(stderr, "Reprograming, testing mod %zd...\n", p.recv_socks / 2);
270         attach_ebpf(fd[0], p.recv_socks / 2);
271         test_recv_order(p, fd, p.recv_socks / 2);
272
273         for (i = 0; i < p.recv_socks; ++i)
274                 close(fd[i]);
275 }
276
277 static void test_reuseport_cbpf(const struct test_params p)
278 {
279         int i, fd[p.recv_socks];
280
281         fprintf(stderr, "Testing CBPF mod %zd...\n", p.recv_socks);
282         build_recv_group(p, fd, p.recv_socks, attach_cbpf);
283         test_recv_order(p, fd, p.recv_socks);
284
285         fprintf(stderr, "Reprograming, testing mod %zd...\n", p.recv_socks / 2);
286         attach_cbpf(fd[0], p.recv_socks / 2);
287         test_recv_order(p, fd, p.recv_socks / 2);
288
289         for (i = 0; i < p.recv_socks; ++i)
290                 close(fd[i]);
291 }
292
293 static void test_extra_filter(const struct test_params p)
294 {
295         struct sockaddr * const addr =
296                 new_any_sockaddr(p.recv_family, p.recv_port);
297         int fd1, fd2, opt;
298
299         fprintf(stderr, "Testing too many filters...\n");
300         fd1 = socket(p.recv_family, p.protocol, 0);
301         if (fd1 < 0)
302                 error(1, errno, "failed to create socket 1");
303         fd2 = socket(p.recv_family, p.protocol, 0);
304         if (fd2 < 0)
305                 error(1, errno, "failed to create socket 2");
306
307         opt = 1;
308         if (setsockopt(fd1, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
309                 error(1, errno, "failed to set SO_REUSEPORT on socket 1");
310         if (setsockopt(fd2, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
311                 error(1, errno, "failed to set SO_REUSEPORT on socket 2");
312
313         attach_ebpf(fd1, 10);
314         attach_ebpf(fd2, 10);
315
316         if (bind(fd1, addr, sockaddr_size()))
317                 error(1, errno, "failed to bind recv socket 1");
318
319         if (!bind(fd2, addr, sockaddr_size()) && errno != EADDRINUSE)
320                 error(1, errno, "bind socket 2 should fail with EADDRINUSE");
321
322         free(addr);
323 }
324
325 static void test_filter_no_reuseport(const struct test_params p)
326 {
327         struct sockaddr * const addr =
328                 new_any_sockaddr(p.recv_family, p.recv_port);
329         const char bpf_license[] = "GPL";
330         struct bpf_insn ecode[] = {
331                 { BPF_ALU64 | BPF_MOV | BPF_K, BPF_REG_0, 0, 0, 10 },
332                 { BPF_JMP | BPF_EXIT, 0, 0, 0, 0 }
333         };
334         struct sock_filter ccode[] = {{ BPF_RET | BPF_A, 0, 0, 0 }};
335         union bpf_attr eprog;
336         struct sock_fprog cprog;
337         int fd, bpf_fd;
338
339         fprintf(stderr, "Testing filters on non-SO_REUSEPORT socket...\n");
340
341         memset(&eprog, 0, sizeof(eprog));
342         eprog.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
343         eprog.insn_cnt = ARRAY_SIZE(ecode);
344         eprog.insns = (uint64_t)ecode;
345         eprog.license = (uint64_t)bpf_license;
346         eprog.kern_version = 0;
347
348         memset(&cprog, 0, sizeof(cprog));
349         cprog.len = ARRAY_SIZE(ccode);
350         cprog.filter = ccode;
351
352
353         bpf_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &eprog, sizeof(eprog));
354         if (bpf_fd < 0)
355                 error(1, errno, "ebpf error");
356         fd = socket(p.recv_family, p.protocol, 0);
357         if (fd < 0)
358                 error(1, errno, "failed to create socket 1");
359
360         if (bind(fd, addr, sockaddr_size()))
361                 error(1, errno, "failed to bind recv socket 1");
362
363         errno = 0;
364         if (!setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &bpf_fd,
365                         sizeof(bpf_fd)) || errno != EINVAL)
366                 error(1, errno, "setsockopt should have returned EINVAL");
367
368         errno = 0;
369         if (!setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, &cprog,
370                        sizeof(cprog)) || errno != EINVAL)
371                 error(1, errno, "setsockopt should have returned EINVAL");
372
373         free(addr);
374 }
375
376 static void test_filter_without_bind(void)
377 {
378         int fd1, fd2;
379
380         fprintf(stderr, "Testing filter add without bind...\n");
381         fd1 = socket(AF_INET, SOCK_DGRAM, 0);
382         if (fd1 < 0)
383                 error(1, errno, "failed to create socket 1");
384         fd2 = socket(AF_INET, SOCK_DGRAM, 0);
385         if (fd2 < 0)
386                 error(1, errno, "failed to create socket 2");
387
388         attach_ebpf(fd1, 10);
389         attach_cbpf(fd2, 10);
390
391         close(fd1);
392         close(fd2);
393 }
394
395
396 int main(void)
397 {
398         fprintf(stderr, "---- IPv4 UDP ----\n");
399         test_reuseport_ebpf((struct test_params) {
400                 .recv_family = AF_INET,
401                 .send_family = AF_INET,
402                 .protocol = SOCK_DGRAM,
403                 .recv_socks = 10,
404                 .recv_port = 8000,
405                 .send_port_min = 9000});
406         test_reuseport_cbpf((struct test_params) {
407                 .recv_family = AF_INET,
408                 .send_family = AF_INET,
409                 .protocol = SOCK_DGRAM,
410                 .recv_socks = 10,
411                 .recv_port = 8001,
412                 .send_port_min = 9020});
413         test_extra_filter((struct test_params) {
414                 .recv_family = AF_INET,
415                 .protocol = SOCK_DGRAM,
416                 .recv_port = 8002});
417         test_filter_no_reuseport((struct test_params) {
418                 .recv_family = AF_INET,
419                 .protocol = SOCK_DGRAM,
420                 .recv_port = 8008});
421
422         fprintf(stderr, "---- IPv6 UDP ----\n");
423         test_reuseport_ebpf((struct test_params) {
424                 .recv_family = AF_INET6,
425                 .send_family = AF_INET6,
426                 .protocol = SOCK_DGRAM,
427                 .recv_socks = 10,
428                 .recv_port = 8003,
429                 .send_port_min = 9040});
430         test_reuseport_cbpf((struct test_params) {
431                 .recv_family = AF_INET6,
432                 .send_family = AF_INET6,
433                 .protocol = SOCK_DGRAM,
434                 .recv_socks = 10,
435                 .recv_port = 8004,
436                 .send_port_min = 9060});
437         test_extra_filter((struct test_params) {
438                 .recv_family = AF_INET6,
439                 .protocol = SOCK_DGRAM,
440                 .recv_port = 8005});
441         test_filter_no_reuseport((struct test_params) {
442                 .recv_family = AF_INET6,
443                 .protocol = SOCK_DGRAM,
444                 .recv_port = 8009});
445
446         fprintf(stderr, "---- IPv6 UDP w/ mapped IPv4 ----\n");
447         test_reuseport_ebpf((struct test_params) {
448                 .recv_family = AF_INET6,
449                 .send_family = AF_INET,
450                 .protocol = SOCK_DGRAM,
451                 .recv_socks = 10,
452                 .recv_port = 8006,
453                 .send_port_min = 9080});
454         test_reuseport_cbpf((struct test_params) {
455                 .recv_family = AF_INET6,
456                 .send_family = AF_INET,
457                 .protocol = SOCK_DGRAM,
458                 .recv_socks = 10,
459                 .recv_port = 8007,
460                 .send_port_min = 9100});
461
462
463         test_filter_without_bind();
464
465         fprintf(stderr, "SUCCESS\n");
466         return 0;
467 }