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 if (map_type == __MAX_BPF_MAP_TYPE) 136 continue; 137 138 map_type_name = btf__str_by_offset(btf, e->name_off); 139 map_type_str = libbpf_bpf_map_type_str(map_type); 140 ASSERT_OK_PTR(map_type_str, map_type_name); 141 142 snprintf(buf, sizeof(buf), "BPF_MAP_TYPE_%s", map_type_str); 143 uppercase(buf); 144 145 /* Special case for map_type_name BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED 146 * where it and BPF_MAP_TYPE_CGROUP_STORAGE have the same enum value 147 * (map_type). For this enum value, libbpf_bpf_map_type_str() picks 148 * BPF_MAP_TYPE_CGROUP_STORAGE. The same for 149 * BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE_DEPRECATED and 150 * BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE. 151 */ 152 if (strcmp(map_type_name, "BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED") == 0) 153 continue; 154 if (strcmp(map_type_name, "BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE_DEPRECATED") == 0) 155 continue; 156 157 ASSERT_STREQ(buf, map_type_name, "exp_str_value"); 158 } 159 160 cleanup: 161 btf__free(btf); 162 } 163 164 /* 165 * Test case to check that all bpf_prog_type variants are covered by 166 * libbpf_bpf_prog_type_str. 167 */ 168 static void test_libbpf_bpf_prog_type_str(void) 169 { 170 struct btf *btf; 171 const struct btf_type *t; 172 const struct btf_enum *e; 173 int i, n, id; 174 175 btf = btf__parse("/sys/kernel/btf/vmlinux", NULL); 176 if (!ASSERT_OK_PTR(btf, "btf_parse")) 177 return; 178 179 /* find enum bpf_prog_type and enumerate each value */ 180 id = btf__find_by_name_kind(btf, "bpf_prog_type", BTF_KIND_ENUM); 181 if (!ASSERT_GT(id, 0, "bpf_prog_type_id")) 182 goto cleanup; 183 t = btf__type_by_id(btf, id); 184 e = btf_enum(t); 185 n = btf_vlen(t); 186 for (i = 0; i < n; e++, i++) { 187 enum bpf_prog_type prog_type = (enum bpf_prog_type)e->val; 188 const char *prog_type_name; 189 const char *prog_type_str; 190 char buf[256]; 191 192 if (prog_type == __MAX_BPF_PROG_TYPE) 193 continue; 194 195 prog_type_name = btf__str_by_offset(btf, e->name_off); 196 prog_type_str = libbpf_bpf_prog_type_str(prog_type); 197 ASSERT_OK_PTR(prog_type_str, prog_type_name); 198 199 snprintf(buf, sizeof(buf), "BPF_PROG_TYPE_%s", prog_type_str); 200 uppercase(buf); 201 202 ASSERT_STREQ(buf, prog_type_name, "exp_str_value"); 203 } 204 205 cleanup: 206 btf__free(btf); 207 } 208 209 /* 210 * Run all libbpf str conversion tests. 211 */ 212 void test_libbpf_str(void) 213 { 214 if (test__start_subtest("bpf_attach_type_str")) 215 test_libbpf_bpf_attach_type_str(); 216 217 if (test__start_subtest("bpf_link_type_str")) 218 test_libbpf_bpf_link_type_str(); 219 220 if (test__start_subtest("bpf_map_type_str")) 221 test_libbpf_bpf_map_type_str(); 222 223 if (test__start_subtest("bpf_prog_type_str")) 224 test_libbpf_bpf_prog_type_str(); 225 } 226