OSDN Git Service

libbpf: Factor out low-level BPF program loading helper
authorAndrii Nakryiko <andrii@kernel.org>
Thu, 3 Dec 2020 20:46:31 +0000 (12:46 -0800)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 4 Dec 2020 01:38:21 +0000 (17:38 -0800)
Refactor low-level API for BPF program loading to not rely on public API
types. This allows painless extension without constant efforts to cleverly not
break backwards compatibility.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20201203204634.1325171-12-andrii@kernel.org
tools/lib/bpf/bpf.c
tools/lib/bpf/libbpf.c
tools/lib/bpf/libbpf_internal.h

index 4025266..5d681ce 100644 (file)
@@ -215,59 +215,52 @@ alloc_zero_tailing_info(const void *orecord, __u32 cnt,
        return info;
 }
 
-int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
-                          char *log_buf, size_t log_buf_sz)
+int libbpf__bpf_prog_load(const struct bpf_prog_load_params *load_attr)
 {
        void *finfo = NULL, *linfo = NULL;
        union bpf_attr attr;
-       __u32 log_level;
        int fd;
 
-       if (!load_attr || !log_buf != !log_buf_sz)
+       if (!load_attr->log_buf != !load_attr->log_buf_sz)
                return -EINVAL;
 
-       log_level = load_attr->log_level;
-       if (log_level > (4 | 2 | 1) || (log_level && !log_buf))
+       if (load_attr->log_level > (4 | 2 | 1) || (load_attr->log_level && !load_attr->log_buf))
                return -EINVAL;
 
        memset(&attr, 0, sizeof(attr));
        attr.prog_type = load_attr->prog_type;
        attr.expected_attach_type = load_attr->expected_attach_type;
-       if (attr.prog_type == BPF_PROG_TYPE_STRUCT_OPS ||
-           attr.prog_type == BPF_PROG_TYPE_LSM) {
-               attr.attach_btf_id = load_attr->attach_btf_id;
-       } else if (attr.prog_type == BPF_PROG_TYPE_TRACING ||
-                  attr.prog_type == BPF_PROG_TYPE_EXT) {
-               attr.attach_btf_id = load_attr->attach_btf_id;
-               attr.attach_prog_fd = load_attr->attach_prog_fd;
-       } else {
-               attr.prog_ifindex = load_attr->prog_ifindex;
-               attr.kern_version = load_attr->kern_version;
-       }
-       attr.insn_cnt = (__u32)load_attr->insns_cnt;
+
+       attr.attach_btf_id = load_attr->attach_btf_id;
+       attr.attach_prog_fd = load_attr->attach_prog_fd;
+
+       attr.prog_ifindex = load_attr->prog_ifindex;
+       attr.kern_version = load_attr->kern_version;
+
+       attr.insn_cnt = (__u32)load_attr->insn_cnt;
        attr.insns = ptr_to_u64(load_attr->insns);
        attr.license = ptr_to_u64(load_attr->license);
 
-       attr.log_level = log_level;
-       if (log_level) {
-               attr.log_buf = ptr_to_u64(log_buf);
-               attr.log_size = log_buf_sz;
-       } else {
-               attr.log_buf = ptr_to_u64(NULL);
-               attr.log_size = 0;
+       attr.log_level = load_attr->log_level;
+       if (attr.log_level) {
+               attr.log_buf = ptr_to_u64(load_attr->log_buf);
+               attr.log_size = load_attr->log_buf_sz;
        }
 
        attr.prog_btf_fd = load_attr->prog_btf_fd;
+       attr.prog_flags = load_attr->prog_flags;
+
        attr.func_info_rec_size = load_attr->func_info_rec_size;
        attr.func_info_cnt = load_attr->func_info_cnt;
        attr.func_info = ptr_to_u64(load_attr->func_info);
+
        attr.line_info_rec_size = load_attr->line_info_rec_size;
        attr.line_info_cnt = load_attr->line_info_cnt;
        attr.line_info = ptr_to_u64(load_attr->line_info);
+
        if (load_attr->name)
                memcpy(attr.prog_name, load_attr->name,
-                      min(strlen(load_attr->name), BPF_OBJ_NAME_LEN - 1));
-       attr.prog_flags = load_attr->prog_flags;
+                      min(strlen(load_attr->name), (size_t)BPF_OBJ_NAME_LEN - 1));
 
        fd = sys_bpf_prog_load(&attr, sizeof(attr));
        if (fd >= 0)
@@ -307,19 +300,19 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
                }
 
                fd = sys_bpf_prog_load(&attr, sizeof(attr));
