Skip to contentSkip to conversation

libbpf: Add new interfaces

PATCH In review Andrey Ignatov 3 participants 6 messages Feb 14, 2019 – Feb 15, 2019

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover libbpf: Add new interfaces

The patch set adds a couple of new interfaces to libbpf:

Patch 1 adds bpf_map__resize() to resize map before loading bpf_object; Patch 2 adds bpf_object__btf() to get struct btf * from bpf_object__btf.

Andrey Ignatov (2):
libbpf: Introduce bpf_map__resize
libbpf: Introduce bpf_object__btf

 tools/lib/bpf/libbpf.c   | 19 +++++++++++++++++++
 tools/lib/bpf/libbpf.h   |  4 ++++
 tools/lib/bpf/libbpf.map |  2 ++
 3 files changed, 25 insertions(+)
Signature · 1 line
2.17.1
#1 lore raw

PATCH 1/2 libbpf: Introduce bpf_map__resize

Add bpf_map__resize() to change max_entries for a map.

Quite often necessary map size is unknown at compile time and can be calculated only at run time.

Currently the following approach is used to do so:
* bpf_object__open_buffer() to open Elf file from a buffer;
* bpf_object__find_map_by_name() to find relevant map;
* bpf_map__def() to get map attributes and create struct bpf_create_map_attr from them;
* update max_entries in bpf_create_map_attr;
* bpf_create_map_xattr() to create new map with updated max_entries;
* bpf_map__reuse_fd() to replace the map in bpf_object with newly created one.

And after all this bpf_object can finally be loaded. The map will have new size.

It 1) is quite a lot of steps; 2) doesn't take BTF into account.

For "2)" even more steps should be made and some of them require changes to libbpf (e.g. to get struct btf * from bpf_object).

Instead the whole problem can be solved by introducing simple bpf_map__resize() API that checks the map and sets new max_entries if the map is not loaded yet.

So the new steps are:
* bpf_object__open_buffer() to open Elf file from a buffer;
* bpf_object__find_map_by_name() to find relevant map;
* bpf_map__resize() to update max_entries.

That's much simpler and works with BTF.

---
 tools/lib/bpf/libbpf.c   | 14 ++++++++++++++
 tools/lib/bpf/libbpf.h   |  1 +
 tools/lib/bpf/libbpf.map |  1 +
 3 files changed, 16 insertions(+)
tools/lib/bpf/libbpf.c +14 -0
index e3c39edfb9d3..690e7b079202 100644
@@ -1114,6 +1114,20 @@ int bpf_map__reuse_fd(struct bpf_map *map, int fd)
 	return -errno;
 }
 
+int bpf_map__resize(struct bpf_map *map, __u32 max_entries)
+{
+	if (!map || !max_entries)
+		return -EINVAL;
+
+	/* If map already created, its attributes can't be changed. */
+	if (map->fd >= 0)
+		return -EBUSY;
+
+	map->def.max_entries = max_entries;
+
+	return 0;
+}
+
 static int
 bpf_object__probe_name(struct bpf_object *obj)
 {
tools/lib/bpf/libbpf.h +1 -0
index 69a7c25eaccc..987fd92661d6 100644
@@ -294,6 +294,7 @@ LIBBPF_API int bpf_map__set_priv(struct bpf_map *map, void *priv,
 				 bpf_map_clear_priv_t clear_priv);
 LIBBPF_API void *bpf_map__priv(struct bpf_map *map);
 LIBBPF_API int bpf_map__reuse_fd(struct bpf_map *map, int fd);
+LIBBPF_API int bpf_map__resize(struct bpf_map *map, __u32 max_entries);
 LIBBPF_API bool bpf_map__is_offload_neutral(struct bpf_map *map);
 LIBBPF_API void bpf_map__set_ifindex(struct bpf_map *map, __u32 ifindex);
 LIBBPF_API int bpf_map__pin(struct bpf_map *map, const char *path);
tools/lib/bpf/libbpf.map +1 -0
index 5fc8222209f8..16f342c3d4bc 100644
@@ -130,6 +130,7 @@ LIBBPF_0.0.2 {
 		bpf_probe_helper;
 		bpf_probe_map_type;
 		bpf_probe_prog_type;
+		bpf_map__resize;
 		bpf_map_lookup_elem_flags;
 		bpf_object__find_map_fd_by_name;
 		bpf_get_link_xdp_id;
Signature · 1 line
2.17.1
Acked-by on v1 1/2
#2 lore raw

Re: [PATCH bpf-next 1/2] libbpf: Introduce bpf_map__resize

Quoted 27 lines · Andrey Ignatov

Add bpf_map__resize() to change max_entries for a map.

Quite often necessary map size is unknown at compile time and can be calculated only at run time.

Currently the following approach is used to do so:
* bpf_object__open_buffer() to open Elf file from a buffer;
* bpf_object__find_map_by_name() to find relevant map;
* bpf_map__def() to get map attributes and create struct bpf_create_map_attr from them;
* update max_entries in bpf_create_map_attr;
* bpf_create_map_xattr() to create new map with updated max_entries;
* bpf_map__reuse_fd() to replace the map in bpf_object with newly created one.

And after all this bpf_object can finally be loaded. The map will have new size.

It 1) is quite a lot of steps; 2) doesn't take BTF into account.

