1// SPDX-License-Identifier: GPL-2.0
2#include <uapi/linux/bpf.h>
3#include <linux/if_link.h>
4#include <test_progs.h>
5
6#include "test_xdp_devmap_helpers.skel.h"
7#include "test_xdp_with_devmap_frags_helpers.skel.h"
8#include "test_xdp_with_devmap_helpers.skel.h"
9
10#define IFINDEX_LO 1
11
12static void test_xdp_with_devmap_helpers(void)
13{
14	struct test_xdp_with_devmap_helpers *skel;
15	struct bpf_prog_info info = {};
16	struct bpf_devmap_val val = {
17		.ifindex = IFINDEX_LO,
18	};
19	__u32 len = sizeof(info);
20	int err, dm_fd, map_fd;
21	__u32 idx = 0;
22
23
24	skel = test_xdp_with_devmap_helpers__open_and_load();
25	if (!ASSERT_OK_PTR(skel, "test_xdp_with_devmap_helpers__open_and_load"))
26		return;
27
28	dm_fd = bpf_program__fd(skel->progs.xdp_redir_prog);
29	err = bpf_xdp_attach(IFINDEX_LO, dm_fd, XDP_FLAGS_SKB_MODE, NULL);
30	if (!ASSERT_OK(err, "Generic attach of program with 8-byte devmap"))
31		goto out_close;
32
33	err = bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_SKB_MODE, NULL);
34	ASSERT_OK(err, "XDP program detach");
35
36	dm_fd = bpf_program__fd(skel->progs.xdp_dummy_dm);
37	map_fd = bpf_map__fd(skel->maps.dm_ports);
38	err = bpf_prog_get_info_by_fd(dm_fd, &info, &len);
39	if (!ASSERT_OK(err, "bpf_prog_get_info_by_fd"))
40		goto out_close;
41
42	val.bpf_prog.fd = dm_fd;
43	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
44	ASSERT_OK(err, "Add program to devmap entry");
45
46	err = bpf_map_lookup_elem(map_fd, &idx, &val);
47	ASSERT_OK(err, "Read devmap entry");
48	ASSERT_EQ(info.id, val.bpf_prog.id, "Match program id to devmap entry prog_id");
49
50	/* can not attach BPF_XDP_DEVMAP program to a device */
51	err = bpf_xdp_attach(IFINDEX_LO, dm_fd, XDP_FLAGS_SKB_MODE, NULL);
52	if (!ASSERT_NEQ(err, 0, "Attach of BPF_XDP_DEVMAP program"))
53		bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_SKB_MODE, NULL);
54
55	val.ifindex = 1;
56	val.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_dummy_prog);
57	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
58	ASSERT_NEQ(err, 0, "Add non-BPF_XDP_DEVMAP program to devmap entry");
59
60	/* Try to attach BPF_XDP program with frags to devmap when we have
61	 * already loaded a BPF_XDP program on the map
62	 */
63	idx = 1;
64	val.ifindex = 1;
65	val.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_dummy_dm_frags);
66	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
67	ASSERT_NEQ(err, 0, "Add BPF_XDP program with frags to devmap entry");
68
69out_close:
70	test_xdp_with_devmap_helpers__destroy(skel);
71}
72
73static void test_neg_xdp_devmap_helpers(void)
74{
75	struct test_xdp_devmap_helpers *skel;
76
77	skel = test_xdp_devmap_helpers__open_and_load();
78	if (!ASSERT_EQ(skel, NULL,
79		    "Load of XDP program accessing egress ifindex without attach type")) {
80		test_xdp_devmap_helpers__destroy(skel);
81	}
82}
83
84static void test_xdp_with_devmap_frags_helpers(void)
85{
86	struct test_xdp_with_devmap_frags_helpers *skel;
87	struct bpf_prog_info info = {};
88	struct bpf_devmap_val val = {
89		.ifindex = IFINDEX_LO,
90	};
91	__u32 len = sizeof(info);
92	int err, dm_fd_frags, map_fd;
93	__u32 idx = 0;
94
95	skel = test_xdp_with_devmap_frags_helpers__open_and_load();
96	if (!ASSERT_OK_PTR(skel, "test_xdp_with_devmap_helpers__open_and_load"))
97		return;
98
99	dm_fd_frags = bpf_program__fd(skel->progs.xdp_dummy_dm_frags);
100	map_fd = bpf_map__fd(skel->maps.dm_ports);
101	err = bpf_prog_get_info_by_fd(dm_fd_frags, &info, &len);
102	if (!ASSERT_OK(err, "bpf_prog_get_info_by_fd"))
103		goto out_close;
104
105	val.bpf_prog.fd = dm_fd_frags;
106	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
107	ASSERT_OK(err, "Add frags program to devmap entry");
108
109	err = bpf_map_lookup_elem(map_fd, &idx, &val);
110	ASSERT_OK(err, "Read devmap entry");
111	ASSERT_EQ(info.id, val.bpf_prog.id,
112		  "Match program id to devmap entry prog_id");
113
114	/* Try to attach BPF_XDP program to devmap when we have
115	 * already loaded a BPF_XDP program with frags on the map
116	 */
117	idx = 1;
118	val.ifindex = 1;
119	val.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_dummy_dm);
120	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
121	ASSERT_NEQ(err, 0, "Add BPF_XDP program to devmap entry");
122
123out_close:
124	test_xdp_with_devmap_frags_helpers__destroy(skel);
125}
126
127void serial_test_xdp_devmap_attach(void)
128{
129	if (test__start_subtest("DEVMAP with programs in entries"))
130		test_xdp_with_devmap_helpers();
131
132	if (test__start_subtest("DEVMAP with frags programs in entries"))
133		test_xdp_with_devmap_frags_helpers();
134
135	if (test__start_subtest("Verifier check of DEVMAP programs"))
136		test_neg_xdp_devmap_helpers();
137}
138