1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */ 3 4 #include <ctype.h> 5 #include <test_progs.h> 6 #include <bpf/btf.h> 7 8 /* 9 * Utility function uppercasing an entire string. 10 */ 11 static void uppercase(char *s) 12 { 13 for (; *s != '\0'; s++) 14 *s = toupper(*s); 15 } 16 17 /* 18 * Test case to check that all bpf_attach_type variants are covered by 19 * libbpf_bpf_attach_type_str. 20 */ 21 static void test_libbpf_bpf_attach_type_str(void) 22 { 23 struct btf *btf; 24 const struct btf_type *t; 25 const struct btf_enum *e; 26 int i, n, id; 27 28 btf = btf__parse("/sys/kernel/btf/vmlinux", NULL); 29 if (!ASSERT_OK_PTR(btf, "btf_parse")) 30 return; 31 32 /* find enum bpf_attach_type and enumerate each value */ 33 id = btf__find_by_name_kind(btf, "bpf_attach_type", BTF_KIND_ENUM); 34 if (!ASSERT_GT(id, 0, "bpf_attach_type_id")) 35 goto cleanup; 36 t = btf__type_by_id(btf, id); 37 e = btf_enum(t); 38 n = btf_vlen(t); 39 for (i = 0; i < n; e++, i++) { 40 enum bpf_attach_type attach_type = (enum bpf_attach_type)e->val; 41 const char *attach_type_name; 42 const char *attach_type_str; 43 char buf[256]; 44 45 if (attach_type == __MAX_BPF_ATTACH_TYPE) 46 continue; 47 48 attach_type_name = btf__str_by_offset(btf, e->name_off); 49 attach_type_str = libbpf_bpf_attach_type_str(attach_type); 50 ASSERT_OK_PTR(attach_type_str, attach_type_name); 51 52 snprintf(buf, sizeof(buf), "BPF_%s", attach_type_str); 53 uppercase(buf); 54 55 ASSERT_STREQ(buf, attach_type_name, "exp_str_value"); 56 } 57 58 cleanup: 59 btf__free(btf); 60 } 61 62 /* 63 * Test case to check that all bpf_link_type variants are covered by 64 * libbpf_bpf_link_type_str. 65 */ 66 static void test_libbpf_bpf_link_type_str(void) 67 { 68 struct btf *btf; 69 const struct btf_type *t; 70 const struct btf_enum *e; 71 int i, n, id; 72 73 btf = btf__parse("/sys/kernel/btf/vmlinux", NULL); 74 if (!ASSERT_OK_PTR(btf, "btf_parse")) 75 return; 76 77 /* find enum bpf_link_type and enumerate each value */ 78 id = btf__find_by_name_kind(btf, "bpf_link_type", BTF_KIND_ENUM); 79 if (!ASSERT_GT(id, 0, "bpf_link_type_id")) 80 goto cleanup; 81 t = btf__type_by_id(btf, id); 82 e = btf_enum(t); 83 n = btf_vlen(t); 84 for (i = 0; i < n; e++, i++) { 85 enum bpf_link_type link_type = (enum bpf_link_type)e->val; 86 const char *link_type_name; 87 const char *link_type_str; 88 char buf[256]; 89 90 if (link_type == MAX_BPF_LINK_TYPE) 91 continue; 92 93 link_type_name = btf__str_by_offset(btf, e->name_off); 94 link_type_str = libbpf_bpf_link_type_str(link_type); 95 ASSERT_OK_PTR(link_type_str, link_type_name); 96 97 snprintf(buf, sizeof(buf), "BPF_LINK_TYPE_%s", link_type_str); 98 uppercase(buf); 99 100 ASSERT_STREQ(buf, link_type_name, "exp_str_value"); 101 } 102 103 cleanup: 104 btf__free(btf); 105 } 106 107 /* 108 * Test case to check that all bpf_map_type variants are covered by 109 * libbpf_bpf_map_type_str. 110 */ 111 static void test_libbpf_bpf_map_type_str(void) 112 { 113 struct btf *btf; 114 const struct btf_type *t; 115 const struct btf_enum *e; 116 int i, n, id; 117 118 btf = btf__parse("/sys/kernel/btf/vmlinux", NULL); 119 if (!ASSERT_OK_PTR(btf, "btf_parse")) 120 return; 121 122 /* find enum bpf_map_type and enumerate each value */ 123 id = btf__find_by_name_kind(btf, "bpf_map_type", BTF_KIND_ENUM); 124 if (!ASSERT_GT(id, 0, "bpf_map_type_id")) 125 goto cleanup; 126 t = btf__type_by_id(btf, id); 127 e = btf_enum(t); 128 n = btf_vlen(t); 129 for (i = 0; i < n; e++, i++) { 130 enum bpf_map_type map_type = (enum bpf_map_type)e->val; 131 const char *map_type_name; 132 const char *map_type_str; 133 char buf[256]; 134 135 map_type_name = btf__str_by_offset(btf, e->name_off); 136 map_type_str = libbpf_bpf_map_type_str(map_type); 137 ASSERT_OK_PTR(map_type_str, map_type_name); 138 139 snprintf(buf, sizeof(buf), "BPF_MAP_TYPE_%s", map_type_str); 140 uppercase(buf); 141 142 ASSERT_STREQ(buf, map_type_name, "exp_str_value"); 143 } 144 145 cleanup: 146 btf__free(btf); 147 } 148 149 /* 150 * Test case to check that all bpf_prog_type variants are covered by 151 * libbpf_bpf_prog_type_str. 152 */ 153 static void test_libbpf_bpf_prog_type_str(void) 154 { 155 struct btf *btf; 156 const struct btf_type *t; 157 const struct btf_enum *e; 158 int i, n, id; 159 160 btf = btf__parse("/sys/kernel/btf/vmlinux", NULL); 161 if (!ASSERT_OK_PTR(btf, "btf_parse")) 162 return; 163 164 /* find enum bpf_prog_type and enumerate each value */ 165 id = btf__find_by_name_kind(btf, "bpf_prog_type", BTF_KIND_ENUM); 166 if (!ASSERT_GT(id, 0, "bpf_prog_type_id")) 167 goto cleanup; 168 t = btf__type_by_id(btf, id); 169 e = btf_enum(t); 170 n = btf_vlen(t); 171 for (i = 0; i < n; e++, i++) { 172 enum bpf_prog_type prog_type = (enum bpf_prog_type)e->val; 173 const char *prog_type_name; 174 const char *prog_type_str; 175 char buf[256]; 176 177 prog_type_name = btf__str_by_offset(btf, e->name_off); 178 prog_type_str = libbpf_bpf_prog_type_str(prog_type); 179 ASSERT_OK_PTR(prog_type_str, prog_type_name); 180 181 snprintf(buf, sizeof(buf), "BPF_PROG_TYPE_%s", prog_type_str); 182 uppercase(buf); 183 184 ASSERT_STREQ(buf, prog_type_name, "exp_str_value"); 185 } 186 187 cleanup: 188 btf__free(btf); 189 } 190 191 /* 192 * Run all libbpf str conversion tests. 193 */ 194 void test_libbpf_str(void) 195 { 196 if (test__start_subtest("bpf_attach_type_str")) 197 test_libbpf_bpf_attach_type_str(); 198 199 if (test__start_subtest("bpf_link_type_str")) 200 test_libbpf_bpf_link_type_str(); 201 202 if (test__start_subtest("bpf_map_type_str")) 203 test_libbpf_bpf_map_type_str(); 204 205 if (test__start_subtest("bpf_prog_type_str")) 206 test_libbpf_bpf_prog_type_str(); 207 } 208