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
test_xdp_with_devmap_helpers(void)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_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
69 out_close:
70 test_xdp_with_devmap_helpers__destroy(skel);
71 }
72
test_neg_xdp_devmap_helpers(void)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
test_xdp_with_devmap_frags_helpers(void)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_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
123 out_close:
124 test_xdp_with_devmap_frags_helpers__destroy(skel);
125 }
126
serial_test_xdp_devmap_attach(void)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