-
                if (fd >= 0)
                        goto done;
        }
 
-       if (log_level || !log_buf)
+       if (load_attr->log_level || !load_attr->log_buf)
                goto done;
 
        /* Try again with log */
-       attr.log_buf = ptr_to_u64(log_buf);
-       attr.log_size = log_buf_sz;
+       attr.log_buf = ptr_to_u64(load_attr->log_buf);
+       attr.log_size = load_attr->log_buf_sz;
        attr.log_level = 1;
-       log_buf[0] = 0;
+       load_attr->log_buf[0] = 0;
+
        fd = sys_bpf_prog_load(&attr, sizeof(attr));
 done:
        free(finfo);
@@ -327,6 +320,49 @@ done:
        return fd;
 }
 
+int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
+                          char *log_buf, size_t log_buf_sz)
+{
+       struct bpf_prog_load_params p = {};
+
+       if (!load_attr || !log_buf != !log_buf_sz)
+               return -EINVAL;
+
+       p.prog_type = load_attr->prog_type;
+       p.expected_attach_type = load_attr->expected_attach_type;
+       switch (p.prog_type) {
+       case BPF_PROG_TYPE_STRUCT_OPS:
+       case BPF_PROG_TYPE_LSM:
+               p.attach_btf_id = load_attr->attach_btf_id;
+               break;
+       case BPF_PROG_TYPE_TRACING:
+       case BPF_PROG_TYPE_EXT:
+               p.attach_btf_id = load_attr->attach_btf_id;
+               p.attach_prog_fd = load_attr->attach_prog_fd;
+               break;
+       default:
+               p.prog_ifindex = load_attr->prog_ifindex;
+               p.kern_version = load_attr->kern_version;
+       }
+       p.insn_cnt = load_attr->insns_cnt;
+       p.insns = load_attr->insns;
+       p.license = load_attr->license;
+       p.log_level = load_attr->log_level;
+       p.log_buf = log_buf;
+       p.log_buf_sz = log_buf_sz;
+       p.prog_btf_fd = load_attr->prog_btf_fd;
+       p.func_info_rec_size = load_attr->func_info_rec_size;
+       p.func_info_cnt = load_attr->func_info_cnt;
+       p.func_info = load_attr->func_info;
+       p.line_info_rec_size = load_attr->line_info_rec_size;
+       p.line_info_cnt = load_attr->line_info_cnt;
+       p.line_info = load_attr->line_info;
+       p.name = load_attr->name;
+       p.prog_flags = load_attr->prog_flags;
+
+       return libbpf__bpf_prog_load(&p);
+}
+
 int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
                     size_t insns_cnt, const char *license,
                     __u32 kern_version, char *log_buf,
