soreuseport: pass skb to secondary UDP socket lookup
[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         close(bpf_fd);
128 }
129
130 static void attach_cbpf(int fd, uint16_t mod)
131 {
132         struct sock_filter code[] = {
133                 /* A = (uint32_t)skb[0] */
134                 { BPF_LD  | BPF_W | BPF_ABS, 0, 0, 0 },
135                 /* A = A % mod */
136                 { BPF_ALU | BPF_MOD, 0, 0, mod },
137                 /* return A */
138                 { BPF_RET | BPF_A, 0, 0, 0 },
139         };
140         struct sock_fprog p = {
141                 .len = ARRAY_SIZE(code),
142                 .filter = code,
143         };
144
145         if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, &p, sizeof(p)))
146                 error(1, errno, "failed to set SO_ATTACH_REUSEPORT_CBPF");
147 }
148
149 static void build_recv_group(const struct test_params p, int fd[], uint16_t mod,
150                              void (*attach_bpf)(int, uint16_t))
151 {
152         struct sockaddr * const addr =
153                 new_any_sockaddr(p.recv_family, p.recv_port);
154         int i, opt;
155
156         for (i = 0; i < p.recv_socks; ++i) {
157                 fd[i] = socket(p.recv_family, p.protocol, 0);
158                 if (fd[i] < 0)
159                         error(1, errno, "failed to create recv %d", i);
160
161                 opt = 1;
162                 if (setsockopt(fd[i], SOL_SOCKET, SO_REUSEPORT, &opt,
163                                sizeof(opt)))
164                         error(1, errno, "failed to set SO_REUSEPORT on %d", i);
165
166                 if (i == 0)
167                         attach_bpf(fd[i], mod);
168
169                 if (bind(fd[i], addr, sockaddr_size()))
170                         error(1, errno, "failed to bind recv socket %d", i);
171
172                 if (p.protocol == SOCK_STREAM)
173                         if (listen(fd[i], p.recv_socks * 10))
174                                 error(1, errno, "failed to listen on socket");
175         }
176         free(addr);
177 }
178
179 static void send_from(struct test_params p, uint16_t sport, char *buf,
180                       size_t len)
181 {
182         struct sockaddr * const saddr = new_any_sockaddr(p.send_family, sport);
183         struct sockaddr * const daddr =
184                 new_loopback_sockaddr(p.send_family, p.recv_port);
185         const int fd = socket(p.send_family, p.protocol, 0);
186
187         if (fd < 0)
188                 error(1, errno, "failed to create send socket");
189
190         if (bind(fd, saddr, sockaddr_size()))
191                 error(1, errno, "failed to bind send socket");
192         if (connect(fd, daddr, sockaddr_size()))
193                 error(1, errno, "failed to connect");
194
195         if (send(fd, buf, len, 0) < 0)
196                 error(1, errno, "failed to send message");
197
198         close(fd);
199         free(saddr);
200         free(daddr);
201 }
202
203 static void test_recv_order(const struct test_params p, int fd[], int mod)
204 {
205         char recv_buf[8], send_buf[8];
206         struct msghdr msg;
207         struct iovec recv_io = { recv_buf, 8 };
208         struct epoll_event ev;
209         int epfd, conn, i, sport, expected;
210         uint32_t data, ndata;
211
212         epfd = epoll_create(1);
213         if (epfd < 0)
214                 error(1, errno, "failed to create epoll");
215         for (i = 0; i < p.recv_socks; ++i) {
216                 ev.events = EPOLLIN;
217                 ev.data.fd = fd[i];
218                 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd[i], &ev))
219                         error(1, errno, "failed to register sock %d epoll", i);
220         }
221
222         memset(&msg, 0, sizeof(msg));
223         msg.msg_iov = &recv_io;
224         msg.msg_iovlen = 1;
225
226         for (data = 0; data < p.recv_socks * 2; ++data) {
227                 sport = p.send_port_min + data;
228                 ndata = htonl(data);
229                 memcpy(send_buf, &ndata, sizeof(ndata));
230                 send_from(p, sport, send_buf, sizeof(ndata));
231
232                 i = epoll_wait(epfd, &ev, 1, -1);
233                 if (i < 0)
234                         error(1, errno, "epoll wait failed");
235
236                 if (p.protocol == SOCK_STREAM) {
237                         conn = accept(ev.data.fd, NULL, NULL);
238                         if (conn < 0)
239                                 error(1, errno, "error accepting");
240                         i = recvmsg(conn, &msg, 0);
241                         close(conn);
242                 } else {
243                         i = recvmsg(ev.data.fd, &msg, 0);
244                 }
245                 if (i < 0)
246                         error(1, errno, "recvmsg error");
247                 if (i != sizeof(ndata))
248                         error(1, 0, "expected size %zd got %d",
249                               sizeof(ndata), i);
250
251                 for (i = 0; i < p.recv_socks; ++i)
252                         if (ev.data.fd == fd[i])
253                                 break;
254                 memcpy(&ndata, recv_buf, sizeof(ndata));
255                 fprintf(stderr, "Socket %d: %d\n", i, ntohl(ndata));
256
257                 expected = (sport % mod);
258                 if (i != expected)
259                         error(1, 0, "expected socket %d", expected);
260         }
261 }
262
263 static void test_reuseport_ebpf(const struct test_params p)
264 {
265         int i, fd[p.recv_socks];
266
267         fprintf(stderr, "Testing EBPF mod %zd...\n", p.recv_socks);
268         build_recv_group(p, fd, p.recv_socks, attach_ebpf);
269         test_recv_order(p, fd, p.recv_socks);
270
271         fprintf(stderr, "Reprograming, testing mod %zd...\n", p.recv_socks / 2);
272         attach_ebpf(fd[0], p.recv_socks / 2);
273         test_recv_order(p, fd, p.recv_socks / 2);
274
275         for (i = 0; i < p.recv_socks; ++i)
276                 close(fd[i]);
277 }
278
279 static void test_reuseport_cbpf(const struct test_params p)
280 {
281         int i, fd[p.recv_socks];
282
283         fprintf(stderr, "Testing CBPF mod %zd...\n", p.recv_socks);
284         build_recv_group(p, fd, p.recv_socks, attach_cbpf);
285         test_recv_order(p, fd, p.recv_socks);
286
287         fprintf(stderr, "Reprograming, testing mod %zd...\n", p.recv_socks / 2);
288         attach_cbpf(fd[0], p.recv_socks / 2);
289         test_recv_order(p, fd, p.recv_socks / 2);
290
291         for (i = 0; i < p.recv_socks; ++i)
292                 close(fd[i]);
293 }
294
295 static void test_extra_filter(const struct test_params p)
296 {
297         struct sockaddr * const addr =
298                 new_any_sockaddr(p.recv_family, p.recv_port);
299         int fd1, fd2, opt;
300
301         fprintf(stderr, "Testing too many filters...\n");
302         fd1 = socket(p.recv_family, p.protocol, 0);
303         if (fd1 < 0)
304                 error(1, errno, "failed to create socket 1");
305         fd2 = socket(p.recv_family, p.protocol, 0);
306         if (fd2 < 0)
307                 error(1, errno, "failed to create socket 2");
308
309         opt = 1;
310         if (setsockopt(fd1, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
311                 error(1, errno, "failed to set SO_REUSEPORT on socket 1");
312         if (setsockopt(fd2, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
313                 error(1, errno, "failed to set SO_REUSEPORT on socket 2");
314
315         attach_ebpf(fd1, 10);
316         attach_ebpf(fd2, 10);
317
318         if (bind(fd1, addr, sockaddr_size()))
319                 error(1, errno, "failed to bind recv socket 1");
320
321         if (!bind(fd2, addr, sockaddr_size()) && errno != EADDRINUSE)
322                 error(1, errno, "bind socket 2 should fail with EADDRINUSE");
323
324         free(addr);
325 }
326
327 static void test_filter_no_reuseport(const struct test_params p)
328 {
329         struct sockaddr * const addr =
330                 new_any_sockaddr(p.recv_family, p.recv_port);
331         const char bpf_license[] = "GPL";
332         struct bpf_insn ecode[] = {
333                 { BPF_ALU64 | BPF_MOV | BPF_K, BPF_REG_0, 0, 0, 10 },
334                 { BPF_JMP | BPF_EXIT, 0, 0, 0, 0 }
335         };
336         struct sock_filter ccode[] = {{ BPF_RET | BPF_A, 0, 0, 0 }};
337         union bpf_attr eprog;
338         struct sock_fprog cprog;
339         int fd, bpf_fd;
340
341         fprintf(stderr, "Testing filters on non-SO_REUSEPORT socket...\n");
342
343         memset(&eprog, 0, sizeof(eprog));
344         eprog.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
345         eprog.insn_cnt = ARRAY_SIZE(ecode);
346         eprog.insns = (uint64_t)ecode;
347         eprog.license = (uint64_t)bpf_license;
348         eprog.kern_version = 0;
349
350         memset(&cprog, 0, sizeof(cprog));
351         cprog.len = ARRAY_SIZE(ccode);
352         cprog.filter = ccode;
353
354
355         bpf_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &eprog, sizeof(eprog));
356         if (bpf_fd < 0)
357                 error(1, errno, "ebpf error");
358         fd = socket(p.recv_family, p.protocol, 0);
359         if (fd < 0)
360                 error(1, errno, "failed to create socket 1");
361
362         if (bind(fd, addr, sockaddr_size()))
363                 error(1, errno, "failed to bind recv socket 1");
364
365         errno = 0;
366         if (!setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &bpf_fd,
367                         sizeof(bpf_fd)) || errno != EINVAL)
368                 error(1, errno, "setsockopt should have returned EINVAL");
369
370         errno = 0;
371         if (!setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, &cprog,
372                        sizeof(cprog)) || errno != EINVAL)
373                 error(1, errno, "setsockopt should have returned EINVAL");
374
375         free(addr);
376 }
377
378 static void test_filter_without_bind(void)
379 {
380         int fd1, fd2;
381
382         fprintf(stderr, "Testing filter add without bind...\n");
383         fd1 = socket(AF_INET, SOCK_DGRAM, 0);
384         if (fd1 < 0)
385                 error(1, errno, "failed to create socket 1");
386         fd2 = socket(AF_INET, SOCK_DGRAM, 0);
387         if (fd2 < 0)
388                 error(1, errno, "failed to create socket 2");
389
390         attach_ebpf(fd1, 10);
391         attach_cbpf(fd2, 10);
392
393         close(fd1);
394         close(fd2);
395 }
396
397
398 int main(void)
399 {
400         fprintf(stderr, "---- IPv4 UDP ----\n");
401         /* NOTE: UDP socket lookups traverse a different code path when there
402          * are > 10 sockets in a group.  Run the bpf test through both paths.
403          */
404         test_reuseport_ebpf((struct test_params) {
405                 .recv_family = AF_INET,
406                 .send_family = AF_INET,
407                 .protocol = SOCK_DGRAM,
408                 .recv_socks = 10,
409                 .recv_port = 8000,
410                 .send_port_min = 9000});
411         test_reuseport_ebpf((struct test_params) {
412                 .recv_family = AF_INET,
413                 .send_family = AF_INET,
414                 .protocol = SOCK_DGRAM,
415                 .recv_socks = 20,
416                 .recv_port = 8000,
417                 .send_port_min = 9000});
418         test_reuseport_cbpf((struct test_params) {
419                 .recv_family = AF_INET,
420                 .send_family = AF_INET,
421                 .protocol = SOCK_DGRAM,
422                 .recv_socks = 10,
423                 .recv_port = 8001,
424                 .send_port_min = 9020});
425         test_reuseport_cbpf((struct test_params) {
426                 .recv_family = AF_INET,
427                 .send_family = AF_INET,
428                 .protocol = SOCK_DGRAM,
429                 .recv_socks = 20,
430                 .recv_port = 8001,
431                 .send_port_min = 9020});
432         test_extra_filter((struct test_params) {
433                 .recv_family = AF_INET,
434                 .protocol = SOCK_DGRAM,
435                 .recv_port = 8002});
436         test_filter_no_reuseport((struct test_params) {
437                 .recv_family = AF_INET,
438                 .protocol = SOCK_DGRAM,
439                 .recv_port = 8008});
440
441         fprintf(stderr, "---- IPv6 UDP ----\n");
442         test_reuseport_ebpf((struct test_params) {
443                 .recv_family = AF_INET6,
444                 .send_family = AF_INET6,
445                 .protocol = SOCK_DGRAM,
446                 .recv_socks = 10,
447                 .recv_port = 8003,
448                 .send_port_min = 9040});
449         test_reuseport_ebpf((struct test_params) {
450                 .recv_family = AF_INET6,
451                 .send_family = AF_INET6,
452                 .protocol = SOCK_DGRAM,
453                 .recv_socks = 20,
454                 .recv_port = 8003,
455                 .send_port_min = 9040});
456         test_reuseport_cbpf((struct test_params) {
457                 .recv_family = AF_INET6,
458                 .send_family = AF_INET6,
459                 .protocol = SOCK_DGRAM,
460                 .recv_socks = 10,
461                 .recv_port = 8004,
462                 .send_port_min = 9060});
463         test_reuseport_cbpf((struct test_params) {
464                 .recv_family = AF_INET6,
465                 .send_family = AF_INET6,
466                 .protocol = SOCK_DGRAM,
467                 .recv_socks = 20,
468                 .recv_port = 8004,
469                 .send_port_min = 9060});
470         test_extra_filter((struct test_params) {
471                 .recv_family = AF_INET6,
472                 .protocol = SOCK_DGRAM,
473                 .recv_port = 8005});
474         test_filter_no_reuseport((struct test_params) {
475                 .recv_family = AF_INET6,
476                 .protocol = SOCK_DGRAM,
477                 .recv_port = 8009});
478
479         fprintf(stderr, "---- IPv6 UDP w/ mapped IPv4 ----\n");
480         test_reuseport_ebpf((struct test_params) {
481                 .recv_family = AF_INET6,
482                 .send_family = AF_INET,
483                 .protocol = SOCK_DGRAM,
484                 .recv_socks = 20,
485                 .recv_port = 8006,
486                 .send_port_min = 9080});
487         test_reuseport_ebpf((struct test_params) {
488                 .recv_family = AF_INET6,
489                 .send_family = AF_INET,
490                 .protocol = SOCK_DGRAM,
491                 .recv_socks = 10,
492                 .recv_port = 8006,
493                 .send_port_min = 9080});
494         test_reuseport_cbpf((struct test_params) {
495                 .recv_family = AF_INET6,
496                 .send_family = AF_INET,
497                 .protocol = SOCK_DGRAM,
498                 .recv_socks = 10,
499                 .recv_port = 8007,
500                 .send_port_min = 9100});
501         test_reuseport_cbpf((struct test_params) {
502                 .recv_family = AF_INET6,
503                 .send_family = AF_INET,
504                 .protocol = SOCK_DGRAM,
505                 .recv_socks = 20,
506                 .recv_port = 8007,
507                 .send_port_min = 9100});
508
509
510         test_filter_without_bind();
511
512         fprintf(stderr, "SUCCESS\n");
513         return 0;
514 }