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 
12 static 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_obj_get_info_by_fd(dm_fd, &info, &len);
39 	if (!ASSERT_OK(err, "bpf_obj_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 
69 out_close:
70 	test_xdp_with_devmap_helpers__destroy(skel);
71 }
72 
73 static 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 
84 static 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_obj_get_info_by_fd(dm_fd_frags, &info, &len);
102 	if (!ASSERT_OK(err, "bpf_obj_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 
123 out_close:
124 	test_xdp_with_devmap_frags_helpers__destroy(skel);
125 }
126 
127 void 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