Commit addb9fc9 authored by Nikita V. Shirokov's avatar Nikita V. Shirokov Committed by Daniel Borkmann
Browse files

bpf: adding support for map in map in libbpf



idea is pretty simple. for specified map (pointed by struct bpf_map)
we would provide descriptor of already loaded map, which is going to be
used as a prototype for inner map. proposed workflow:
1) open bpf's object (bpf_object__open)
2) create bpf's map which is going to be used as a prototype
3) find (by name) map-in-map which you want to load and update w/
descriptor of inner map w/ a new helper from this patch
4) load bpf program w/ bpf_object__load

Signed-off-by: default avatarNikita V. Shirokov <tehnerd@tehnerd.com>
Acked-by: default avatarYonghong Song <yhs@fb.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent 5b32a23e
Loading
Loading
Loading
Loading
+34 −6
Original line number Diff line number Diff line
@@ -175,6 +175,7 @@ struct bpf_map {
	char *name;
	size_t offset;
	int map_ifindex;
	int inner_map_fd;
	struct bpf_map_def def;
	__u32 btf_key_type_id;
	__u32 btf_value_type_id;
@@ -605,6 +606,14 @@ static int compare_bpf_map(const void *_a, const void *_b)
	return a->offset - b->offset;
}

static bool bpf_map_type__is_map_in_map(enum bpf_map_type type)
{
	if (type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
	    type == BPF_MAP_TYPE_HASH_OF_MAPS)
		return true;
	return false;
}

static int
bpf_object__init_maps(struct bpf_object *obj, int flags)
{
@@ -668,13 +677,15 @@ bpf_object__init_maps(struct bpf_object *obj, int flags)
	}
	obj->nr_maps = nr_maps;

	for (i = 0; i < nr_maps; i++) {
		/*
		 * fill all fd with -1 so won't close incorrect
		 * fd (fd=0 is stdin) when failure (zclose won't close
		 * negative fd)).
		 */
	for (i = 0; i < nr_maps; i++)
		obj->maps[i].fd = -1;
		obj->maps[i].inner_map_fd = -1;
	}

	/*
	 * Fill obj->maps using data in "maps" section.
@@ -1222,6 +1233,9 @@ bpf_object__create_maps(struct bpf_object *obj)
		create_attr.btf_fd = 0;
		create_attr.btf_key_type_id = 0;
		create_attr.btf_value_type_id = 0;
		if (bpf_map_type__is_map_in_map(def->type) &&
		    map->inner_map_fd >= 0)
			create_attr.inner_map_fd = map->inner_map_fd;

		if (obj->btf && !bpf_map_find_btf_info(map, obj->btf)) {
			create_attr.btf_fd = btf__fd(obj->btf);
@@ -2681,6 +2695,20 @@ void bpf_map__set_ifindex(struct bpf_map *map, __u32 ifindex)
	map->map_ifindex = ifindex;
}

int bpf_map__set_inner_map_fd(struct bpf_map *map, int fd)
{
	if (!bpf_map_type__is_map_in_map(map->def.type)) {
		pr_warning("error: unsupported map type\n");
		return -EINVAL;
	}
	if (map->inner_map_fd != -1) {
		pr_warning("error: inner_map_fd already specified\n");
		return -EINVAL;
	}
	map->inner_map_fd = fd;
	return 0;
}

static struct bpf_map *
__bpf_map__iter(struct bpf_map *m, struct bpf_object *obj, int i)
{
+2 −0
Original line number Diff line number Diff line
@@ -297,6 +297,8 @@ 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);
LIBBPF_API int bpf_map__unpin(struct bpf_map *map, const char *path);

LIBBPF_API int bpf_map__set_inner_map_fd(struct bpf_map *map, int fd);

LIBBPF_API long libbpf_get_error(const void *ptr);

struct bpf_prog_load_attr {