Thread (4 messages) 4 messages, 2 authors, 2021-11-29

Re: [PATCH bpf-next v2 1/2] libbpf: Support static initialization of BPF_MAP_TYPE_PROG_ARRAY

From: Andrii Nakryiko <hidden>
Date: 2021-11-29 06:33:19

On Sun, Nov 28, 2021 at 6:17 AM Hengqi Chen [off-list ref] wrote:
Support static initialization of BPF_MAP_TYPE_PROG_ARRAY with a
syntax similar to map-in-map initialization ([0]):

    SEC("socket")
    int tailcall_1(void *ctx)
    {
        return 0;
    }

    struct {
        __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
        __uint(max_entries, 2);
        __uint(key_size, sizeof(__u32));
        __array(values, int (void *));
    } prog_array_init SEC(".maps") = {
        .values = {
            [1] = (void *)&tailcall_1,
        },
    };

Here's the relevant part of libbpf debug log showing what's
going on with prog-array initialization:

libbpf: sec '.relsocket': collecting relocation for section(3) 'socket'
libbpf: sec '.relsocket': relo #0: insn #2 against 'prog_array_init'
libbpf: prog 'entry': found map 0 (prog_array_init, sec 4, off 0) for insn #0
libbpf: .maps relo #0: for 3 value 0 rel->r_offset 32 name 53 ('tailcall_1')
libbpf: .maps relo #0: map 'prog_array_init' slot [1] points to prog 'tailcall_1'
libbpf: map 'prog_array_init': created successfully, fd=5
libbpf: map 'prog_array_init': slot [1] set to prog 'tailcall_1' fd=6

  [0] Closes: https://github.com/libbpf/libbpf/issues/354

Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
---
 tools/lib/bpf/libbpf.c | 139 ++++++++++++++++++++++++++++++++---------
 1 file changed, 111 insertions(+), 28 deletions(-)
[...]
-               targ_map = bpf_object__find_map_by_name(obj, name);
-               if (!targ_map)
-                       return -ESRCH;
+               if (is_map_in_map) {
+                       targ_map = bpf_object__find_map_by_name(obj, name);
+                       if (!targ_map)
+                               return -ESRCH;
+               }
+               if (is_prog_array) {
+                       targ_prog = bpf_object__find_program_by_name(obj, name);
+                       if (!targ_prog)
+                               return -ESRCH;
+                       if (targ_prog->sec_idx != sym->st_shndx ||
+                           targ_prog->sec_insn_off * 8 != sym->st_value ||
+                           prog_is_subprog(obj, targ_prog)) {
+                               pr_warn(".maps relo #%d: '%s' isn't an entry-point BPF program\n",
+                                       i, name);
+                               return -LIBBPF_ERRNO__RELOC;
+                       }
+               }
I've slightly adjusted this part to have an exhaustive if
(is_map_in_map) else if (is_prog_array) else { return -EINVAL; }. I've
also added an error message when someone is trying to put non-BPF
program into BPF_MAP_TYPE_PROG_ARRAY, like this:

  libbpf: .maps relo #0: 'value' isn't a valid program reference

Awesome work, applied to bpf-next, thanks.
quoted hunk ↗ jump to hunk
                var = btf__type_by_id(obj->btf, vi->type);
                def = skip_mods_and_typedefs(obj->btf, var->type, NULL);
@@ -6287,10 +6369,10 @@ static int bpf_object__collect_map_relos(struct bpf_object *obj,
                               (new_sz - map->init_slots_sz) * host_ptr_sz);
                        map->init_slots_sz = new_sz;
                }
-               map->init_slots[moff] = targ_map;
+               map->init_slots[moff] = is_map_in_map ? (void *)targ_map : (void *)targ_prog;

-               pr_debug(".maps relo #%d: map '%s' slot [%d] points to map '%s'\n",
-                        i, map->name, moff, name);
+               pr_debug(".maps relo #%d: map '%s' slot [%d] points to %s '%s'\n",
+                        i, map->name, moff, type, name);
        }

        return 0;
@@ -7304,6 +7386,7 @@ int bpf_object__load_xattr(struct bpf_object_load_attr *attr)
        err = err ? : bpf_object__create_maps(obj);
        err = err ? : bpf_object__relocate(obj, obj->btf_custom_path ? : attr->target_btf_path);
        err = err ? : bpf_object__load_progs(obj, attr->log_level);
+       err = err ? : bpf_object_init_prog_arrays(obj);

        if (obj->gen_loader) {
                /* reset FDs */
--
2.30.2
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help