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