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