File Index
Files and directories
Sign in
FILE

xdp_devmap_attach.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/prog_tests/xdp_devmap_attach.c C
  1// SPDX-License-Identifier: GPL-2.0
  2#include <arpa/inet.h>
  3#include <uapi/linux/bpf.h>
  4#include <linux/if_link.h>
  5#include <network_helpers.h>
  6#include <net/if.h>
  7#include <test_progs.h>
  8
  9#include "test_xdp_devmap_helpers.skel.h"
 10#include "test_xdp_devmap_tailcall.skel.h"
 11#include "test_xdp_with_devmap_frags_helpers.skel.h"
 12#include "test_xdp_with_devmap_helpers.skel.h"
 13
 14#define IFINDEX_LO 1
 15#define TEST_NS "devmap_attach_ns"
 16
 17static void test_xdp_with_devmap_helpers(void)
 18{
 19	struct test_xdp_with_devmap_helpers *skel = NULL;
 20	struct bpf_prog_info info = {};
 21	struct bpf_devmap_val val = {
 22		.ifindex = IFINDEX_LO,
 23	};
 24	__u32 len = sizeof(info);
 25	int err, dm_fd, dm_fd_redir, map_fd;
 26	struct nstoken *nstoken = NULL;
 27	char data[ETH_HLEN] = {};
 28	__u32 idx = 0;
 29
 30	SYS(out_close, "ip netns add %s", TEST_NS);
 31	nstoken = open_netns(TEST_NS);
 32	if (!ASSERT_OK_PTR(nstoken, "open_netns"))
 33		goto out_close;
 34	SYS(out_close, "ip link set dev lo up");
 35
 36	skel = test_xdp_with_devmap_helpers__open_and_load();
 37	if (!ASSERT_OK_PTR(skel, "test_xdp_with_devmap_helpers__open_and_load"))
 38		goto out_close;
 39
 40	dm_fd_redir = bpf_program__fd(skel->progs.xdp_redir_prog);
 41	err = bpf_xdp_attach(IFINDEX_LO, dm_fd_redir, XDP_FLAGS_SKB_MODE, NULL);
 42	if (!ASSERT_OK(err, "Generic attach of program with 8-byte devmap"))
 43		goto out_close;
 44
 45	dm_fd = bpf_program__fd(skel->progs.xdp_dummy_dm);
 46	map_fd = bpf_map__fd(skel->maps.dm_ports);
 47	err = bpf_prog_get_info_by_fd(dm_fd, &info, &len);
 48	if (!ASSERT_OK(err, "bpf_prog_get_info_by_fd"))
 49		goto out_close;
 50
 51	val.bpf_prog.fd = dm_fd;
 52	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
 53	ASSERT_OK(err, "Add program to devmap entry");
 54
 55	err = bpf_map_lookup_elem(map_fd, &idx, &val);
 56	ASSERT_OK(err, "Read devmap entry");
 57	ASSERT_EQ(info.id, val.bpf_prog.id, "Match program id to devmap entry prog_id");
 58
 59	/* send a packet to trigger any potential bugs in there */
 60	DECLARE_LIBBPF_OPTS(bpf_test_run_opts, opts,
 61			    .data_in = &data,
 62			    .data_size_in = sizeof(data),
 63			    .flags = BPF_F_TEST_XDP_LIVE_FRAMES,
 64			    .repeat = 1,
 65		);
 66	err = bpf_prog_test_run_opts(dm_fd_redir, &opts);
 67	ASSERT_OK(err, "XDP test run");
 68
 69	/* wait for the packets to be flushed */
 70	kern_sync_rcu();
 71
 72	err = bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_SKB_MODE, NULL);
 73	ASSERT_OK(err, "XDP program detach");
 74
 75	/* can not attach BPF_XDP_DEVMAP program to a device */
 76	err = bpf_xdp_attach(IFINDEX_LO, dm_fd, XDP_FLAGS_SKB_MODE, NULL);
 77	if (!ASSERT_NEQ(err, 0, "Attach of BPF_XDP_DEVMAP program"))
 78		bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_SKB_MODE, NULL);
 79
 80	val.ifindex = 1;
 81	val.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_dummy_prog);
 82	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
 83	ASSERT_NEQ(err, 0, "Add non-BPF_XDP_DEVMAP program to devmap entry");
 84
 85	/* Try to attach BPF_XDP program with frags to devmap when we have
 86	 * already loaded a BPF_XDP program on the map
 87	 */
 88	idx = 1;
 89	val.ifindex = 1;
 90	val.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_dummy_dm_frags);
 91	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
 92	ASSERT_NEQ(err, 0, "Add BPF_XDP program with frags to devmap entry");
 93
 94out_close:
 95	close_netns(nstoken);
 96	SYS_NOFAIL("ip netns del %s", TEST_NS);
 97	test_xdp_with_devmap_helpers__destroy(skel);
 98}
 99
