summaryrefslogtreecommitdiff
path: root/tools/lib/bpf/libbpf.c
diff options
context:
space:
mode:
authorAndrii Nakryiko <andriin@fb.com>2019-10-04 15:40:35 -0700
committerAlexei Starovoitov <ast@kernel.org>2019-10-05 18:09:47 -0700
commit2ce8450ef5a381e5ffeb4682c0093a3ab5d07008 (patch)
treebe97146a8e0eac4a465259ed2b11393685c09622 /tools/lib/bpf/libbpf.c
parent5e61f27070292d4ad3af51dc68eebab6c1df69d3 (diff)
libbpf: add bpf_object__open_{file, mem} w/ extensible opts
Add new set of bpf_object__open APIs using new approach to optional parameters extensibility allowing simpler ABI compatibility approach. This patch demonstrates an approach to implementing libbpf APIs that makes it easy to extend existing APIs with extra optional parameters in such a way, that ABI compatibility is preserved without having to do symbol versioning and generating lots of boilerplate code to handle it. To facilitate succinct code for working with options, add OPTS_VALID, OPTS_HAS, and OPTS_GET macros that hide all the NULL, size, and zero checks. Additionally, newly added libbpf APIs are encouraged to follow similar pattern of having all mandatory parameters as formal function parameters and always have optional (NULL-able) xxx_opts struct, which should always have real struct size as a first field and the rest would be optional parameters added over time, which tune the behavior of existing API, if specified by user. Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'tools/lib/bpf/libbpf.c')
-rw-r--r--tools/lib/bpf/libbpf.c87
1 files changed, 68 insertions, 19 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 024334b29b54..d471d33400ae 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -505,7 +505,8 @@ static __u32 get_kernel_version(void)
static struct bpf_object *bpf_object__new(const char *path,
const void *obj_buf,
- size_t obj_buf_sz)
+ size_t obj_buf_sz,
+ const char *obj_name)
{
struct bpf_object *obj;
char *end;
@@ -517,11 +518,17 @@ static struct bpf_object *bpf_object__new(const char *path,
}
strcpy(obj->path, path);
- /* Using basename() GNU version which doesn't modify arg. */
- strncpy(obj->name, basename((void *)path), sizeof(obj->name) - 1);
- end = strchr(obj->name, '.');
- if (end)
- *end = 0;
+ if (obj_name) {
+ strncpy(obj->name, obj_name, sizeof(obj->name) - 1);
+ obj->name[sizeof(obj->name) - 1] = 0;
+ } else {
+ /* Using basename() GNU version which doesn't modify arg. */
+ strncpy(obj->name, basename((void *)path),
+ sizeof(obj->name) - 1);
+ end = strchr(obj->name, '.');
+ if (end)
+ *end = 0;
+ }
obj->efile.fd = -1;
/*
@@ -3547,7 +3554,7 @@ bpf_object__load_progs(struct bpf_object *obj, int log_level)
static struct bpf_object *
__bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz,
- int flags)
+ const char *obj_name, int flags)
{
struct bpf_object *obj;
int err;
@@ -3557,7 +3564,7 @@ __bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz,
return ERR_PTR(-LIBBPF_ERRNO__LIBELF);
}
- obj = bpf_object__new(path, obj_buf, obj_buf_sz);
+ obj = bpf_object__new(path, obj_buf, obj_buf_sz, obj_name);
if (IS_ERR(obj))
return obj;
@@ -3583,7 +3590,7 @@ __bpf_object__open_xattr(struct bpf_object_open_attr *attr, int flags)
pr_debug("loading %s\n", attr->file);
- return __bpf_object__open(attr->file, NULL, 0, flags);
+ return __bpf_object__open(attr->file, NULL, 0, NULL, flags);
}
struct bpf_object *bpf_object__open_xattr(struct bpf_object_open_attr *attr)
@@ -3601,25 +3608,67 @@ struct bpf_object *bpf_object__open(const char *path)
return bpf_object__open_xattr(&attr);
}
-struct bpf_object *bpf_object__open_buffer(void *obj_buf,
- size_t obj_buf_sz,
- const char *name)
+struct bpf_object *
+bpf_object__open_file(const char *path, struct bpf_object_open_opts *opts)
+{
+ const char *obj_name;
+ bool relaxed_maps;
+
+ if (!OPTS_VALID(opts, bpf_object_open_opts))
+ return ERR_PTR(-EINVAL);
+ if (!path)
+ return ERR_PTR(-EINVAL);
+
+ pr_debug("loading %s\n", path);
+
+ obj_name = OPTS_GET(opts, object_name, path);
+ relaxed_maps = OPTS_GET(opts, relaxed_maps, false);
+ return __bpf_object__open(path, NULL, 0, obj_name,
+ relaxed_maps ? MAPS_RELAX_COMPAT : 0);
+}
+
+struct bpf_object *
+bpf_object__open_mem(const void *obj_buf, size_t obj_buf_sz,
+ struct bpf_object_open_opts *opts)
{
char tmp_name[64];
+ const char *obj_name;
+ bool relaxed_maps;
- /* param validation */
- if (!obj_buf || obj_buf_sz <= 0)
- return NULL;
+ if (!OPTS_VALID(opts, bpf_object_open_opts))
+ return ERR_PTR(-EINVAL);
+ if (!obj_buf || obj_buf_sz == 0)
+ return ERR_PTR(-EINVAL);
- if (!name) {
+ obj_name = OPTS_GET(opts, object_name, NULL);
+ if (!obj_name) {
snprintf(tmp_name, sizeof(tmp_name), "%lx-%lx",
(unsigned long)obj_buf,
(unsigned long)obj_buf_sz);
- name = tmp_name;
+ obj_name = tmp_name;
}
- pr_debug("loading object '%s' from buffer\n", name);
+ pr_debug("loading object '%s' from buffer\n", obj_name);
+
+ relaxed_maps = OPTS_GET(opts, relaxed_maps, false);
+ return __bpf_object__open(obj_name, obj_buf, obj_buf_sz, obj_name,
+ relaxed_maps ? MAPS_RELAX_COMPAT : 0);
+}
+
+struct bpf_object *
+bpf_object__open_buffer(const void *obj_buf, size_t obj_buf_sz,
+ const char *name)
+{
+ LIBBPF_OPTS(bpf_object_open_opts, opts,
+ .object_name = name,
+ /* wrong default, but backwards-compatible */
+ .relaxed_maps = true,
+ );
+
+ /* returning NULL is wrong, but backwards-compatible */
+ if (!obj_buf || obj_buf_sz == 0)
+ return NULL;
- return __bpf_object__open(name, obj_buf, obj_buf_sz, true);
+ return bpf_object__open_mem(obj_buf, obj_buf_sz, &opts);
}
int bpf_object__unload(struct bpf_object *obj)