xref: /linux/tools/testing/selftests/bpf/prog_tests/bpftool_metadata.c (revision c17ee635fd3a482b2ad2bf5e269755c2eae5f25e)
1*1c0b5059SAlexis Lothoré (eBPF Foundation) // SPDX-License-Identifier: GPL-2.0-only
2*1c0b5059SAlexis Lothoré (eBPF Foundation) #include <bpftool_helpers.h>
3*1c0b5059SAlexis Lothoré (eBPF Foundation) #include <test_progs.h>
4*1c0b5059SAlexis Lothoré (eBPF Foundation) #include <linux/bpf.h>
5*1c0b5059SAlexis Lothoré (eBPF Foundation) #include <string.h>
6*1c0b5059SAlexis Lothoré (eBPF Foundation) #include <unistd.h>
7*1c0b5059SAlexis Lothoré (eBPF Foundation) #include <fcntl.h>
8*1c0b5059SAlexis Lothoré (eBPF Foundation) #include <sys/stat.h>
9*1c0b5059SAlexis Lothoré (eBPF Foundation) #include <stdbool.h>
10*1c0b5059SAlexis Lothoré (eBPF Foundation) 
11*1c0b5059SAlexis Lothoré (eBPF Foundation) #define BPFFS_DIR	"/sys/fs/bpf/test_metadata"
12*1c0b5059SAlexis Lothoré (eBPF Foundation) #define BPFFS_USED	BPFFS_DIR "/used"
13*1c0b5059SAlexis Lothoré (eBPF Foundation) #define BPFFS_UNUSED	BPFFS_DIR "/unused"
14*1c0b5059SAlexis Lothoré (eBPF Foundation) 
15*1c0b5059SAlexis Lothoré (eBPF Foundation) #define BPF_FILE_USED		"metadata_used.bpf.o"
16*1c0b5059SAlexis Lothoré (eBPF Foundation) #define BPF_FILE_UNUSED		"metadata_unused.bpf.o"
17*1c0b5059SAlexis Lothoré (eBPF Foundation) #define METADATA_MAP_NAME	"metadata.rodata"
18*1c0b5059SAlexis Lothoré (eBPF Foundation) 
19*1c0b5059SAlexis Lothoré (eBPF Foundation) #define MAX_BPFTOOL_OUTPUT_LEN	(64*1024)
20*1c0b5059SAlexis Lothoré (eBPF Foundation) 
21*1c0b5059SAlexis Lothoré (eBPF Foundation) #define MAX_TOKENS_TO_CHECK	3
22*1c0b5059SAlexis Lothoré (eBPF Foundation) static char output[MAX_BPFTOOL_OUTPUT_LEN];
23*1c0b5059SAlexis Lothoré (eBPF Foundation) 
24*1c0b5059SAlexis Lothoré (eBPF Foundation) struct test_desc {
25*1c0b5059SAlexis Lothoré (eBPF Foundation) 	char *name;
26*1c0b5059SAlexis Lothoré (eBPF Foundation) 	char *bpf_prog;
27*1c0b5059SAlexis Lothoré (eBPF Foundation) 	char *bpffs_path;
28*1c0b5059SAlexis Lothoré (eBPF Foundation) 	char *expected_output[MAX_TOKENS_TO_CHECK];
29*1c0b5059SAlexis Lothoré (eBPF Foundation) 	char *expected_output_json[MAX_TOKENS_TO_CHECK];
30*1c0b5059SAlexis Lothoré (eBPF Foundation) 	char *metadata_map_name;
31*1c0b5059SAlexis Lothoré (eBPF Foundation) };
32*1c0b5059SAlexis Lothoré (eBPF Foundation) 
33*1c0b5059SAlexis Lothoré (eBPF Foundation) static int setup(struct test_desc *test)
34*1c0b5059SAlexis Lothoré (eBPF Foundation) {
35*1c0b5059SAlexis Lothoré (eBPF Foundation) 	return mkdir(BPFFS_DIR, 0700);
36*1c0b5059SAlexis Lothoré (eBPF Foundation) }
37*1c0b5059SAlexis Lothoré (eBPF Foundation) 
38*1c0b5059SAlexis Lothoré (eBPF Foundation) static void cleanup(struct test_desc *test)
39*1c0b5059SAlexis Lothoré (eBPF Foundation) {
40*1c0b5059SAlexis Lothoré (eBPF Foundation) 	unlink(test->bpffs_path);
41*1c0b5059SAlexis Lothoré (eBPF Foundation) 	rmdir(BPFFS_DIR);
42*1c0b5059SAlexis Lothoré (eBPF Foundation) }
43*1c0b5059SAlexis Lothoré (eBPF Foundation) 
44*1c0b5059SAlexis Lothoré (eBPF Foundation) static int check_metadata(char *buf, char * const *tokens, int count)
45*1c0b5059SAlexis Lothoré (eBPF Foundation) {
46*1c0b5059SAlexis Lothoré (eBPF Foundation) 	int i;
47*1c0b5059SAlexis Lothoré (eBPF Foundation) 
48*1c0b5059SAlexis Lothoré (eBPF Foundation) 	for (i = 0; i < count && tokens[i]; i++)
49*1c0b5059SAlexis Lothoré (eBPF Foundation) 		if (!strstr(buf, tokens[i]))
50*1c0b5059SAlexis Lothoré (eBPF Foundation) 			return 1;
51*1c0b5059SAlexis Lothoré (eBPF Foundation) 
52*1c0b5059SAlexis Lothoré (eBPF Foundation) 	return 0;
53*1c0b5059SAlexis Lothoré (eBPF Foundation) }
54*1c0b5059SAlexis Lothoré (eBPF Foundation) 
55*1c0b5059SAlexis Lothoré (eBPF Foundation) static void run_test(struct test_desc *test)
56*1c0b5059SAlexis Lothoré (eBPF Foundation) {
57*1c0b5059SAlexis Lothoré (eBPF Foundation) 	int ret;
58*1c0b5059SAlexis Lothoré (eBPF Foundation) 	char cmd[MAX_BPFTOOL_CMD_LEN];
59*1c0b5059SAlexis Lothoré (eBPF Foundation) 
60*1c0b5059SAlexis Lothoré (eBPF Foundation) 	ret = snprintf(cmd, MAX_BPFTOOL_CMD_LEN, "prog load %s %s",
61*1c0b5059SAlexis Lothoré (eBPF Foundation) 			test->bpf_prog, test->bpffs_path);
62*1c0b5059SAlexis Lothoré (eBPF Foundation) 	if (!ASSERT_GT(ret, 0, "format prog insert command"))
63*1c0b5059SAlexis Lothoré (eBPF Foundation) 		return;
64*1c0b5059SAlexis Lothoré (eBPF Foundation) 	ret = run_bpftool_command(cmd);
65*1c0b5059SAlexis Lothoré (eBPF Foundation) 	if (!ASSERT_OK(ret, "load program"))
66*1c0b5059SAlexis Lothoré (eBPF Foundation) 		return;
67*1c0b5059SAlexis Lothoré (eBPF Foundation) 
68*1c0b5059SAlexis Lothoré (eBPF Foundation) 	/* Check output with default format */
69*1c0b5059SAlexis Lothoré (eBPF Foundation) 	ret = snprintf(cmd, MAX_BPFTOOL_CMD_LEN, "prog show pinned %s",
70*1c0b5059SAlexis Lothoré (eBPF Foundation) 		       test->bpffs_path);
71*1c0b5059SAlexis Lothoré (eBPF Foundation) 	if (!ASSERT_GT(ret, 0, "format pinned prog check command"))
72*1c0b5059SAlexis Lothoré (eBPF Foundation) 		return;
73*1c0b5059SAlexis Lothoré (eBPF Foundation) 	ret = get_bpftool_command_output(cmd, output,
74*1c0b5059SAlexis Lothoré (eBPF Foundation) 			MAX_BPFTOOL_OUTPUT_LEN);
75*1c0b5059SAlexis Lothoré (eBPF Foundation) 	if (ASSERT_OK(ret, "get program info")) {
76*1c0b5059SAlexis Lothoré (eBPF Foundation) 		ret = check_metadata(output, test->expected_output,
77*1c0b5059SAlexis Lothoré (eBPF Foundation) 				ARRAY_SIZE(test->expected_output));
78*1c0b5059SAlexis Lothoré (eBPF Foundation) 		ASSERT_OK(ret, "find metadata");
79*1c0b5059SAlexis Lothoré (eBPF Foundation) 	}
80*1c0b5059SAlexis Lothoré (eBPF Foundation) 
81*1c0b5059SAlexis Lothoré (eBPF Foundation) 	/* Check output with json format */
82*1c0b5059SAlexis Lothoré (eBPF Foundation) 	ret = snprintf(cmd, MAX_BPFTOOL_CMD_LEN, "prog -j show pinned %s",
83*1c0b5059SAlexis Lothoré (eBPF Foundation) 		       test->bpffs_path);
84*1c0b5059SAlexis Lothoré (eBPF Foundation) 	if (!ASSERT_GT(ret, 0, "format pinned prog check command in json"))
85*1c0b5059SAlexis Lothoré (eBPF Foundation) 		return;
86*1c0b5059SAlexis Lothoré (eBPF Foundation) 	ret = get_bpftool_command_output(cmd, output,
87*1c0b5059SAlexis Lothoré (eBPF Foundation) 					 MAX_BPFTOOL_OUTPUT_LEN);
88*1c0b5059SAlexis Lothoré (eBPF Foundation) 	if (ASSERT_OK(ret, "get program info in json")) {
89*1c0b5059SAlexis Lothoré (eBPF Foundation) 		ret = check_metadata(output, test->expected_output_json,
90*1c0b5059SAlexis Lothoré (eBPF Foundation) 				ARRAY_SIZE(test->expected_output_json));
91*1c0b5059SAlexis Lothoré (eBPF Foundation) 		ASSERT_OK(ret, "find metadata in json");
92*1c0b5059SAlexis Lothoré (eBPF Foundation) 	}
93*1c0b5059SAlexis Lothoré (eBPF Foundation) 
94*1c0b5059SAlexis Lothoré (eBPF Foundation) 	/* Check that the corresponding map can be found and accessed */
95*1c0b5059SAlexis Lothoré (eBPF Foundation) 	ret = snprintf(cmd, MAX_BPFTOOL_CMD_LEN, "map show name %s",
96*1c0b5059SAlexis Lothoré (eBPF Foundation) 		       test->metadata_map_name);
97*1c0b5059SAlexis Lothoré (eBPF Foundation) 	if (!ASSERT_GT(ret, 0, "format map check command"))
98*1c0b5059SAlexis Lothoré (eBPF Foundation) 		return;
99*1c0b5059SAlexis Lothoré (eBPF Foundation) 	ASSERT_OK(run_bpftool_command(cmd), "access metadata map");
100*1c0b5059SAlexis Lothoré (eBPF Foundation) }
101*1c0b5059SAlexis Lothoré (eBPF Foundation) 
102*1c0b5059SAlexis Lothoré (eBPF Foundation) static struct test_desc tests[] = {
103*1c0b5059SAlexis Lothoré (eBPF Foundation) 	{
104*1c0b5059SAlexis Lothoré (eBPF Foundation) 		.name = "metadata_unused",
105*1c0b5059SAlexis Lothoré (eBPF Foundation) 		.bpf_prog = BPF_FILE_UNUSED,
106*1c0b5059SAlexis Lothoré (eBPF Foundation) 		.bpffs_path = BPFFS_UNUSED,
107*1c0b5059SAlexis Lothoré (eBPF Foundation) 		.expected_output = {
108*1c0b5059SAlexis Lothoré (eBPF Foundation) 			"a = \"foo\"",
109*1c0b5059SAlexis Lothoré (eBPF Foundation) 			"b = 1"
110*1c0b5059SAlexis Lothoré (eBPF Foundation) 		},
111*1c0b5059SAlexis Lothoré (eBPF Foundation) 		.expected_output_json = {
112*1c0b5059SAlexis Lothoré (eBPF Foundation) 			"\"metadata\":{\"a\":\"foo\",\"b\":1}"
113*1c0b5059SAlexis Lothoré (eBPF Foundation) 		},
114*1c0b5059SAlexis Lothoré (eBPF Foundation) 		.metadata_map_name = METADATA_MAP_NAME
115*1c0b5059SAlexis Lothoré (eBPF Foundation) 	},
116*1c0b5059SAlexis Lothoré (eBPF Foundation) 	{
117*1c0b5059SAlexis Lothoré (eBPF Foundation) 		.name = "metadata_used",
118*1c0b5059SAlexis Lothoré (eBPF Foundation) 		.bpf_prog = BPF_FILE_USED,
119*1c0b5059SAlexis Lothoré (eBPF Foundation) 		.bpffs_path = BPFFS_USED,
120*1c0b5059SAlexis Lothoré (eBPF Foundation) 		.expected_output = {
121*1c0b5059SAlexis Lothoré (eBPF Foundation) 			"a = \"bar\"",
122*1c0b5059SAlexis Lothoré (eBPF Foundation) 			"b = 2"
123*1c0b5059SAlexis Lothoré (eBPF Foundation) 		},
124*1c0b5059SAlexis Lothoré (eBPF Foundation) 		.expected_output_json = {
125*1c0b5059SAlexis Lothoré (eBPF Foundation) 			"\"metadata\":{\"a\":\"bar\",\"b\":2}"
126*1c0b5059SAlexis Lothoré (eBPF Foundation) 		},
127*1c0b5059SAlexis Lothoré (eBPF Foundation) 		.metadata_map_name = METADATA_MAP_NAME
128*1c0b5059SAlexis Lothoré (eBPF Foundation) 	}
129*1c0b5059SAlexis Lothoré (eBPF Foundation) };
130*1c0b5059SAlexis Lothoré (eBPF Foundation) static const int tests_count = ARRAY_SIZE(tests);
131*1c0b5059SAlexis Lothoré (eBPF Foundation) 
132*1c0b5059SAlexis Lothoré (eBPF Foundation) void test_bpftool_metadata(void)
133*1c0b5059SAlexis Lothoré (eBPF Foundation) {
134*1c0b5059SAlexis Lothoré (eBPF Foundation) 	int i;
135*1c0b5059SAlexis Lothoré (eBPF Foundation) 
136*1c0b5059SAlexis Lothoré (eBPF Foundation) 	for (i = 0; i < tests_count; i++) {
137*1c0b5059SAlexis Lothoré (eBPF Foundation) 		if (!test__start_subtest(tests[i].name))
138*1c0b5059SAlexis Lothoré (eBPF Foundation) 			continue;
139*1c0b5059SAlexis Lothoré (eBPF Foundation) 		if (ASSERT_OK(setup(&tests[i]), "setup bpffs pin dir")) {
140*1c0b5059SAlexis Lothoré (eBPF Foundation) 			run_test(&tests[i]);
141*1c0b5059SAlexis Lothoré (eBPF Foundation) 			cleanup(&tests[i]);
142*1c0b5059SAlexis Lothoré (eBPF Foundation) 		}
143*1c0b5059SAlexis Lothoré (eBPF Foundation) 	}
144*1c0b5059SAlexis Lothoré (eBPF Foundation) }
145