]> Git Repo - J-linux.git/blob - tools/testing/selftests/bpf/prog_tests/tc_netkit.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / tools / testing / selftests / bpf / prog_tests / tc_netkit.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2023 Isovalent */
3 #include <uapi/linux/if_link.h>
4 #include <net/if.h>
5 #include <test_progs.h>
6
7 #define netkit_peer "nk0"
8 #define netkit_name "nk1"
9
10 #define ping_addr_neigh         0x0a000002 /* 10.0.0.2 */
11 #define ping_addr_noneigh       0x0a000003 /* 10.0.0.3 */
12
13 #include "test_tc_link.skel.h"
14 #include "netlink_helpers.h"
15 #include "tc_helpers.h"
16
17 #define MARK            42
18 #define PRIO            0xeb9f
19 #define ICMP_ECHO       8
20
21 struct icmphdr {
22         __u8            type;
23         __u8            code;
24         __sum16         checksum;
25         struct {
26                 __be16  id;
27                 __be16  sequence;
28         } echo;
29 };
30
31 struct iplink_req {
32         struct nlmsghdr  n;
33         struct ifinfomsg i;
34         char             buf[1024];
35 };
36
37 static int create_netkit(int mode, int policy, int peer_policy, int *ifindex,
38                          bool same_netns, int scrub, int peer_scrub)
39 {
40         struct rtnl_handle rth = { .fd = -1 };
41         struct iplink_req req = {};
42         struct rtattr *linkinfo, *data;
43         const char *type = "netkit";
44         int err;
45
46         err = rtnl_open(&rth, 0);
47         if (!ASSERT_OK(err, "open_rtnetlink"))
48                 return err;
49
50         memset(&req, 0, sizeof(req));
51         req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
52         req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
53         req.n.nlmsg_type = RTM_NEWLINK;
54         req.i.ifi_family = AF_UNSPEC;
55
56         addattr_l(&req.n, sizeof(req), IFLA_IFNAME, netkit_name,
57                   strlen(netkit_name));
58         linkinfo = addattr_nest(&req.n, sizeof(req), IFLA_LINKINFO);
59         addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type, strlen(type));
60         data = addattr_nest(&req.n, sizeof(req), IFLA_INFO_DATA);
61         addattr32(&req.n, sizeof(req), IFLA_NETKIT_POLICY, policy);
62         addattr32(&req.n, sizeof(req), IFLA_NETKIT_PEER_POLICY, peer_policy);
63         addattr32(&req.n, sizeof(req), IFLA_NETKIT_SCRUB, scrub);
64         addattr32(&req.n, sizeof(req), IFLA_NETKIT_PEER_SCRUB, peer_scrub);
65         addattr32(&req.n, sizeof(req), IFLA_NETKIT_MODE, mode);
66         addattr_nest_end(&req.n, data);
67         addattr_nest_end(&req.n, linkinfo);
68
69         err = rtnl_talk(&rth, &req.n, NULL);
70         ASSERT_OK(err, "talk_rtnetlink");
71         rtnl_close(&rth);
72         *ifindex = if_nametoindex(netkit_name);
73
74         ASSERT_GT(*ifindex, 0, "retrieve_ifindex");
75         ASSERT_OK(system("ip netns add foo"), "create netns");
76         ASSERT_OK(system("ip link set dev " netkit_name " up"),
77                          "up primary");
78         ASSERT_OK(system("ip addr add dev " netkit_name " 10.0.0.1/24"),
79                          "addr primary");
80
81         if (mode == NETKIT_L3) {
82                 ASSERT_EQ(system("ip link set dev " netkit_name
83                                  " addr ee:ff:bb:cc:aa:dd 2> /dev/null"), 512,
84                                  "set hwaddress");
85         } else {
86                 ASSERT_OK(system("ip link set dev " netkit_name
87                                  " addr ee:ff:bb:cc:aa:dd"),
88                                  "set hwaddress");
89         }
90         if (same_netns) {
91                 ASSERT_OK(system("ip link set dev " netkit_peer " up"),
92                                  "up peer");
93                 ASSERT_OK(system("ip addr add dev " netkit_peer " 10.0.0.2/24"),
94                                  "addr peer");
95         } else {
96                 ASSERT_OK(system("ip link set " netkit_peer " netns foo"),
97                                  "move peer");
98                 ASSERT_OK(system("ip netns exec foo ip link set dev "
99                                  netkit_peer " up"), "up peer");
100                 ASSERT_OK(system("ip netns exec foo ip addr add dev "
101                                  netkit_peer " 10.0.0.2/24"), "addr peer");
102         }
103         return err;
104 }
105
106 static void move_netkit(void)
107 {
108         ASSERT_OK(system("ip link set " netkit_peer " netns foo"),
109                          "move peer");
110         ASSERT_OK(system("ip netns exec foo ip link set dev "
111                          netkit_peer " up"), "up peer");
112         ASSERT_OK(system("ip netns exec foo ip addr add dev "
113                          netkit_peer " 10.0.0.2/24"), "addr peer");
114 }
115
116 static void destroy_netkit(void)
117 {
118         ASSERT_OK(system("ip link del dev " netkit_name), "del primary");
119         ASSERT_OK(system("ip netns del foo"), "delete netns");
120         ASSERT_EQ(if_nametoindex(netkit_name), 0, netkit_name "_ifindex");
121 }
122
123 static int __send_icmp(__u32 dest)
124 {
125         int sock, ret, mark = MARK, prio = PRIO;
126         struct sockaddr_in addr;
127         struct icmphdr icmp;
128
129         ret = write_sysctl("/proc/sys/net/ipv4/ping_group_range", "0 0");
130         if (!ASSERT_OK(ret, "write_sysctl(net.ipv4.ping_group_range)"))
131                 return ret;
132
133         sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
134         if (!ASSERT_GE(sock, 0, "icmp_socket"))
135                 return -errno;
136
137         ret = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
138                          netkit_name, strlen(netkit_name) + 1);
139         if (!ASSERT_OK(ret, "setsockopt(SO_BINDTODEVICE)"))
140                 goto out;
141
142         ret = setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark));
143         if (!ASSERT_OK(ret, "setsockopt(SO_MARK)"))
144                 goto out;
145
146         ret = setsockopt(sock, SOL_SOCKET, SO_PRIORITY,
147                          &prio, sizeof(prio));
148         if (!ASSERT_OK(ret, "setsockopt(SO_PRIORITY)"))
149                 goto out;
150
151         memset(&addr, 0, sizeof(addr));
152         addr.sin_family = AF_INET;
153         addr.sin_addr.s_addr = htonl(dest);
154
155         memset(&icmp, 0, sizeof(icmp));
156         icmp.type = ICMP_ECHO;
157         icmp.echo.id = 1234;
158         icmp.echo.sequence = 1;
159
160         ret = sendto(sock, &icmp, sizeof(icmp), 0,
161                      (struct sockaddr *)&addr, sizeof(addr));
162         if (!ASSERT_GE(ret, 0, "icmp_sendto"))
163                 ret = -errno;
164         else
165                 ret = 0;
166 out:
167         close(sock);
168         return ret;
169 }
170
171 static int send_icmp(void)
172 {
173         return __send_icmp(ping_addr_neigh);
174 }
175
176 void serial_test_tc_netkit_basic(void)
177 {
178         LIBBPF_OPTS(bpf_prog_query_opts, optq);
179         LIBBPF_OPTS(bpf_netkit_opts, optl);
180         __u32 prog_ids[2], link_ids[2];
181         __u32 pid1, pid2, lid1, lid2;
182         struct test_tc_link *skel;
183         struct bpf_link *link;
184         int err, ifindex;
185
186         err = create_netkit(NETKIT_L2, NETKIT_PASS, NETKIT_PASS,
187                             &ifindex, false, NETKIT_SCRUB_DEFAULT,
188                             NETKIT_SCRUB_DEFAULT);
189         if (err)
190                 return;
191
192         skel = test_tc_link__open();
193         if (!ASSERT_OK_PTR(skel, "skel_open"))
194                 goto cleanup;
195
196         ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1,
197                   BPF_NETKIT_PRIMARY), 0, "tc1_attach_type");
198         ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc2,
199                   BPF_NETKIT_PEER), 0, "tc2_attach_type");
200
201         err = test_tc_link__load(skel);
202         if (!ASSERT_OK(err, "skel_load"))
203                 goto cleanup;
204
205         pid1 = id_from_prog_fd(bpf_program__fd(skel->progs.tc1));
206         pid2 = id_from_prog_fd(bpf_program__fd(skel->progs.tc2));
207
208         ASSERT_NEQ(pid1, pid2, "prog_ids_1_2");
209
210         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
211         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
212
213         ASSERT_EQ(skel->bss->seen_tc1, false, "seen_tc1");
214         ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
215
216         link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl);
217         if (!ASSERT_OK_PTR(link, "link_attach"))
218                 goto cleanup;
219
220         skel->links.tc1 = link;
221
222         lid1 = id_from_link_fd(bpf_link__fd(skel->links.tc1));
223
224         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
225         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
226
227         optq.prog_ids = prog_ids;
228         optq.link_ids = link_ids;
229
230         memset(prog_ids, 0, sizeof(prog_ids));
231         memset(link_ids, 0, sizeof(link_ids));
232         optq.count = ARRAY_SIZE(prog_ids);
233
234         err = bpf_prog_query_opts(ifindex, BPF_NETKIT_PRIMARY, &optq);
235         if (!ASSERT_OK(err, "prog_query"))
236                 goto cleanup;
237
238         ASSERT_EQ(optq.count, 1, "count");
239         ASSERT_EQ(optq.revision, 2, "revision");
240         ASSERT_EQ(optq.prog_ids[0], pid1, "prog_ids[0]");
241         ASSERT_EQ(optq.link_ids[0], lid1, "link_ids[0]");
242         ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
243         ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]");
244
245         tc_skel_reset_all_seen(skel);
246         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
247
248         ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
249         ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
250
251         link = bpf_program__attach_netkit(skel->progs.tc2, ifindex, &optl);
252         if (!ASSERT_OK_PTR(link, "link_attach"))
253                 goto cleanup;
254
255         skel->links.tc2 = link;
256
257         lid2 = id_from_link_fd(bpf_link__fd(skel->links.tc2));
258         ASSERT_NEQ(lid1, lid2, "link_ids_1_2");
259
260         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
261         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 1);
262
263         memset(prog_ids, 0, sizeof(prog_ids));
264         memset(link_ids, 0, sizeof(link_ids));
265         optq.count = ARRAY_SIZE(prog_ids);
266
267         err = bpf_prog_query_opts(ifindex, BPF_NETKIT_PEER, &optq);
268         if (!ASSERT_OK(err, "prog_query"))
269                 goto cleanup;
270
271         ASSERT_EQ(optq.count, 1, "count");
272         ASSERT_EQ(optq.revision, 2, "revision");
273         ASSERT_EQ(optq.prog_ids[0], pid2, "prog_ids[0]");
274         ASSERT_EQ(optq.link_ids[0], lid2, "link_ids[0]");
275         ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
276         ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]");
277
278         tc_skel_reset_all_seen(skel);
279         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
280
281         ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
282         ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
283 cleanup:
284         test_tc_link__destroy(skel);
285
286         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
287         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
288         destroy_netkit();
289 }
290
291 static void serial_test_tc_netkit_multi_links_target(int mode, int target)
292 {
293         LIBBPF_OPTS(bpf_prog_query_opts, optq);
294         LIBBPF_OPTS(bpf_netkit_opts, optl);
295         __u32 prog_ids[3], link_ids[3];
296         __u32 pid1, pid2, lid1, lid2;
297         struct test_tc_link *skel;
298         struct bpf_link *link;
299         int err, ifindex;
300
301         err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
302                             &ifindex, false, NETKIT_SCRUB_DEFAULT,
303                             NETKIT_SCRUB_DEFAULT);
304         if (err)
305                 return;
306
307         skel = test_tc_link__open();
308         if (!ASSERT_OK_PTR(skel, "skel_open"))
309                 goto cleanup;
310
311         ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1,
312                   target), 0, "tc1_attach_type");
313         ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc2,
314                   target), 0, "tc2_attach_type");
315
316         err = test_tc_link__load(skel);
317         if (!ASSERT_OK(err, "skel_load"))
318                 goto cleanup;
319
320         pid1 = id_from_prog_fd(bpf_program__fd(skel->progs.tc1));
321         pid2 = id_from_prog_fd(bpf_program__fd(skel->progs.tc2));
322
323         ASSERT_NEQ(pid1, pid2, "prog_ids_1_2");
324
325         assert_mprog_count_ifindex(ifindex, target, 0);
326
327         ASSERT_EQ(skel->bss->seen_tc1, false, "seen_tc1");
328         ASSERT_EQ(skel->bss->seen_eth, false, "seen_eth");
329         ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
330
331         link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl);
332         if (!ASSERT_OK_PTR(link, "link_attach"))
333                 goto cleanup;
334
335         skel->links.tc1 = link;
336
337         lid1 = id_from_link_fd(bpf_link__fd(skel->links.tc1));
338
339         assert_mprog_count_ifindex(ifindex, target, 1);
340
341         optq.prog_ids = prog_ids;
342         optq.link_ids = link_ids;
343
344         memset(prog_ids, 0, sizeof(prog_ids));
345         memset(link_ids, 0, sizeof(link_ids));
346         optq.count = ARRAY_SIZE(prog_ids);
347
348         err = bpf_prog_query_opts(ifindex, target, &optq);
349         if (!ASSERT_OK(err, "prog_query"))
350                 goto cleanup;
351
352         ASSERT_EQ(optq.count, 1, "count");
353         ASSERT_EQ(optq.revision, 2, "revision");
354         ASSERT_EQ(optq.prog_ids[0], pid1, "prog_ids[0]");
355         ASSERT_EQ(optq.link_ids[0], lid1, "link_ids[0]");
356         ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
357         ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]");
358
359         tc_skel_reset_all_seen(skel);
360         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
361
362         ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
363         ASSERT_EQ(skel->bss->seen_eth, true, "seen_eth");
364         ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
365
366         LIBBPF_OPTS_RESET(optl,
367                 .flags = BPF_F_BEFORE,
368                 .relative_fd = bpf_program__fd(skel->progs.tc1),
369         );
370
371         link = bpf_program__attach_netkit(skel->progs.tc2, ifindex, &optl);
372         if (!ASSERT_OK_PTR(link, "link_attach"))
373                 goto cleanup;
374
375         skel->links.tc2 = link;
376
377         lid2 = id_from_link_fd(bpf_link__fd(skel->links.tc2));
378         ASSERT_NEQ(lid1, lid2, "link_ids_1_2");
379
380         assert_mprog_count_ifindex(ifindex, target, 2);
381
382         memset(prog_ids, 0, sizeof(prog_ids));
383         memset(link_ids, 0, sizeof(link_ids));
384         optq.count = ARRAY_SIZE(prog_ids);
385
386         err = bpf_prog_query_opts(ifindex, target, &optq);
387         if (!ASSERT_OK(err, "prog_query"))
388                 goto cleanup;
389
390         ASSERT_EQ(optq.count, 2, "count");
391         ASSERT_EQ(optq.revision, 3, "revision");
392         ASSERT_EQ(optq.prog_ids[0], pid2, "prog_ids[0]");
393         ASSERT_EQ(optq.link_ids[0], lid2, "link_ids[0]");
394         ASSERT_EQ(optq.prog_ids[1], pid1, "prog_ids[1]");
395         ASSERT_EQ(optq.link_ids[1], lid1, "link_ids[1]");
396         ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
397         ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]");
398
399         tc_skel_reset_all_seen(skel);
400         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
401
402         ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
403         ASSERT_EQ(skel->bss->seen_eth, true, "seen_eth");
404         ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
405 cleanup:
406         test_tc_link__destroy(skel);
407
408         assert_mprog_count_ifindex(ifindex, target, 0);
409         destroy_netkit();
410 }
411
412 void serial_test_tc_netkit_multi_links(void)
413 {
414         serial_test_tc_netkit_multi_links_target(NETKIT_L2, BPF_NETKIT_PRIMARY);
415         serial_test_tc_netkit_multi_links_target(NETKIT_L3, BPF_NETKIT_PRIMARY);
416         serial_test_tc_netkit_multi_links_target(NETKIT_L2, BPF_NETKIT_PEER);
417         serial_test_tc_netkit_multi_links_target(NETKIT_L3, BPF_NETKIT_PEER);
418 }
419
420 static void serial_test_tc_netkit_multi_opts_target(int mode, int target)
421 {
422         LIBBPF_OPTS(bpf_prog_attach_opts, opta);
423         LIBBPF_OPTS(bpf_prog_detach_opts, optd);
424         LIBBPF_OPTS(bpf_prog_query_opts, optq);
425         __u32 pid1, pid2, fd1, fd2;
426         __u32 prog_ids[3];
427         struct test_tc_link *skel;
428         int err, ifindex;
429
430         err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
431                             &ifindex, false, NETKIT_SCRUB_DEFAULT,
432                             NETKIT_SCRUB_DEFAULT);
433         if (err)
434                 return;
435
436         skel = test_tc_link__open_and_load();
437         if (!ASSERT_OK_PTR(skel, "skel_load"))
438                 goto cleanup;
439
440         fd1 = bpf_program__fd(skel->progs.tc1);
441         fd2 = bpf_program__fd(skel->progs.tc2);
442
443         pid1 = id_from_prog_fd(fd1);
444         pid2 = id_from_prog_fd(fd2);
445
446         ASSERT_NEQ(pid1, pid2, "prog_ids_1_2");
447
448         assert_mprog_count_ifindex(ifindex, target, 0);
449
450         ASSERT_EQ(skel->bss->seen_tc1, false, "seen_tc1");
451         ASSERT_EQ(skel->bss->seen_eth, false, "seen_eth");
452         ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
453
454         err = bpf_prog_attach_opts(fd1, ifindex, target, &opta);
455         if (!ASSERT_EQ(err, 0, "prog_attach"))
456                 goto cleanup;
457
458         assert_mprog_count_ifindex(ifindex, target, 1);
459
460         optq.prog_ids = prog_ids;
461
462         memset(prog_ids, 0, sizeof(prog_ids));
463         optq.count = ARRAY_SIZE(prog_ids);
464
465         err = bpf_prog_query_opts(ifindex, target, &optq);
466         if (!ASSERT_OK(err, "prog_query"))
467                 goto cleanup_fd1;
468
469         ASSERT_EQ(optq.count, 1, "count");
470         ASSERT_EQ(optq.revision, 2, "revision");
471         ASSERT_EQ(optq.prog_ids[0], pid1, "prog_ids[0]");
472         ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
473
474         tc_skel_reset_all_seen(skel);
475         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
476
477         ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
478         ASSERT_EQ(skel->bss->seen_eth, true, "seen_eth");
479         ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
480
481         LIBBPF_OPTS_RESET(opta,
482                 .flags = BPF_F_BEFORE,
483                 .relative_fd = fd1,
484         );
485
486         err = bpf_prog_attach_opts(fd2, ifindex, target, &opta);
487         if (!ASSERT_EQ(err, 0, "prog_attach"))
488                 goto cleanup_fd1;
489
490         assert_mprog_count_ifindex(ifindex, target, 2);
491
492         memset(prog_ids, 0, sizeof(prog_ids));
493         optq.count = ARRAY_SIZE(prog_ids);
494
495         err = bpf_prog_query_opts(ifindex, target, &optq);
496         if (!ASSERT_OK(err, "prog_query"))
497                 goto cleanup_fd2;
498
499         ASSERT_EQ(optq.count, 2, "count");
500         ASSERT_EQ(optq.revision, 3, "revision");
501         ASSERT_EQ(optq.prog_ids[0], pid2, "prog_ids[0]");
502         ASSERT_EQ(optq.prog_ids[1], pid1, "prog_ids[1]");
503         ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
504
505         tc_skel_reset_all_seen(skel);
506         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
507
508         ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
509         ASSERT_EQ(skel->bss->seen_eth, true, "seen_eth");
510         ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
511
512 cleanup_fd2:
513         err = bpf_prog_detach_opts(fd2, ifindex, target, &optd);
514         ASSERT_OK(err, "prog_detach");
515         assert_mprog_count_ifindex(ifindex, target, 1);
516 cleanup_fd1:
517         err = bpf_prog_detach_opts(fd1, ifindex, target, &optd);
518         ASSERT_OK(err, "prog_detach");
519         assert_mprog_count_ifindex(ifindex, target, 0);
520 cleanup:
521         test_tc_link__destroy(skel);
522
523         assert_mprog_count_ifindex(ifindex, target, 0);
524         destroy_netkit();
525 }
526
527 void serial_test_tc_netkit_multi_opts(void)
528 {
529         serial_test_tc_netkit_multi_opts_target(NETKIT_L2, BPF_NETKIT_PRIMARY);
530         serial_test_tc_netkit_multi_opts_target(NETKIT_L3, BPF_NETKIT_PRIMARY);
531         serial_test_tc_netkit_multi_opts_target(NETKIT_L2, BPF_NETKIT_PEER);
532         serial_test_tc_netkit_multi_opts_target(NETKIT_L3, BPF_NETKIT_PEER);
533 }
534
535 void serial_test_tc_netkit_device(void)
536 {
537         LIBBPF_OPTS(bpf_prog_query_opts, optq);
538         LIBBPF_OPTS(bpf_netkit_opts, optl);
539         __u32 prog_ids[2], link_ids[2];
540         __u32 pid1, pid2, lid1;
541         struct test_tc_link *skel;
542         struct bpf_link *link;
543         int err, ifindex, ifindex2;
544
545         err = create_netkit(NETKIT_L3, NETKIT_PASS, NETKIT_PASS,
546                             &ifindex, true, NETKIT_SCRUB_DEFAULT,
547                             NETKIT_SCRUB_DEFAULT);
548         if (err)
549                 return;
550
551         ifindex2 = if_nametoindex(netkit_peer);
552         ASSERT_NEQ(ifindex, ifindex2, "ifindex_1_2");
553
554         skel = test_tc_link__open();
555         if (!ASSERT_OK_PTR(skel, "skel_open"))
556                 goto cleanup;
557
558         ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1,
559                   BPF_NETKIT_PRIMARY), 0, "tc1_attach_type");
560         ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc2,
561                   BPF_NETKIT_PEER), 0, "tc2_attach_type");
562         ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc3,
563                   BPF_NETKIT_PRIMARY), 0, "tc3_attach_type");
564
565         err = test_tc_link__load(skel);
566         if (!ASSERT_OK(err, "skel_load"))
567                 goto cleanup;
568
569         pid1 = id_from_prog_fd(bpf_program__fd(skel->progs.tc1));
570         pid2 = id_from_prog_fd(bpf_program__fd(skel->progs.tc2));
571
572         ASSERT_NEQ(pid1, pid2, "prog_ids_1_2");
573
574         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
575         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
576
577         ASSERT_EQ(skel->bss->seen_tc1, false, "seen_tc1");
578         ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
579
580         link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl);
581         if (!ASSERT_OK_PTR(link, "link_attach"))
582                 goto cleanup;
583
584         skel->links.tc1 = link;
585
586         lid1 = id_from_link_fd(bpf_link__fd(skel->links.tc1));
587
588         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
589         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
590
591         optq.prog_ids = prog_ids;
592         optq.link_ids = link_ids;
593
594         memset(prog_ids, 0, sizeof(prog_ids));
595         memset(link_ids, 0, sizeof(link_ids));
596         optq.count = ARRAY_SIZE(prog_ids);
597
598         err = bpf_prog_query_opts(ifindex, BPF_NETKIT_PRIMARY, &optq);
599         if (!ASSERT_OK(err, "prog_query"))
600                 goto cleanup;
601
602         ASSERT_EQ(optq.count, 1, "count");
603         ASSERT_EQ(optq.revision, 2, "revision");
604         ASSERT_EQ(optq.prog_ids[0], pid1, "prog_ids[0]");
605         ASSERT_EQ(optq.link_ids[0], lid1, "link_ids[0]");
606         ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
607         ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]");
608
609         tc_skel_reset_all_seen(skel);
610         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
611
612         ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
613         ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
614
615         memset(prog_ids, 0, sizeof(prog_ids));
616         memset(link_ids, 0, sizeof(link_ids));
617         optq.count = ARRAY_SIZE(prog_ids);
618
619         err = bpf_prog_query_opts(ifindex2, BPF_NETKIT_PRIMARY, &optq);
620         ASSERT_EQ(err, -EACCES, "prog_query_should_fail");
621
622         err = bpf_prog_query_opts(ifindex2, BPF_NETKIT_PEER, &optq);
623         ASSERT_EQ(err, -EACCES, "prog_query_should_fail");
624
625         link = bpf_program__attach_netkit(skel->progs.tc2, ifindex2, &optl);
626         if (!ASSERT_ERR_PTR(link, "link_attach_should_fail")) {
627                 bpf_link__destroy(link);
628                 goto cleanup;
629         }
630
631         link = bpf_program__attach_netkit(skel->progs.tc3, ifindex2, &optl);
632         if (!ASSERT_ERR_PTR(link, "link_attach_should_fail")) {
633                 bpf_link__destroy(link);
634                 goto cleanup;
635         }
636
637         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
638         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
639 cleanup:
640         test_tc_link__destroy(skel);
641
642         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
643         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
644         destroy_netkit();
645 }
646
647 static void serial_test_tc_netkit_neigh_links_target(int mode, int target)
648 {
649         LIBBPF_OPTS(bpf_prog_query_opts, optq);
650         LIBBPF_OPTS(bpf_netkit_opts, optl);
651         __u32 prog_ids[2], link_ids[2];
652         __u32 pid1, lid1;
653         struct test_tc_link *skel;
654         struct bpf_link *link;
655         int err, ifindex;
656
657         err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
658                             &ifindex, false, NETKIT_SCRUB_DEFAULT,
659                             NETKIT_SCRUB_DEFAULT);
660         if (err)
661                 return;
662
663         skel = test_tc_link__open();
664         if (!ASSERT_OK_PTR(skel, "skel_open"))
665                 goto cleanup;
666
667         ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1,
668                   BPF_NETKIT_PRIMARY), 0, "tc1_attach_type");
669
670         err = test_tc_link__load(skel);
671         if (!ASSERT_OK(err, "skel_load"))
672                 goto cleanup;
673
674         pid1 = id_from_prog_fd(bpf_program__fd(skel->progs.tc1));
675
676         assert_mprog_count_ifindex(ifindex, target, 0);
677
678         ASSERT_EQ(skel->bss->seen_tc1, false, "seen_tc1");
679         ASSERT_EQ(skel->bss->seen_eth, false, "seen_eth");
680
681         link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl);
682         if (!ASSERT_OK_PTR(link, "link_attach"))
683                 goto cleanup;
684
685         skel->links.tc1 = link;
686
687         lid1 = id_from_link_fd(bpf_link__fd(skel->links.tc1));
688
689         assert_mprog_count_ifindex(ifindex, target, 1);
690
691         optq.prog_ids = prog_ids;
692         optq.link_ids = link_ids;
693
694         memset(prog_ids, 0, sizeof(prog_ids));
695         memset(link_ids, 0, sizeof(link_ids));
696         optq.count = ARRAY_SIZE(prog_ids);
697
698         err = bpf_prog_query_opts(ifindex, target, &optq);
699         if (!ASSERT_OK(err, "prog_query"))
700                 goto cleanup;
701
702         ASSERT_EQ(optq.count, 1, "count");
703         ASSERT_EQ(optq.revision, 2, "revision");
704         ASSERT_EQ(optq.prog_ids[0], pid1, "prog_ids[0]");
705         ASSERT_EQ(optq.link_ids[0], lid1, "link_ids[0]");
706         ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
707         ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]");
708
709         tc_skel_reset_all_seen(skel);
710         ASSERT_EQ(__send_icmp(ping_addr_noneigh), 0, "icmp_pkt");
711
712         ASSERT_EQ(skel->bss->seen_tc1, true /* L2: ARP */, "seen_tc1");
713         ASSERT_EQ(skel->bss->seen_eth, mode == NETKIT_L3, "seen_eth");
714 cleanup:
715         test_tc_link__destroy(skel);
716
717         assert_mprog_count_ifindex(ifindex, target, 0);
718         destroy_netkit();
719 }
720
721 void serial_test_tc_netkit_neigh_links(void)
722 {
723         serial_test_tc_netkit_neigh_links_target(NETKIT_L2, BPF_NETKIT_PRIMARY);
724         serial_test_tc_netkit_neigh_links_target(NETKIT_L3, BPF_NETKIT_PRIMARY);
725 }
726
727 static void serial_test_tc_netkit_pkt_type_mode(int mode)
728 {
729         LIBBPF_OPTS(bpf_netkit_opts, optl_nk);
730         LIBBPF_OPTS(bpf_tcx_opts, optl_tcx);
731         int err, ifindex, ifindex2;
732         struct test_tc_link *skel;
733         struct bpf_link *link;
734
735         err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
736                             &ifindex, true, NETKIT_SCRUB_DEFAULT,
737                             NETKIT_SCRUB_DEFAULT);
738         if (err)
739                 return;
740
741         ifindex2 = if_nametoindex(netkit_peer);
742         ASSERT_NEQ(ifindex, ifindex2, "ifindex_1_2");
743
744         skel = test_tc_link__open();
745         if (!ASSERT_OK_PTR(skel, "skel_open"))
746                 goto cleanup;
747
748         ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1,
749                   BPF_NETKIT_PRIMARY), 0, "tc1_attach_type");
750         ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc7,
751                   BPF_TCX_INGRESS), 0, "tc7_attach_type");
752
753         err = test_tc_link__load(skel);
754         if (!ASSERT_OK(err, "skel_load"))
755                 goto cleanup;
756
757         assert_mprog_count_ifindex(ifindex,  BPF_NETKIT_PRIMARY, 0);
758         assert_mprog_count_ifindex(ifindex2, BPF_TCX_INGRESS, 0);
759
760         link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl_nk);
761         if (!ASSERT_OK_PTR(link, "link_attach"))
762                 goto cleanup;
763
764         skel->links.tc1 = link;
765
766         assert_mprog_count_ifindex(ifindex,  BPF_NETKIT_PRIMARY, 1);
767         assert_mprog_count_ifindex(ifindex2, BPF_TCX_INGRESS, 0);
768
769         link = bpf_program__attach_tcx(skel->progs.tc7, ifindex2, &optl_tcx);
770         if (!ASSERT_OK_PTR(link, "link_attach"))
771                 goto cleanup;
772
773         skel->links.tc7 = link;
774
775         assert_mprog_count_ifindex(ifindex,  BPF_NETKIT_PRIMARY, 1);
776         assert_mprog_count_ifindex(ifindex2, BPF_TCX_INGRESS, 1);
777
778         move_netkit();
779
780         tc_skel_reset_all_seen(skel);
781         skel->bss->set_type = true;
782         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
783
784         ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
785         ASSERT_EQ(skel->bss->seen_tc7, true, "seen_tc7");
786
787         ASSERT_EQ(skel->bss->seen_host,  true, "seen_host");
788         ASSERT_EQ(skel->bss->seen_mcast, true, "seen_mcast");
789 cleanup:
790         test_tc_link__destroy(skel);
791
792         assert_mprog_count_ifindex(ifindex,  BPF_NETKIT_PRIMARY, 0);
793         destroy_netkit();
794 }
795
796 void serial_test_tc_netkit_pkt_type(void)
797 {
798         serial_test_tc_netkit_pkt_type_mode(NETKIT_L2);
799         serial_test_tc_netkit_pkt_type_mode(NETKIT_L3);
800 }
801
802 static void serial_test_tc_netkit_scrub_type(int scrub)
803 {
804         LIBBPF_OPTS(bpf_netkit_opts, optl);
805         struct test_tc_link *skel;
806         struct bpf_link *link;
807         int err, ifindex;
808
809         err = create_netkit(NETKIT_L2, NETKIT_PASS, NETKIT_PASS,
810                             &ifindex, false, scrub, scrub);
811         if (err)
812                 return;
813
814         skel = test_tc_link__open();
815         if (!ASSERT_OK_PTR(skel, "skel_open"))
816                 goto cleanup;
817
818         ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc8,
819                   BPF_NETKIT_PRIMARY), 0, "tc8_attach_type");
820
821         err = test_tc_link__load(skel);
822         if (!ASSERT_OK(err, "skel_load"))
823                 goto cleanup;
824
825         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
826         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
827
828         ASSERT_EQ(skel->bss->seen_tc8, false, "seen_tc8");
829
830         link = bpf_program__attach_netkit(skel->progs.tc8, ifindex, &optl);
831         if (!ASSERT_OK_PTR(link, "link_attach"))
832                 goto cleanup;
833
834         skel->links.tc8 = link;
835
836         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
837         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
838
839         tc_skel_reset_all_seen(skel);
840         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
841
842         ASSERT_EQ(skel->bss->seen_tc8, true, "seen_tc8");
843         ASSERT_EQ(skel->bss->mark, scrub == NETKIT_SCRUB_NONE ? MARK : 0, "mark");
844         ASSERT_EQ(skel->bss->prio, scrub == NETKIT_SCRUB_NONE ? PRIO : 0, "prio");
845 cleanup:
846         test_tc_link__destroy(skel);
847
848         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
849         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
850         destroy_netkit();
851 }
852
853 void serial_test_tc_netkit_scrub(void)
854 {
855         serial_test_tc_netkit_scrub_type(NETKIT_SCRUB_DEFAULT);
856         serial_test_tc_netkit_scrub_type(NETKIT_SCRUB_NONE);
857 }
This page took 0.076572 seconds and 4 git commands to generate.