index ca20e49..103d66e 100644 (file)
@@ -6809,7 +6809,7 @@ static int
 load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
             char *license, __u32 kern_version, int *pfd)
 {
-       struct bpf_load_program_attr load_attr;
+       struct bpf_prog_load_params load_attr = {};
        char *cp, errmsg[STRERR_BUFSIZE];
        size_t log_buf_size = 0;
        char *log_buf = NULL;
@@ -6828,7 +6828,6 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
        if (!insns || !insns_cnt)
                return -EINVAL;
 
-       memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
        load_attr.prog_type = prog->type;
        /* old kernels might not support specifying expected_attach_type */
        if (!kernel_supports(FEAT_EXP_ATTACH_TYPE) && prog->sec_def &&
@@ -6839,19 +6838,14 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
        if (kernel_supports(FEAT_PROG_NAME))
                load_attr.name = prog->name;
        load_attr.insns = insns;
-       load_attr.insns_cnt = insns_cnt;
+       load_attr.insn_cnt = insns_cnt;
        load_attr.license = license;
-       if (prog->type == BPF_PROG_TYPE_STRUCT_OPS ||
-           prog->type == BPF_PROG_TYPE_LSM) {
-               load_attr.attach_btf_id = prog->attach_btf_id;
-       } else if (prog->type == BPF_PROG_TYPE_TRACING ||
-                  prog->type == BPF_PROG_TYPE_EXT) {
-               load_attr.attach_prog_fd = prog->attach_prog_fd;
-               load_attr.attach_btf_id = prog->attach_btf_id;
-       } else {
-               load_attr.kern_version = kern_version;
-               load_attr.prog_ifindex = prog->prog_ifindex;
-       }
+       load_attr.attach_btf_id = prog->attach_btf_id;
+       load_attr.attach_prog_fd = prog->attach_prog_fd;
+       load_attr.attach_btf_id = prog->attach_btf_id;
+       load_attr.kern_version = kern_version;
+       load_attr.prog_ifindex = prog->prog_ifindex;
+
        /* specify func_info/line_info only if kernel supports them */
        btf_fd = bpf_object__btf_fd(prog->obj);
        if (btf_fd >= 0 && kernel_supports(FEAT_BTF_FUNC)) {
@@ -6875,7 +6869,9 @@ retry_load:
                *log_buf = 0;
        }
 
-       ret = bpf_load_program_xattr(&load_attr, log_buf, log_buf_size);
+       load_attr.log_buf = log_buf;
+       load_attr.log_buf_sz = log_buf_size;
+       ret = libbpf__bpf_prog_load(&load_attr);
 
        if (ret >= 0) {
                if (log_buf && load_attr.log_level)
@@ -6916,9 +6912,9 @@ retry_load:
                pr_warn("-- BEGIN DUMP LOG ---\n");
                pr_warn("\n%s\n", log_buf);
                pr_warn("-- END LOG --\n");
-       } else if (load_attr.insns_cnt >= BPF_MAXINSNS) {
+       } else if (load_attr.insn_cnt >= BPF_MAXINSNS) {
                pr_warn("Program too large (%zu insns), at most %d insns\n",
-                       load_attr.insns_cnt, BPF_MAXINSNS);
+                       load_attr.insn_cnt, BPF_MAXINSNS);
                ret = -LIBBPF_ERRNO__PROG2BIG;
        } else if (load_attr.prog_type != BPF_PROG_TYPE_KPROBE) {
                /* Wrong program type? */
@@ -6926,7 +6922,9 @@ retry_load:
 
                load_attr.prog_type = BPF_PROG_TYPE_KPROBE;
                load_attr.expected_attach_type = 0;
-               fd = bpf_load_program_xattr(&load_attr, NULL, 0);
+               load_attr.log_buf = NULL;
+               load_attr.log_buf_sz = 0;
+               fd = libbpf__bpf_prog_load(&load_attr);
                if (fd >= 0) {
                        close(fd);
                        ret = -LIBBPF_ERRNO__PROGTYPE;
index e569ae6..681073a 100644 (file)
@@ -151,6 +151,35 @@ int parse_cpu_mask_file(const char *fcpu, bool **mask, int *mask_sz);
 int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
                         const char *str_sec, size_t str_len);
 
+struct bpf_prog_load_params {
+       enum bpf_prog_type prog_type;
+       enum bpf_attach_type expected_attach_type;
+       const char *name;
+       const struct bpf_insn *insns;
+       size_t insn_cnt;
+       const char *license;
+       __u32 kern_version;
+       __u32 attach_prog_fd;
+       __u32 attach_btf_id;
+       __u32 prog_ifindex;
+       __u32 prog_btf_fd;
+       __u32 prog_flags;
+
+       __u32 func_info_rec_size;
+       const void *func_info;
+       __u32 func_info_cnt;
+
+       __u32 line_info_rec_size;
+       const void *line_info;
+       __u32 line_info_cnt;
+
+       __u32 log_level;
+       char *log_buf;
+       size_t log_buf_sz;
+};
+
+int libbpf__bpf_prog_load(const struct bpf_prog_load_params *load_attr);
+
 int bpf_object__section_size(const struct bpf_object *obj, const char *name,
                             __u32 *size);
 int bpf_object__variable_offset(const struct bpf_object *obj, const char *name,