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