For "2)" even more steps should be made and some of them require changes to libbpf (e.g. to get struct btf * from bpf_object).

Instead the whole problem can be solved by introducing simple bpf_map__resize() API that checks the map and sets new max_entries if the map is not loaded yet.

Quoted 8 lines

So the new steps are:
* bpf_object__open_buffer() to open Elf file from a buffer;
* bpf_object__find_map_by_name() to find relevant map;
* bpf_map__resize() to update max_entries.

That's much simpler and works with BTF.

#3 lore raw

PATCH 2/2 libbpf: Introduce bpf_object__btf

In reply to Andrey Ignatov

Add new accessor for bpf_object to get opaque struct btf * from it.

struct btf * is needed for all operations with BTF and it's present in bpf_object. The only thing missing is a way to get it.

Example use-case is to get BTF key_type_id an value_type_id for a map in bpf_object. It can be done with btf__get_map_kv_tids() but that function requires struct btf *.

Similar API can be added for struct btf_ext but no use-case for it yet.

---
 tools/lib/bpf/libbpf.c   | 5 +++++
 tools/lib/bpf/libbpf.h   | 3 +++
 tools/lib/bpf/libbpf.map | 1 +
 3 files changed, 9 insertions(+)
tools/lib/bpf/libbpf.c +5 -0
index 690e7b079202..a77a327c2bb8 100644
@@ -2332,6 +2332,11 @@ unsigned int bpf_object__kversion(struct bpf_object *obj)
 	return obj ? obj->kern_version : 0;
 }
 
+struct btf *bpf_object__btf(struct bpf_object *obj)
+{
+	return obj ? obj->btf : NULL;
+}
+
 int bpf_object__btf_fd(const struct bpf_object *obj)
 {
 	return obj->btf ? btf__fd(obj->btf) : -1;
tools/lib/bpf/libbpf.h +3 -0
index 987fd92661d6..6c0168f8bba5 100644
@@ -89,6 +89,9 @@ LIBBPF_API int bpf_object__load(struct bpf_object *obj);
 LIBBPF_API int bpf_object__unload(struct bpf_object *obj);
 LIBBPF_API const char *bpf_object__name(struct bpf_object *obj);
 LIBBPF_API unsigned int bpf_object__kversion(struct bpf_object *obj);
+
+struct btf;
+LIBBPF_API struct btf *bpf_object__btf(struct bpf_object *obj);
 LIBBPF_API int bpf_object__btf_fd(const struct bpf_object *obj);
 
 LIBBPF_API struct bpf_program *
tools/lib/bpf/libbpf.map +1 -0
index 16f342c3d4bc..99dfa710c818 100644
@@ -132,6 +132,7 @@ LIBBPF_0.0.2 {
 		bpf_probe_prog_type;
 		bpf_map__resize;
 		bpf_map_lookup_elem_flags;
+		bpf_object__btf;
 		bpf_object__find_map_fd_by_name;
 		bpf_get_link_xdp_id;
 		btf__dedup;
Signature · 1 line
2.17.1
Acked-by on v1 2/2
#4 lore raw

Re: [PATCH bpf-next 2/2] libbpf: Introduce bpf_object__btf

Quoted 6 lines · Andrey Ignatov

Add new accessor for bpf_object to get opaque struct btf * from it.

struct btf * is needed for all operations with BTF and it's present in bpf_object. The only thing missing is a way to get it.

Example use-case is to get BTF key_type_id an value_type_id for a map in

nit: an => and

Quoted 6 lines

bpf_object. It can be done with btf__get_map_kv_tids() but that function requires struct btf *.

Similar API can be added for struct btf_ext but no use-case for it yet.

maintainer
#5 lore raw

Re: [PATCH bpf-next 2/2] libbpf: Introduce bpf_object__btf

Quoted 10 lines · Yonghong Song
Quoted 6 lines · Andrey Ignatov

Add new accessor for bpf_object to get opaque struct btf * from it.

struct btf * is needed for all operations with BTF and it's present in bpf_object. The only thing missing is a way to get it.

Example use-case is to get BTF key_type_id an value_type_id for a map in

nit: an => and

Quoted 2 lines

bpf_object. It can be done with btf__get_map_kv_tids() but that function requires struct btf *.

Series applied and fixed above typo, thanks!