History

bpf: libbpf: Provide basic API support to specify BPF obj name

This patch extends the libbpf to provide API support to allow specifying BPF object name. In tools/lib/bpf/libbpf, the C symbol of the function and the map is used. Regarding section name, all maps are under the same section named "maps". Hence, section name is not a good choice for map's name. To be consistent with map, bpf_prog also follows and uses its function symbol as the prog's name. This patch adds logic to collect function's symbols in libbpf. There is existing codes to collect the map's symbols and no change is needed. The bpf_load_program_name() and bpf_map_create_name() are added to take the name argument. For the other bpf_map_create_xxx() variants, a name argument is directly added to them. In samples/bpf, bpf_load.c in particular, the symbol is also used as the map's name and the map symbols has already been collected in the existing code. For bpf_prog, bpf_load.c does not collect the function symbol name. We can consider to collect them later if there is a need to continue supporting the bpf_load.c.

Martin KaFai Lau committed 9 years ago

Commit 88cda1c1 parent ad5b1777 files · +157 −47Browse files

Unified · Split

7 files
  1. samples/bpf/bpf_load.c +2 −0
  2. samples/bpf/map_perf_test_user.c +1 −0
  3. tools/include/uapi/linux/bpf.h +10 −0
  4. tools/lib/bpf/bpf.c +44 −13
  5. tools/lib/bpf/bpf.h +16 −7
  6. tools/lib/bpf/libbpf.c +83 −26
  7. tools/testing/selftests/bpf/test_verifier.c +1 −1
