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_helpers.skel.h"
8 
9 #define IFINDEX_LO 1
10 
11 struct bpf_devmap_val {
12 	u32 ifindex;   /* device index */
13 	union {
14 		int fd;  /* prog fd on map write */
15 		u32 id;  /* prog id on map read */
16 	} bpf_prog;
17 };
18 
19 void test_xdp_with_devmap_helpers(void)
20 {
21 	struct test_xdp_with_devmap_helpers *skel;
22 	struct bpf_prog_info info = {};
23 	struct bpf_devmap_val val = {
24 		.ifindex = IFINDEX_LO,
25 	};
26 	__u32 len = sizeof(info);
27 	__u32 duration = 0, idx = 0;
28 	int err, dm_fd, map_fd;
29 
30 
31 	skel = test_xdp_with_devmap_helpers__open_and_load();
32 	if (CHECK_FAIL(!skel)) {
33 		perror("test_xdp_with_devmap_helpers__open_and_load");
34 		return;
35 	}
36 
37 	/* can not attach program with DEVMAPs that allow programs
38 	 * as xdp generic
39 	 */
40 	dm_fd = bpf_program__fd(skel->progs.xdp_redir_prog);
41 	err = bpf_set_link_xdp_fd(IFINDEX_LO, dm_fd, XDP_FLAGS_SKB_MODE);
42 	CHECK(err == 0, "Generic attach of program with 8-byte devmap",
43 	      "should have failed\n");
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_obj_get_info_by_fd(dm_fd, &info, &len);
48 	if (CHECK_FAIL(err))
49 		goto out_close;
50 
51 	val.bpf_prog.fd = dm_fd;
52 	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
53 	CHECK(err, "Add program to devmap entry",
54 	      "err %d errno %d\n", err, errno);
55 
56 	err = bpf_map_lookup_elem(map_fd, &idx, &val);
57 	CHECK(err, "Read devmap entry", "err %d errno %d\n", err, errno);
58 	CHECK(info.id != val.bpf_prog.id, "Expected program id in devmap entry",
59 	      "expected %u read %u\n", info.id, val.bpf_prog.id);
60 
61 	/* can not attach BPF_XDP_DEVMAP program to a device */
62 	err = bpf_set_link_xdp_fd(IFINDEX_LO, dm_fd, XDP_FLAGS_SKB_MODE);
63 	CHECK(err == 0, "Attach of BPF_XDP_DEVMAP program",
64 	      "should have failed\n");
65 
66 	val.ifindex = 1;
67 	val.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_dummy_prog);
68 	err = bpf_map_update_elem(map_fd, &idx, &val, 0);
69 	CHECK(err == 0, "Add non-BPF_XDP_DEVMAP program to devmap entry",
70 	      "should have failed\n");
71 
72 out_close:
73 	test_xdp_with_devmap_helpers__destroy(skel);
74 }
75 
76 void test_neg_xdp_devmap_helpers(void)
77 {
78 	struct test_xdp_devmap_helpers *skel;
79 	__u32 duration = 0;
80 
81 	skel = test_xdp_devmap_helpers__open_and_load();
82 	if (CHECK(skel,
83 		  "Load of XDP program accessing egress ifindex without attach type",
84 		  "should have failed\n")) {
85 		test_xdp_devmap_helpers__destroy(skel);
86 	}
87 }
88 
89 
90 void test_xdp_devmap_attach(void)
91 {
92 	if (test__start_subtest("DEVMAP with programs in entries"))
93 		test_xdp_with_devmap_helpers();
94 
95 	if (test__start_subtest("Verifier check of DEVMAP programs"))
96 		test_neg_xdp_devmap_helpers();
97 }
98