]> Git Repo - linux.git/blob - tools/testing/selftests/bpf/prog_tests/tc_netkit.c
Linux 6.14-rc3
[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 NETKIT_HEADROOM 32
18 #define NETKIT_TAILROOM 8
19
20 #define MARK            42
21 #define PRIO            0xeb9f
22 #define ICMP_ECHO       8
23
24 #define FLAG_ADJUST_ROOM (1 << 0)
25 #define FLAG_SAME_NETNS  (1 << 1)
26
27 struct icmphdr {
28         __u8            type;
29         __u8            code;
30         __sum16         checksum;
31         struct {
32                 __be16  id;
33                 __be16  sequence;
34         } echo;
35 };
36
37 struct iplink_req {
38         struct nlmsghdr  n;
39         struct ifinfomsg i;
40         char             buf[1024];
41 };
42
43 static int create_netkit(int mode, int policy, int peer_policy, int *ifindex,
44                          int scrub, int peer_scrub, __u32 flags)
45 {
46         struct rtnl_handle rth = { .fd = -1 };
47         struct iplink_req req = {};
48         struct rtattr *linkinfo, *data;
49         const char *type = "netkit";
50         int err;
51
52         err = rtnl_open(&rth, 0);
53         if (!ASSERT_OK(err, "open_rtnetlink"))
54                 return err;
55
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;
61
62         addattr_l(&req.n, sizeof(req), IFLA_IFNAME, netkit_name,
63                   strlen(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);
75         }
76         addattr_nest_end(&req.n, data);
77         addattr_nest_end(&req.n, linkinfo);
78
79         err = rtnl_talk(&rth, &req.n, NULL);
80         ASSERT_OK(err, "talk_rtnetlink");
81         rtnl_close(&rth);
82         *ifindex = if_nametoindex(netkit_name);
83
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"),
87                          "up primary");
88         ASSERT_OK(system("ip addr add dev " netkit_name " 10.0.0.1/24"),
89                          "addr primary");
90
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,
94                                  "set hwaddress");
95         } else {
96                 ASSERT_OK(system("ip link set dev " netkit_name
97                                  " addr ee:ff:bb:cc:aa:dd"),
98                                  "set hwaddress");
99         }
100         if (flags & FLAG_SAME_NETNS) {
101                 ASSERT_OK(system("ip link set dev " netkit_peer " up"),
102                                  "up peer");
103                 ASSERT_OK(system("ip addr add dev " netkit_peer " 10.0.0.2/24"),
104                                  "addr peer");
105         } else {
106                 ASSERT_OK(system("ip link set " netkit_peer " netns foo"),
107                                  "move peer");
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");
112         }
113         return err;
114 }
115
116 static void move_netkit(void)
117 {
118         ASSERT_OK(system("ip link set " netkit_peer " netns foo"),
119                          "move peer");
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");
124 }
125
126 static void destroy_netkit(void)
127 {
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");
131 }
132
133 static int __send_icmp(__u32 dest)
134 {
135         int sock, ret, mark = MARK, prio = PRIO;
136         struct sockaddr_in addr;
137         struct icmphdr icmp;
138
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)"))
141                 return ret;
142
143         sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
144         if (!ASSERT_GE(sock, 0, "icmp_socket"))
145                 return -errno;
146
147         ret = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
148                          netkit_name, strlen(netkit_name) + 1);
149         if (!ASSERT_OK(ret, "setsockopt(SO_BINDTODEVICE)"))
150                 goto out;
151
152         ret = setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark));
153         if (!ASSERT_OK(ret, "setsockopt(SO_MARK)"))
154                 goto out;
155
156         ret = setsockopt(sock, SOL_SOCKET, SO_PRIORITY,
157                          &prio, sizeof(prio));
158         if (!ASSERT_OK(ret, "setsockopt(SO_PRIORITY)"))
159                 goto out;
160
161         memset(&addr, 0, sizeof(addr));
162         addr.sin_family = AF_INET;
163         addr.sin_addr.s_addr = htonl(dest);
164
165         memset(&icmp, 0, sizeof(icmp));
166         icmp.type = ICMP_ECHO;
167         icmp.echo.id = 1234;
168         icmp.echo.sequence = 1;
169
170         ret = sendto(sock, &icmp, sizeof(icmp), 0,
171                      (struct sockaddr *)&addr, sizeof(addr));
172         if (!ASSERT_GE(ret, 0, "icmp_sendto"))
173                 ret = -errno;
174         else
175                 ret = 0;
176 out:
177         close(sock);
178         return ret;
179 }
180
181 static int send_icmp(void)
182 {
183         return __send_icmp(ping_addr_neigh);
184 }
185
186 void serial_test_tc_netkit_basic(void)
187 {
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;
194         int err, ifindex;
195
196         err = create_netkit(NETKIT_L2, NETKIT_PASS, NETKIT_PASS,
197                             &ifindex, NETKIT_SCRUB_DEFAULT,
198                             NETKIT_SCRUB_DEFAULT, 0);
199         if (err)
200                 return;
201
202         skel = test_tc_link__open();
203         if (!ASSERT_OK_PTR(skel, "skel_open"))
204                 goto cleanup;
205
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");
210
211         err = test_tc_link__load(skel);
212         if (!ASSERT_OK(err, "skel_load"))
213                 goto cleanup;
214
215         pid1 = id_from_prog_fd(bpf_program__fd(skel->progs.tc1));
216         pid2 = id_from_prog_fd(bpf_program__fd(skel->progs.tc2));
217
218         ASSERT_NEQ(pid1, pid2, "prog_ids_1_2");
219
220         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
221         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
222
223         ASSERT_EQ(skel->bss->seen_tc1, false, "seen_tc1");
224         ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
225
226         link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl);
227         if (!ASSERT_OK_PTR(link, "link_attach"))
228                 goto cleanup;
229
230         skel->links.tc1 = link;
231
232         lid1 = id_from_link_fd(bpf_link__fd(skel->links.tc1));
233
234         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
235         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
236
237         optq.prog_ids = prog_ids;
238         optq.link_ids = link_ids;
239
240         memset(prog_ids, 0, sizeof(prog_ids));
241         memset(link_ids, 0, sizeof(link_ids));
242         optq.count = ARRAY_SIZE(prog_ids);
243
244         err = bpf_prog_query_opts(ifindex, BPF_NETKIT_PRIMARY, &optq);
245         if (!ASSERT_OK(err, "prog_query"))
246                 goto cleanup;
247
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]");
254
255         tc_skel_reset_all_seen(skel);
256         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
257
258         ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
259         ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
260
261         link = bpf_program__attach_netkit(skel->progs.tc2, ifindex, &optl);
262         if (!ASSERT_OK_PTR(link, "link_attach"))
263                 goto cleanup;
264
265         skel->links.tc2 = link;
266
267         lid2 = id_from_link_fd(bpf_link__fd(skel->links.tc2));
268         ASSERT_NEQ(lid1, lid2, "link_ids_1_2");
269
270         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
271         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 1);
272
273         memset(prog_ids, 0, sizeof(prog_ids));
274         memset(link_ids, 0, sizeof(link_ids));
275         optq.count = ARRAY_SIZE(prog_ids);
276
277         err = bpf_prog_query_opts(ifindex, BPF_NETKIT_PEER, &optq);
278         if (!ASSERT_OK(err, "prog_query"))
279                 goto cleanup;
280
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]");
287
288         tc_skel_reset_all_seen(skel);
289         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
290
291         ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
292         ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
293 cleanup:
294         test_tc_link__destroy(skel);
295
296         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
297         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
298         destroy_netkit();
299 }
300
301 static void serial_test_tc_netkit_multi_links_target(int mode, int target)
302 {
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;
309         int err, ifindex;
310
311         err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
312                             &ifindex, NETKIT_SCRUB_DEFAULT,
313                             NETKIT_SCRUB_DEFAULT, 0);
314         if (err)
315                 return;
316
317         skel = test_tc_link__open();
318         if (!ASSERT_OK_PTR(skel, "skel_open"))
319                 goto cleanup;
320
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");
325
326         err = test_tc_link__load(skel);
327         if (!ASSERT_OK(err, "skel_load"))
328                 goto cleanup;
329
330         pid1 = id_from_prog_fd(bpf_program__fd(skel->progs.tc1));
331         pid2 = id_from_prog_fd(bpf_program__fd(skel->progs.tc2));
332
333         ASSERT_NEQ(pid1, pid2, "prog_ids_1_2");
334
335         assert_mprog_count_ifindex(ifindex, target, 0);
336
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");
340
341         link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl);
342         if (!ASSERT_OK_PTR(link, "link_attach"))
343                 goto cleanup;
344
345         skel->links.tc1 = link;
346
347         lid1 = id_from_link_fd(bpf_link__fd(skel->links.tc1));
348
349         assert_mprog_count_ifindex(ifindex, target, 1);
350
351         optq.prog_ids = prog_ids;
352         optq.link_ids = link_ids;
353
354         memset(prog_ids, 0, sizeof(prog_ids));
355         memset(link_ids, 0, sizeof(link_ids));
356         optq.count = ARRAY_SIZE(prog_ids);
357
358         err = bpf_prog_query_opts(ifindex, target, &optq);
359         if (!ASSERT_OK(err, "prog_query"))
360                 goto cleanup;
361
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]");
368
369         tc_skel_reset_all_seen(skel);
370         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
371
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");
375
376         LIBBPF_OPTS_RESET(optl,
377                 .flags = BPF_F_BEFORE,
378                 .relative_fd = bpf_program__fd(skel->progs.tc1),
379         );
380
381         link = bpf_program__attach_netkit(skel->progs.tc2, ifindex, &optl);
382         if (!ASSERT_OK_PTR(link, "link_attach"))
383                 goto cleanup;
384
385         skel->links.tc2 = link;
386
387         lid2 = id_from_link_fd(bpf_link__fd(skel->links.tc2));
388         ASSERT_NEQ(lid1, lid2, "link_ids_1_2");
389
390         assert_mprog_count_ifindex(ifindex, target, 2);
391
392         memset(prog_ids, 0, sizeof(prog_ids));
393         memset(link_ids, 0, sizeof(link_ids));
394         optq.count = ARRAY_SIZE(prog_ids);
395
396         err = bpf_prog_query_opts(ifindex, target, &optq);
397         if (!ASSERT_OK(err, "prog_query"))
398                 goto cleanup;
399
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]");
408
409         tc_skel_reset_all_seen(skel);
410         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
411
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");
415 cleanup:
416         test_tc_link__destroy(skel);
417
418         assert_mprog_count_ifindex(ifindex, target, 0);
419         destroy_netkit();
420 }
421
422 void serial_test_tc_netkit_multi_links(void)
423 {
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);
428 }
429
430 static void serial_test_tc_netkit_multi_opts_target(int mode, int target)
431 {
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;
436         __u32 prog_ids[3];
437         struct test_tc_link *skel;
438         int err, ifindex;
439
440         err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
441                             &ifindex, NETKIT_SCRUB_DEFAULT,
442                             NETKIT_SCRUB_DEFAULT, 0);
443         if (err)
444                 return;
445
446         skel = test_tc_link__open_and_load();
447         if (!ASSERT_OK_PTR(skel, "skel_load"))
448                 goto cleanup;
449
450         fd1 = bpf_program__fd(skel->progs.tc1);
451         fd2 = bpf_program__fd(skel->progs.tc2);
452
453         pid1 = id_from_prog_fd(fd1);
454         pid2 = id_from_prog_fd(fd2);
455
456         ASSERT_NEQ(pid1, pid2, "prog_ids_1_2");
457
458         assert_mprog_count_ifindex(ifindex, target, 0);
459
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");
463
464         err = bpf_prog_attach_opts(fd1, ifindex, target, &opta);
465         if (!ASSERT_EQ(err, 0, "prog_attach"))
466                 goto cleanup;
467
468         assert_mprog_count_ifindex(ifindex, target, 1);
469
470         optq.prog_ids = prog_ids;
471
472         memset(prog_ids, 0, sizeof(prog_ids));
473         optq.count = ARRAY_SIZE(prog_ids);
474
475         err = bpf_prog_query_opts(ifindex, target, &optq);
476         if (!ASSERT_OK(err, "prog_query"))
477                 goto cleanup_fd1;
478
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]");
483
484         tc_skel_reset_all_seen(skel);
485         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
486
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");
490
491         LIBBPF_OPTS_RESET(opta,
492                 .flags = BPF_F_BEFORE,
493                 .relative_fd = fd1,
494         );
495
496         err = bpf_prog_attach_opts(fd2, ifindex, target, &opta);
497         if (!ASSERT_EQ(err, 0, "prog_attach"))
498                 goto cleanup_fd1;
499
500         assert_mprog_count_ifindex(ifindex, target, 2);
501
502         memset(prog_ids, 0, sizeof(prog_ids));
503         optq.count = ARRAY_SIZE(prog_ids);
504
505         err = bpf_prog_query_opts(ifindex, target, &optq);
506         if (!ASSERT_OK(err, "prog_query"))
507                 goto cleanup_fd2;
508
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]");
514
515         tc_skel_reset_all_seen(skel);
516         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
517
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");
521
522 cleanup_fd2:
523         err = bpf_prog_detach_opts(fd2, ifindex, target, &optd);
524         ASSERT_OK(err, "prog_detach");
525         assert_mprog_count_ifindex(ifindex, target, 1);
526 cleanup_fd1:
527         err = bpf_prog_detach_opts(fd1, ifindex, target, &optd);
528         ASSERT_OK(err, "prog_detach");
529         assert_mprog_count_ifindex(ifindex, target, 0);
530 cleanup:
531         test_tc_link__destroy(skel);
532
533         assert_mprog_count_ifindex(ifindex, target, 0);
534         destroy_netkit();
535 }
536
537 void serial_test_tc_netkit_multi_opts(void)
538 {
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);
543 }
544
545 void serial_test_tc_netkit_device(void)
546 {
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;
554
555         err = create_netkit(NETKIT_L3, NETKIT_PASS, NETKIT_PASS,
556                             &ifindex, NETKIT_SCRUB_DEFAULT,
557                             NETKIT_SCRUB_DEFAULT, FLAG_SAME_NETNS);
558         if (err)
559                 return;
560
561         ifindex2 = if_nametoindex(netkit_peer);
562         ASSERT_NEQ(ifindex, ifindex2, "ifindex_1_2");
563
564         skel = test_tc_link__open();
565         if (!ASSERT_OK_PTR(skel, "skel_open"))
566                 goto cleanup;
567
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");
574
575         err = test_tc_link__load(skel);
576         if (!ASSERT_OK(err, "skel_load"))
577                 goto cleanup;
578
579         pid1 = id_from_prog_fd(bpf_program__fd(skel->progs.tc1));
580         pid2 = id_from_prog_fd(bpf_program__fd(skel->progs.tc2));
581
582         ASSERT_NEQ(pid1, pid2, "prog_ids_1_2");
583
584         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
585         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
586
587         ASSERT_EQ(skel->bss->seen_tc1, false, "seen_tc1");
588         ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
589
590         link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl);
591         if (!ASSERT_OK_PTR(link, "link_attach"))
592                 goto cleanup;
593
594         skel->links.tc1 = link;
595
596         lid1 = id_from_link_fd(bpf_link__fd(skel->links.tc1));
597
598         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
599         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
600
601         optq.prog_ids = prog_ids;
602         optq.link_ids = link_ids;
603
604         memset(prog_ids, 0, sizeof(prog_ids));
605         memset(link_ids, 0, sizeof(link_ids));
606         optq.count = ARRAY_SIZE(prog_ids);
607
608         err = bpf_prog_query_opts(ifindex, BPF_NETKIT_PRIMARY, &optq);
609         if (!ASSERT_OK(err, "prog_query"))
610                 goto cleanup;
611
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]");
618
619         tc_skel_reset_all_seen(skel);
620         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
621
622         ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
623         ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
624
625         memset(prog_ids, 0, sizeof(prog_ids));
626         memset(link_ids, 0, sizeof(link_ids));
627         optq.count = ARRAY_SIZE(prog_ids);
628
629         err = bpf_prog_query_opts(ifindex2, BPF_NETKIT_PRIMARY, &optq);
630         ASSERT_EQ(err, -EACCES, "prog_query_should_fail");
631
632         err = bpf_prog_query_opts(ifindex2, BPF_NETKIT_PEER, &optq);
633         ASSERT_EQ(err, -EACCES, "prog_query_should_fail");
634
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);
638                 goto cleanup;
639         }
640
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);
644                 goto cleanup;
645         }
646
647         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
648         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
649 cleanup:
650         test_tc_link__destroy(skel);
651
652         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
653         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
654         destroy_netkit();
655 }
656
657 static void serial_test_tc_netkit_neigh_links_target(int mode, int target)
658 {
659         LIBBPF_OPTS(bpf_prog_query_opts, optq);
660         LIBBPF_OPTS(bpf_netkit_opts, optl);
661         __u32 prog_ids[2], link_ids[2];
662         __u32 pid1, lid1;
663         struct test_tc_link *skel;
664         struct bpf_link *link;
665         int err, ifindex;
666
667         err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
668                             &ifindex, NETKIT_SCRUB_DEFAULT,
669                             NETKIT_SCRUB_DEFAULT, 0);
670         if (err)
671                 return;
672
673         skel = test_tc_link__open();
674         if (!ASSERT_OK_PTR(skel, "skel_open"))
675                 goto cleanup;
676
677         ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1,
678                   BPF_NETKIT_PRIMARY), 0, "tc1_attach_type");
679
680         err = test_tc_link__load(skel);
681         if (!ASSERT_OK(err, "skel_load"))
682                 goto cleanup;
683
684         pid1 = id_from_prog_fd(bpf_program__fd(skel->progs.tc1));
685
686         assert_mprog_count_ifindex(ifindex, target, 0);
687
688         ASSERT_EQ(skel->bss->seen_tc1, false, "seen_tc1");
689         ASSERT_EQ(skel->bss->seen_eth, false, "seen_eth");
690
691         link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl);
692         if (!ASSERT_OK_PTR(link, "link_attach"))
693                 goto cleanup;
694
695         skel->links.tc1 = link;
696
697         lid1 = id_from_link_fd(bpf_link__fd(skel->links.tc1));
698
699         assert_mprog_count_ifindex(ifindex, target, 1);
700
701         optq.prog_ids = prog_ids;
702         optq.link_ids = link_ids;
703
704         memset(prog_ids, 0, sizeof(prog_ids));
705         memset(link_ids, 0, sizeof(link_ids));
706         optq.count = ARRAY_SIZE(prog_ids);
707
708         err = bpf_prog_query_opts(ifindex, target, &optq);
709         if (!ASSERT_OK(err, "prog_query"))
710                 goto cleanup;
711
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]");
718
719         tc_skel_reset_all_seen(skel);
720         ASSERT_EQ(__send_icmp(ping_addr_noneigh), 0, "icmp_pkt");
721
722         ASSERT_EQ(skel->bss->seen_tc1, true /* L2: ARP */, "seen_tc1");
723         ASSERT_EQ(skel->bss->seen_eth, mode == NETKIT_L3, "seen_eth");
724 cleanup:
725         test_tc_link__destroy(skel);
726
727         assert_mprog_count_ifindex(ifindex, target, 0);
728         destroy_netkit();
729 }
730
731 void serial_test_tc_netkit_neigh_links(void)
732 {
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);
735 }
736
737 static void serial_test_tc_netkit_pkt_type_mode(int mode)
738 {
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;
744
745         err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
746                             &ifindex, NETKIT_SCRUB_DEFAULT,
747                             NETKIT_SCRUB_DEFAULT, FLAG_SAME_NETNS);
748         if (err)
749                 return;
750
751         ifindex2 = if_nametoindex(netkit_peer);
752         ASSERT_NEQ(ifindex, ifindex2, "ifindex_1_2");
753
754         skel = test_tc_link__open();
755         if (!ASSERT_OK_PTR(skel, "skel_open"))
756                 goto cleanup;
757
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");
762
763         err = test_tc_link__load(skel);
764         if (!ASSERT_OK(err, "skel_load"))
765                 goto cleanup;
766
767         assert_mprog_count_ifindex(ifindex,  BPF_NETKIT_PRIMARY, 0);
768         assert_mprog_count_ifindex(ifindex2, BPF_TCX_INGRESS, 0);
769
770         link = bpf_program__attach_netkit(skel->progs.tc1, ifindex, &optl_nk);
771         if (!ASSERT_OK_PTR(link, "link_attach"))
772                 goto cleanup;
773
774         skel->links.tc1 = link;
775
776         assert_mprog_count_ifindex(ifindex,  BPF_NETKIT_PRIMARY, 1);
777         assert_mprog_count_ifindex(ifindex2, BPF_TCX_INGRESS, 0);
778
779         link = bpf_program__attach_tcx(skel->progs.tc7, ifindex2, &optl_tcx);
780         if (!ASSERT_OK_PTR(link, "link_attach"))
781                 goto cleanup;
782
783         skel->links.tc7 = link;
784
785         assert_mprog_count_ifindex(ifindex,  BPF_NETKIT_PRIMARY, 1);
786         assert_mprog_count_ifindex(ifindex2, BPF_TCX_INGRESS, 1);
787
788         move_netkit();
789
790         tc_skel_reset_all_seen(skel);
791         skel->bss->set_type = true;
792         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
793
794         ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
795         ASSERT_EQ(skel->bss->seen_tc7, true, "seen_tc7");
796
797         ASSERT_EQ(skel->bss->seen_host,  true, "seen_host");
798         ASSERT_EQ(skel->bss->seen_mcast, true, "seen_mcast");
799 cleanup:
800         test_tc_link__destroy(skel);
801
802         assert_mprog_count_ifindex(ifindex,  BPF_NETKIT_PRIMARY, 0);
803         destroy_netkit();
804 }
805
806 void serial_test_tc_netkit_pkt_type(void)
807 {
808         serial_test_tc_netkit_pkt_type_mode(NETKIT_L2);
809         serial_test_tc_netkit_pkt_type_mode(NETKIT_L3);
810 }
811
812 static void serial_test_tc_netkit_scrub_type(int scrub, bool room)
813 {
814         LIBBPF_OPTS(bpf_netkit_opts, optl);
815         struct test_tc_link *skel;
816         struct bpf_link *link;
817         int err, ifindex;
818
819         err = create_netkit(NETKIT_L2, NETKIT_PASS, NETKIT_PASS,
820                             &ifindex, scrub, scrub,
821                             room ? FLAG_ADJUST_ROOM : 0);
822         if (err)
823                 return;
824
825         skel = test_tc_link__open();
826         if (!ASSERT_OK_PTR(skel, "skel_open"))
827                 goto cleanup;
828
829         ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc8,
830                   BPF_NETKIT_PRIMARY), 0, "tc8_attach_type");
831
832         err = test_tc_link__load(skel);
833         if (!ASSERT_OK(err, "skel_load"))
834                 goto cleanup;
835
836         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
837         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
838
839         ASSERT_EQ(skel->bss->seen_tc8, false, "seen_tc8");
840
841         link = bpf_program__attach_netkit(skel->progs.tc8, ifindex, &optl);
842         if (!ASSERT_OK_PTR(link, "link_attach"))
843                 goto cleanup;
844
845         skel->links.tc8 = link;
846
847         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 1);
848         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
849
850         tc_skel_reset_all_seen(skel);
851         ASSERT_EQ(send_icmp(), 0, "icmp_pkt");
852
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");
858 cleanup:
859         test_tc_link__destroy(skel);
860
861         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PRIMARY, 0);
862         assert_mprog_count_ifindex(ifindex, BPF_NETKIT_PEER, 0);
863         destroy_netkit();
864 }
865
866 void serial_test_tc_netkit_scrub(void)
867 {
868         serial_test_tc_netkit_scrub_type(NETKIT_SCRUB_DEFAULT, false);
869         serial_test_tc_netkit_scrub_type(NETKIT_SCRUB_NONE, true);
870 }
This page took 0.082388 seconds and 4 git commands to generate.