1cd13c91dSDaniel Borkmann // SPDX-License-Identifier: GPL-2.0
2cd13c91dSDaniel Borkmann /* Copyright (c) 2023 Isovalent */
3cd13c91dSDaniel Borkmann #include <uapi/linux/if_link.h>
4cd13c91dSDaniel Borkmann #include <net/if.h>
5cd13c91dSDaniel Borkmann #include <test_progs.h>
6cd13c91dSDaniel Borkmann
7cd13c91dSDaniel Borkmann #define loopback 1
8cd13c91dSDaniel Borkmann #define ping_cmd "ping -q -c1 -w1 127.0.0.1 > /dev/null"
9cd13c91dSDaniel Borkmann
10cd13c91dSDaniel Borkmann #include "test_tc_link.skel.h"
11cd13c91dSDaniel Borkmann #include "tc_helpers.h"
12cd13c91dSDaniel Borkmann
serial_test_tc_opts_basic(void)13cd13c91dSDaniel Borkmann void serial_test_tc_opts_basic(void)
14cd13c91dSDaniel Borkmann {
15cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
16cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
17cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq);
18cd13c91dSDaniel Borkmann __u32 fd1, fd2, id1, id2;
19cd13c91dSDaniel Borkmann struct test_tc_link *skel;
20cd13c91dSDaniel Borkmann __u32 prog_ids[2];
21cd13c91dSDaniel Borkmann int err;
22cd13c91dSDaniel Borkmann
23cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load();
24cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load"))
25cd13c91dSDaniel Borkmann goto cleanup;
26cd13c91dSDaniel Borkmann
27cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1);
28cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2);
29cd13c91dSDaniel Borkmann
30cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1);
31cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2);
32cd13c91dSDaniel Borkmann
33cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2");
34cd13c91dSDaniel Borkmann
35cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_INGRESS, 0);
36cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_EGRESS, 0);
37cd13c91dSDaniel Borkmann
38cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, false, "seen_tc1");
39cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
40cd13c91dSDaniel Borkmann
41cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, BPF_TCX_INGRESS, &opta);
42cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
43cd13c91dSDaniel Borkmann goto cleanup;
44cd13c91dSDaniel Borkmann
45cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_INGRESS, 1);
46cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_EGRESS, 0);
47cd13c91dSDaniel Borkmann
48cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids;
49cd13c91dSDaniel Borkmann
50cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
51cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
52cd13c91dSDaniel Borkmann
53cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, BPF_TCX_INGRESS, &optq);
54cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
55cd13c91dSDaniel Borkmann goto cleanup_in;
56cd13c91dSDaniel Borkmann
57cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 1, "count");
58cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 2, "revision");
59cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
60cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
61cd13c91dSDaniel Borkmann
6237345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
63cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
64cd13c91dSDaniel Borkmann
65cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
66cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
67cd13c91dSDaniel Borkmann
68cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, BPF_TCX_EGRESS, &opta);
69cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
70cd13c91dSDaniel Borkmann goto cleanup_in;
71cd13c91dSDaniel Borkmann
72cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_INGRESS, 1);
73cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_EGRESS, 1);
74cd13c91dSDaniel Borkmann
75cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
76cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
77cd13c91dSDaniel Borkmann
78cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, BPF_TCX_EGRESS, &optq);
79cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
80cd13c91dSDaniel Borkmann goto cleanup_eg;
81cd13c91dSDaniel Borkmann
82cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 1, "count");
83cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 2, "revision");
84cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]");
85cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
86cd13c91dSDaniel Borkmann
8737345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
88cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
89cd13c91dSDaniel Borkmann
90cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
91cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
92cd13c91dSDaniel Borkmann
93cd13c91dSDaniel Borkmann cleanup_eg:
94cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, BPF_TCX_EGRESS, &optd);
95cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach_eg");
96cd13c91dSDaniel Borkmann
97cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_INGRESS, 1);
98cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_EGRESS, 0);
99cd13c91dSDaniel Borkmann
100cd13c91dSDaniel Borkmann cleanup_in:
101cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, BPF_TCX_INGRESS, &optd);
102cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach_in");
103cd13c91dSDaniel Borkmann
104cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_INGRESS, 0);
105cd13c91dSDaniel Borkmann assert_mprog_count(BPF_TCX_EGRESS, 0);
106cd13c91dSDaniel Borkmann
107cd13c91dSDaniel Borkmann cleanup:
108cd13c91dSDaniel Borkmann test_tc_link__destroy(skel);
109cd13c91dSDaniel Borkmann }
110cd13c91dSDaniel Borkmann
test_tc_opts_before_target(int target)111cd13c91dSDaniel Borkmann static void test_tc_opts_before_target(int target)
112cd13c91dSDaniel Borkmann {
113cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
114cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
115cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq);
116cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4;
117cd13c91dSDaniel Borkmann struct test_tc_link *skel;
118cd13c91dSDaniel Borkmann __u32 prog_ids[5];
119cd13c91dSDaniel Borkmann int err;
120cd13c91dSDaniel Borkmann
121cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load();
122cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load"))
123cd13c91dSDaniel Borkmann goto cleanup;
124cd13c91dSDaniel Borkmann
125cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1);
126cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2);
127cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3);
128cd13c91dSDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4);
129cd13c91dSDaniel Borkmann
130cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1);
131cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2);
132cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3);
133cd13c91dSDaniel Borkmann id4 = id_from_prog_fd(fd4);
134cd13c91dSDaniel Borkmann
135cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2");
136cd13c91dSDaniel Borkmann ASSERT_NEQ(id3, id4, "prog_ids_3_4");
137cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3");
138cd13c91dSDaniel Borkmann
139cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
140cd13c91dSDaniel Borkmann
141cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
142cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
143cd13c91dSDaniel Borkmann goto cleanup;
144cd13c91dSDaniel Borkmann
145cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
146cd13c91dSDaniel Borkmann
147cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta);
148cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
149cd13c91dSDaniel Borkmann goto cleanup_target;
150cd13c91dSDaniel Borkmann
151cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
152cd13c91dSDaniel Borkmann
153cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids;
154cd13c91dSDaniel Borkmann
155cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
156cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
157cd13c91dSDaniel Borkmann
158cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
159cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
160cd13c91dSDaniel Borkmann goto cleanup_target2;
161cd13c91dSDaniel Borkmann
162cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count");
163cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 3, "revision");
164cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
165cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]");
166cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
167cd13c91dSDaniel Borkmann
16837345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
169cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
170cd13c91dSDaniel Borkmann
171cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
172cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
173cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3");
174cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4");
175cd13c91dSDaniel Borkmann
176cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
177cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
178cd13c91dSDaniel Borkmann .relative_fd = fd2,
179cd13c91dSDaniel Borkmann );
180cd13c91dSDaniel Borkmann
181cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta);
182cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
183cd13c91dSDaniel Borkmann goto cleanup_target2;
184cd13c91dSDaniel Borkmann
185cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
186cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
187cd13c91dSDaniel Borkmann
188cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
189cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
190cd13c91dSDaniel Borkmann goto cleanup_target3;
191cd13c91dSDaniel Borkmann
192cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 3, "count");
193cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 4, "revision");
194cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
195cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]");
196cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id2, "prog_ids[2]");
197cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], 0, "prog_ids[3]");
198cd13c91dSDaniel Borkmann
199cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
200cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
201cd13c91dSDaniel Borkmann .relative_id = id1,
202cd13c91dSDaniel Borkmann );
203cd13c91dSDaniel Borkmann
204cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd4, loopback, target, &opta);
205cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
206cd13c91dSDaniel Borkmann goto cleanup_target3;
207cd13c91dSDaniel Borkmann
208cd13c91dSDaniel Borkmann assert_mprog_count(target, 4);
209cd13c91dSDaniel Borkmann
210cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
211cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
212cd13c91dSDaniel Borkmann
213cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
214cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
215cd13c91dSDaniel Borkmann goto cleanup_target4;
216cd13c91dSDaniel Borkmann
217cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 4, "count");
218cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision");
219cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id4, "prog_ids[0]");
220cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]");
221cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id3, "prog_ids[2]");
222cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], id2, "prog_ids[3]");
223cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]");
224cd13c91dSDaniel Borkmann
22537345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
226cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
227cd13c91dSDaniel Borkmann
228cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
229cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
230cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, true, "seen_tc3");
231cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4");
232cd13c91dSDaniel Borkmann
233cd13c91dSDaniel Borkmann cleanup_target4:
234cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd4, loopback, target, &optd);
235cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
236cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
237cd13c91dSDaniel Borkmann
238cd13c91dSDaniel Borkmann cleanup_target3:
239cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd);
240cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
241cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
242cd13c91dSDaniel Borkmann
243cd13c91dSDaniel Borkmann cleanup_target2:
244cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
245cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
246cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
247cd13c91dSDaniel Borkmann
248cd13c91dSDaniel Borkmann cleanup_target:
249cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
250cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
251cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
252cd13c91dSDaniel Borkmann
253cd13c91dSDaniel Borkmann cleanup:
254cd13c91dSDaniel Borkmann test_tc_link__destroy(skel);
255cd13c91dSDaniel Borkmann }
256cd13c91dSDaniel Borkmann
serial_test_tc_opts_before(void)257cd13c91dSDaniel Borkmann void serial_test_tc_opts_before(void)
258cd13c91dSDaniel Borkmann {
259cd13c91dSDaniel Borkmann test_tc_opts_before_target(BPF_TCX_INGRESS);
260cd13c91dSDaniel Borkmann test_tc_opts_before_target(BPF_TCX_EGRESS);
261cd13c91dSDaniel Borkmann }
262cd13c91dSDaniel Borkmann
test_tc_opts_after_target(int target)263cd13c91dSDaniel Borkmann static void test_tc_opts_after_target(int target)
264cd13c91dSDaniel Borkmann {
265cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
266cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
267cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq);
268cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4;
269cd13c91dSDaniel Borkmann struct test_tc_link *skel;
270cd13c91dSDaniel Borkmann __u32 prog_ids[5];
271cd13c91dSDaniel Borkmann int err;
272cd13c91dSDaniel Borkmann
273cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load();
274cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load"))
275cd13c91dSDaniel Borkmann goto cleanup;
276cd13c91dSDaniel Borkmann
277cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1);
278cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2);
279cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3);
280cd13c91dSDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4);
281cd13c91dSDaniel Borkmann
282cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1);
283cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2);
284cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3);
285cd13c91dSDaniel Borkmann id4 = id_from_prog_fd(fd4);
286cd13c91dSDaniel Borkmann
287cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2");
288cd13c91dSDaniel Borkmann ASSERT_NEQ(id3, id4, "prog_ids_3_4");
289cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3");
290cd13c91dSDaniel Borkmann
291cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
292cd13c91dSDaniel Borkmann
293cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
294cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
295cd13c91dSDaniel Borkmann goto cleanup;
296cd13c91dSDaniel Borkmann
297cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
298cd13c91dSDaniel Borkmann
299cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta);
300cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
301cd13c91dSDaniel Borkmann goto cleanup_target;
302cd13c91dSDaniel Borkmann
303cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
304cd13c91dSDaniel Borkmann
305cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids;
306cd13c91dSDaniel Borkmann
307cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
308cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
309cd13c91dSDaniel Borkmann
310cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
311cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
312cd13c91dSDaniel Borkmann goto cleanup_target2;
313cd13c91dSDaniel Borkmann
314cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count");
315cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 3, "revision");
316cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
317cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]");
318cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
319cd13c91dSDaniel Borkmann
32037345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
321cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
322cd13c91dSDaniel Borkmann
323cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
324cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
325cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3");
326cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4");
327cd13c91dSDaniel Borkmann
328cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
329cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
330cd13c91dSDaniel Borkmann .relative_fd = fd1,
331cd13c91dSDaniel Borkmann );
332cd13c91dSDaniel Borkmann
333cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta);
334cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
335cd13c91dSDaniel Borkmann goto cleanup_target2;
336cd13c91dSDaniel Borkmann
337cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
338cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
339cd13c91dSDaniel Borkmann
340cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
341cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
342cd13c91dSDaniel Borkmann goto cleanup_target3;
343cd13c91dSDaniel Borkmann
344cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 3, "count");
345cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 4, "revision");
346cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
347cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]");
348cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id2, "prog_ids[2]");
349cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], 0, "prog_ids[3]");
350cd13c91dSDaniel Borkmann
351cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
352cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
353cd13c91dSDaniel Borkmann .relative_id = id2,
354cd13c91dSDaniel Borkmann );
355cd13c91dSDaniel Borkmann
356cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd4, loopback, target, &opta);
357cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
358cd13c91dSDaniel Borkmann goto cleanup_target3;
359cd13c91dSDaniel Borkmann
360cd13c91dSDaniel Borkmann assert_mprog_count(target, 4);
361cd13c91dSDaniel Borkmann
362cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
363cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
364cd13c91dSDaniel Borkmann
365cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
366cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
367cd13c91dSDaniel Borkmann goto cleanup_target4;
368cd13c91dSDaniel Borkmann
369cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 4, "count");
370cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision");
371cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
372cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]");
373cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id2, "prog_ids[2]");
374cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]");
375cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]");
376cd13c91dSDaniel Borkmann
37737345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
378cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
379cd13c91dSDaniel Borkmann
380cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
381cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
382cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, true, "seen_tc3");
383cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4");
384cd13c91dSDaniel Borkmann
385cd13c91dSDaniel Borkmann cleanup_target4:
386cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd4, loopback, target, &optd);
387cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
388cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
389cd13c91dSDaniel Borkmann
390cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
391cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
392cd13c91dSDaniel Borkmann
393cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
394cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
395cd13c91dSDaniel Borkmann goto cleanup_target3;
396cd13c91dSDaniel Borkmann
397cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 3, "count");
398cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 6, "revision");
399cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
400cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]");
401cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id2, "prog_ids[2]");
402cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], 0, "prog_ids[3]");
403cd13c91dSDaniel Borkmann
404cd13c91dSDaniel Borkmann cleanup_target3:
405cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd);
406cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
407cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
408cd13c91dSDaniel Borkmann
409cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
410cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
411cd13c91dSDaniel Borkmann
412cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
413cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
414cd13c91dSDaniel Borkmann goto cleanup_target2;
415cd13c91dSDaniel Borkmann
416cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count");
417cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 7, "revision");
418cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
419cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]");
420cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
421cd13c91dSDaniel Borkmann
422cd13c91dSDaniel Borkmann cleanup_target2:
423cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
424cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
425cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
426cd13c91dSDaniel Borkmann
427cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
428cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
429cd13c91dSDaniel Borkmann
430cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
431cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
432cd13c91dSDaniel Borkmann goto cleanup_target;
433cd13c91dSDaniel Borkmann
434cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 1, "count");
435cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 8, "revision");
436cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
437cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
438cd13c91dSDaniel Borkmann
439cd13c91dSDaniel Borkmann cleanup_target:
440cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
441cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
442cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
443cd13c91dSDaniel Borkmann
444cd13c91dSDaniel Borkmann cleanup:
445cd13c91dSDaniel Borkmann test_tc_link__destroy(skel);
446cd13c91dSDaniel Borkmann }
447cd13c91dSDaniel Borkmann
serial_test_tc_opts_after(void)448cd13c91dSDaniel Borkmann void serial_test_tc_opts_after(void)
449cd13c91dSDaniel Borkmann {
450cd13c91dSDaniel Borkmann test_tc_opts_after_target(BPF_TCX_INGRESS);
451cd13c91dSDaniel Borkmann test_tc_opts_after_target(BPF_TCX_EGRESS);
452cd13c91dSDaniel Borkmann }
453cd13c91dSDaniel Borkmann
test_tc_opts_revision_target(int target)454cd13c91dSDaniel Borkmann static void test_tc_opts_revision_target(int target)
455cd13c91dSDaniel Borkmann {
456cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
457cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
458cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq);
459cd13c91dSDaniel Borkmann __u32 fd1, fd2, id1, id2;
460cd13c91dSDaniel Borkmann struct test_tc_link *skel;
461cd13c91dSDaniel Borkmann __u32 prog_ids[3];
462cd13c91dSDaniel Borkmann int err;
463cd13c91dSDaniel Borkmann
464cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load();
465cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load"))
466cd13c91dSDaniel Borkmann goto cleanup;
467cd13c91dSDaniel Borkmann
468cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1);
469cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2);
470cd13c91dSDaniel Borkmann
471cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1);
472cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2);
473cd13c91dSDaniel Borkmann
474cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2");
475cd13c91dSDaniel Borkmann
476cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
477cd13c91dSDaniel Borkmann
478cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
479cd13c91dSDaniel Borkmann .expected_revision = 1,
480cd13c91dSDaniel Borkmann );
481cd13c91dSDaniel Borkmann
482cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
483cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
484cd13c91dSDaniel Borkmann goto cleanup;
485cd13c91dSDaniel Borkmann
486cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
487cd13c91dSDaniel Borkmann
488cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
489cd13c91dSDaniel Borkmann .expected_revision = 1,
490cd13c91dSDaniel Borkmann );
491cd13c91dSDaniel Borkmann
492cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta);
493cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, -ESTALE, "prog_attach"))
494cd13c91dSDaniel Borkmann goto cleanup_target;
495cd13c91dSDaniel Borkmann
496cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
497cd13c91dSDaniel Borkmann
498cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
499cd13c91dSDaniel Borkmann .expected_revision = 2,
500cd13c91dSDaniel Borkmann );
501cd13c91dSDaniel Borkmann
502cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta);
503cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
504cd13c91dSDaniel Borkmann goto cleanup_target;
505cd13c91dSDaniel Borkmann
506cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
507cd13c91dSDaniel Borkmann
508cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids;
509cd13c91dSDaniel Borkmann
510cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
511cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
512cd13c91dSDaniel Borkmann
513cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
514cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
515cd13c91dSDaniel Borkmann goto cleanup_target2;
516cd13c91dSDaniel Borkmann
517cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count");
518cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 3, "revision");
519cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
520cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]");
521cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
522cd13c91dSDaniel Borkmann
52337345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
524cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
525cd13c91dSDaniel Borkmann
526cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
527cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
528cd13c91dSDaniel Borkmann
529cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
530cd13c91dSDaniel Borkmann .expected_revision = 2,
531cd13c91dSDaniel Borkmann );
532cd13c91dSDaniel Borkmann
533cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
534cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ESTALE, "prog_detach");
535cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
536cd13c91dSDaniel Borkmann
537cd13c91dSDaniel Borkmann cleanup_target2:
538cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
539cd13c91dSDaniel Borkmann .expected_revision = 3,
540cd13c91dSDaniel Borkmann );
541cd13c91dSDaniel Borkmann
542cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
543cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
544cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
545cd13c91dSDaniel Borkmann
546cd13c91dSDaniel Borkmann cleanup_target:
547cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd);
548cd13c91dSDaniel Borkmann
549cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
550cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
551cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
552cd13c91dSDaniel Borkmann
553cd13c91dSDaniel Borkmann cleanup:
554cd13c91dSDaniel Borkmann test_tc_link__destroy(skel);
555cd13c91dSDaniel Borkmann }
556cd13c91dSDaniel Borkmann
serial_test_tc_opts_revision(void)557cd13c91dSDaniel Borkmann void serial_test_tc_opts_revision(void)
558cd13c91dSDaniel Borkmann {
559cd13c91dSDaniel Borkmann test_tc_opts_revision_target(BPF_TCX_INGRESS);
560cd13c91dSDaniel Borkmann test_tc_opts_revision_target(BPF_TCX_EGRESS);
561cd13c91dSDaniel Borkmann }
562cd13c91dSDaniel Borkmann
test_tc_chain_classic(int target,bool chain_tc_old)563cd13c91dSDaniel Borkmann static void test_tc_chain_classic(int target, bool chain_tc_old)
564cd13c91dSDaniel Borkmann {
565cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_tc_opts, tc_opts, .handle = 1, .priority = 1);
566cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_tc_hook, tc_hook, .ifindex = loopback);
567cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
568cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
569cd13c91dSDaniel Borkmann bool hook_created = false, tc_attached = false;
570cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, id1, id2, id3;
571cd13c91dSDaniel Borkmann struct test_tc_link *skel;
572cd13c91dSDaniel Borkmann int err;
573cd13c91dSDaniel Borkmann
574cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load();
575cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load"))
576cd13c91dSDaniel Borkmann goto cleanup;
577cd13c91dSDaniel Borkmann
578cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1);
579cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2);
580cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3);
581cd13c91dSDaniel Borkmann
582cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1);
583cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2);
584cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3);
585cd13c91dSDaniel Borkmann
586cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2");
587cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3");
588cd13c91dSDaniel Borkmann
589cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
590cd13c91dSDaniel Borkmann
591cd13c91dSDaniel Borkmann if (chain_tc_old) {
592cd13c91dSDaniel Borkmann tc_hook.attach_point = target == BPF_TCX_INGRESS ?
593cd13c91dSDaniel Borkmann BPF_TC_INGRESS : BPF_TC_EGRESS;
594cd13c91dSDaniel Borkmann err = bpf_tc_hook_create(&tc_hook);
595cd13c91dSDaniel Borkmann if (err == 0)
596cd13c91dSDaniel Borkmann hook_created = true;
597cd13c91dSDaniel Borkmann err = err == -EEXIST ? 0 : err;
598cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "bpf_tc_hook_create"))
599cd13c91dSDaniel Borkmann goto cleanup;
600cd13c91dSDaniel Borkmann
601cd13c91dSDaniel Borkmann tc_opts.prog_fd = fd3;
602cd13c91dSDaniel Borkmann err = bpf_tc_attach(&tc_hook, &tc_opts);
603cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "bpf_tc_attach"))
604cd13c91dSDaniel Borkmann goto cleanup;
605cd13c91dSDaniel Borkmann tc_attached = true;
606cd13c91dSDaniel Borkmann }
607cd13c91dSDaniel Borkmann
608cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
609cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
610cd13c91dSDaniel Borkmann goto cleanup;
611cd13c91dSDaniel Borkmann
612cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta);
613cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
614cd13c91dSDaniel Borkmann goto cleanup_detach;
615cd13c91dSDaniel Borkmann
616cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
617cd13c91dSDaniel Borkmann
61837345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
619cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
620cd13c91dSDaniel Borkmann
621cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
622cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
623cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, chain_tc_old, "seen_tc3");
624cd13c91dSDaniel Borkmann
625cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
626cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_detach"))
627cd13c91dSDaniel Borkmann goto cleanup_detach;
628cd13c91dSDaniel Borkmann
629cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
630cd13c91dSDaniel Borkmann
63137345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
632cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
633cd13c91dSDaniel Borkmann
634cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
635cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
636cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, chain_tc_old, "seen_tc3");
637cd13c91dSDaniel Borkmann
638cd13c91dSDaniel Borkmann cleanup_detach:
639cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
640cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_detach"))
641cd13c91dSDaniel Borkmann goto cleanup;
642cd13c91dSDaniel Borkmann
643b7736826SDaniel Borkmann assert_mprog_count(target, 0);
644cd13c91dSDaniel Borkmann cleanup:
645cd13c91dSDaniel Borkmann if (tc_attached) {
646cd13c91dSDaniel Borkmann tc_opts.flags = tc_opts.prog_fd = tc_opts.prog_id = 0;
647cd13c91dSDaniel Borkmann err = bpf_tc_detach(&tc_hook, &tc_opts);
648cd13c91dSDaniel Borkmann ASSERT_OK(err, "bpf_tc_detach");
649cd13c91dSDaniel Borkmann }
650cd13c91dSDaniel Borkmann if (hook_created) {
651cd13c91dSDaniel Borkmann tc_hook.attach_point = BPF_TC_INGRESS | BPF_TC_EGRESS;
652cd13c91dSDaniel Borkmann bpf_tc_hook_destroy(&tc_hook);
653cd13c91dSDaniel Borkmann }
654cd13c91dSDaniel Borkmann test_tc_link__destroy(skel);
655cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
656cd13c91dSDaniel Borkmann }
657cd13c91dSDaniel Borkmann
serial_test_tc_opts_chain_classic(void)658cd13c91dSDaniel Borkmann void serial_test_tc_opts_chain_classic(void)
659cd13c91dSDaniel Borkmann {
660cd13c91dSDaniel Borkmann test_tc_chain_classic(BPF_TCX_INGRESS, false);
661cd13c91dSDaniel Borkmann test_tc_chain_classic(BPF_TCX_EGRESS, false);
662cd13c91dSDaniel Borkmann test_tc_chain_classic(BPF_TCX_INGRESS, true);
663cd13c91dSDaniel Borkmann test_tc_chain_classic(BPF_TCX_EGRESS, true);
664cd13c91dSDaniel Borkmann }
665cd13c91dSDaniel Borkmann
test_tc_opts_replace_target(int target)666cd13c91dSDaniel Borkmann static void test_tc_opts_replace_target(int target)
667cd13c91dSDaniel Borkmann {
668cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
669cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
670cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq);
671cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, id1, id2, id3, detach_fd;
672cd13c91dSDaniel Borkmann __u32 prog_ids[4], prog_flags[4];
673cd13c91dSDaniel Borkmann struct test_tc_link *skel;
674cd13c91dSDaniel Borkmann int err;
675cd13c91dSDaniel Borkmann
676cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load();
677cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load"))
678cd13c91dSDaniel Borkmann goto cleanup;
679cd13c91dSDaniel Borkmann
680cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1);
681cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2);
682cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3);
683cd13c91dSDaniel Borkmann
684cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1);
685cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2);
686cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3);
687cd13c91dSDaniel Borkmann
688cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2");
689cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3");
690cd13c91dSDaniel Borkmann
691cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
692cd13c91dSDaniel Borkmann
693cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
694cd13c91dSDaniel Borkmann .expected_revision = 1,
695cd13c91dSDaniel Borkmann );
696cd13c91dSDaniel Borkmann
697cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
698cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
699cd13c91dSDaniel Borkmann goto cleanup;
700cd13c91dSDaniel Borkmann
701cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
702cd13c91dSDaniel Borkmann
703cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
704cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
705cd13c91dSDaniel Borkmann .relative_id = id1,
706cd13c91dSDaniel Borkmann .expected_revision = 2,
707cd13c91dSDaniel Borkmann );
708cd13c91dSDaniel Borkmann
709cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta);
710cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
711cd13c91dSDaniel Borkmann goto cleanup_target;
712cd13c91dSDaniel Borkmann
713cd13c91dSDaniel Borkmann detach_fd = fd2;
714cd13c91dSDaniel Borkmann
715cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
716cd13c91dSDaniel Borkmann
717cd13c91dSDaniel Borkmann optq.prog_attach_flags = prog_flags;
718cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids;
719cd13c91dSDaniel Borkmann
720cd13c91dSDaniel Borkmann memset(prog_flags, 0, sizeof(prog_flags));
721cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
722cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
723cd13c91dSDaniel Borkmann
724cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
725cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
726cd13c91dSDaniel Borkmann goto cleanup_target2;
727cd13c91dSDaniel Borkmann
728cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count");
729cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 3, "revision");
730cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]");
731cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]");
732cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
733cd13c91dSDaniel Borkmann
734cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_attach_flags[0], 0, "prog_flags[0]");
735cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_attach_flags[1], 0, "prog_flags[1]");
736cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_attach_flags[2], 0, "prog_flags[2]");
737cd13c91dSDaniel Borkmann
73837345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
739cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
740cd13c91dSDaniel Borkmann
741cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
742cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
743cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3");
744cd13c91dSDaniel Borkmann
745cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
746cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE,
747cd13c91dSDaniel Borkmann .replace_prog_fd = fd2,
748cd13c91dSDaniel Borkmann .expected_revision = 3,
749cd13c91dSDaniel Borkmann );
750cd13c91dSDaniel Borkmann
751cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta);
752cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
753cd13c91dSDaniel Borkmann goto cleanup_target2;
754cd13c91dSDaniel Borkmann
755cd13c91dSDaniel Borkmann detach_fd = fd3;
756cd13c91dSDaniel Borkmann
757cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
758cd13c91dSDaniel Borkmann
759cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
760cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
761cd13c91dSDaniel Borkmann
762cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
763cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
764cd13c91dSDaniel Borkmann goto cleanup_target2;
765cd13c91dSDaniel Borkmann
766cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count");
767cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 4, "revision");
768cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id3, "prog_ids[0]");
769cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]");
770cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
771cd13c91dSDaniel Borkmann
77237345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
773cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
774cd13c91dSDaniel Borkmann
775cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
776cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2");
777cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, true, "seen_tc3");
778cd13c91dSDaniel Borkmann
779cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
780cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE | BPF_F_BEFORE,
781cd13c91dSDaniel Borkmann .replace_prog_fd = fd3,
782cd13c91dSDaniel Borkmann .relative_fd = fd1,
783cd13c91dSDaniel Borkmann .expected_revision = 4,
784cd13c91dSDaniel Borkmann );
785cd13c91dSDaniel Borkmann
786cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta);
787cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
788cd13c91dSDaniel Borkmann goto cleanup_target2;
789cd13c91dSDaniel Borkmann
790cd13c91dSDaniel Borkmann detach_fd = fd2;
791cd13c91dSDaniel Borkmann
792cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
793cd13c91dSDaniel Borkmann
794cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
795cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
796cd13c91dSDaniel Borkmann
797cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
798cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
799cd13c91dSDaniel Borkmann goto cleanup_target2;
800cd13c91dSDaniel Borkmann
801cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count");
802cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision");
803cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]");
804cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]");
805cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
806cd13c91dSDaniel Borkmann
80737345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
808cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
809cd13c91dSDaniel Borkmann
810cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
811cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
812cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3");
813cd13c91dSDaniel Borkmann
814cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
815cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE,
816cd13c91dSDaniel Borkmann .replace_prog_fd = fd2,
817cd13c91dSDaniel Borkmann );
818cd13c91dSDaniel Borkmann
819cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta);
820cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EEXIST, "prog_attach");
821cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
822cd13c91dSDaniel Borkmann
823cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
824cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE | BPF_F_AFTER,
825cd13c91dSDaniel Borkmann .replace_prog_fd = fd2,
826cd13c91dSDaniel Borkmann .relative_fd = fd1,
827cd13c91dSDaniel Borkmann .expected_revision = 5,
828cd13c91dSDaniel Borkmann );
829cd13c91dSDaniel Borkmann
830cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta);
831cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ERANGE, "prog_attach");
832cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
833cd13c91dSDaniel Borkmann
834cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
835cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE | BPF_F_AFTER | BPF_F_REPLACE,
836cd13c91dSDaniel Borkmann .replace_prog_fd = fd2,
837cd13c91dSDaniel Borkmann .relative_fd = fd1,
838cd13c91dSDaniel Borkmann .expected_revision = 5,
839cd13c91dSDaniel Borkmann );
840cd13c91dSDaniel Borkmann
841cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta);
842cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ERANGE, "prog_attach");
843cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
844cd13c91dSDaniel Borkmann
845cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
846cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
847cd13c91dSDaniel Borkmann .relative_id = id1,
848cd13c91dSDaniel Borkmann .expected_revision = 5,
849cd13c91dSDaniel Borkmann );
850cd13c91dSDaniel Borkmann
851cd13c91dSDaniel Borkmann cleanup_target2:
852cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(detach_fd, loopback, target, &optd);
853cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
854cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
855cd13c91dSDaniel Borkmann
856cd13c91dSDaniel Borkmann cleanup_target:
857cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd);
858cd13c91dSDaniel Borkmann
859cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
860cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
861cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
862cd13c91dSDaniel Borkmann
863cd13c91dSDaniel Borkmann cleanup:
864cd13c91dSDaniel Borkmann test_tc_link__destroy(skel);
865cd13c91dSDaniel Borkmann }
866cd13c91dSDaniel Borkmann
serial_test_tc_opts_replace(void)867cd13c91dSDaniel Borkmann void serial_test_tc_opts_replace(void)
868cd13c91dSDaniel Borkmann {
869cd13c91dSDaniel Borkmann test_tc_opts_replace_target(BPF_TCX_INGRESS);
870cd13c91dSDaniel Borkmann test_tc_opts_replace_target(BPF_TCX_EGRESS);
871cd13c91dSDaniel Borkmann }
872cd13c91dSDaniel Borkmann
test_tc_opts_invalid_target(int target)873cd13c91dSDaniel Borkmann static void test_tc_opts_invalid_target(int target)
874cd13c91dSDaniel Borkmann {
875cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
876cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
877cd13c91dSDaniel Borkmann __u32 fd1, fd2, id1, id2;
878cd13c91dSDaniel Borkmann struct test_tc_link *skel;
879cd13c91dSDaniel Borkmann int err;
880cd13c91dSDaniel Borkmann
881cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load();
882cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load"))
883cd13c91dSDaniel Borkmann goto cleanup;
884cd13c91dSDaniel Borkmann
885cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1);
886cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2);
887cd13c91dSDaniel Borkmann
888cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1);
889cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2);
890cd13c91dSDaniel Borkmann
891cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2");
892cd13c91dSDaniel Borkmann
893cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
894cd13c91dSDaniel Borkmann
895cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
896cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE | BPF_F_AFTER,
897cd13c91dSDaniel Borkmann );
898cd13c91dSDaniel Borkmann
899cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
900cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ERANGE, "prog_attach");
901cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
902cd13c91dSDaniel Borkmann
903cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
904cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE | BPF_F_ID,
905cd13c91dSDaniel Borkmann );
906cd13c91dSDaniel Borkmann
907cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
908cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_attach");
909cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
910cd13c91dSDaniel Borkmann
911cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
912cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER | BPF_F_ID,
913cd13c91dSDaniel Borkmann );
914cd13c91dSDaniel Borkmann
915cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
916cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_attach");
917cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
918cd13c91dSDaniel Borkmann
919cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
920cd13c91dSDaniel Borkmann .relative_fd = fd2,
921cd13c91dSDaniel Borkmann );
922cd13c91dSDaniel Borkmann
923cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
924cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EINVAL, "prog_attach");
925cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
926cd13c91dSDaniel Borkmann
927cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
928cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE | BPF_F_AFTER,
929cd13c91dSDaniel Borkmann .relative_fd = fd2,
930cd13c91dSDaniel Borkmann );
931cd13c91dSDaniel Borkmann
932cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
933cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_attach");
934cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
935cd13c91dSDaniel Borkmann
936cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
937cd13c91dSDaniel Borkmann .flags = BPF_F_ID,
938cd13c91dSDaniel Borkmann .relative_id = id2,
939cd13c91dSDaniel Borkmann );
940cd13c91dSDaniel Borkmann
941cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
942cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EINVAL, "prog_attach");
943cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
944cd13c91dSDaniel Borkmann
945cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
946cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
947cd13c91dSDaniel Borkmann .relative_fd = fd1,
948cd13c91dSDaniel Borkmann );
949cd13c91dSDaniel Borkmann
950cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
951cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_attach");
952cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
953cd13c91dSDaniel Borkmann
954cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
955cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
956cd13c91dSDaniel Borkmann .relative_fd = fd1,
957cd13c91dSDaniel Borkmann );
958cd13c91dSDaniel Borkmann
959cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
960cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_attach");
961cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
962cd13c91dSDaniel Borkmann
963cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta);
964cd13c91dSDaniel Borkmann
965cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
966cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
967cd13c91dSDaniel Borkmann goto cleanup;
968cd13c91dSDaniel Borkmann
969cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
970cd13c91dSDaniel Borkmann
971cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta);
972cd13c91dSDaniel Borkmann
973cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
974cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EEXIST, "prog_attach");
975cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
976cd13c91dSDaniel Borkmann
977cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
978cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
979cd13c91dSDaniel Borkmann .relative_fd = fd1,
980cd13c91dSDaniel Borkmann );
981cd13c91dSDaniel Borkmann
982cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
983cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EEXIST, "prog_attach");
984cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
985cd13c91dSDaniel Borkmann
986cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
987cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
988cd13c91dSDaniel Borkmann .relative_fd = fd1,
989cd13c91dSDaniel Borkmann );
990cd13c91dSDaniel Borkmann
991cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
992cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EEXIST, "prog_attach");
993cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
994cd13c91dSDaniel Borkmann
995cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
996cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE,
997cd13c91dSDaniel Borkmann .relative_fd = fd1,
998cd13c91dSDaniel Borkmann );
999cd13c91dSDaniel Borkmann
1000cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
1001cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EINVAL, "prog_attach_x1");
1002cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
1003cd13c91dSDaniel Borkmann
1004cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
1005cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE,
1006cd13c91dSDaniel Borkmann .replace_prog_fd = fd1,
1007cd13c91dSDaniel Borkmann );
1008cd13c91dSDaniel Borkmann
1009cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
1010cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EEXIST, "prog_attach");
1011cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
1012cd13c91dSDaniel Borkmann
1013cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
1014cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1015cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
1016cd13c91dSDaniel Borkmann cleanup:
1017cd13c91dSDaniel Borkmann test_tc_link__destroy(skel);
1018cd13c91dSDaniel Borkmann }
1019cd13c91dSDaniel Borkmann
serial_test_tc_opts_invalid(void)1020cd13c91dSDaniel Borkmann void serial_test_tc_opts_invalid(void)
1021cd13c91dSDaniel Borkmann {
1022cd13c91dSDaniel Borkmann test_tc_opts_invalid_target(BPF_TCX_INGRESS);
1023cd13c91dSDaniel Borkmann test_tc_opts_invalid_target(BPF_TCX_EGRESS);
1024cd13c91dSDaniel Borkmann }
1025cd13c91dSDaniel Borkmann
test_tc_opts_prepend_target(int target)1026cd13c91dSDaniel Borkmann static void test_tc_opts_prepend_target(int target)
1027cd13c91dSDaniel Borkmann {
1028cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
1029cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
1030cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq);
1031cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4;
1032cd13c91dSDaniel Borkmann struct test_tc_link *skel;
1033cd13c91dSDaniel Borkmann __u32 prog_ids[5];
1034cd13c91dSDaniel Borkmann int err;
1035cd13c91dSDaniel Borkmann
1036cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load();
1037cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load"))
1038cd13c91dSDaniel Borkmann goto cleanup;
1039cd13c91dSDaniel Borkmann
1040cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1);
1041cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2);
1042cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3);
1043cd13c91dSDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4);
1044cd13c91dSDaniel Borkmann
1045cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1);
1046cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2);
1047cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3);
1048cd13c91dSDaniel Borkmann id4 = id_from_prog_fd(fd4);
1049cd13c91dSDaniel Borkmann
1050cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2");
1051cd13c91dSDaniel Borkmann ASSERT_NEQ(id3, id4, "prog_ids_3_4");
1052cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3");
1053cd13c91dSDaniel Borkmann
1054cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
1055cd13c91dSDaniel Borkmann
1056cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
1057cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1058cd13c91dSDaniel Borkmann goto cleanup;
1059cd13c91dSDaniel Borkmann
1060cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
1061cd13c91dSDaniel Borkmann
1062cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
1063cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
1064cd13c91dSDaniel Borkmann );
1065cd13c91dSDaniel Borkmann
1066cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta);
1067cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1068cd13c91dSDaniel Borkmann goto cleanup_target;
1069cd13c91dSDaniel Borkmann
1070cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1071cd13c91dSDaniel Borkmann
1072cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids;
1073cd13c91dSDaniel Borkmann
1074cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
1075cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
1076cd13c91dSDaniel Borkmann
1077cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
1078cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
1079cd13c91dSDaniel Borkmann goto cleanup_target2;
1080cd13c91dSDaniel Borkmann
1081cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count");
1082cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 3, "revision");
1083cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]");
1084cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]");
1085cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
1086cd13c91dSDaniel Borkmann
108737345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
1088cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
1089cd13c91dSDaniel Borkmann
1090cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
1091cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
1092cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3");
1093cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4");
1094cd13c91dSDaniel Borkmann
1095cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
1096cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
1097cd13c91dSDaniel Borkmann );
1098cd13c91dSDaniel Borkmann
1099cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta);
1100cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1101cd13c91dSDaniel Borkmann goto cleanup_target2;
1102cd13c91dSDaniel Borkmann
1103cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
1104cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
1105cd13c91dSDaniel Borkmann );
1106cd13c91dSDaniel Borkmann
1107cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd4, loopback, target, &opta);
1108cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1109cd13c91dSDaniel Borkmann goto cleanup_target3;
1110cd13c91dSDaniel Borkmann
1111cd13c91dSDaniel Borkmann assert_mprog_count(target, 4);
1112cd13c91dSDaniel Borkmann
1113cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
1114cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
1115cd13c91dSDaniel Borkmann
1116cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
1117cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
1118cd13c91dSDaniel Borkmann goto cleanup_target4;
1119cd13c91dSDaniel Borkmann
1120cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 4, "count");
1121cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision");
1122cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id4, "prog_ids[0]");
1123cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]");
1124cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id2, "prog_ids[2]");
1125cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], id1, "prog_ids[3]");
1126cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]");
1127cd13c91dSDaniel Borkmann
112837345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
1129cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
1130cd13c91dSDaniel Borkmann
1131cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
1132cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
1133cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, true, "seen_tc3");
1134cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4");
1135cd13c91dSDaniel Borkmann
1136cd13c91dSDaniel Borkmann cleanup_target4:
1137cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd4, loopback, target, &optd);
1138cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1139cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
1140cd13c91dSDaniel Borkmann
1141cd13c91dSDaniel Borkmann cleanup_target3:
1142cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd);
1143cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1144cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1145cd13c91dSDaniel Borkmann
1146cd13c91dSDaniel Borkmann cleanup_target2:
1147cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
1148cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1149cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
1150cd13c91dSDaniel Borkmann
1151cd13c91dSDaniel Borkmann cleanup_target:
1152cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
1153cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1154cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
1155cd13c91dSDaniel Borkmann
1156cd13c91dSDaniel Borkmann cleanup:
1157cd13c91dSDaniel Borkmann test_tc_link__destroy(skel);
1158cd13c91dSDaniel Borkmann }
1159cd13c91dSDaniel Borkmann
serial_test_tc_opts_prepend(void)1160cd13c91dSDaniel Borkmann void serial_test_tc_opts_prepend(void)
1161cd13c91dSDaniel Borkmann {
1162cd13c91dSDaniel Borkmann test_tc_opts_prepend_target(BPF_TCX_INGRESS);
1163cd13c91dSDaniel Borkmann test_tc_opts_prepend_target(BPF_TCX_EGRESS);
1164cd13c91dSDaniel Borkmann }
1165cd13c91dSDaniel Borkmann
test_tc_opts_append_target(int target)1166cd13c91dSDaniel Borkmann static void test_tc_opts_append_target(int target)
1167cd13c91dSDaniel Borkmann {
1168cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
1169cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
1170cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq);
1171cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4;
1172cd13c91dSDaniel Borkmann struct test_tc_link *skel;
1173cd13c91dSDaniel Borkmann __u32 prog_ids[5];
1174cd13c91dSDaniel Borkmann int err;
1175cd13c91dSDaniel Borkmann
1176cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load();
1177cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load"))
1178cd13c91dSDaniel Borkmann goto cleanup;
1179cd13c91dSDaniel Borkmann
1180cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1);
1181cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2);
1182cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3);
1183cd13c91dSDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4);
1184cd13c91dSDaniel Borkmann
1185cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1);
1186cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2);
1187cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3);
1188cd13c91dSDaniel Borkmann id4 = id_from_prog_fd(fd4);
1189cd13c91dSDaniel Borkmann
1190cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2");
1191cd13c91dSDaniel Borkmann ASSERT_NEQ(id3, id4, "prog_ids_3_4");
1192cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3");
1193cd13c91dSDaniel Borkmann
1194cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
1195cd13c91dSDaniel Borkmann
1196cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
1197cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1198cd13c91dSDaniel Borkmann goto cleanup;
1199cd13c91dSDaniel Borkmann
1200cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
1201cd13c91dSDaniel Borkmann
1202cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
1203cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
1204cd13c91dSDaniel Borkmann );
1205cd13c91dSDaniel Borkmann
1206cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta);
1207cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1208cd13c91dSDaniel Borkmann goto cleanup_target;
1209cd13c91dSDaniel Borkmann
1210cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1211cd13c91dSDaniel Borkmann
1212cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids;
1213cd13c91dSDaniel Borkmann
1214cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
1215cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
1216cd13c91dSDaniel Borkmann
1217cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
1218cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
1219cd13c91dSDaniel Borkmann goto cleanup_target2;
1220cd13c91dSDaniel Borkmann
1221cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count");
1222cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 3, "revision");
1223cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
1224cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]");
1225cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
1226cd13c91dSDaniel Borkmann
122737345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
1228cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
1229cd13c91dSDaniel Borkmann
1230cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
1231cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
1232cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3");
1233cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4");
1234cd13c91dSDaniel Borkmann
1235cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
1236cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
1237cd13c91dSDaniel Borkmann );
1238cd13c91dSDaniel Borkmann
1239cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta);
1240cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1241cd13c91dSDaniel Borkmann goto cleanup_target2;
1242cd13c91dSDaniel Borkmann
1243cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
1244cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
1245cd13c91dSDaniel Borkmann );
1246cd13c91dSDaniel Borkmann
1247cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd4, loopback, target, &opta);
1248cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1249cd13c91dSDaniel Borkmann goto cleanup_target3;
1250cd13c91dSDaniel Borkmann
1251cd13c91dSDaniel Borkmann assert_mprog_count(target, 4);
1252cd13c91dSDaniel Borkmann
1253cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
1254cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
1255cd13c91dSDaniel Borkmann
1256cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
1257cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
1258cd13c91dSDaniel Borkmann goto cleanup_target4;
1259cd13c91dSDaniel Borkmann
1260cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 4, "count");
1261cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision");
1262cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
1263cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]");
1264cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id3, "prog_ids[2]");
1265cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]");
1266cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]");
1267cd13c91dSDaniel Borkmann
126837345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
1269cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
1270cd13c91dSDaniel Borkmann
1271cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1");
1272cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2");
1273cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc3, true, "seen_tc3");
1274cd13c91dSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4");
1275cd13c91dSDaniel Borkmann
1276cd13c91dSDaniel Borkmann cleanup_target4:
1277cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd4, loopback, target, &optd);
1278cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1279cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
1280cd13c91dSDaniel Borkmann
1281cd13c91dSDaniel Borkmann cleanup_target3:
1282cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd);
1283cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1284cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1285cd13c91dSDaniel Borkmann
1286cd13c91dSDaniel Borkmann cleanup_target2:
1287cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
1288cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1289cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
1290cd13c91dSDaniel Borkmann
1291cd13c91dSDaniel Borkmann cleanup_target:
1292cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
1293cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1294cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
1295cd13c91dSDaniel Borkmann
1296cd13c91dSDaniel Borkmann cleanup:
1297cd13c91dSDaniel Borkmann test_tc_link__destroy(skel);
1298cd13c91dSDaniel Borkmann }
1299cd13c91dSDaniel Borkmann
serial_test_tc_opts_append(void)1300cd13c91dSDaniel Borkmann void serial_test_tc_opts_append(void)
1301cd13c91dSDaniel Borkmann {
1302cd13c91dSDaniel Borkmann test_tc_opts_append_target(BPF_TCX_INGRESS);
1303cd13c91dSDaniel Borkmann test_tc_opts_append_target(BPF_TCX_EGRESS);
1304cd13c91dSDaniel Borkmann }
1305cd13c91dSDaniel Borkmann
test_tc_opts_dev_cleanup_target(int target)1306cd13c91dSDaniel Borkmann static void test_tc_opts_dev_cleanup_target(int target)
1307cd13c91dSDaniel Borkmann {
1308cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
1309cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
1310cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq);
1311cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4;
1312cd13c91dSDaniel Borkmann struct test_tc_link *skel;
1313cd13c91dSDaniel Borkmann int err, ifindex;
1314cd13c91dSDaniel Borkmann
1315cd13c91dSDaniel Borkmann ASSERT_OK(system("ip link add dev tcx_opts1 type veth peer name tcx_opts2"), "add veth");
1316cd13c91dSDaniel Borkmann ifindex = if_nametoindex("tcx_opts1");
1317cd13c91dSDaniel Borkmann ASSERT_NEQ(ifindex, 0, "non_zero_ifindex");
1318cd13c91dSDaniel Borkmann
1319cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load();
1320cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load"))
1321cd13c91dSDaniel Borkmann goto cleanup;
1322cd13c91dSDaniel Borkmann
1323cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1);
1324cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2);
1325cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3);
1326cd13c91dSDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4);
1327cd13c91dSDaniel Borkmann
1328cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1);
1329cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2);
1330cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3);
1331cd13c91dSDaniel Borkmann id4 = id_from_prog_fd(fd4);
1332cd13c91dSDaniel Borkmann
1333cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2");
1334cd13c91dSDaniel Borkmann ASSERT_NEQ(id3, id4, "prog_ids_3_4");
1335cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3");
1336cd13c91dSDaniel Borkmann
1337cd13c91dSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 0);
1338cd13c91dSDaniel Borkmann
1339cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, ifindex, target, &opta);
1340cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1341cd13c91dSDaniel Borkmann goto cleanup;
1342cd13c91dSDaniel Borkmann
1343cd13c91dSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 1);
1344cd13c91dSDaniel Borkmann
1345cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, ifindex, target, &opta);
1346cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1347cd13c91dSDaniel Borkmann goto cleanup1;
1348cd13c91dSDaniel Borkmann
1349cd13c91dSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 2);
1350cd13c91dSDaniel Borkmann
1351cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, ifindex, target, &opta);
1352cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1353cd13c91dSDaniel Borkmann goto cleanup2;
1354cd13c91dSDaniel Borkmann
1355cd13c91dSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 3);
1356cd13c91dSDaniel Borkmann
1357cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd4, ifindex, target, &opta);
1358cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1359cd13c91dSDaniel Borkmann goto cleanup3;
1360cd13c91dSDaniel Borkmann
1361cd13c91dSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 4);
1362cd13c91dSDaniel Borkmann
1363cd13c91dSDaniel Borkmann ASSERT_OK(system("ip link del dev tcx_opts1"), "del veth");
1364cd13c91dSDaniel Borkmann ASSERT_EQ(if_nametoindex("tcx_opts1"), 0, "dev1_removed");
1365cd13c91dSDaniel Borkmann ASSERT_EQ(if_nametoindex("tcx_opts2"), 0, "dev2_removed");
1366cd13c91dSDaniel Borkmann return;
1367cd13c91dSDaniel Borkmann cleanup3:
1368cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd);
1369cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1370cd13c91dSDaniel Borkmann
1371cd13c91dSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 2);
1372cd13c91dSDaniel Borkmann cleanup2:
1373cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
1374cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1375cd13c91dSDaniel Borkmann
1376cd13c91dSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 1);
1377cd13c91dSDaniel Borkmann cleanup1:
1378cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
1379cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1380cd13c91dSDaniel Borkmann
1381cd13c91dSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 0);
1382cd13c91dSDaniel Borkmann cleanup:
1383cd13c91dSDaniel Borkmann test_tc_link__destroy(skel);
1384cd13c91dSDaniel Borkmann
1385cd13c91dSDaniel Borkmann ASSERT_OK(system("ip link del dev tcx_opts1"), "del veth");
1386cd13c91dSDaniel Borkmann ASSERT_EQ(if_nametoindex("tcx_opts1"), 0, "dev1_removed");
1387cd13c91dSDaniel Borkmann ASSERT_EQ(if_nametoindex("tcx_opts2"), 0, "dev2_removed");
1388cd13c91dSDaniel Borkmann }
1389cd13c91dSDaniel Borkmann
serial_test_tc_opts_dev_cleanup(void)1390cd13c91dSDaniel Borkmann void serial_test_tc_opts_dev_cleanup(void)
1391cd13c91dSDaniel Borkmann {
1392cd13c91dSDaniel Borkmann test_tc_opts_dev_cleanup_target(BPF_TCX_INGRESS);
1393cd13c91dSDaniel Borkmann test_tc_opts_dev_cleanup_target(BPF_TCX_EGRESS);
1394cd13c91dSDaniel Borkmann }
1395cd13c91dSDaniel Borkmann
test_tc_opts_mixed_target(int target)1396cd13c91dSDaniel Borkmann static void test_tc_opts_mixed_target(int target)
1397cd13c91dSDaniel Borkmann {
1398cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
1399cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
1400cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq);
1401cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_tcx_opts, optl);
1402cd13c91dSDaniel Borkmann __u32 pid1, pid2, pid3, pid4, lid2, lid4;
1403cd13c91dSDaniel Borkmann __u32 prog_flags[4], link_flags[4];
1404cd13c91dSDaniel Borkmann __u32 prog_ids[4], link_ids[4];
1405cd13c91dSDaniel Borkmann struct test_tc_link *skel;
1406cd13c91dSDaniel Borkmann struct bpf_link *link;
1407cd13c91dSDaniel Borkmann int err, detach_fd;
1408cd13c91dSDaniel Borkmann
1409cd13c91dSDaniel Borkmann skel = test_tc_link__open();
1410cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_open"))
1411cd13c91dSDaniel Borkmann goto cleanup;
1412cd13c91dSDaniel Borkmann
1413cd13c91dSDaniel Borkmann ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1, target),
1414cd13c91dSDaniel Borkmann 0, "tc1_attach_type");
1415cd13c91dSDaniel Borkmann ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc2, target),
1416cd13c91dSDaniel Borkmann 0, "tc2_attach_type");
1417cd13c91dSDaniel Borkmann ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc3, target),
1418cd13c91dSDaniel Borkmann 0, "tc3_attach_type");
1419cd13c91dSDaniel Borkmann ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc4, target),
1420cd13c91dSDaniel Borkmann 0, "tc4_attach_type");
1421cd13c91dSDaniel Borkmann
1422cd13c91dSDaniel Borkmann err = test_tc_link__load(skel);
1423cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "skel_load"))
1424cd13c91dSDaniel Borkmann goto cleanup;
1425cd13c91dSDaniel Borkmann
1426cd13c91dSDaniel Borkmann pid1 = id_from_prog_fd(bpf_program__fd(skel->progs.tc1));
1427cd13c91dSDaniel Borkmann pid2 = id_from_prog_fd(bpf_program__fd(skel->progs.tc2));
1428cd13c91dSDaniel Borkmann pid3 = id_from_prog_fd(bpf_program__fd(skel->progs.tc3));
1429cd13c91dSDaniel Borkmann pid4 = id_from_prog_fd(bpf_program__fd(skel->progs.tc4));
1430cd13c91dSDaniel Borkmann
1431cd13c91dSDaniel Borkmann ASSERT_NEQ(pid1, pid2, "prog_ids_1_2");
1432cd13c91dSDaniel Borkmann ASSERT_NEQ(pid3, pid4, "prog_ids_3_4");
1433cd13c91dSDaniel Borkmann ASSERT_NEQ(pid2, pid3, "prog_ids_2_3");
1434cd13c91dSDaniel Borkmann
1435cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
1436cd13c91dSDaniel Borkmann
1437cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(bpf_program__fd(skel->progs.tc1),
1438cd13c91dSDaniel Borkmann loopback, target, &opta);
1439cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1440cd13c91dSDaniel Borkmann goto cleanup;
1441cd13c91dSDaniel Borkmann
1442cd13c91dSDaniel Borkmann detach_fd = bpf_program__fd(skel->progs.tc1);
1443cd13c91dSDaniel Borkmann
1444cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
1445cd13c91dSDaniel Borkmann
1446cd13c91dSDaniel Borkmann link = bpf_program__attach_tcx(skel->progs.tc2, loopback, &optl);
1447cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(link, "link_attach"))
1448cd13c91dSDaniel Borkmann goto cleanup1;
1449cd13c91dSDaniel Borkmann skel->links.tc2 = link;
1450cd13c91dSDaniel Borkmann
1451cd13c91dSDaniel Borkmann lid2 = id_from_link_fd(bpf_link__fd(skel->links.tc2));
1452cd13c91dSDaniel Borkmann
1453cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1454cd13c91dSDaniel Borkmann
1455cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
1456cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE,
1457cd13c91dSDaniel Borkmann .replace_prog_fd = bpf_program__fd(skel->progs.tc1),
1458cd13c91dSDaniel Borkmann );
1459cd13c91dSDaniel Borkmann
1460cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(bpf_program__fd(skel->progs.tc2),
1461cd13c91dSDaniel Borkmann loopback, target, &opta);
1462cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EEXIST, "prog_attach");
1463cd13c91dSDaniel Borkmann
1464cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1465cd13c91dSDaniel Borkmann
1466cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
1467cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE,
1468cd13c91dSDaniel Borkmann .replace_prog_fd = bpf_program__fd(skel->progs.tc2),
1469cd13c91dSDaniel Borkmann );
1470cd13c91dSDaniel Borkmann
1471cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(bpf_program__fd(skel->progs.tc1),
1472cd13c91dSDaniel Borkmann loopback, target, &opta);
1473cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EEXIST, "prog_attach");
1474cd13c91dSDaniel Borkmann
1475cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1476cd13c91dSDaniel Borkmann
1477cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
1478cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE,
1479cd13c91dSDaniel Borkmann .replace_prog_fd = bpf_program__fd(skel->progs.tc2),
1480cd13c91dSDaniel Borkmann );
1481cd13c91dSDaniel Borkmann
1482cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(bpf_program__fd(skel->progs.tc3),
1483cd13c91dSDaniel Borkmann loopback, target, &opta);
1484cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EBUSY, "prog_attach");
1485cd13c91dSDaniel Borkmann
1486cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1487cd13c91dSDaniel Borkmann
1488cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
1489cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE,
1490cd13c91dSDaniel Borkmann .replace_prog_fd = bpf_program__fd(skel->progs.tc1),
1491cd13c91dSDaniel Borkmann );
1492cd13c91dSDaniel Borkmann
1493cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(bpf_program__fd(skel->progs.tc3),
1494cd13c91dSDaniel Borkmann loopback, target, &opta);
1495cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1496cd13c91dSDaniel Borkmann goto cleanup1;
1497cd13c91dSDaniel Borkmann
1498cd13c91dSDaniel Borkmann detach_fd = bpf_program__fd(skel->progs.tc3);
1499cd13c91dSDaniel Borkmann
1500cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1501cd13c91dSDaniel Borkmann
1502cd13c91dSDaniel Borkmann link = bpf_program__attach_tcx(skel->progs.tc4, loopback, &optl);
1503cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(link, "link_attach"))
1504cd13c91dSDaniel Borkmann goto cleanup1;
1505cd13c91dSDaniel Borkmann skel->links.tc4 = link;
1506cd13c91dSDaniel Borkmann
1507cd13c91dSDaniel Borkmann lid4 = id_from_link_fd(bpf_link__fd(skel->links.tc4));
1508cd13c91dSDaniel Borkmann
1509cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
1510cd13c91dSDaniel Borkmann
1511cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
1512cd13c91dSDaniel Borkmann .flags = BPF_F_REPLACE,
1513cd13c91dSDaniel Borkmann .replace_prog_fd = bpf_program__fd(skel->progs.tc4),
1514cd13c91dSDaniel Borkmann );
1515cd13c91dSDaniel Borkmann
1516cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(bpf_program__fd(skel->progs.tc2),
1517cd13c91dSDaniel Borkmann loopback, target, &opta);
1518cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EEXIST, "prog_attach");
1519cd13c91dSDaniel Borkmann
1520cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids;
1521cd13c91dSDaniel Borkmann optq.prog_attach_flags = prog_flags;
1522cd13c91dSDaniel Borkmann optq.link_ids = link_ids;
1523cd13c91dSDaniel Borkmann optq.link_attach_flags = link_flags;
1524cd13c91dSDaniel Borkmann
1525cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
1526cd13c91dSDaniel Borkmann memset(prog_flags, 0, sizeof(prog_flags));
1527cd13c91dSDaniel Borkmann memset(link_ids, 0, sizeof(link_ids));
1528cd13c91dSDaniel Borkmann memset(link_flags, 0, sizeof(link_flags));
1529cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
1530cd13c91dSDaniel Borkmann
1531cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
1532cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
1533cd13c91dSDaniel Borkmann goto cleanup1;
1534cd13c91dSDaniel Borkmann
1535cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 3, "count");
1536cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision");
1537cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], pid3, "prog_ids[0]");
1538cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_attach_flags[0], 0, "prog_flags[0]");
1539cd13c91dSDaniel Borkmann ASSERT_EQ(optq.link_ids[0], 0, "link_ids[0]");
1540cd13c91dSDaniel Borkmann ASSERT_EQ(optq.link_attach_flags[0], 0, "link_flags[0]");
1541cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], pid2, "prog_ids[1]");
1542cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_attach_flags[1], 0, "prog_flags[1]");
1543cd13c91dSDaniel Borkmann ASSERT_EQ(optq.link_ids[1], lid2, "link_ids[1]");
1544cd13c91dSDaniel Borkmann ASSERT_EQ(optq.link_attach_flags[1], 0, "link_flags[1]");
1545cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], pid4, "prog_ids[2]");
1546cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_attach_flags[2], 0, "prog_flags[2]");
1547cd13c91dSDaniel Borkmann ASSERT_EQ(optq.link_ids[2], lid4, "link_ids[2]");
1548cd13c91dSDaniel Borkmann ASSERT_EQ(optq.link_attach_flags[2], 0, "link_flags[2]");
1549cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], 0, "prog_ids[3]");
1550cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_attach_flags[3], 0, "prog_flags[3]");
1551cd13c91dSDaniel Borkmann ASSERT_EQ(optq.link_ids[3], 0, "link_ids[3]");
1552cd13c91dSDaniel Borkmann ASSERT_EQ(optq.link_attach_flags[3], 0, "link_flags[3]");
1553cd13c91dSDaniel Borkmann
1554cd13c91dSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
1555cd13c91dSDaniel Borkmann
1556cd13c91dSDaniel Borkmann cleanup1:
1557cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(detach_fd, loopback, target, &optd);
1558cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1559cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1560cd13c91dSDaniel Borkmann
1561cd13c91dSDaniel Borkmann cleanup:
1562cd13c91dSDaniel Borkmann test_tc_link__destroy(skel);
1563cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
1564cd13c91dSDaniel Borkmann }
1565cd13c91dSDaniel Borkmann
serial_test_tc_opts_mixed(void)1566cd13c91dSDaniel Borkmann void serial_test_tc_opts_mixed(void)
1567cd13c91dSDaniel Borkmann {
1568cd13c91dSDaniel Borkmann test_tc_opts_mixed_target(BPF_TCX_INGRESS);
1569cd13c91dSDaniel Borkmann test_tc_opts_mixed_target(BPF_TCX_EGRESS);
1570cd13c91dSDaniel Borkmann }
1571cd13c91dSDaniel Borkmann
test_tc_opts_demixed_target(int target)1572cd13c91dSDaniel Borkmann static void test_tc_opts_demixed_target(int target)
1573cd13c91dSDaniel Borkmann {
1574cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
1575cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
1576cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_tcx_opts, optl);
1577cd13c91dSDaniel Borkmann struct test_tc_link *skel;
1578cd13c91dSDaniel Borkmann struct bpf_link *link;
1579cd13c91dSDaniel Borkmann __u32 pid1, pid2;
1580cd13c91dSDaniel Borkmann int err;
1581cd13c91dSDaniel Borkmann
1582cd13c91dSDaniel Borkmann skel = test_tc_link__open();
1583cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_open"))
1584cd13c91dSDaniel Borkmann goto cleanup;
1585cd13c91dSDaniel Borkmann
1586cd13c91dSDaniel Borkmann ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc1, target),
1587cd13c91dSDaniel Borkmann 0, "tc1_attach_type");
1588cd13c91dSDaniel Borkmann ASSERT_EQ(bpf_program__set_expected_attach_type(skel->progs.tc2, target),
1589cd13c91dSDaniel Borkmann 0, "tc2_attach_type");
1590cd13c91dSDaniel Borkmann
1591cd13c91dSDaniel Borkmann err = test_tc_link__load(skel);
1592cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "skel_load"))
1593cd13c91dSDaniel Borkmann goto cleanup;
1594cd13c91dSDaniel Borkmann
1595cd13c91dSDaniel Borkmann pid1 = id_from_prog_fd(bpf_program__fd(skel->progs.tc1));
1596cd13c91dSDaniel Borkmann pid2 = id_from_prog_fd(bpf_program__fd(skel->progs.tc2));
1597cd13c91dSDaniel Borkmann ASSERT_NEQ(pid1, pid2, "prog_ids_1_2");
1598cd13c91dSDaniel Borkmann
1599cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
1600cd13c91dSDaniel Borkmann
1601cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(bpf_program__fd(skel->progs.tc1),
1602cd13c91dSDaniel Borkmann loopback, target, &opta);
1603cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1604cd13c91dSDaniel Borkmann goto cleanup;
1605cd13c91dSDaniel Borkmann
1606cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
1607cd13c91dSDaniel Borkmann
1608cd13c91dSDaniel Borkmann link = bpf_program__attach_tcx(skel->progs.tc2, loopback, &optl);
1609cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(link, "link_attach"))
1610cd13c91dSDaniel Borkmann goto cleanup1;
1611cd13c91dSDaniel Borkmann skel->links.tc2 = link;
1612cd13c91dSDaniel Borkmann
1613cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1614cd13c91dSDaniel Borkmann
1615cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
1616cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
1617cd13c91dSDaniel Borkmann );
1618cd13c91dSDaniel Borkmann
1619cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd);
1620cd13c91dSDaniel Borkmann ASSERT_EQ(err, -EBUSY, "prog_detach");
1621cd13c91dSDaniel Borkmann
1622cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1623cd13c91dSDaniel Borkmann
1624cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
1625cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
1626cd13c91dSDaniel Borkmann );
1627cd13c91dSDaniel Borkmann
1628cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd);
1629cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1630cd13c91dSDaniel Borkmann
1631cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
1632cd13c91dSDaniel Borkmann goto cleanup;
1633cd13c91dSDaniel Borkmann
1634cd13c91dSDaniel Borkmann cleanup1:
1635cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(bpf_program__fd(skel->progs.tc1),
1636cd13c91dSDaniel Borkmann loopback, target, &optd);
1637cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1638cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1639cd13c91dSDaniel Borkmann
1640cd13c91dSDaniel Borkmann cleanup:
1641cd13c91dSDaniel Borkmann test_tc_link__destroy(skel);
1642cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
1643cd13c91dSDaniel Borkmann }
1644cd13c91dSDaniel Borkmann
serial_test_tc_opts_demixed(void)1645cd13c91dSDaniel Borkmann void serial_test_tc_opts_demixed(void)
1646cd13c91dSDaniel Borkmann {
1647cd13c91dSDaniel Borkmann test_tc_opts_demixed_target(BPF_TCX_INGRESS);
1648cd13c91dSDaniel Borkmann test_tc_opts_demixed_target(BPF_TCX_EGRESS);
1649cd13c91dSDaniel Borkmann }
1650cd13c91dSDaniel Borkmann
test_tc_opts_detach_target(int target)1651cd13c91dSDaniel Borkmann static void test_tc_opts_detach_target(int target)
1652cd13c91dSDaniel Borkmann {
1653cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
1654cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
1655cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq);
1656cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4;
1657cd13c91dSDaniel Borkmann struct test_tc_link *skel;
1658cd13c91dSDaniel Borkmann __u32 prog_ids[5];
1659cd13c91dSDaniel Borkmann int err;
1660cd13c91dSDaniel Borkmann
1661cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load();
1662cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load"))
1663cd13c91dSDaniel Borkmann goto cleanup;
1664cd13c91dSDaniel Borkmann
1665cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1);
1666cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2);
1667cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3);
1668cd13c91dSDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4);
1669cd13c91dSDaniel Borkmann
1670cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1);
1671cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2);
1672cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3);
1673cd13c91dSDaniel Borkmann id4 = id_from_prog_fd(fd4);
1674cd13c91dSDaniel Borkmann
1675cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2");
1676cd13c91dSDaniel Borkmann ASSERT_NEQ(id3, id4, "prog_ids_3_4");
1677cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3");
1678cd13c91dSDaniel Borkmann
1679cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
1680cd13c91dSDaniel Borkmann
1681cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
1682cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1683cd13c91dSDaniel Borkmann goto cleanup;
1684cd13c91dSDaniel Borkmann
1685cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
1686cd13c91dSDaniel Borkmann
1687cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta);
1688cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1689cd13c91dSDaniel Borkmann goto cleanup1;
1690cd13c91dSDaniel Borkmann
1691cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1692cd13c91dSDaniel Borkmann
1693cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta);
1694cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1695cd13c91dSDaniel Borkmann goto cleanup2;
1696cd13c91dSDaniel Borkmann
1697cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
1698cd13c91dSDaniel Borkmann
1699cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd4, loopback, target, &opta);
1700cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1701cd13c91dSDaniel Borkmann goto cleanup3;
1702cd13c91dSDaniel Borkmann
1703cd13c91dSDaniel Borkmann assert_mprog_count(target, 4);
1704cd13c91dSDaniel Borkmann
1705cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids;
1706cd13c91dSDaniel Borkmann
1707cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
1708cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
1709cd13c91dSDaniel Borkmann
1710cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
1711cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
1712cd13c91dSDaniel Borkmann goto cleanup4;
1713cd13c91dSDaniel Borkmann
1714cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 4, "count");
1715cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision");
1716cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
1717cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]");
1718cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id3, "prog_ids[2]");
1719cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]");
1720cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]");
1721cd13c91dSDaniel Borkmann
1722cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
1723cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
1724cd13c91dSDaniel Borkmann );
1725cd13c91dSDaniel Borkmann
1726cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd);
1727cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1728cd13c91dSDaniel Borkmann
1729cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
1730cd13c91dSDaniel Borkmann
1731cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
1732cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
1733cd13c91dSDaniel Borkmann
1734cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
1735cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
1736cd13c91dSDaniel Borkmann goto cleanup4;
1737cd13c91dSDaniel Borkmann
1738cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 3, "count");
1739cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 6, "revision");
1740cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]");
1741cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]");
1742cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id4, "prog_ids[2]");
1743cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], 0, "prog_ids[3]");
1744cd13c91dSDaniel Borkmann
1745cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
1746cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
1747cd13c91dSDaniel Borkmann );
1748cd13c91dSDaniel Borkmann
1749cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd);
1750cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1751cd13c91dSDaniel Borkmann
1752cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1753cd13c91dSDaniel Borkmann
1754cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
1755cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
1756cd13c91dSDaniel Borkmann
1757cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
1758cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
1759cd13c91dSDaniel Borkmann goto cleanup4;
1760cd13c91dSDaniel Borkmann
1761cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count");
1762cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 7, "revision");
1763cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]");
1764cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]");
1765cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
1766cd13c91dSDaniel Borkmann
1767cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd);
1768cd13c91dSDaniel Borkmann
1769cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd);
1770cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1771cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
1772cd13c91dSDaniel Borkmann
1773cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
1774cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1775cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
1776cd13c91dSDaniel Borkmann
1777cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
1778cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
1779cd13c91dSDaniel Borkmann );
1780cd13c91dSDaniel Borkmann
1781cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd);
1782cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_detach");
1783cd13c91dSDaniel Borkmann
1784cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
1785cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
1786cd13c91dSDaniel Borkmann );
1787cd13c91dSDaniel Borkmann
1788cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd);
1789cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_detach");
1790cd13c91dSDaniel Borkmann goto cleanup;
1791cd13c91dSDaniel Borkmann
1792cd13c91dSDaniel Borkmann cleanup4:
1793cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd4, loopback, target, &optd);
1794cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1795cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
1796cd13c91dSDaniel Borkmann
1797cd13c91dSDaniel Borkmann cleanup3:
1798cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd);
1799cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1800cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1801cd13c91dSDaniel Borkmann
1802cd13c91dSDaniel Borkmann cleanup2:
1803cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
1804cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1805cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
1806cd13c91dSDaniel Borkmann
1807cd13c91dSDaniel Borkmann cleanup1:
1808cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
1809cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1810cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
1811cd13c91dSDaniel Borkmann
1812cd13c91dSDaniel Borkmann cleanup:
1813cd13c91dSDaniel Borkmann test_tc_link__destroy(skel);
1814cd13c91dSDaniel Borkmann }
1815cd13c91dSDaniel Borkmann
serial_test_tc_opts_detach(void)1816cd13c91dSDaniel Borkmann void serial_test_tc_opts_detach(void)
1817cd13c91dSDaniel Borkmann {
1818cd13c91dSDaniel Borkmann test_tc_opts_detach_target(BPF_TCX_INGRESS);
1819cd13c91dSDaniel Borkmann test_tc_opts_detach_target(BPF_TCX_EGRESS);
1820cd13c91dSDaniel Borkmann }
1821cd13c91dSDaniel Borkmann
test_tc_opts_detach_before_target(int target)1822cd13c91dSDaniel Borkmann static void test_tc_opts_detach_before_target(int target)
1823cd13c91dSDaniel Borkmann {
1824cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
1825cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
1826cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq);
1827cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4;
1828cd13c91dSDaniel Borkmann struct test_tc_link *skel;
1829cd13c91dSDaniel Borkmann __u32 prog_ids[5];
1830cd13c91dSDaniel Borkmann int err;
1831cd13c91dSDaniel Borkmann
1832cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load();
1833cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load"))
1834cd13c91dSDaniel Borkmann goto cleanup;
1835cd13c91dSDaniel Borkmann
1836cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1);
1837cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2);
1838cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3);
1839cd13c91dSDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4);
1840cd13c91dSDaniel Borkmann
1841cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1);
1842cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2);
1843cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3);
1844cd13c91dSDaniel Borkmann id4 = id_from_prog_fd(fd4);
1845cd13c91dSDaniel Borkmann
1846cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2");
1847cd13c91dSDaniel Borkmann ASSERT_NEQ(id3, id4, "prog_ids_3_4");
1848cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3");
1849cd13c91dSDaniel Borkmann
1850cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
1851cd13c91dSDaniel Borkmann
1852cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
1853cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1854cd13c91dSDaniel Borkmann goto cleanup;
1855cd13c91dSDaniel Borkmann
1856cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
1857cd13c91dSDaniel Borkmann
1858cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta);
1859cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1860cd13c91dSDaniel Borkmann goto cleanup1;
1861cd13c91dSDaniel Borkmann
1862cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1863cd13c91dSDaniel Borkmann
1864cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta);
1865cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1866cd13c91dSDaniel Borkmann goto cleanup2;
1867cd13c91dSDaniel Borkmann
1868cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
1869cd13c91dSDaniel Borkmann
1870cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd4, loopback, target, &opta);
1871cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
1872cd13c91dSDaniel Borkmann goto cleanup3;
1873cd13c91dSDaniel Borkmann
1874cd13c91dSDaniel Borkmann assert_mprog_count(target, 4);
1875cd13c91dSDaniel Borkmann
1876cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids;
1877cd13c91dSDaniel Borkmann
1878cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
1879cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
1880cd13c91dSDaniel Borkmann
1881cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
1882cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
1883cd13c91dSDaniel Borkmann goto cleanup4;
1884cd13c91dSDaniel Borkmann
1885cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 4, "count");
1886cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision");
1887cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
1888cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]");
1889cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id3, "prog_ids[2]");
1890cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]");
1891cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]");
1892cd13c91dSDaniel Borkmann
1893cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
1894cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
1895cd13c91dSDaniel Borkmann .relative_fd = fd2,
1896cd13c91dSDaniel Borkmann );
1897cd13c91dSDaniel Borkmann
1898cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
1899cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1900cd13c91dSDaniel Borkmann
1901cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
1902cd13c91dSDaniel Borkmann
1903cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
1904cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
1905cd13c91dSDaniel Borkmann
1906cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
1907cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
1908cd13c91dSDaniel Borkmann goto cleanup4;
1909cd13c91dSDaniel Borkmann
1910cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 3, "count");
1911cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 6, "revision");
1912cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]");
1913cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]");
1914cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id4, "prog_ids[2]");
1915cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], 0, "prog_ids[3]");
1916cd13c91dSDaniel Borkmann
1917cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
1918cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
1919cd13c91dSDaniel Borkmann .relative_fd = fd2,
1920cd13c91dSDaniel Borkmann );
1921cd13c91dSDaniel Borkmann
1922cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
1923cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_detach");
1924cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
1925cd13c91dSDaniel Borkmann
1926cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
1927cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
1928cd13c91dSDaniel Borkmann .relative_fd = fd4,
1929cd13c91dSDaniel Borkmann );
1930cd13c91dSDaniel Borkmann
1931cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
1932cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ERANGE, "prog_detach");
1933cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
1934cd13c91dSDaniel Borkmann
1935cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
1936cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
1937cd13c91dSDaniel Borkmann .relative_fd = fd1,
1938cd13c91dSDaniel Borkmann );
1939cd13c91dSDaniel Borkmann
1940cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
1941cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_detach");
1942cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
1943cd13c91dSDaniel Borkmann
1944cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
1945cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
1946cd13c91dSDaniel Borkmann .relative_fd = fd3,
1947cd13c91dSDaniel Borkmann );
1948cd13c91dSDaniel Borkmann
1949cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
1950cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1951cd13c91dSDaniel Borkmann
1952cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
1953cd13c91dSDaniel Borkmann
1954cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
1955cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
1956cd13c91dSDaniel Borkmann
1957cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
1958cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
1959cd13c91dSDaniel Borkmann goto cleanup4;
1960cd13c91dSDaniel Borkmann
1961cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count");
1962cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 7, "revision");
1963cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id3, "prog_ids[0]");
1964cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id4, "prog_ids[1]");
1965cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
1966cd13c91dSDaniel Borkmann
1967cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
1968cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
1969cd13c91dSDaniel Borkmann .relative_fd = fd4,
1970cd13c91dSDaniel Borkmann );
1971cd13c91dSDaniel Borkmann
1972cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd);
1973cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1974cd13c91dSDaniel Borkmann
1975cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
1976cd13c91dSDaniel Borkmann
1977cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
1978cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
1979cd13c91dSDaniel Borkmann
1980cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
1981cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
1982cd13c91dSDaniel Borkmann goto cleanup4;
1983cd13c91dSDaniel Borkmann
1984cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 1, "count");
1985cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 8, "revision");
1986cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id4, "prog_ids[0]");
1987cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
1988cd13c91dSDaniel Borkmann
1989cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
1990cd13c91dSDaniel Borkmann .flags = BPF_F_BEFORE,
1991cd13c91dSDaniel Borkmann );
1992cd13c91dSDaniel Borkmann
1993cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd);
1994cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
1995cd13c91dSDaniel Borkmann
1996cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
1997cd13c91dSDaniel Borkmann goto cleanup;
1998cd13c91dSDaniel Borkmann
1999cd13c91dSDaniel Borkmann cleanup4:
2000cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd4, loopback, target, &optd);
2001cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
2002cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
2003cd13c91dSDaniel Borkmann
2004cd13c91dSDaniel Borkmann cleanup3:
2005cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd);
2006cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
2007cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
2008cd13c91dSDaniel Borkmann
2009cd13c91dSDaniel Borkmann cleanup2:
2010cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
2011cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
2012cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
2013cd13c91dSDaniel Borkmann
2014cd13c91dSDaniel Borkmann cleanup1:
2015cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
2016cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
2017cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
2018cd13c91dSDaniel Borkmann
2019cd13c91dSDaniel Borkmann cleanup:
2020cd13c91dSDaniel Borkmann test_tc_link__destroy(skel);
2021cd13c91dSDaniel Borkmann }
2022cd13c91dSDaniel Borkmann
serial_test_tc_opts_detach_before(void)2023cd13c91dSDaniel Borkmann void serial_test_tc_opts_detach_before(void)
2024cd13c91dSDaniel Borkmann {
2025cd13c91dSDaniel Borkmann test_tc_opts_detach_before_target(BPF_TCX_INGRESS);
2026cd13c91dSDaniel Borkmann test_tc_opts_detach_before_target(BPF_TCX_EGRESS);
2027cd13c91dSDaniel Borkmann }
2028cd13c91dSDaniel Borkmann
test_tc_opts_detach_after_target(int target)2029cd13c91dSDaniel Borkmann static void test_tc_opts_detach_after_target(int target)
2030cd13c91dSDaniel Borkmann {
2031cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
2032cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
2033cd13c91dSDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq);
2034cd13c91dSDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4;
2035cd13c91dSDaniel Borkmann struct test_tc_link *skel;
2036cd13c91dSDaniel Borkmann __u32 prog_ids[5];
2037cd13c91dSDaniel Borkmann int err;
2038cd13c91dSDaniel Borkmann
2039cd13c91dSDaniel Borkmann skel = test_tc_link__open_and_load();
2040cd13c91dSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load"))
2041cd13c91dSDaniel Borkmann goto cleanup;
2042cd13c91dSDaniel Borkmann
2043cd13c91dSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1);
2044cd13c91dSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2);
2045cd13c91dSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3);
2046cd13c91dSDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4);
2047cd13c91dSDaniel Borkmann
2048cd13c91dSDaniel Borkmann id1 = id_from_prog_fd(fd1);
2049cd13c91dSDaniel Borkmann id2 = id_from_prog_fd(fd2);
2050cd13c91dSDaniel Borkmann id3 = id_from_prog_fd(fd3);
2051cd13c91dSDaniel Borkmann id4 = id_from_prog_fd(fd4);
2052cd13c91dSDaniel Borkmann
2053cd13c91dSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2");
2054cd13c91dSDaniel Borkmann ASSERT_NEQ(id3, id4, "prog_ids_3_4");
2055cd13c91dSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3");
2056cd13c91dSDaniel Borkmann
2057cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
2058cd13c91dSDaniel Borkmann
2059cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
2060cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
2061cd13c91dSDaniel Borkmann goto cleanup;
2062cd13c91dSDaniel Borkmann
2063cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
2064cd13c91dSDaniel Borkmann
2065cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta);
2066cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
2067cd13c91dSDaniel Borkmann goto cleanup1;
2068cd13c91dSDaniel Borkmann
2069cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
2070cd13c91dSDaniel Borkmann
2071cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta);
2072cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
2073cd13c91dSDaniel Borkmann goto cleanup2;
2074cd13c91dSDaniel Borkmann
2075cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
2076cd13c91dSDaniel Borkmann
2077cd13c91dSDaniel Borkmann err = bpf_prog_attach_opts(fd4, loopback, target, &opta);
2078cd13c91dSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
2079cd13c91dSDaniel Borkmann goto cleanup3;
2080cd13c91dSDaniel Borkmann
2081cd13c91dSDaniel Borkmann assert_mprog_count(target, 4);
2082cd13c91dSDaniel Borkmann
2083cd13c91dSDaniel Borkmann optq.prog_ids = prog_ids;
2084cd13c91dSDaniel Borkmann
2085cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
2086cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
2087cd13c91dSDaniel Borkmann
2088cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
2089cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
2090cd13c91dSDaniel Borkmann goto cleanup4;
2091cd13c91dSDaniel Borkmann
2092cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 4, "count");
2093cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision");
2094cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
2095cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]");
2096cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id3, "prog_ids[2]");
2097cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]");
2098cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]");
2099cd13c91dSDaniel Borkmann
2100cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
2101cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
2102cd13c91dSDaniel Borkmann .relative_fd = fd1,
2103cd13c91dSDaniel Borkmann );
2104cd13c91dSDaniel Borkmann
2105cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
2106cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
2107cd13c91dSDaniel Borkmann
2108cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
2109cd13c91dSDaniel Borkmann
2110cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
2111cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
2112cd13c91dSDaniel Borkmann
2113cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
2114cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
2115cd13c91dSDaniel Borkmann goto cleanup4;
2116cd13c91dSDaniel Borkmann
2117cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 3, "count");
2118cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 6, "revision");
2119cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
2120cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id3, "prog_ids[1]");
2121cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id4, "prog_ids[2]");
2122cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], 0, "prog_ids[3]");
2123cd13c91dSDaniel Borkmann
2124cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
2125cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
2126cd13c91dSDaniel Borkmann .relative_fd = fd1,
2127cd13c91dSDaniel Borkmann );
2128cd13c91dSDaniel Borkmann
2129cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
2130cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_detach");
2131cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
2132cd13c91dSDaniel Borkmann
2133cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
2134cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
2135cd13c91dSDaniel Borkmann .relative_fd = fd4,
2136cd13c91dSDaniel Borkmann );
2137cd13c91dSDaniel Borkmann
2138cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
2139cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ERANGE, "prog_detach");
2140cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
2141cd13c91dSDaniel Borkmann
2142cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
2143cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
2144cd13c91dSDaniel Borkmann .relative_fd = fd3,
2145cd13c91dSDaniel Borkmann );
2146cd13c91dSDaniel Borkmann
2147cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
2148cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ERANGE, "prog_detach");
2149cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
2150cd13c91dSDaniel Borkmann
2151cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
2152cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
2153cd13c91dSDaniel Borkmann .relative_fd = fd1,
2154cd13c91dSDaniel Borkmann );
2155cd13c91dSDaniel Borkmann
2156cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
2157cd13c91dSDaniel Borkmann ASSERT_EQ(err, -ERANGE, "prog_detach");
2158cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
2159cd13c91dSDaniel Borkmann
2160cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
2161cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
2162cd13c91dSDaniel Borkmann .relative_fd = fd1,
2163cd13c91dSDaniel Borkmann );
2164cd13c91dSDaniel Borkmann
2165cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd);
2166cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
2167cd13c91dSDaniel Borkmann
2168cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
2169cd13c91dSDaniel Borkmann
2170cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
2171cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
2172cd13c91dSDaniel Borkmann
2173cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
2174cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
2175cd13c91dSDaniel Borkmann goto cleanup4;
2176cd13c91dSDaniel Borkmann
2177cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 2, "count");
2178cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 7, "revision");
2179cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
2180cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id4, "prog_ids[1]");
2181cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]");
2182cd13c91dSDaniel Borkmann
2183cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
2184cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
2185cd13c91dSDaniel Borkmann .relative_fd = fd1,
2186cd13c91dSDaniel Borkmann );
2187cd13c91dSDaniel Borkmann
2188cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd);
2189cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
2190cd13c91dSDaniel Borkmann
2191cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
2192cd13c91dSDaniel Borkmann
2193cd13c91dSDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
2194cd13c91dSDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
2195cd13c91dSDaniel Borkmann
2196cd13c91dSDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
2197cd13c91dSDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
2198cd13c91dSDaniel Borkmann goto cleanup4;
2199cd13c91dSDaniel Borkmann
2200cd13c91dSDaniel Borkmann ASSERT_EQ(optq.count, 1, "count");
2201cd13c91dSDaniel Borkmann ASSERT_EQ(optq.revision, 8, "revision");
2202cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
2203cd13c91dSDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
2204cd13c91dSDaniel Borkmann
2205cd13c91dSDaniel Borkmann LIBBPF_OPTS_RESET(optd,
2206cd13c91dSDaniel Borkmann .flags = BPF_F_AFTER,
2207cd13c91dSDaniel Borkmann );
2208cd13c91dSDaniel Borkmann
2209cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd);
2210cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
2211cd13c91dSDaniel Borkmann
2212cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
2213cd13c91dSDaniel Borkmann goto cleanup;
2214cd13c91dSDaniel Borkmann
2215cd13c91dSDaniel Borkmann cleanup4:
2216cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd4, loopback, target, &optd);
2217cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
2218cd13c91dSDaniel Borkmann assert_mprog_count(target, 3);
2219cd13c91dSDaniel Borkmann
2220cd13c91dSDaniel Borkmann cleanup3:
2221cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd);
2222cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
2223cd13c91dSDaniel Borkmann assert_mprog_count(target, 2);
2224cd13c91dSDaniel Borkmann
2225cd13c91dSDaniel Borkmann cleanup2:
2226cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
2227cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
2228cd13c91dSDaniel Borkmann assert_mprog_count(target, 1);
2229cd13c91dSDaniel Borkmann
2230cd13c91dSDaniel Borkmann cleanup1:
2231cd13c91dSDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
2232cd13c91dSDaniel Borkmann ASSERT_OK(err, "prog_detach");
2233cd13c91dSDaniel Borkmann assert_mprog_count(target, 0);
2234cd13c91dSDaniel Borkmann
2235cd13c91dSDaniel Borkmann cleanup:
2236cd13c91dSDaniel Borkmann test_tc_link__destroy(skel);
2237cd13c91dSDaniel Borkmann }
2238cd13c91dSDaniel Borkmann
serial_test_tc_opts_detach_after(void)2239cd13c91dSDaniel Borkmann void serial_test_tc_opts_detach_after(void)
2240cd13c91dSDaniel Borkmann {
2241cd13c91dSDaniel Borkmann test_tc_opts_detach_after_target(BPF_TCX_INGRESS);
2242cd13c91dSDaniel Borkmann test_tc_opts_detach_after_target(BPF_TCX_EGRESS);
2243cd13c91dSDaniel Borkmann }
224421ce6abeSDaniel Borkmann
test_tc_opts_delete_empty(int target,bool chain_tc_old)224521ce6abeSDaniel Borkmann static void test_tc_opts_delete_empty(int target, bool chain_tc_old)
224621ce6abeSDaniel Borkmann {
224721ce6abeSDaniel Borkmann LIBBPF_OPTS(bpf_tc_hook, tc_hook, .ifindex = loopback);
224821ce6abeSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
224921ce6abeSDaniel Borkmann int err;
225021ce6abeSDaniel Borkmann
225121ce6abeSDaniel Borkmann assert_mprog_count(target, 0);
225221ce6abeSDaniel Borkmann if (chain_tc_old) {
225321ce6abeSDaniel Borkmann tc_hook.attach_point = target == BPF_TCX_INGRESS ?
225421ce6abeSDaniel Borkmann BPF_TC_INGRESS : BPF_TC_EGRESS;
225521ce6abeSDaniel Borkmann err = bpf_tc_hook_create(&tc_hook);
225621ce6abeSDaniel Borkmann ASSERT_OK(err, "bpf_tc_hook_create");
2257b7736826SDaniel Borkmann assert_mprog_count(target, 0);
225821ce6abeSDaniel Borkmann }
225921ce6abeSDaniel Borkmann err = bpf_prog_detach_opts(0, loopback, target, &optd);
226021ce6abeSDaniel Borkmann ASSERT_EQ(err, -ENOENT, "prog_detach");
226121ce6abeSDaniel Borkmann if (chain_tc_old) {
226221ce6abeSDaniel Borkmann tc_hook.attach_point = BPF_TC_INGRESS | BPF_TC_EGRESS;
226321ce6abeSDaniel Borkmann bpf_tc_hook_destroy(&tc_hook);
226421ce6abeSDaniel Borkmann }
226521ce6abeSDaniel Borkmann assert_mprog_count(target, 0);
226621ce6abeSDaniel Borkmann }
226721ce6abeSDaniel Borkmann
serial_test_tc_opts_delete_empty(void)226821ce6abeSDaniel Borkmann void serial_test_tc_opts_delete_empty(void)
226921ce6abeSDaniel Borkmann {
227021ce6abeSDaniel Borkmann test_tc_opts_delete_empty(BPF_TCX_INGRESS, false);
227121ce6abeSDaniel Borkmann test_tc_opts_delete_empty(BPF_TCX_EGRESS, false);
227221ce6abeSDaniel Borkmann test_tc_opts_delete_empty(BPF_TCX_INGRESS, true);
227321ce6abeSDaniel Borkmann test_tc_opts_delete_empty(BPF_TCX_EGRESS, true);
227421ce6abeSDaniel Borkmann }
2275ccd9a8beSDaniel Borkmann
test_tc_chain_mixed(int target)2276ccd9a8beSDaniel Borkmann static void test_tc_chain_mixed(int target)
2277ccd9a8beSDaniel Borkmann {
2278ccd9a8beSDaniel Borkmann LIBBPF_OPTS(bpf_tc_opts, tc_opts, .handle = 1, .priority = 1);
2279ccd9a8beSDaniel Borkmann LIBBPF_OPTS(bpf_tc_hook, tc_hook, .ifindex = loopback);
2280ccd9a8beSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
2281ccd9a8beSDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
2282ccd9a8beSDaniel Borkmann __u32 fd1, fd2, fd3, id1, id2, id3;
2283ccd9a8beSDaniel Borkmann struct test_tc_link *skel;
2284ccd9a8beSDaniel Borkmann int err, detach_fd;
2285ccd9a8beSDaniel Borkmann
2286ccd9a8beSDaniel Borkmann skel = test_tc_link__open_and_load();
2287ccd9a8beSDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load"))
2288ccd9a8beSDaniel Borkmann goto cleanup;
2289ccd9a8beSDaniel Borkmann
2290ccd9a8beSDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc4);
2291ccd9a8beSDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc5);
2292ccd9a8beSDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc6);
2293ccd9a8beSDaniel Borkmann
2294ccd9a8beSDaniel Borkmann id1 = id_from_prog_fd(fd1);
2295ccd9a8beSDaniel Borkmann id2 = id_from_prog_fd(fd2);
2296ccd9a8beSDaniel Borkmann id3 = id_from_prog_fd(fd3);
2297ccd9a8beSDaniel Borkmann
2298ccd9a8beSDaniel Borkmann ASSERT_NEQ(id1, id2, "prog_ids_1_2");
2299ccd9a8beSDaniel Borkmann ASSERT_NEQ(id2, id3, "prog_ids_2_3");
2300ccd9a8beSDaniel Borkmann
2301ccd9a8beSDaniel Borkmann assert_mprog_count(target, 0);
2302ccd9a8beSDaniel Borkmann
2303ccd9a8beSDaniel Borkmann tc_hook.attach_point = target == BPF_TCX_INGRESS ?
2304ccd9a8beSDaniel Borkmann BPF_TC_INGRESS : BPF_TC_EGRESS;
2305ccd9a8beSDaniel Borkmann err = bpf_tc_hook_create(&tc_hook);
2306ccd9a8beSDaniel Borkmann err = err == -EEXIST ? 0 : err;
2307ccd9a8beSDaniel Borkmann if (!ASSERT_OK(err, "bpf_tc_hook_create"))
2308ccd9a8beSDaniel Borkmann goto cleanup;
2309ccd9a8beSDaniel Borkmann
2310ccd9a8beSDaniel Borkmann tc_opts.prog_fd = fd2;
2311ccd9a8beSDaniel Borkmann err = bpf_tc_attach(&tc_hook, &tc_opts);
2312ccd9a8beSDaniel Borkmann if (!ASSERT_OK(err, "bpf_tc_attach"))
2313ccd9a8beSDaniel Borkmann goto cleanup_hook;
2314ccd9a8beSDaniel Borkmann
2315ccd9a8beSDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta);
2316ccd9a8beSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
2317ccd9a8beSDaniel Borkmann goto cleanup_filter;
2318ccd9a8beSDaniel Borkmann
2319ccd9a8beSDaniel Borkmann detach_fd = fd3;
2320ccd9a8beSDaniel Borkmann
2321ccd9a8beSDaniel Borkmann assert_mprog_count(target, 1);
2322ccd9a8beSDaniel Borkmann
232337345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
2324ccd9a8beSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
2325ccd9a8beSDaniel Borkmann
2326ccd9a8beSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4");
2327ccd9a8beSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc5, false, "seen_tc5");
2328ccd9a8beSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc6, true, "seen_tc6");
2329ccd9a8beSDaniel Borkmann
2330ccd9a8beSDaniel Borkmann LIBBPF_OPTS_RESET(opta,
2331ccd9a8beSDaniel Borkmann .flags = BPF_F_REPLACE,
2332ccd9a8beSDaniel Borkmann .replace_prog_fd = fd3,
2333ccd9a8beSDaniel Borkmann );
2334ccd9a8beSDaniel Borkmann
2335ccd9a8beSDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
2336ccd9a8beSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
2337ccd9a8beSDaniel Borkmann goto cleanup_opts;
2338ccd9a8beSDaniel Borkmann
2339ccd9a8beSDaniel Borkmann detach_fd = fd1;
2340ccd9a8beSDaniel Borkmann
2341ccd9a8beSDaniel Borkmann assert_mprog_count(target, 1);
2342ccd9a8beSDaniel Borkmann
234337345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
2344ccd9a8beSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
2345ccd9a8beSDaniel Borkmann
2346ccd9a8beSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4");
2347ccd9a8beSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc5, true, "seen_tc5");
2348ccd9a8beSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc6, false, "seen_tc6");
2349ccd9a8beSDaniel Borkmann
2350ccd9a8beSDaniel Borkmann cleanup_opts:
2351ccd9a8beSDaniel Borkmann err = bpf_prog_detach_opts(detach_fd, loopback, target, &optd);
2352ccd9a8beSDaniel Borkmann ASSERT_OK(err, "prog_detach");
2353b7736826SDaniel Borkmann assert_mprog_count(target, 0);
2354ccd9a8beSDaniel Borkmann
235537345b85SDaniel Borkmann tc_skel_reset_all_seen(skel);
2356ccd9a8beSDaniel Borkmann ASSERT_OK(system(ping_cmd), ping_cmd);
2357ccd9a8beSDaniel Borkmann
2358ccd9a8beSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4");
2359ccd9a8beSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc5, true, "seen_tc5");
2360ccd9a8beSDaniel Borkmann ASSERT_EQ(skel->bss->seen_tc6, false, "seen_tc6");
2361ccd9a8beSDaniel Borkmann
2362ccd9a8beSDaniel Borkmann cleanup_filter:
2363ccd9a8beSDaniel Borkmann tc_opts.flags = tc_opts.prog_fd = tc_opts.prog_id = 0;
2364ccd9a8beSDaniel Borkmann err = bpf_tc_detach(&tc_hook, &tc_opts);
2365ccd9a8beSDaniel Borkmann ASSERT_OK(err, "bpf_tc_detach");
2366ccd9a8beSDaniel Borkmann
2367ccd9a8beSDaniel Borkmann cleanup_hook:
2368ccd9a8beSDaniel Borkmann tc_hook.attach_point = BPF_TC_INGRESS | BPF_TC_EGRESS;
2369ccd9a8beSDaniel Borkmann bpf_tc_hook_destroy(&tc_hook);
2370ccd9a8beSDaniel Borkmann
2371ccd9a8beSDaniel Borkmann cleanup:
2372ccd9a8beSDaniel Borkmann test_tc_link__destroy(skel);
2373ccd9a8beSDaniel Borkmann }
2374ccd9a8beSDaniel Borkmann
serial_test_tc_opts_chain_mixed(void)2375ccd9a8beSDaniel Borkmann void serial_test_tc_opts_chain_mixed(void)
2376ccd9a8beSDaniel Borkmann {
2377ccd9a8beSDaniel Borkmann test_tc_chain_mixed(BPF_TCX_INGRESS);
2378ccd9a8beSDaniel Borkmann test_tc_chain_mixed(BPF_TCX_EGRESS);
2379ccd9a8beSDaniel Borkmann }
2380d1a783daSDaniel Borkmann
generate_dummy_prog(void)2381d1a783daSDaniel Borkmann static int generate_dummy_prog(void)
2382d1a783daSDaniel Borkmann {
2383d1a783daSDaniel Borkmann const struct bpf_insn prog_insns[] = {
2384d1a783daSDaniel Borkmann BPF_MOV64_IMM(BPF_REG_0, 0),
2385d1a783daSDaniel Borkmann BPF_EXIT_INSN(),
2386d1a783daSDaniel Borkmann };
2387d1a783daSDaniel Borkmann const size_t prog_insn_cnt = sizeof(prog_insns) / sizeof(struct bpf_insn);
2388d1a783daSDaniel Borkmann LIBBPF_OPTS(bpf_prog_load_opts, opts);
2389d1a783daSDaniel Borkmann const size_t log_buf_sz = 256;
2390*9e191338SAndrii Nakryiko char log_buf[log_buf_sz];
2391d1a783daSDaniel Borkmann int fd = -1;
2392d1a783daSDaniel Borkmann
2393d1a783daSDaniel Borkmann opts.log_buf = log_buf;
2394d1a783daSDaniel Borkmann opts.log_size = log_buf_sz;
2395d1a783daSDaniel Borkmann
2396d1a783daSDaniel Borkmann log_buf[0] = '\0';
2397d1a783daSDaniel Borkmann opts.log_level = 0;
2398d1a783daSDaniel Borkmann fd = bpf_prog_load(BPF_PROG_TYPE_SCHED_CLS, "tcx_prog", "GPL",
2399d1a783daSDaniel Borkmann prog_insns, prog_insn_cnt, &opts);
2400d1a783daSDaniel Borkmann ASSERT_STREQ(log_buf, "", "log_0");
2401d1a783daSDaniel Borkmann ASSERT_GE(fd, 0, "prog_fd");
2402d1a783daSDaniel Borkmann return fd;
2403d1a783daSDaniel Borkmann }
2404d1a783daSDaniel Borkmann
test_tc_opts_max_target(int target,int flags,bool relative)2405d1a783daSDaniel Borkmann static void test_tc_opts_max_target(int target, int flags, bool relative)
2406d1a783daSDaniel Borkmann {
2407d1a783daSDaniel Borkmann int err, ifindex, i, prog_fd, last_fd = -1;
2408d1a783daSDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
2409d1a783daSDaniel Borkmann const int max_progs = 63;
2410d1a783daSDaniel Borkmann
2411d1a783daSDaniel Borkmann ASSERT_OK(system("ip link add dev tcx_opts1 type veth peer name tcx_opts2"), "add veth");
2412d1a783daSDaniel Borkmann ifindex = if_nametoindex("tcx_opts1");
2413d1a783daSDaniel Borkmann ASSERT_NEQ(ifindex, 0, "non_zero_ifindex");
2414d1a783daSDaniel Borkmann
2415d1a783daSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, 0);
2416d1a783daSDaniel Borkmann
2417d1a783daSDaniel Borkmann for (i = 0; i < max_progs; i++) {
2418d1a783daSDaniel Borkmann prog_fd = generate_dummy_prog();
2419d1a783daSDaniel Borkmann if (!ASSERT_GE(prog_fd, 0, "dummy_prog"))
2420d1a783daSDaniel Borkmann goto cleanup;
2421d1a783daSDaniel Borkmann err = bpf_prog_attach_opts(prog_fd, ifindex, target, &opta);
2422d1a783daSDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
2423d1a783daSDaniel Borkmann goto cleanup;
2424d1a783daSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, i + 1);
2425d1a783daSDaniel Borkmann if (i == max_progs - 1 && relative)
2426d1a783daSDaniel Borkmann last_fd = prog_fd;
2427d1a783daSDaniel Borkmann else
2428d1a783daSDaniel Borkmann close(prog_fd);
2429d1a783daSDaniel Borkmann }
2430d1a783daSDaniel Borkmann
2431d1a783daSDaniel Borkmann prog_fd = generate_dummy_prog();
2432d1a783daSDaniel Borkmann if (!ASSERT_GE(prog_fd, 0, "dummy_prog"))
2433d1a783daSDaniel Borkmann goto cleanup;
2434d1a783daSDaniel Borkmann opta.flags = flags;
2435d1a783daSDaniel Borkmann if (last_fd > 0)
2436d1a783daSDaniel Borkmann opta.relative_fd = last_fd;
2437d1a783daSDaniel Borkmann err = bpf_prog_attach_opts(prog_fd, ifindex, target, &opta);
2438d1a783daSDaniel Borkmann ASSERT_EQ(err, -ERANGE, "prog_64_attach");
2439d1a783daSDaniel Borkmann assert_mprog_count_ifindex(ifindex, target, max_progs);
2440d1a783daSDaniel Borkmann close(prog_fd);
2441d1a783daSDaniel Borkmann cleanup:
2442d1a783daSDaniel Borkmann if (last_fd > 0)
2443d1a783daSDaniel Borkmann close(last_fd);
2444d1a783daSDaniel Borkmann ASSERT_OK(system("ip link del dev tcx_opts1"), "del veth");
2445d1a783daSDaniel Borkmann ASSERT_EQ(if_nametoindex("tcx_opts1"), 0, "dev1_removed");
2446d1a783daSDaniel Borkmann ASSERT_EQ(if_nametoindex("tcx_opts2"), 0, "dev2_removed");
2447d1a783daSDaniel Borkmann }
2448d1a783daSDaniel Borkmann
serial_test_tc_opts_max(void)2449d1a783daSDaniel Borkmann void serial_test_tc_opts_max(void)
2450d1a783daSDaniel Borkmann {
2451d1a783daSDaniel Borkmann test_tc_opts_max_target(BPF_TCX_INGRESS, 0, false);
2452d1a783daSDaniel Borkmann test_tc_opts_max_target(BPF_TCX_EGRESS, 0, false);
2453d1a783daSDaniel Borkmann
2454d1a783daSDaniel Borkmann test_tc_opts_max_target(BPF_TCX_INGRESS, BPF_F_BEFORE, false);
2455d1a783daSDaniel Borkmann test_tc_opts_max_target(BPF_TCX_EGRESS, BPF_F_BEFORE, true);
2456d1a783daSDaniel Borkmann
2457d1a783daSDaniel Borkmann test_tc_opts_max_target(BPF_TCX_INGRESS, BPF_F_AFTER, true);
2458d1a783daSDaniel Borkmann test_tc_opts_max_target(BPF_TCX_EGRESS, BPF_F_AFTER, false);
2459d1a783daSDaniel Borkmann }
2460f9b08790SDaniel Borkmann
test_tc_opts_query_target(int target)2461f9b08790SDaniel Borkmann static void test_tc_opts_query_target(int target)
2462f9b08790SDaniel Borkmann {
2463f9b08790SDaniel Borkmann const size_t attr_size = offsetofend(union bpf_attr, query);
2464f9b08790SDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
2465f9b08790SDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
2466f9b08790SDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq);
2467f9b08790SDaniel Borkmann __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4;
2468f9b08790SDaniel Borkmann struct test_tc_link *skel;
2469f9b08790SDaniel Borkmann union bpf_attr attr;
2470f9b08790SDaniel Borkmann __u32 prog_ids[5];
2471f9b08790SDaniel Borkmann int err;
2472f9b08790SDaniel Borkmann
2473f9b08790SDaniel Borkmann skel = test_tc_link__open_and_load();
2474f9b08790SDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load"))
2475f9b08790SDaniel Borkmann goto cleanup;
2476f9b08790SDaniel Borkmann
2477f9b08790SDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1);
2478f9b08790SDaniel Borkmann fd2 = bpf_program__fd(skel->progs.tc2);
2479f9b08790SDaniel Borkmann fd3 = bpf_program__fd(skel->progs.tc3);
2480f9b08790SDaniel Borkmann fd4 = bpf_program__fd(skel->progs.tc4);
2481f9b08790SDaniel Borkmann
2482f9b08790SDaniel Borkmann id1 = id_from_prog_fd(fd1);
2483f9b08790SDaniel Borkmann id2 = id_from_prog_fd(fd2);
2484f9b08790SDaniel Borkmann id3 = id_from_prog_fd(fd3);
2485f9b08790SDaniel Borkmann id4 = id_from_prog_fd(fd4);
2486f9b08790SDaniel Borkmann
2487f9b08790SDaniel Borkmann assert_mprog_count(target, 0);
2488f9b08790SDaniel Borkmann
2489f9b08790SDaniel Borkmann LIBBPF_OPTS_RESET(opta,
2490f9b08790SDaniel Borkmann .expected_revision = 1,
2491f9b08790SDaniel Borkmann );
2492f9b08790SDaniel Borkmann
2493f9b08790SDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
2494f9b08790SDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
2495f9b08790SDaniel Borkmann goto cleanup;
2496f9b08790SDaniel Borkmann
2497f9b08790SDaniel Borkmann assert_mprog_count(target, 1);
2498f9b08790SDaniel Borkmann
2499f9b08790SDaniel Borkmann LIBBPF_OPTS_RESET(opta,
2500f9b08790SDaniel Borkmann .expected_revision = 2,
2501f9b08790SDaniel Borkmann );
2502f9b08790SDaniel Borkmann
2503f9b08790SDaniel Borkmann err = bpf_prog_attach_opts(fd2, loopback, target, &opta);
2504f9b08790SDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
2505f9b08790SDaniel Borkmann goto cleanup1;
2506f9b08790SDaniel Borkmann
2507f9b08790SDaniel Borkmann assert_mprog_count(target, 2);
2508f9b08790SDaniel Borkmann
2509f9b08790SDaniel Borkmann LIBBPF_OPTS_RESET(opta,
2510f9b08790SDaniel Borkmann .expected_revision = 3,
2511f9b08790SDaniel Borkmann );
2512f9b08790SDaniel Borkmann
2513f9b08790SDaniel Borkmann err = bpf_prog_attach_opts(fd3, loopback, target, &opta);
2514f9b08790SDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
2515f9b08790SDaniel Borkmann goto cleanup2;
2516f9b08790SDaniel Borkmann
2517f9b08790SDaniel Borkmann assert_mprog_count(target, 3);
2518f9b08790SDaniel Borkmann
2519f9b08790SDaniel Borkmann LIBBPF_OPTS_RESET(opta,
2520f9b08790SDaniel Borkmann .expected_revision = 4,
2521f9b08790SDaniel Borkmann );
2522f9b08790SDaniel Borkmann
2523f9b08790SDaniel Borkmann err = bpf_prog_attach_opts(fd4, loopback, target, &opta);
2524f9b08790SDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
2525f9b08790SDaniel Borkmann goto cleanup3;
2526f9b08790SDaniel Borkmann
2527f9b08790SDaniel Borkmann assert_mprog_count(target, 4);
2528f9b08790SDaniel Borkmann
2529f9b08790SDaniel Borkmann /* Test 1: Double query via libbpf API */
2530f9b08790SDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
2531f9b08790SDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
2532f9b08790SDaniel Borkmann goto cleanup4;
2533f9b08790SDaniel Borkmann
2534f9b08790SDaniel Borkmann ASSERT_EQ(optq.count, 4, "count");
2535f9b08790SDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision");
2536f9b08790SDaniel Borkmann ASSERT_EQ(optq.prog_ids, NULL, "prog_ids");
2537f9b08790SDaniel Borkmann ASSERT_EQ(optq.link_ids, NULL, "link_ids");
2538f9b08790SDaniel Borkmann
2539f9b08790SDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
2540f9b08790SDaniel Borkmann optq.prog_ids = prog_ids;
2541f9b08790SDaniel Borkmann
2542f9b08790SDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
2543f9b08790SDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
2544f9b08790SDaniel Borkmann goto cleanup4;
2545f9b08790SDaniel Borkmann
2546f9b08790SDaniel Borkmann ASSERT_EQ(optq.count, 4, "count");
2547f9b08790SDaniel Borkmann ASSERT_EQ(optq.revision, 5, "revision");
2548f9b08790SDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
2549f9b08790SDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]");
2550f9b08790SDaniel Borkmann ASSERT_EQ(optq.prog_ids[2], id3, "prog_ids[2]");
2551f9b08790SDaniel Borkmann ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]");
2552f9b08790SDaniel Borkmann ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]");
2553f9b08790SDaniel Borkmann ASSERT_EQ(optq.link_ids, NULL, "link_ids");
2554f9b08790SDaniel Borkmann
2555f9b08790SDaniel Borkmann /* Test 2: Double query via bpf_attr & bpf(2) directly */
2556f9b08790SDaniel Borkmann memset(&attr, 0, attr_size);
2557f9b08790SDaniel Borkmann attr.query.target_ifindex = loopback;
2558f9b08790SDaniel Borkmann attr.query.attach_type = target;
2559f9b08790SDaniel Borkmann
2560f9b08790SDaniel Borkmann err = syscall(__NR_bpf, BPF_PROG_QUERY, &attr, attr_size);
2561f9b08790SDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
2562f9b08790SDaniel Borkmann goto cleanup4;
2563f9b08790SDaniel Borkmann
2564f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.count, 4, "count");
2565f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.revision, 5, "revision");
2566f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.query_flags, 0, "query_flags");
2567f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.attach_flags, 0, "attach_flags");
2568f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.target_ifindex, loopback, "target_ifindex");
2569f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.attach_type, target, "attach_type");
2570f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.prog_ids, 0, "prog_ids");
2571f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.prog_attach_flags, 0, "prog_attach_flags");
2572f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.link_ids, 0, "link_ids");
2573f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.link_attach_flags, 0, "link_attach_flags");
2574f9b08790SDaniel Borkmann
2575f9b08790SDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
2576f9b08790SDaniel Borkmann attr.query.prog_ids = ptr_to_u64(prog_ids);
2577f9b08790SDaniel Borkmann
2578f9b08790SDaniel Borkmann err = syscall(__NR_bpf, BPF_PROG_QUERY, &attr, attr_size);
2579f9b08790SDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
2580f9b08790SDaniel Borkmann goto cleanup4;
2581f9b08790SDaniel Borkmann
2582f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.count, 4, "count");
2583f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.revision, 5, "revision");
2584f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.query_flags, 0, "query_flags");
2585f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.attach_flags, 0, "attach_flags");
2586f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.target_ifindex, loopback, "target_ifindex");
2587f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.attach_type, target, "attach_type");
2588f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.prog_ids, ptr_to_u64(prog_ids), "prog_ids");
2589f9b08790SDaniel Borkmann ASSERT_EQ(prog_ids[0], id1, "prog_ids[0]");
2590f9b08790SDaniel Borkmann ASSERT_EQ(prog_ids[1], id2, "prog_ids[1]");
2591f9b08790SDaniel Borkmann ASSERT_EQ(prog_ids[2], id3, "prog_ids[2]");
2592f9b08790SDaniel Borkmann ASSERT_EQ(prog_ids[3], id4, "prog_ids[3]");
2593f9b08790SDaniel Borkmann ASSERT_EQ(prog_ids[4], 0, "prog_ids[4]");
2594f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.prog_attach_flags, 0, "prog_attach_flags");
2595f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.link_ids, 0, "link_ids");
2596f9b08790SDaniel Borkmann ASSERT_EQ(attr.query.link_attach_flags, 0, "link_attach_flags");
2597f9b08790SDaniel Borkmann
2598f9b08790SDaniel Borkmann cleanup4:
2599f9b08790SDaniel Borkmann err = bpf_prog_detach_opts(fd4, loopback, target, &optd);
2600f9b08790SDaniel Borkmann ASSERT_OK(err, "prog_detach");
2601f9b08790SDaniel Borkmann assert_mprog_count(target, 3);
2602f9b08790SDaniel Borkmann
2603f9b08790SDaniel Borkmann cleanup3:
2604f9b08790SDaniel Borkmann err = bpf_prog_detach_opts(fd3, loopback, target, &optd);
2605f9b08790SDaniel Borkmann ASSERT_OK(err, "prog_detach");
2606f9b08790SDaniel Borkmann assert_mprog_count(target, 2);
2607f9b08790SDaniel Borkmann
2608f9b08790SDaniel Borkmann cleanup2:
2609f9b08790SDaniel Borkmann err = bpf_prog_detach_opts(fd2, loopback, target, &optd);
2610f9b08790SDaniel Borkmann ASSERT_OK(err, "prog_detach");
2611f9b08790SDaniel Borkmann assert_mprog_count(target, 1);
2612f9b08790SDaniel Borkmann
2613f9b08790SDaniel Borkmann cleanup1:
2614f9b08790SDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
2615f9b08790SDaniel Borkmann ASSERT_OK(err, "prog_detach");
2616f9b08790SDaniel Borkmann assert_mprog_count(target, 0);
2617f9b08790SDaniel Borkmann
2618f9b08790SDaniel Borkmann cleanup:
2619f9b08790SDaniel Borkmann test_tc_link__destroy(skel);
2620f9b08790SDaniel Borkmann }
2621f9b08790SDaniel Borkmann
serial_test_tc_opts_query(void)2622f9b08790SDaniel Borkmann void serial_test_tc_opts_query(void)
2623f9b08790SDaniel Borkmann {
2624f9b08790SDaniel Borkmann test_tc_opts_query_target(BPF_TCX_INGRESS);
2625f9b08790SDaniel Borkmann test_tc_opts_query_target(BPF_TCX_EGRESS);
2626f9b08790SDaniel Borkmann }
2627685446b0SDaniel Borkmann
test_tc_opts_query_attach_target(int target)2628685446b0SDaniel Borkmann static void test_tc_opts_query_attach_target(int target)
2629685446b0SDaniel Borkmann {
2630685446b0SDaniel Borkmann LIBBPF_OPTS(bpf_prog_attach_opts, opta);
2631685446b0SDaniel Borkmann LIBBPF_OPTS(bpf_prog_detach_opts, optd);
2632685446b0SDaniel Borkmann LIBBPF_OPTS(bpf_prog_query_opts, optq);
2633685446b0SDaniel Borkmann struct test_tc_link *skel;
2634685446b0SDaniel Borkmann __u32 prog_ids[2];
2635685446b0SDaniel Borkmann __u32 fd1, id1;
2636685446b0SDaniel Borkmann int err;
2637685446b0SDaniel Borkmann
2638685446b0SDaniel Borkmann skel = test_tc_link__open_and_load();
2639685446b0SDaniel Borkmann if (!ASSERT_OK_PTR(skel, "skel_load"))
2640685446b0SDaniel Borkmann goto cleanup;
2641685446b0SDaniel Borkmann
2642685446b0SDaniel Borkmann fd1 = bpf_program__fd(skel->progs.tc1);
2643685446b0SDaniel Borkmann id1 = id_from_prog_fd(fd1);
2644685446b0SDaniel Borkmann
2645685446b0SDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
2646685446b0SDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
2647685446b0SDaniel Borkmann goto cleanup;
2648685446b0SDaniel Borkmann
2649685446b0SDaniel Borkmann ASSERT_EQ(optq.count, 0, "count");
2650685446b0SDaniel Borkmann ASSERT_EQ(optq.revision, 1, "revision");
2651685446b0SDaniel Borkmann
2652685446b0SDaniel Borkmann LIBBPF_OPTS_RESET(opta,
2653685446b0SDaniel Borkmann .expected_revision = optq.revision,
2654685446b0SDaniel Borkmann );
2655685446b0SDaniel Borkmann
2656685446b0SDaniel Borkmann err = bpf_prog_attach_opts(fd1, loopback, target, &opta);
2657685446b0SDaniel Borkmann if (!ASSERT_EQ(err, 0, "prog_attach"))
2658685446b0SDaniel Borkmann goto cleanup;
2659685446b0SDaniel Borkmann
2660685446b0SDaniel Borkmann memset(prog_ids, 0, sizeof(prog_ids));
2661685446b0SDaniel Borkmann optq.prog_ids = prog_ids;
2662685446b0SDaniel Borkmann optq.count = ARRAY_SIZE(prog_ids);
2663685446b0SDaniel Borkmann
2664685446b0SDaniel Borkmann err = bpf_prog_query_opts(loopback, target, &optq);
2665685446b0SDaniel Borkmann if (!ASSERT_OK(err, "prog_query"))
2666685446b0SDaniel Borkmann goto cleanup1;
2667685446b0SDaniel Borkmann
2668685446b0SDaniel Borkmann ASSERT_EQ(optq.count, 1, "count");
2669685446b0SDaniel Borkmann ASSERT_EQ(optq.revision, 2, "revision");
2670685446b0SDaniel Borkmann ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]");
2671685446b0SDaniel Borkmann ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]");
2672685446b0SDaniel Borkmann
2673685446b0SDaniel Borkmann cleanup1:
2674685446b0SDaniel Borkmann err = bpf_prog_detach_opts(fd1, loopback, target, &optd);
2675685446b0SDaniel Borkmann ASSERT_OK(err, "prog_detach");
2676685446b0SDaniel Borkmann assert_mprog_count(target, 0);
2677685446b0SDaniel Borkmann cleanup:
2678685446b0SDaniel Borkmann test_tc_link__destroy(skel);
2679685446b0SDaniel Borkmann }
2680685446b0SDaniel Borkmann
serial_test_tc_opts_query_attach(void)2681685446b0SDaniel Borkmann void serial_test_tc_opts_query_attach(void)
2682685446b0SDaniel Borkmann {
2683685446b0SDaniel Borkmann test_tc_opts_query_attach_target(BPF_TCX_INGRESS);
2684685446b0SDaniel Borkmann test_tc_opts_query_attach_target(BPF_TCX_EGRESS);
2685685446b0SDaniel Borkmann }
2686