100static void test_neg_xdp_devmap_helpers(void)
101{
102	struct test_xdp_devmap_helpers *skel;
103
104	skel = test_xdp_devmap_helpers__open_and_load();
105	if (!ASSERT_EQ(skel, NULL,
106		    "Load of XDP program accessing egress ifindex without attach type")) {
107		test_xdp_devmap_helpers__destroy(skel);
108	}
109}
110
111static void test_xdp_devmap_tailcall(enum bpf_attach_type prog_dev,
112				     enum bpf_attach_type prog_tail,
113				     bool expect_reject)
114{
115	struct test_xdp_devmap_tailcall *skel;
116	int err;
117
118	skel = test_xdp_devmap_tailcall__open();
119	if (!ASSERT_OK_PTR(skel, "test_xdp_devmap_tailcall__open"))
120		return;
121
122	bpf_program__set_expected_attach_type(skel->progs.xdp_devmap, prog_dev);
123	bpf_program__set_expected_attach_type(skel->progs.xdp_entry, prog_tail);
124
125	err = test_xdp_devmap_tailcall__load(skel);
126	if (expect_reject)
127		ASSERT_ERR(err, "test_xdp_devmap_tailcall__load");
128	else
129		ASSERT_OK(err, "test_xdp_devmap_tailcall__load");
130
131	test_xdp_devmap_tailcall__destroy(skel);
132}
133
134static void test_xdp_with_devmap_frags_helpers(void)
135{
136	struct test_xdp_with_devmap_frags_helpers *skel;
137	struct bpf_prog_info info = {};
138	struct bpf_devmap_val val = {
139		.ifindex = IFINDEX_LO,
140	};
141	__u32 len = sizeof(info);
142	int err, dm_fd_frags, map_fd;
143	__u32 idx = 0;
144
145	skel = test_xdp_with_devmap_frags_helpers__open_and_load();
146	if (!ASSERT_OK_PTR(skel, "test_xdp_with_devmap_helpers__open_and_load"))
147		return;
148
149	dm_fd_frags = bpf_program__fd(skel->progs.xdp_dummy_dm_frags);
150	map_fd = bpf_map__fd(skel->maps.dm_ports);
151	err = bpf_prog_get_info_by_fd(dm_fd_frags, &info, &len);
152	if (!ASSERT_OK(err, "bpf_prog_get_info_by_fd"))
153		goto out_close;
154
155	val.bpf_prog.fd = dm_fd_frags;
156	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
157	ASSERT_OK(err, "Add frags program to devmap entry");
158
159	err = bpf_map_lookup_elem(map_fd, &idx, &val);
160	ASSERT_OK(err, "Read devmap entry");
161	ASSERT_EQ(info.id, val.bpf_prog.id,
162		  "Match program id to devmap entry prog_id");
163
164	/* Try to attach BPF_XDP program to devmap when we have
165	 * already loaded a BPF_XDP program with frags on the map
166	 */
167	idx = 1;
168	val.ifindex = 1;
169	val.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_dummy_dm);
170	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
171	ASSERT_NEQ(err, 0, "Add BPF_XDP program to devmap entry");
172
173out_close:
174	test_xdp_with_devmap_frags_helpers__destroy(skel);
175}
176
177static void test_xdp_with_devmap_helpers_veth(void)
178{
179	struct test_xdp_with_devmap_helpers *skel = NULL;
180	struct bpf_prog_info info = {};
181	struct bpf_devmap_val val = {};
182	struct nstoken *nstoken = NULL;
183	__u32 len = sizeof(info);
184	int err, dm_fd, dm_fd_redir, map_fd, ifindex_dst;
185	char data[ETH_HLEN] = {};
186	__u32 idx = 0;
187
188	SYS(out_close, "ip netns add %s", TEST_NS);
189	nstoken = open_netns(TEST_NS);
190	if (!ASSERT_OK_PTR(nstoken, "open_netns"))
191		goto out_close;
192
193	SYS(out_close, "ip link add veth_src type veth peer name veth_dst");
194	SYS(out_close, "ip link set dev veth_src up");
195	SYS(out_close, "ip link set dev veth_dst up");
196
197	val.ifindex = if_nametoindex("veth_src");
198	ifindex_dst = if_nametoindex("veth_dst");
199	if (!ASSERT_NEQ(val.ifindex, 0, "val.ifindex") ||
200	    !ASSERT_NEQ(ifindex_dst, 0, "ifindex_dst"))
201		goto out_close;
202
203	skel = test_xdp_with_devmap_helpers__open_and_load();
204	if (!ASSERT_OK_PTR(skel, "test_xdp_with_devmap_helpers__open_and_load"))
205		goto out_close;
206
207	dm_fd_redir = bpf_program__fd(skel->progs.xdp_redir_prog);
208	err = bpf_xdp_attach(val.ifindex, dm_fd_redir, XDP_FLAGS_DRV_MODE, NULL);
209	if (!ASSERT_OK(err, "Attach of program with 8-byte devmap"))
210		goto out_close;
211
212	dm_fd = bpf_program__fd(skel->progs.xdp_dummy_dm);
213	map_fd = bpf_map__fd(skel->maps.dm_ports);
214	err = bpf_prog_get_info_by_fd(dm_fd, &info, &len);
215	if (!ASSERT_OK(err, "bpf_prog_get_info_by_fd"))
216		goto out_close;
217
218	val.bpf_prog.fd = dm_fd;
219	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
220	ASSERT_OK(err, "Add program to devmap entry");
221
222	err = bpf_map_lookup_elem(map_fd, &idx, &val);
223	ASSERT_OK(err, "Read devmap entry");
224	ASSERT_EQ(info.id, val.bpf_prog.id, "Match program id to devmap entry prog_id");
225
226	/* attach dummy to other side to enable reception */
227	dm_fd = bpf_program__fd(skel->progs.xdp_dummy_prog);
228	err = bpf_xdp_attach(ifindex_dst, dm_fd, XDP_FLAGS_DRV_MODE, NULL);
229	if (!ASSERT_OK(err, "Attach of dummy XDP"))
230		goto out_close;
231
232	/* send a packet to trigger any potential bugs in there */
233	DECLARE_LIBBPF_OPTS(bpf_test_run_opts, opts,
234			    .data_in = &data,
235			    .data_size_in = sizeof(data),
236			    .flags = BPF_F_TEST_XDP_LIVE_FRAMES,
237			    .repeat = 1,
238		);
239	err = bpf_prog_test_run_opts(dm_fd_redir, &opts);
240	ASSERT_OK(err, "XDP test run");
241
242	/* wait for the packets to be flushed */
243	kern_sync_rcu();
244
245	err = bpf_xdp_detach(val.ifindex, XDP_FLAGS_DRV_MODE, NULL);
246	ASSERT_OK(err, "XDP program detach");
247
248	err = bpf_xdp_detach(ifindex_dst, XDP_FLAGS_DRV_MODE, NULL);
249	ASSERT_OK(err, "XDP program detach");
250
251out_close:
252	close_netns(nstoken);
253	SYS_NOFAIL("ip netns del %s", TEST_NS);
254	test_xdp_with_devmap_helpers__destroy(skel);
255}
256
257void serial_test_xdp_devmap_attach(void)
258{
259	if (test__start_subtest("DEVMAP with programs in entries"))
260		test_xdp_with_devmap_helpers();
261
262	if (test__start_subtest("DEVMAP with frags programs in entries"))
263		test_xdp_with_devmap_frags_helpers();
264
265	if (test__start_subtest("Verifier check of DEVMAP programs")) {
266		test_neg_xdp_devmap_helpers();
267		test_xdp_devmap_tailcall(BPF_XDP_DEVMAP, BPF_XDP_DEVMAP, false);
268		test_xdp_devmap_tailcall(0, 0, true);
269		test_xdp_devmap_tailcall(BPF_XDP_DEVMAP, 0, true);
270		test_xdp_devmap_tailcall(0, BPF_XDP_DEVMAP, true);
271	}
272
273	if (test__start_subtest("DEVMAP with programs in entries on veth"))
274		test_xdp_with_devmap_helpers_veth();
275}
~/ Read-only file preview.