samples/bpf/bpf_load.c+2−0
@@ -221,6 +221,7 @@ static int load_maps(struct bpf_map_data *maps, int nr_maps, · 220 unmodified lines
221221 int inner_map_fd = map_fd[maps[i].def.inner_map_idx];
222222
223223 map_fd[i] = bpf_create_map_in_map_node(maps[i].def.type,
224+ maps[i].name,
224225 maps[i].def.key_size,
225226 inner_map_fd,
226227 maps[i].def.max_entries,
@@ -228,6 +229,7 @@ static int load_maps(struct bpf_map_data *maps, int nr_maps, · 1 unmodified line
228229 numa_node);
229230 } else {
230231 map_fd[i] = bpf_create_map_node(maps[i].def.type,
232+ maps[i].name,
231233 maps[i].def.key_size,
232234 maps[i].def.value_size,
233235 maps[i].def.max_entries,
samples/bpf/map_perf_test_user.c+1−0
@@ -137,6 +137,7 @@ static void do_test_lru(enum test_type test, int cpu) · 136 unmodified lines
137137
138138 inner_lru_map_fds[cpu] =
139139 bpf_create_map_node(BPF_MAP_TYPE_LRU_HASH,
140+ test_map_names[INNER_LRU_HASH_PREALLOC],
140141 sizeof(uint32_t),
141142 sizeof(long),
142143 inner_lru_hash_size, 0,
tools/include/uapi/linux/bpf.h+10−0
@@ -175,6 +175,8 @@ enum bpf_attach_type { · 174 unmodified lines
175175 /* Specify numa node during map creation */
176176 #define BPF_F_NUMA_NODE (1U << 2)
177177
178+#define BPF_OBJ_NAME_LEN 16U
179+
178180 union bpf_attr {
179181 struct { /* anonymous struct used by BPF_MAP_CREATE command */
180182 __u32 map_type; /* one of enum bpf_map_type */
@@ -188,6 +190,7 @@ union bpf_attr { · 7 unmodified lines
188190 __u32 numa_node; /* numa node (effective only if
189191 * BPF_F_NUMA_NODE is set).
190192 */
193+ __u8 map_name[BPF_OBJ_NAME_LEN];
191194 };
192195
193196 struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */
@@ -210,6 +213,7 @@ union bpf_attr { · 16 unmodified lines
210213 __aligned_u64 log_buf; /* user supplied buffer */
211214 __u32 kern_version; /* checked when prog_type=kprobe */
212215 __u32 prog_flags;
216+ __u8 prog_name[BPF_OBJ_NAME_LEN];
213217 };
214218
215219 struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -812,6 +816,11 @@ struct bpf_prog_info { · 596 unmodified lines
812816 __u32 xlated_prog_len;
813817 __aligned_u64 jited_prog_insns;
814818 __aligned_u64 xlated_prog_insns;
819+ __u64 load_time; /* ns since boottime */
820+ __u32 created_by_uid;
821+ __u32 nr_map_ids;
822+ __aligned_u64 map_ids;
823+ __u8 name[BPF_OBJ_NAME_LEN];
815824 } __attribute__((aligned(8)));
816825
817826 struct bpf_map_info {
@@ -821,6 +830,7 @@ struct bpf_map_info { · 3 unmodified lines
821830 __u32 value_size;
822831 __u32 max_entries;
823832 __u32 map_flags;
833+ __u8 name[BPF_OBJ_NAME_LEN];
824834 } __attribute__((aligned(8)));
825835
826836 /* User bpf_sock_ops struct to access socket values and specify request ops
tools/lib/bpf/bpf.c+44−13
@@ -46,6 +46,8 @@ · 45 unmodified lines
4646 # endif
4747 #endif
4848
49+#define min(x, y) ((x) < (y) ? (x) : (y))
50+
4951 static inline __u64 ptr_to_u64(const void *ptr)
5052 {
5153 return (__u64) (unsigned long) ptr;
@@ -57,10 +59,11 @@ static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr, · 5 unmodified lines
5759 return syscall(__NR_bpf, cmd, attr, size);
5860 }
5961
60−int bpf_create_map_node(enum bpf_map_type map_type, int key_size,
61− int value_size, int max_entries, __u32 map_flags,
62− int node)
62+int bpf_create_map_node(enum bpf_map_type map_type, const char *name,
63+ int key_size, int value_size, int max_entries,
64+ __u32 map_flags, int node)
6365 {
66+ __u32 name_len = name ? strlen(name) : 0;
6467 union bpf_attr attr;
6568
6669 memset(&attr, '\0', sizeof(attr));
@@ -70,6 +73,8 @@ int bpf_create_map_node(enum bpf_map_type map_type, int key_size, · 3 unmodified lines
7073 attr.value_size = value_size;
7174 attr.max_entries = max_entries;
7275 attr.map_flags = map_flags;
76+ memcpy(attr.map_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1));
77+
7378 if (node >= 0) {
7479 attr.map_flags |= BPF_F_NUMA_NODE;
7580 attr.numa_node = node;
@@ -81,14 +86,23 @@ int bpf_create_map_node(enum bpf_map_type map_type, int key_size, · 5 unmodified lines
8186 int bpf_create_map(enum bpf_map_type map_type, int key_size,
8287 int value_size, int max_entries, __u32 map_flags)
8388 {
84− return bpf_create_map_node(map_type, key_size, value_size,
89+ return bpf_create_map_node(map_type, NULL, key_size, value_size,
8590 max_entries, map_flags, -1);
8691 }
8792
88−int bpf_create_map_in_map_node(enum bpf_map_type map_type, int key_size,
89− int inner_map_fd, int max_entries,
93+int bpf_create_map_name(enum bpf_map_type map_type, const char *name,
94+ int key_size, int value_size, int max_entries,
95+ __u32 map_flags)
96+{
97+ return bpf_create_map_node(map_type, name, key_size, value_size,
98+ max_entries, map_flags, -1);
99+}
100+
101+int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name,
102+ int key_size, int inner_map_fd, int max_entries,
90103 __u32 map_flags, int node)
91104 {
105+ __u32 name_len = name ? strlen(name) : 0;
92106 union bpf_attr attr;
93107
94108 memset(&attr, '\0', sizeof(attr));
@@ -99,6 +113,8 @@ int bpf_create_map_in_map_node(enum bpf_map_type map_type, int key_size, · 4 unmodified lines
99113 attr.inner_map_fd = inner_map_fd;
100114 attr.max_entries = max_entries;
101115 attr.map_flags = map_flags;
116+ memcpy(attr.map_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1));
117+
102118 if (node >= 0) {
103119 attr.map_flags |= BPF_F_NUMA_NODE;
104120 attr.numa_node = node;
@@ -107,19 +123,24 @@ int bpf_create_map_in_map_node(enum bpf_map_type map_type, int key_size, · 2 unmodified lines
107123 return sys_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
108124 }
109125
110−int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size,
111− int inner_map_fd, int max_entries, __u32 map_flags)
126+int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
127+ int key_size, int inner_map_fd, int max_entries,
128+ __u32 map_flags)
112129 {
113− return bpf_create_map_in_map_node(map_type, key_size, inner_map_fd,
114− max_entries, map_flags, -1);
130+ return bpf_create_map_in_map_node(map_type, name, key_size,
131+ inner_map_fd, max_entries, map_flags,
132+ -1);
115133 }
116134
117−int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
118− size_t insns_cnt, const char *license,
119− __u32 kern_version, char *log_buf, size_t log_buf_sz)
135+int bpf_load_program_name(enum bpf_prog_type type, const char *name,
136+ const struct bpf_insn *insns,
137+ size_t insns_cnt, const char *license,
138+ __u32 kern_version, char *log_buf,
139+ size_t log_buf_sz)
120140 {
121141 int fd;
122142 union bpf_attr attr;
143+ __u32 name_len = name ? strlen(name) : 0;
123144
124145 bzero(&attr, sizeof(attr));
125146 attr.prog_type = type;
@@ -130,6 +151,7 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, · 4 unmodified lines
130151 attr.log_size = 0;
131152 attr.log_level = 0;
132153 attr.kern_version = kern_version;
154+ memcpy(attr.prog_name, name, min(name_len, BPF_OBJ_NAME_LEN - 1));
133155
134156 fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
135157 if (fd >= 0 || !log_buf || !log_buf_sz)
@@ -143,6 +165,15 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, · 7 unmodified lines
143165 return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
144166 }
145167
168+int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
169+ size_t insns_cnt, const char *license,
170+ __u32 kern_version, char *log_buf,
171+ size_t log_buf_sz)
172+{
173+ return bpf_load_program_name(type, NULL, insns, insns_cnt, license,
174+ kern_version, log_buf, log_buf_sz);
175+}
176+
146177 int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
147178 size_t insns_cnt, int strict_alignment,
148179 const char *license, __u32 kern_version,
tools/lib/bpf/bpf.h+16−7
@@ -24,19 +24,28 @@ · 23 unmodified lines
2424 #include <linux/bpf.h>
2525 #include <stddef.h>
2626
27−int bpf_create_map_node(enum bpf_map_type map_type, int key_size,
28− int value_size, int max_entries, __u32 map_flags,
29− int node);
27+int bpf_create_map_node(enum bpf_map_type map_type, const char *name,
28+ int key_size, int value_size, int max_entries,
29+ __u32 map_flags, int node);
30+int bpf_create_map_name(enum bpf_map_type map_type, const char *name,
31+ int key_size, int value_size, int max_entries,
32+ __u32 map_flags);
3033 int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
3134 int max_entries, __u32 map_flags);
32−int bpf_create_map_in_map_node(enum bpf_map_type map_type, int key_size,
33− int inner_map_fd, int max_entries,
35+int bpf_create_map_in_map_node(enum bpf_map_type map_type, const char *name,
36+ int key_size, int inner_map_fd, int max_entries,
3437 __u32 map_flags, int node);
35−int bpf_create_map_in_map(enum bpf_map_type map_type, int key_size,
36− int inner_map_fd, int max_entries, __u32 map_flags);
38+int bpf_create_map_in_map(enum bpf_map_type map_type, const char *name,
39+ int key_size, int inner_map_fd, int max_entries,
40+ __u32 map_flags);
3741
3842 /* Recommend log buffer size */
3943 #define BPF_LOG_BUF_SIZE 65536
44+int bpf_load_program_name(enum bpf_prog_type type, const char *name,
45+ const struct bpf_insn *insns,
46+ size_t insns_cnt, const char *license,
47+ __u32 kern_version, char *log_buf,
48+ size_t log_buf_sz);
4049 int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
4150 size_t insns_cnt, const char *license,
4251 __u32 kern_version, char *log_buf,
tools/lib/bpf/libbpf.c+83−26
@@ -171,6 +171,7 @@ int libbpf_strerror(int err, char *buf, size_t size) · 170 unmodified lines
171171 struct bpf_program {
172172 /* Index in elf obj file, for relocation use. */
173173 int idx;
174+ char *name;
174175 char *section_name;
175176 struct bpf_insn *insns;
176177 size_t insns_cnt;
@@ -283,6 +284,7 @@ static void bpf_program__exit(struct bpf_program *prog) · 106 unmodified lines
283284 prog->clear_priv = NULL;
284285
285286 bpf_program__unload(prog);
287+ zfree(&prog->name);
286288 zfree(&prog->section_name);
287289 zfree(&prog->insns);
288290 zfree(&prog->reloc_desc);
@@ -293,26 +295,27 @@ static void bpf_program__exit(struct bpf_program *prog) · 4 unmodified lines
293295 }
294296
295297 static int
296−bpf_program__init(void *data, size_t size, char *name, int idx,
297− struct bpf_program *prog)
298+bpf_program__init(void *data, size_t size, char *section_name, int idx,
299+ struct bpf_program *prog)
298300 {
299301 if (size < sizeof(struct bpf_insn)) {
300− pr_warning("corrupted section '%s'\n", name);
302+ pr_warning("corrupted section '%s'\n", section_name);
301303 return -EINVAL;
302304 }
303305
304306 bzero(prog, sizeof(*prog));
305307
306− prog->section_name = strdup(name);
308+ prog->section_name = strdup(section_name);
307309 if (!prog->section_name) {
308− pr_warning("failed to alloc name for prog %s\n",
309− name);
310+ pr_warning("failed to alloc name for prog under section %s\n",
311+ section_name);
310312 goto errout;
311313 }
312314
313315 prog->insns = malloc(size);
314316 if (!prog->insns) {
315− pr_warning("failed to alloc insns for %s\n", name);
317+ pr_warning("failed to alloc insns for prog under section %s\n",
318+ section_name);
316319 goto errout;
317320 }
318321 prog->insns_cnt = size / sizeof(struct bpf_insn);
@@ -331,12 +334,12 @@ errout: · 12 unmodified lines
331334
332335 static int
333336 bpf_object__add_program(struct bpf_object *obj, void *data, size_t size,
334− char *name, int idx)
337+ char *section_name, int idx)
335338 {
336339 struct bpf_program prog, *progs;
337340 int nr_progs, err;
338341
339− err = bpf_program__init(data, size, name, idx, &prog);
342+ err = bpf_program__init(data, size, section_name, idx, &prog);
340343 if (err)
341344 return err;
342345
@@ -350,8 +353,8 @@ bpf_object__add_program(struct bpf_object *obj, void *data, size_t size, · 7 unmodified lines
350353 * is still valid, so don't need special treat for
351354 * bpf_close_object().
352355 */
353− pr_warning("failed to alloc a new program '%s'\n",
354− name);
356+ pr_warning("failed to alloc a new program under section '%s'\n",
357+ section_name);
355358 bpf_program__exit(&prog);
356359 return -ENOMEM;
357360 }
@@ -364,6 +367,54 @@ bpf_object__add_program(struct bpf_object *obj, void *data, size_t size, · 6 unmodified lines
364367 return 0;
365368 }
366369
370+static int
371+bpf_object__init_prog_names(struct bpf_object *obj)
372+{
373+ Elf_Data *symbols = obj->efile.symbols;
374+ struct bpf_program *prog;
375+ size_t pi, si;
376+
377+ for (pi = 0; pi < obj->nr_programs; pi++) {
378+ char *name = NULL;
379+
380+ prog = &obj->programs[pi];
381+
382+ for (si = 0; si < symbols->d_size / sizeof(GElf_Sym) && !name;
383+ si++) {
384+ GElf_Sym sym;
385+
386+ if (!gelf_getsym(symbols, si, &sym))
387+ continue;
388+ if (sym.st_shndx != prog->idx)
389+ continue;
390+
391+ name = elf_strptr(obj->efile.elf,
392+ obj->efile.strtabidx,
393+ sym.st_name);
394+ if (!name) {
395+ pr_warning("failed to get sym name string for prog %s\n",
396+ prog->section_name);
397+ return -LIBBPF_ERRNO__LIBELF;
398+ }
399+ }
400+
401+ if (!name) {
402+ pr_warning("failed to find sym for prog %s\n",
403+ prog->section_name);
404+ return -EINVAL;
405+ }
406+
407+ prog->name = strdup(name);
408+ if (!prog->name) {
409+ pr_warning("failed to allocate memory for prog sym %s\n",
410+ name);
411+ return -ENOMEM;
412+ }
413+ }
414+
415+ return 0;
416+}
417+
367418 static struct bpf_object *bpf_object__new(const char *path,
368419 void *obj_buf,
369420 size_t obj_buf_sz)
@@ -766,8 +817,12 @@ static int bpf_object__elf_collect(struct bpf_object *obj) · 396 unmodified lines
766817 pr_warning("Corrupted ELF file: index of strtab invalid\n");
767818 return LIBBPF_ERRNO__FORMAT;
768819 }
769− if (obj->efile.maps_shndx >= 0)
820+ if (obj->efile.maps_shndx >= 0) {
770821 err = bpf_object__init_maps(obj);
822+ if (err)
823+ goto out;
824+ }
825+ err = bpf_object__init_prog_names(obj);
771826 out:
772827 return err;
773828 }
@@ -870,11 +925,12 @@ bpf_object__create_maps(struct bpf_object *obj) · 96 unmodified lines
870925 struct bpf_map_def *def = &obj->maps[i].def;
871926 int *pfd = &obj->maps[i].fd;
872927
873− *pfd = bpf_create_map(def->type,
874− def->key_size,
875− def->value_size,
876− def->max_entries,
877− 0);
928+ *pfd = bpf_create_map_name(def->type,
929+ obj->maps[i].name,
930+ def->key_size,
931+ def->value_size,
932+ def->max_entries,
933+ 0);
878934 if (*pfd < 0) {
879935 size_t j;
880936 int err = *pfd;
@@ -982,7 +1038,7 @@ static int bpf_object__collect_reloc(struct bpf_object *obj) · 101 unmodified lines
9821038 }
9831039
9841040 static int
985−load_program(enum bpf_prog_type type, struct bpf_insn *insns,
1041+load_program(enum bpf_prog_type type, const char *name, struct bpf_insn *insns,
9861042 int insns_cnt, char *license, u32 kern_version, int *pfd)
9871043 {
9881044 int ret;
@@ -995,8 +1051,8 @@ load_program(enum bpf_prog_type type, struct bpf_insn *insns, · 6 unmodified lines
9951051 if (!log_buf)
9961052 pr_warning("Alloc log buffer for bpf loader error, continue without log\n");
9971053
998− ret = bpf_load_program(type, insns, insns_cnt, license,
999− kern_version, log_buf, BPF_LOG_BUF_SIZE);
1054+ ret = bpf_load_program_name(type, name, insns, insns_cnt, license,
1055+ kern_version, log_buf, BPF_LOG_BUF_SIZE);
10001056
10011057 if (ret >= 0) {
10021058 *pfd = ret;
@@ -1021,9 +1077,9 @@ load_program(enum bpf_prog_type type, struct bpf_insn *insns, · 18 unmodified lines
10211077 if (type != BPF_PROG_TYPE_KPROBE) {
10221078 int fd;
10231079
1024− fd = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns,
1025− insns_cnt, license, kern_version,
1026− NULL, 0);
1080+ fd = bpf_load_program_name(BPF_PROG_TYPE_KPROBE, name,
1081+ insns, insns_cnt, license,
1082+ kern_version, NULL, 0);
10271083 if (fd >= 0) {
10281084 close(fd);
10291085 ret = -LIBBPF_ERRNO__PROGTYPE;
@@ -1067,8 +1123,8 @@ bpf_program__load(struct bpf_program *prog, · 37 unmodified lines
10671123 pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n",
10681124 prog->section_name, prog->instances.nr);
10691125 }
1070− err = load_program(prog->type, prog->insns, prog->insns_cnt,
1071− license, kern_version, &fd);
1126+ err = load_program(prog->type, prog->name, prog->insns,
1127+ prog->insns_cnt, license, kern_version, &fd);
10721128 if (!err)
10731129 prog->instances.fds[0] = fd;
10741130 goto out;
@@ -1096,7 +1152,8 @@ bpf_program__load(struct bpf_program *prog, · 21 unmodified lines
10961152 continue;
10971153 }
10981154
1099− err = load_program(prog->type, result.new_insn_ptr,
1155+ err = load_program(prog->type, prog->name,
1156+ result.new_insn_ptr,
11001157 result.new_insn_cnt,
11011158 license, kern_version, &fd);
11021159
tools/testing/selftests/bpf/test_verifier.c+1−1
@@ -6939,7 +6939,7 @@ static int create_map_in_map(void) · 6938 unmodified lines
69396939 return inner_map_fd;
69406940 }
69416941
6942− outer_map_fd = bpf_create_map_in_map(BPF_MAP_TYPE_ARRAY_OF_MAPS,
6942+ outer_map_fd = bpf_create_map_in_map(BPF_MAP_TYPE_ARRAY_OF_MAPS, NULL,
69436943 sizeof(int), inner_map_fd, 1, 0);
69446944 if (outer_map_fd < 0)
69456945 printf("Failed to create array of maps '%s'!\n",