1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2023 Isovalent */
3 #include <uapi/linux/if_link.h>
5 #include <test_progs.h>
7 #define netkit_peer "nk0"
8 #define netkit_name "nk1"
10 #define ping_addr_neigh 0x0a000002 /* 10.0.0.2 */
11 #define ping_addr_noneigh 0x0a000003 /* 10.0.0.3 */
13 #include "test_tc_link.skel.h"
14 #include "netlink_helpers.h"
15 #include "tc_helpers.h"
17 #define NETKIT_HEADROOM 32
18 #define NETKIT_TAILROOM 8
24 #define FLAG_ADJUST_ROOM (1 << 0)
25 #define FLAG_SAME_NETNS (1 << 1)
43 static int create_netkit(int mode, int policy, int peer_policy, int *ifindex,
44 int scrub, int peer_scrub, __u32 flags)
46 struct rtnl_handle rth = { .fd = -1 };
47 struct iplink_req req = {};
48 struct rtattr *linkinfo, *data;
49 const char *type = "netkit";
52 err = rtnl_open(&rth, 0);
53 if (!ASSERT_OK(err, "open_rtnetlink"))
56 memset(&req, 0, sizeof(req));
57 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
58 req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
59 req.n.nlmsg_type = RTM_NEWLINK;
60 req.i.ifi_family = AF_UNSPEC;
62 addattr_l(&req.n, sizeof(req), IFLA_IFNAME, netkit_name,
64 linkinfo = addattr_nest(&req.n, sizeof(req), IFLA_LINKINFO);
65 addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, type, strlen(type));
66 data = addattr_nest(&req.n, sizeof(req), IFLA_INFO_DATA);
67 addattr32(&req.n, sizeof(req), IFLA_NETKIT_POLICY, policy);
68 addattr32(&req.n, sizeof(req), IFLA_NETKIT_PEER_POLICY, peer_policy);
69 addattr32(&req.n, sizeof(req), IFLA_NETKIT_SCRUB, scrub);
70 addattr32(&req.n, sizeof(req), IFLA_NETKIT_PEER_SCRUB, peer_scrub);
71 addattr32(&req.n, sizeof(req), IFLA_NETKIT_MODE, mode);
72 if (flags & FLAG_ADJUST_ROOM) {
73 addattr16(&req.n, sizeof(req), IFLA_NETKIT_HEADROOM, NETKIT_HEADROOM);
74 addattr16(&req.n, sizeof(req), IFLA_NETKIT_TAILROOM, NETKIT_TAILROOM);
76 addattr_nest_end(&req.n, data);
77 addattr_nest_end(&req.n, linkinfo);
79 err = rtnl_talk(&rth, &req.n, NULL);
80 ASSERT_OK(err, "talk_rtnetlink");
82 *ifindex = if_nametoindex(netkit_name);
84 ASSERT_GT(*ifindex, 0, "retrieve_ifindex");
85 ASSERT_OK(system("ip netns add foo"), "create netns");
86 ASSERT_OK(system("ip link set dev " netkit_name " up"),
88 ASSERT_OK(system("ip addr add dev " netkit_name " 10.0.0.1/24"),
91 if (mode == NETKIT_L3) {
92 ASSERT_EQ(system("ip link set dev " netkit_name
93 " addr ee:ff:bb:cc:aa:dd 2> /dev/null"), 512,
96 ASSERT_OK(system("ip link set dev " netkit_name
97 " addr ee:ff:bb:cc:aa:dd"),
100 if (flags & FLAG_SAME_NETNS) {
101 ASSERT_OK(system("ip link set dev " netkit_peer " up"),
103 ASSERT_OK(system("ip addr add dev " netkit_peer " 10.0.0.2/24"),
106 ASSERT_OK(system("ip link set " netkit_peer " netns foo"),
108 ASSERT_OK(system("ip netns exec foo ip link set dev "
109 netkit_peer " up"), "up peer");
110 ASSERT_OK(system("ip netns exec foo ip addr add dev "
111 netkit_peer " 10.0.0.2/24"), "addr peer");
116 static void move_netkit(void)
118 ASSERT_OK(system("ip link set " netkit_peer " netns foo"),
120 ASSERT_OK(system("ip netns exec foo ip link set dev "
121 netkit_peer " up"), "up peer");
122 ASSERT_OK(system("ip netns exec foo ip addr add dev "
123 netkit_peer " 10.0.0.2/24"), "addr peer");
126 static void destroy_netkit(void)
128 ASSERT_OK(system("ip link del dev " netkit_name), "del primary");
129 ASSERT_OK(system("ip netns del foo"), "delete netns");
130 ASSERT_EQ(if_nametoindex(netkit_name), 0, netkit_name "_ifindex");
133 static int __send_icmp(__u32 dest)
135 int sock, ret, mark = MARK, prio = PRIO;
136 struct sockaddr_in addr;
139 ret = write_sysctl("/proc/sys/net/ipv4/ping_group_range", "0 0");
140 if (!ASSERT_OK(ret, "write_sysctl(net.ipv4.ping_group_range)"))
143 sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
144 if (!ASSERT_GE(sock, 0, "icmp_socket"))
147 ret = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
148 netkit_name, strlen(netkit_name) + 1);
149 if (!ASSERT_OK(ret, "setsockopt(SO_BINDTODEVICE)"))
152 ret = setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark));
153 if (!ASSERT_OK(ret, "setsockopt(SO_MARK)"))
156 ret = setsockopt(sock, SOL_SOCKET, SO_PRIORITY,
157 &prio, sizeof(prio));
158 if (!ASSERT_OK(ret, "setsockopt(SO_PRIORITY)"))
161 memset(&addr, 0, sizeof(addr));
162 addr.sin_family = AF_INET;
163 addr.sin_addr.s_addr = htonl(dest);
165 memset(&icmp, 0, sizeof(icmp));
166 icmp.type = ICMP_ECHO;
168 icmp.echo.sequence = 1;
170 ret = sendto(sock, &icmp, sizeof(icmp), 0,
171 (struct sockaddr *)&addr, sizeof(addr));
172 if (!ASSERT_GE(ret, 0, "icmp_sendto"))
181 static int send_icmp(void)
183 return __send_icmp(ping_addr_neigh);
186 void serial_test_tc_netkit_basic(void)
188 LIBBPF_OPTS(bpf_prog_query_opts, optq);
189 LIBBPF_OPTS(bpf_netkit_opts, optl);
190 __u32 prog_ids[2], link_ids[2];
191 __u32 pid1, pid2, lid1, lid2;
192 struct test_tc_link *skel;
193 struct bpf_link *link;
196 err = create_netkit(NETKIT_L2, NETKIT_PASS, NETKIT_PASS,
197 &ifindex, NETKIT_SCRUB_DEFAULT,
198 NETKIT_SCRUB_DEFAULT, 0);
202 skel = test_tc_link__open();
203 if (!ASSERT_OK_PTR(skel, "skel_open"))
206 ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1,
207 BPF_NETKIT_PRIMARY), 0, "tc1_attach_type");
208 ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc2,
209 BPF_NETKIT_PEER), 0, "tc2_attach_type");
211 err = test_tc_link__load(skel);
212 if (!ASSERT_OK(err, "skel_load"))
215 pid1 = id_from_prog_fd(bpf_program__fd(skel->progs.tc1));
216 pid2 = id_from_prog_fd(bpf_program__fd(skel->progs.tc2));
218 ASSERT_NEQ(pid1, pid2, "prog_ids_1_2");
220 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
221 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
223 ASSERT_EQ(skel->bss->seen_tc1, false, "seen_tc1");
224 ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
226 link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl);
227 if (!ASSERT_OK_PTR(link, "link_attach"))
230 skel->links.tc1 = link;
232 lid1 = id_from_link_fd(bpf_link__fd(skel->links.tc1));
234 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
235 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
237 optq.prog_ids = prog_ids;
238 optq.link_ids = link_ids;
240 memset(prog_ids, 0, sizeof(prog_ids));
241 memset(link_ids, 0, sizeof(link_ids));
242 optq.count = ARRAY_SIZE(prog_ids);
244 err = bpf_prog_query_opts(ifindex, BPF_NETKIT_PRIMARY, &optq);
245 if (!ASSERT_OK(err, "prog_query"))
248 ASSERT_EQ(optq.count, 1, "count");
249 ASSERT_EQ(optq.revision, 2, "revision");
250 ASSERT_EQ(optq.prog_ids[0], pid1, "prog_ids[0]");
251 ASSERT_EQ(optq.link_ids[0], lid1, "link_ids[0]");
252 ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
253 ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]");
255 tc_skel_reset_all_seen(skel);
256 ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
258 ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
259 ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
261 link = bpf_program__attach_netkit(skel->progs.tc2, ifindex, &optl);
262 if (!ASSERT_OK_PTR(link, "link_attach"))
265 skel->links.tc2 = link;
267 lid2 = id_from_link_fd(bpf_link__fd(skel->links.tc2));
268 ASSERT_NEQ(lid1, lid2, "link_ids_1_2");
270 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
271 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 1);
273 memset(prog_ids, 0, sizeof(prog_ids));
274 memset(link_ids, 0, sizeof(link_ids));
275 optq.count = ARRAY_SIZE(prog_ids);
277 err = bpf_prog_query_opts(ifindex, BPF_NETKIT_PEER, &optq);
278 if (!ASSERT_OK(err, "prog_query"))
281 ASSERT_EQ(optq.count, 1, "count");
282 ASSERT_EQ(optq.revision, 2, "revision");
283 ASSERT_EQ(optq.prog_ids[0], pid2, "prog_ids[0]");
284 ASSERT_EQ(optq.link_ids[0], lid2, "link_ids[0]");
285 ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
286 ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]");
288 tc_skel_reset_all_seen(skel);
289 ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
291 ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
292 ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
294 test_tc_link__destroy(skel);
296 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
297 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
301 static void serial_test_tc_netkit_multi_links_target(int mode, int target)
303 LIBBPF_OPTS(bpf_prog_query_opts, optq);
304 LIBBPF_OPTS(bpf_netkit_opts, optl);
305 __u32 prog_ids[3], link_ids[3];
306 __u32 pid1, pid2, lid1, lid2;
307 struct test_tc_link *skel;
308 struct bpf_link *link;
311 err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
312 &ifindex, NETKIT_SCRUB_DEFAULT,
313 NETKIT_SCRUB_DEFAULT, 0);
317 skel = test_tc_link__open();
318 if (!ASSERT_OK_PTR(skel, "skel_open"))
321 ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1,
322 target), 0, "tc1_attach_type");
323 ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc2,
324 target), 0, "tc2_attach_type");
326 err = test_tc_link__load(skel);
327 if (!ASSERT_OK(err, "skel_load"))
330 pid1 = id_from_prog_fd(bpf_program__fd(skel->progs.tc1));
331 pid2 = id_from_prog_fd(bpf_program__fd(skel->progs.tc2));
333 ASSERT_NEQ(pid1, pid2, "prog_ids_1_2");
335 assert_mprog_count_ifindex(ifindex, target, 0);
337 ASSERT_EQ(skel->bss->seen_tc1, false, "seen_tc1");
338 ASSERT_EQ(skel->bss->seen_eth, false, "seen_eth");
339 ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
341 link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl);
342 if (!ASSERT_OK_PTR(link, "link_attach"))
345 skel->links.tc1 = link;
347 lid1 = id_from_link_fd(bpf_link__fd(skel->links.tc1));
349 assert_mprog_count_ifindex(ifindex, target, 1);
351 optq.prog_ids = prog_ids;
352 optq.link_ids = link_ids;
354 memset(prog_ids, 0, sizeof(prog_ids));
355 memset(link_ids, 0, sizeof(link_ids));
356 optq.count = ARRAY_SIZE(prog_ids);
358 err = bpf_prog_query_opts(ifindex, target, &optq);
359 if (!ASSERT_OK(err, "prog_query"))
362 ASSERT_EQ(optq.count, 1, "count");
363 ASSERT_EQ(optq.revision, 2, "revision");
364 ASSERT_EQ(optq.prog_ids[0], pid1, "prog_ids[0]");
365 ASSERT_EQ(optq.link_ids[0], lid1, "link_ids[0]");
366 ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
367 ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]");
369 tc_skel_reset_all_seen(skel);
370 ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
372 ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
373 ASSERT_EQ(skel->bss->seen_eth, true, "seen_eth");
374 ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
376 LIBBPF_OPTS_RESET(optl,
377 .flags = BPF_F_BEFORE,
378 .relative_fd = bpf_program__fd(skel->progs.tc1),
381 link = bpf_program__attach_netkit(skel->progs.tc2, ifindex, &optl);
382 if (!ASSERT_OK_PTR(link, "link_attach"))
385 skel->links.tc2 = link;
387 lid2 = id_from_link_fd(bpf_link__fd(skel->links.tc2));
388 ASSERT_NEQ(lid1, lid2, "link_ids_1_2");
390 assert_mprog_count_ifindex(ifindex, target, 2);
392 memset(prog_ids, 0, sizeof(prog_ids));
393 memset(link_ids, 0, sizeof(link_ids));
394 optq.count = ARRAY_SIZE(prog_ids);
396 err = bpf_prog_query_opts(ifindex, target, &optq);
397 if (!ASSERT_OK(err, "prog_query"))
400 ASSERT_EQ(optq.count, 2, "count");
401 ASSERT_EQ(optq.revision, 3, "revision");
402 ASSERT_EQ(optq.prog_ids[0], pid2, "prog_ids[0]");
403 ASSERT_EQ(optq.link_ids[0], lid2, "link_ids[0]");
404 ASSERT_EQ(optq.prog_ids[1], pid1, "prog_ids[1]");
405 ASSERT_EQ(optq.link_ids[1], lid1, "link_ids[1]");
406 ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
407 ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]");
409 tc_skel_reset_all_seen(skel);
410 ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
412 ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
413 ASSERT_EQ(skel->bss->seen_eth, true, "seen_eth");
414 ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
416 test_tc_link__destroy(skel);
418 assert_mprog_count_ifindex(ifindex, target, 0);
422 void serial_test_tc_netkit_multi_links(void)
424 serial_test_tc_netkit_multi_links_target(NETKIT_L2, BPF_NETKIT_PRIMARY);
425 serial_test_tc_netkit_multi_links_target(NETKIT_L3, BPF_NETKIT_PRIMARY);
426 serial_test_tc_netkit_multi_links_target(NETKIT_L2, BPF_NETKIT_PEER);
427 serial_test_tc_netkit_multi_links_target(NETKIT_L3, BPF_NETKIT_PEER);
430 static void serial_test_tc_netkit_multi_opts_target(int mode, int target)
432 LIBBPF_OPTS(bpf_prog_attach_opts, opta);
433 LIBBPF_OPTS(bpf_prog_detach_opts, optd);
434 LIBBPF_OPTS(bpf_prog_query_opts, optq);
435 __u32 pid1, pid2, fd1, fd2;
437 struct test_tc_link *skel;
440 err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
441 &ifindex, NETKIT_SCRUB_DEFAULT,
442 NETKIT_SCRUB_DEFAULT, 0);
446 skel = test_tc_link__open_and_load();
447 if (!ASSERT_OK_PTR(skel, "skel_load"))
450 fd1 = bpf_program__fd(skel->progs.tc1);
451 fd2 = bpf_program__fd(skel->progs.tc2);
453 pid1 = id_from_prog_fd(fd1);
454 pid2 = id_from_prog_fd(fd2);
456 ASSERT_NEQ(pid1, pid2, "prog_ids_1_2");
458 assert_mprog_count_ifindex(ifindex, target, 0);
460 ASSERT_EQ(skel->bss->seen_tc1, false, "seen_tc1");
461 ASSERT_EQ(skel->bss->seen_eth, false, "seen_eth");
462 ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
464 err = bpf_prog_attach_opts(fd1, ifindex, target, &opta);
465 if (!ASSERT_EQ(err, 0, "prog_attach"))
468 assert_mprog_count_ifindex(ifindex, target, 1);
470 optq.prog_ids = prog_ids;
472 memset(prog_ids, 0, sizeof(prog_ids));
473 optq.count = ARRAY_SIZE(prog_ids);
475 err = bpf_prog_query_opts(ifindex, target, &optq);
476 if (!ASSERT_OK(err, "prog_query"))
479 ASSERT_EQ(optq.count, 1, "count");
480 ASSERT_EQ(optq.revision, 2, "revision");
481 ASSERT_EQ(optq.prog_ids[0], pid1, "prog_ids[0]");
482 ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
484 tc_skel_reset_all_seen(skel);
485 ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
487 ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
488 ASSERT_EQ(skel->bss->seen_eth, true, "seen_eth");
489 ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
491 LIBBPF_OPTS_RESET(opta,
492 .flags = BPF_F_BEFORE,
496 err = bpf_prog_attach_opts(fd2, ifindex, target, &opta);
497 if (!ASSERT_EQ(err, 0, "prog_attach"))
500 assert_mprog_count_ifindex(ifindex, target, 2);
502 memset(prog_ids, 0, sizeof(prog_ids));
503 optq.count = ARRAY_SIZE(prog_ids);
505 err = bpf_prog_query_opts(ifindex, target, &optq);
506 if (!ASSERT_OK(err, "prog_query"))
509 ASSERT_EQ(optq.count, 2, "count");
510 ASSERT_EQ(optq.revision, 3, "revision");
511 ASSERT_EQ(optq.prog_ids[0], pid2, "prog_ids[0]");
512 ASSERT_EQ(optq.prog_ids[1], pid1, "prog_ids[1]");
513 ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
515 tc_skel_reset_all_seen(skel);
516 ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
518 ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
519 ASSERT_EQ(skel->bss->seen_eth, true, "seen_eth");
520 ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
523 err = bpf_prog_detach_opts(fd2, ifindex, target, &optd);
524 ASSERT_OK(err, "prog_detach");
525 assert_mprog_count_ifindex(ifindex, target, 1);
527 err = bpf_prog_detach_opts(fd1, ifindex, target, &optd);
528 ASSERT_OK(err, "prog_detach");
529 assert_mprog_count_ifindex(ifindex, target, 0);
531 test_tc_link__destroy(skel);
533 assert_mprog_count_ifindex(ifindex, target, 0);
537 void serial_test_tc_netkit_multi_opts(void)
539 serial_test_tc_netkit_multi_opts_target(NETKIT_L2, BPF_NETKIT_PRIMARY);
540 serial_test_tc_netkit_multi_opts_target(NETKIT_L3, BPF_NETKIT_PRIMARY);
541 serial_test_tc_netkit_multi_opts_target(NETKIT_L2, BPF_NETKIT_PEER);
542 serial_test_tc_netkit_multi_opts_target(NETKIT_L3, BPF_NETKIT_PEER);
545 void serial_test_tc_netkit_device(void)
547 LIBBPF_OPTS(bpf_prog_query_opts, optq);
548 LIBBPF_OPTS(bpf_netkit_opts, optl);
549 __u32 prog_ids[2], link_ids[2];
550 __u32 pid1, pid2, lid1;
551 struct test_tc_link *skel;
552 struct bpf_link *link;
553 int err, ifindex, ifindex2;
555 err = create_netkit(NETKIT_L3, NETKIT_PASS, NETKIT_PASS,
556 &ifindex, NETKIT_SCRUB_DEFAULT,
557 NETKIT_SCRUB_DEFAULT, FLAG_SAME_NETNS);
561 ifindex2 = if_nametoindex(netkit_peer);
562 ASSERT_NEQ(ifindex, ifindex2, "ifindex_1_2");
564 skel = test_tc_link__open();
565 if (!ASSERT_OK_PTR(skel, "skel_open"))
568 ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1,
569 BPF_NETKIT_PRIMARY), 0, "tc1_attach_type");
570 ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc2,
571 BPF_NETKIT_PEER), 0, "tc2_attach_type");
572 ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc3,
573 BPF_NETKIT_PRIMARY), 0, "tc3_attach_type");
575 err = test_tc_link__load(skel);
576 if (!ASSERT_OK(err, "skel_load"))
579 pid1 = id_from_prog_fd(bpf_program__fd(skel->progs.tc1));
580 pid2 = id_from_prog_fd(bpf_program__fd(skel->progs.tc2));
582 ASSERT_NEQ(pid1, pid2, "prog_ids_1_2");
584 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
585 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
587 ASSERT_EQ(skel->bss->seen_tc1, false, "seen_tc1");
588 ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
590 link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl);
591 if (!ASSERT_OK_PTR(link, "link_attach"))
594 skel->links.tc1 = link;
596 lid1 = id_from_link_fd(bpf_link__fd(skel->links.tc1));
598 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
599 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
601 optq.prog_ids = prog_ids;
602 optq.link_ids = link_ids;
604 memset(prog_ids, 0, sizeof(prog_ids));
605 memset(link_ids, 0, sizeof(link_ids));
606 optq.count = ARRAY_SIZE(prog_ids);
608 err = bpf_prog_query_opts(ifindex, BPF_NETKIT_PRIMARY, &optq);
609 if (!ASSERT_OK(err, "prog_query"))
612 ASSERT_EQ(optq.count, 1, "count");
613 ASSERT_EQ(optq.revision, 2, "revision");
614 ASSERT_EQ(optq.prog_ids[0], pid1, "prog_ids[0]");
615 ASSERT_EQ(optq.link_ids[0], lid1, "link_ids[0]");
616 ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
617 ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]");
619 tc_skel_reset_all_seen(skel);
620 ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
622 ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
623 ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
625 memset(prog_ids, 0, sizeof(prog_ids));
626 memset(link_ids, 0, sizeof(link_ids));
627 optq.count = ARRAY_SIZE(prog_ids);
629 err = bpf_prog_query_opts(ifindex2, BPF_NETKIT_PRIMARY, &optq);
630 ASSERT_EQ(err, -EACCES, "prog_query_should_fail");
632 err = bpf_prog_query_opts(ifindex2, BPF_NETKIT_PEER, &optq);
633 ASSERT_EQ(err, -EACCES, "prog_query_should_fail");
635 link = bpf_program__attach_netkit(skel->progs.tc2, ifindex2, &optl);
636 if (!ASSERT_ERR_PTR(link, "link_attach_should_fail")) {
637 bpf_link__destroy(link);
641 link = bpf_program__attach_netkit(skel->progs.tc3, ifindex2, &optl);
642 if (!ASSERT_ERR_PTR(link, "link_attach_should_fail")) {
643 bpf_link__destroy(link);
647 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
648 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
650 test_tc_link__destroy(skel);
652 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
653 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
657 static void serial_test_tc_netkit_neigh_links_target(int mode, int target)
659 LIBBPF_OPTS(bpf_prog_query_opts, optq);
660 LIBBPF_OPTS(bpf_netkit_opts, optl);
661 __u32 prog_ids[2], link_ids[2];
663 struct test_tc_link *skel;
664 struct bpf_link *link;
667 err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
668 &ifindex, NETKIT_SCRUB_DEFAULT,
669 NETKIT_SCRUB_DEFAULT, 0);
673 skel = test_tc_link__open();
674 if (!ASSERT_OK_PTR(skel, "skel_open"))
677 ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1,
678 BPF_NETKIT_PRIMARY), 0, "tc1_attach_type");
680 err = test_tc_link__load(skel);
681 if (!ASSERT_OK(err, "skel_load"))
684 pid1 = id_from_prog_fd(bpf_program__fd(skel->progs.tc1));
686 assert_mprog_count_ifindex(ifindex, target, 0);
688 ASSERT_EQ(skel->bss->seen_tc1, false, "seen_tc1");
689 ASSERT_EQ(skel->bss->seen_eth, false, "seen_eth");
691 link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl);
692 if (!ASSERT_OK_PTR(link, "link_attach"))
695 skel->links.tc1 = link;
697 lid1 = id_from_link_fd(bpf_link__fd(skel->links.tc1));
699 assert_mprog_count_ifindex(ifindex, target, 1);
701 optq.prog_ids = prog_ids;
702 optq.link_ids = link_ids;
704 memset(prog_ids, 0, sizeof(prog_ids));
705 memset(link_ids, 0, sizeof(link_ids));
706 optq.count = ARRAY_SIZE(prog_ids);
708 err = bpf_prog_query_opts(ifindex, target, &optq);
709 if (!ASSERT_OK(err, "prog_query"))
712 ASSERT_EQ(optq.count, 1, "count");
713 ASSERT_EQ(optq.revision, 2, "revision");
714 ASSERT_EQ(optq.prog_ids[0], pid1, "prog_ids[0]");
715 ASSERT_EQ(optq.link_ids[0], lid1, "link_ids[0]");
716 ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
717 ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]");
719 tc_skel_reset_all_seen(skel);
720 ASSERT_EQ(__send_icmp(ping_addr_noneigh), 0, "icmp_pkt");
722 ASSERT_EQ(skel->bss->seen_tc1, true /* L2: ARP */, "seen_tc1");
723 ASSERT_EQ(skel->bss->seen_eth, mode == NETKIT_L3, "seen_eth");
725 test_tc_link__destroy(skel);
727 assert_mprog_count_ifindex(ifindex, target, 0);
731 void serial_test_tc_netkit_neigh_links(void)
733 serial_test_tc_netkit_neigh_links_target(NETKIT_L2, BPF_NETKIT_PRIMARY);
734 serial_test_tc_netkit_neigh_links_target(NETKIT_L3, BPF_NETKIT_PRIMARY);
737 static void serial_test_tc_netkit_pkt_type_mode(int mode)
739 LIBBPF_OPTS(bpf_netkit_opts, optl_nk);
740 LIBBPF_OPTS(bpf_tcx_opts, optl_tcx);
741 int err, ifindex, ifindex2;
742 struct test_tc_link *skel;
743 struct bpf_link *link;
745 err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
746 &ifindex, NETKIT_SCRUB_DEFAULT,
747 NETKIT_SCRUB_DEFAULT, FLAG_SAME_NETNS);
751 ifindex2 = if_nametoindex(netkit_peer);
752 ASSERT_NEQ(ifindex, ifindex2, "ifindex_1_2");
754 skel = test_tc_link__open();
755 if (!ASSERT_OK_PTR(skel, "skel_open"))
758 ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1,
759 BPF_NETKIT_PRIMARY), 0, "tc1_attach_type");
760 ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc7,
761 BPF_TCX_INGRESS), 0, "tc7_attach_type");
763 err = test_tc_link__load(skel);
764 if (!ASSERT_OK(err, "skel_load"))
767 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
768 assert_mprog_count_ifindex(ifindex2, BPF_TCX_INGRESS, 0);
770 link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl_nk);
771 if (!ASSERT_OK_PTR(link, "link_attach"))
774 skel->links.tc1 = link;
776 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
777 assert_mprog_count_ifindex(ifindex2, BPF_TCX_INGRESS, 0);
779 link = bpf_program__attach_tcx(skel->progs.tc7, ifindex2, &optl_tcx);
780 if (!ASSERT_OK_PTR(link, "link_attach"))
783 skel->links.tc7 = link;
785 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
786 assert_mprog_count_ifindex(ifindex2, BPF_TCX_INGRESS, 1);
790 tc_skel_reset_all_seen(skel);
791 skel->bss->set_type = true;
792 ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
794 ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
795 ASSERT_EQ(skel->bss->seen_tc7, true, "seen_tc7");
797 ASSERT_EQ(skel->bss->seen_host, true, "seen_host");
798 ASSERT_EQ(skel->bss->seen_mcast, true, "seen_mcast");
800 test_tc_link__destroy(skel);
802 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
806 void serial_test_tc_netkit_pkt_type(void)
808 serial_test_tc_netkit_pkt_type_mode(NETKIT_L2);
809 serial_test_tc_netkit_pkt_type_mode(NETKIT_L3);
812 static void serial_test_tc_netkit_scrub_type(int scrub, bool room)
814 LIBBPF_OPTS(bpf_netkit_opts, optl);
815 struct test_tc_link *skel;
816 struct bpf_link *link;
819 err = create_netkit(NETKIT_L2, NETKIT_PASS, NETKIT_PASS,
820 &ifindex, scrub, scrub,
821 room ? FLAG_ADJUST_ROOM : 0);
825 skel = test_tc_link__open();
826 if (!ASSERT_OK_PTR(skel, "skel_open"))
829 ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc8,
830 BPF_NETKIT_PRIMARY), 0, "tc8_attach_type");
832 err = test_tc_link__load(skel);
833 if (!ASSERT_OK(err, "skel_load"))
836 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
837 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
839 ASSERT_EQ(skel->bss->seen_tc8, false, "seen_tc8");
841 link = bpf_program__attach_netkit(skel->progs.tc8, ifindex, &optl);
842 if (!ASSERT_OK_PTR(link, "link_attach"))
845 skel->links.tc8 = link;
847 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
848 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
850 tc_skel_reset_all_seen(skel);
851 ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
853 ASSERT_EQ(skel->bss->seen_tc8, true, "seen_tc8");
854 ASSERT_EQ(skel->bss->mark, scrub == NETKIT_SCRUB_NONE ? MARK : 0, "mark");
855 ASSERT_EQ(skel->bss->prio, scrub == NETKIT_SCRUB_NONE ? PRIO : 0, "prio");
856 ASSERT_EQ(skel->bss->headroom, room ? NETKIT_HEADROOM : 0, "headroom");
857 ASSERT_EQ(skel->bss->tailroom, room ? NETKIT_TAILROOM : 0, "tailroom");
859 test_tc_link__destroy(skel);
861 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
862 assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
866 void serial_test_tc_netkit_scrub(void)
868 serial_test_tc_netkit_scrub_type(NETKIT_SCRUB_DEFAULT, false);
869 serial_test_tc_netkit_scrub_type(NETKIT_SCRUB_NONE, true);