Commit 52d3352e authored by Wang Nan's avatar Wang Nan Committed by Arnaldo Carvalho de Melo

bpf tools: Create eBPF maps defined in an object file

This patch creates maps based on 'map' section in object file using
bpf_create_map(), and stores the fds into an array in 'struct
bpf_object'.

Previous patches parse ELF object file and collects required data, but
doesn't play with the kernel. They belong to the 'opening' phase. This
patch is the first patch in 'loading' phase. The 'loaded' field is
introduced in 'struct bpf_object' to avoid loading an object twice,
because the loading phase clears resources collected during the opening
which becomes useless after loading. In this patch, maps_buf is cleared.
Signed-off-by: default avatarWang Nan <wangnan0@huawei.com>
Acked-by: default avatarAlexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1435716878-189507-17-git-send-email-wangnan0@huawei.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent e3ed2fef
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <gelf.h> #include <gelf.h>
#include "libbpf.h" #include "libbpf.h"
#include "bpf.h"
#define __printf(a, b) __attribute__((format(printf, a, b))) #define __printf(a, b) __attribute__((format(printf, a, b)))
...@@ -105,6 +106,13 @@ struct bpf_object { ...@@ -105,6 +106,13 @@ struct bpf_object {
struct bpf_program *programs; struct bpf_program *programs;
size_t nr_programs; size_t nr_programs;
int *map_fds;
/*
* This field is required because maps_buf will be freed and
* maps_buf_sz will be set to 0 after loaded.
*/
size_t nr_map_fds;
bool loaded;
/* /*
* Information when doing elf related work. Only valid if fd * Information when doing elf related work. Only valid if fd
...@@ -233,6 +241,7 @@ static struct bpf_object *bpf_object__new(const char *path, ...@@ -233,6 +241,7 @@ static struct bpf_object *bpf_object__new(const char *path,
obj->efile.obj_buf = obj_buf; obj->efile.obj_buf = obj_buf;
obj->efile.obj_buf_sz = obj_buf_sz; obj->efile.obj_buf_sz = obj_buf_sz;
obj->loaded = false;
return obj; return obj;
} }
...@@ -565,6 +574,62 @@ bpf_program__collect_reloc(struct bpf_program *prog, ...@@ -565,6 +574,62 @@ bpf_program__collect_reloc(struct bpf_program *prog,
return 0; return 0;
} }
static int
bpf_object__create_maps(struct bpf_object *obj)
{
unsigned int i;
size_t nr_maps;
int *pfd;
nr_maps = obj->maps_buf_sz / sizeof(struct bpf_map_def);
if (!obj->maps_buf || !nr_maps) {
pr_debug("don't need create maps for %s\n",
obj->path);
return 0;
}
obj->map_fds = malloc(sizeof(int) * nr_maps);
if (!obj->map_fds) {
pr_warning("realloc perf_bpf_map_fds failed\n");
return -ENOMEM;
}
obj->nr_map_fds = nr_maps;
/* fill all fd with -1 */
memset(obj->map_fds, -1, sizeof(int) * nr_maps);
pfd = obj->map_fds;
for (i = 0; i < nr_maps; i++) {
struct bpf_map_def def;
def = *(struct bpf_map_def *)(obj->maps_buf +
i * sizeof(struct bpf_map_def));
*pfd = bpf_create_map(def.type,
def.key_size,
def.value_size,
def.max_entries);
if (*pfd < 0) {
size_t j;
int err = *pfd;
pr_warning("failed to create map: %s\n",
strerror(errno));
for (j = 0; j < i; j++)
zclose(obj->map_fds[j]);
obj->nr_map_fds = 0;
zfree(&obj->map_fds);
return err;
}
pr_debug("create map: fd=%d\n", *pfd);
pfd++;
}
zfree(&obj->maps_buf);
obj->maps_buf_sz = 0;
return 0;
}
static int bpf_object__collect_reloc(struct bpf_object *obj) static int bpf_object__collect_reloc(struct bpf_object *obj)
{ {
int i, err; int i, err;
...@@ -668,6 +733,42 @@ struct bpf_object *bpf_object__open_buffer(void *obj_buf, ...@@ -668,6 +733,42 @@ struct bpf_object *bpf_object__open_buffer(void *obj_buf,
return __bpf_object__open("[buffer]", obj_buf, obj_buf_sz); return __bpf_object__open("[buffer]", obj_buf, obj_buf_sz);
} }
int bpf_object__unload(struct bpf_object *obj)
{
size_t i;
if (!obj)
return -EINVAL;
for (i = 0; i < obj->nr_map_fds; i++)
zclose(obj->map_fds[i]);
zfree(&obj->map_fds);
obj->nr_map_fds = 0;
return 0;
}
int bpf_object__load(struct bpf_object *obj)
{
if (!obj)
return -EINVAL;
if (obj->loaded) {
pr_warning("object should not be loaded twice\n");
return -EINVAL;
}
obj->loaded = true;
if (bpf_object__create_maps(obj))
goto out;
return 0;
out:
bpf_object__unload(obj);
pr_warning("failed to load object '%s'\n", obj->path);
return -EINVAL;
}
void bpf_object__close(struct bpf_object *obj) void bpf_object__close(struct bpf_object *obj)
{ {
size_t i; size_t i;
...@@ -676,6 +777,7 @@ void bpf_object__close(struct bpf_object *obj) ...@@ -676,6 +777,7 @@ void bpf_object__close(struct bpf_object *obj)
return; return;
bpf_object__elf_finish(obj); bpf_object__elf_finish(obj);
bpf_object__unload(obj);
zfree(&obj->maps_buf); zfree(&obj->maps_buf);
......
...@@ -30,6 +30,10 @@ struct bpf_object *bpf_object__open_buffer(void *obj_buf, ...@@ -30,6 +30,10 @@ struct bpf_object *bpf_object__open_buffer(void *obj_buf,
size_t obj_buf_sz); size_t obj_buf_sz);
void bpf_object__close(struct bpf_object *object); void bpf_object__close(struct bpf_object *object);
/* Load/unload object into/from kernel */
int bpf_object__load(struct bpf_object *obj);
int bpf_object__unload(struct bpf_object *obj);
/* /*
* We don't need __attribute__((packed)) now since it is * We don't need __attribute__((packed)) now since it is
* unnecessary for 'bpf_map_def' because they are all aligned. * unnecessary for 'bpf_map_def' because they are all aligned.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment