OSDN Git Service

libbpf: Add subskeleton scaffolding
authorDelyan Kratunov <delyank@fb.com>
Wed, 16 Mar 2022 23:37:33 +0000 (23:37 +0000)
committerAndrii Nakryiko <andrii@kernel.org>
Fri, 18 Mar 2022 06:11:16 +0000 (23:11 -0700)
In symmetry with bpf_object__open_skeleton(),
bpf_object__open_subskeleton() performs the actual walking and linking
of maps, progs, and globals described by bpf_*_skeleton objects.

Signed-off-by: Delyan Kratunov <delyank@fb.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/6942a46fbe20e7ebf970affcca307ba616985b15.1647473511.git.delyank@fb.com
tools/lib/bpf/libbpf.c
tools/lib/bpf/libbpf.h
tools/lib/bpf/libbpf.map

index 9de42d1..7526419 100644 (file)
@@ -11989,6 +11989,49 @@ int libbpf_num_possible_cpus(void)
        return tmp_cpus;
 }
 
+static int populate_skeleton_maps(const struct bpf_object *obj,
+                                 struct bpf_map_skeleton *maps,
+                                 size_t map_cnt)
+{
+       int i;
+
+       for (i = 0; i < map_cnt; i++) {
+               struct bpf_map **map = maps[i].map;
+               const char *name = maps[i].name;
+               void **mmaped = maps[i].mmaped;
+
+               *map = bpf_object__find_map_by_name(obj, name);
+               if (!*map) {
+                       pr_warn("failed to find skeleton map '%s'\n", name);
+                       return -ESRCH;
+               }
+
+               /* externs shouldn't be pre-setup from user code */
+               if (mmaped && (*map)->libbpf_type != LIBBPF_MAP_KCONFIG)
+                       *mmaped = (*map)->mmaped;
+       }
+       return 0;
+}
+
+static int populate_skeleton_progs(const struct bpf_object *obj,
+                                  struct bpf_prog_skeleton *progs,
+                                  size_t prog_cnt)
+{
+       int i;
+
+       for (i = 0; i < prog_cnt; i++) {
+               struct bpf_program **prog = progs[i].prog;
+               const char *name = progs[i].name;
+
+               *prog = bpf_object__find_program_by_name(obj, name);
+               if (!*prog) {
+                       pr_warn("failed to find skeleton program '%s'\n", name);
+                       return -ESRCH;
+               }
+       }
+       return 0;
+}
+
 int bpf_object__open_skeleton(struct bpf_object_skeleton *s,
                              const struct bpf_object_open_opts *opts)
 {
@@ -11996,7 +12039,7 @@ int bpf_object__open_skeleton(struct bpf_object_skeleton *s,
                .object_name = s->name,
        );
        struct bpf_object *obj;
-       int i, err;
+       int err;
 
        /* Attempt to preserve opts->object_name, unless overriden by user
         * explicitly. Overwriting object name for skeletons is discouraged,
@@ -12019,37 +12062,91 @@ int bpf_object__open_skeleton(struct bpf_object_skeleton *s,
        }
 
        *s->obj = obj;
+       err = populate_skeleton_maps(obj, s->maps, s->map_cnt);
+       if (err) {
+               pr_warn("failed to populate skeleton maps for '%s': %d\n", s->name, err);
+               return libbpf_err(err);
+       }
 
-       for (i = 0; i < s->map_cnt; i++) {
-               struct bpf_map **map = s->maps[i].map;
-               const char *name = s->maps[i].name;
-               void **mmaped = s->maps[i].mmaped;
+       err = populate_skeleton_progs(obj, s->progs, s->prog_cnt);
+       if (err) {
+               pr_warn("failed to populate skeleton progs for '%s': %d\n", s->name, err);
+               return libbpf_err(err);
+       }
 
-               *map = bpf_object__find_map_by_name(obj, name);
-               if (!*map) {
-                       pr_warn("failed to find skeleton map '%s'\n", name);
-                       return libbpf_err(-ESRCH);
-               }
+       return 0;
+}
 
-               /* externs shouldn't be pre-setup from user code */
-               if (mmaped && (*map)->libbpf_type != LIBBPF_MAP_KCONFIG)
-                       *mmaped = (*map)->mmaped;
+int bpf_object__open_subskeleton(struct bpf_object_subskeleton *s)
+{
+       int err, len, var_idx, i;
+       const char *var_name;
+       const struct bpf_map *map;
+       struct btf *btf;
+       __u32 map_type_id;
+       const struct btf_type *map_type, *var_type;
+       const struct bpf_var_skeleton *var_skel;
+       struct btf_var_secinfo *var;
+
+       if (!s->obj)
+               return libbpf_err(-EINVAL);
+
+       btf = bpf_object__btf(s->obj);
+       if (!btf) {
+               pr_warn("subskeletons require BTF at runtime (object %s)\n",
+                       bpf_object__name(s->obj));
+               return libbpf_err(-errno);
        }
 
-       for (i = 0; i < s->prog_cnt; i++) {
-               struct bpf_program **prog = s->progs[i].prog;
-               const char *name = s->progs[i].name;
+       err = populate_skeleton_maps(s->obj, s->maps, s->map_cnt);
+       if (err) {
+               pr_warn("failed to populate subskeleton maps: %d\n", err);
+               return libbpf_err(err);
+       }
 
-               *prog = bpf_object__find_program_by_name(obj, name);
-               if (!*prog) {
-                       pr_warn("failed to find skeleton program '%s'\n", name);
-                       return libbpf_err(-ESRCH);
-               }
+       err = populate_skeleton_progs(s->obj, s->progs, s->prog_cnt);
+       if (err) {
+               pr_warn("failed to populate subskeleton maps: %d\n", err);
+               return libbpf_err(err);
        }
 
+       for (var_idx = 0; var_idx < s->var_cnt; var_idx++) {
+               var_skel = &s->vars[var_idx];
+               map = *var_skel->map;
+               map_type_id = bpf_map__btf_value_type_id(map);
+               map_type = btf__type_by_id(btf, map_type_id);
+
+               if (!btf_is_datasec(map_type)) {
+                       pr_warn("type for map '%1$s' is not a datasec: %2$s",
+                               bpf_map__name(map),
+                               __btf_kind_str(btf_kind(map_type)));
+                       return libbpf_err(-EINVAL);
+               }
+
+               len = btf_vlen(map_type);
+               var = btf_var_secinfos(map_type);
+               for (i = 0; i < len; i++, var++) {
+                       var_type = btf__type_by_id(btf, var->type);
+                       var_name = btf__name_by_offset(btf, var_type->name_off);
+                       if (strcmp(var_name, var_skel->name) == 0) {
+                               *var_skel->addr = map->mmaped + var->offset;
+                               break;
+                       }
+               }
+       }
        return 0;
 }
 
+void bpf_object__destroy_subskeleton(struct bpf_object_subskeleton *s)
+{
+       if (!s)
+               return;
+       free(s->maps);
+       free(s->progs);
+       free(s->vars);
+       free(s);
+}
+
 int bpf_object__load_skeleton(struct bpf_object_skeleton *s)
 {
        int i, err;
index d5239fb..05dde85 100644 (file)
@@ -1312,6 +1312,35 @@ LIBBPF_API int bpf_object__attach_skeleton(struct bpf_object_skeleton *s);
 LIBBPF_API void bpf_object__detach_skeleton(struct bpf_object_skeleton *s);
 LIBBPF_API void bpf_object__destroy_skeleton(struct bpf_object_skeleton *s);
 
+struct bpf_var_skeleton {
+       const char *name;
+       struct bpf_map **map;
+       void **addr;
+};
+
+struct bpf_object_subskeleton {
+       size_t sz; /* size of this struct, for forward/backward compatibility */
+
+       const struct bpf_object *obj;
+
+       int map_cnt;
+       int map_skel_sz; /* sizeof(struct bpf_map_skeleton) */
+       struct bpf_map_skeleton *maps;
+
+       int prog_cnt;
+       int prog_skel_sz; /* sizeof(struct bpf_prog_skeleton) */
+       struct bpf_prog_skeleton *progs;
+
+       int var_cnt;
+       int var_skel_sz; /* sizeof(struct bpf_var_skeleton) */
+       struct bpf_var_skeleton *vars;
+};
+
+LIBBPF_API int
+bpf_object__open_subskeleton(struct bpf_object_subskeleton *s);
+LIBBPF_API void
+bpf_object__destroy_subskeleton(struct bpf_object_subskeleton *s);
+
 struct gen_loader_opts {
        size_t sz; /* size of this struct, for forward/backward compatiblity */
        const char *data;
index 554c56e..dd35ee5 100644 (file)
@@ -442,6 +442,8 @@ LIBBPF_0.7.0 {
 
 LIBBPF_0.8.0 {
        global:
+               bpf_object__destroy_subskeleton;
+               bpf_object__open_subskeleton;
                libbpf_register_prog_handler;
                libbpf_unregister_prog_handler;
                bpf_program__attach_kprobe_multi_opts;