From: Joe Burton <jevburton@xxxxxxxxxx> Programs may be now loaded with libbpf. Sections with the prefix "map_trace/" will use the new attach type. Signed-off-by: Joe Burton <jevburton@xxxxxxxxxx> --- tools/include/uapi/linux/bpf.h | 22 ++++++ tools/lib/bpf/bpf.c | 13 ++-- tools/lib/bpf/bpf.h | 4 +- tools/lib/bpf/libbpf.c | 118 +++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf.h | 11 +++ tools/lib/bpf/libbpf.map | 1 + 6 files changed, 163 insertions(+), 6 deletions(-) diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 6fc59d61937a..3d5d3dafc066 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -93,6 +93,20 @@ union bpf_iter_link_info { } map; }; +enum bpf_map_trace_type { + BPF_MAP_TRACE_UPDATE_ELEM = 0, + BPF_MAP_TRACE_DELETE_ELEM = 1, + + MAX_BPF_MAP_TRACE_TYPE, +}; + +struct bpf_map_trace_link_info { + __u32 map_fd; + enum bpf_map_trace_type trace_type; +}; + +#define BPF_MAP_TRACE_FUNC(trace_type) "bpf_map_trace__" #trace_type + /* BPF syscall commands, see bpf(2) man-page for more details. */ /** * DOC: eBPF Syscall Preamble @@ -994,6 +1008,7 @@ enum bpf_attach_type { BPF_SK_REUSEPORT_SELECT, BPF_SK_REUSEPORT_SELECT_OR_MIGRATE, BPF_PERF_EVENT, + BPF_TRACE_MAP, __MAX_BPF_ATTACH_TYPE }; @@ -1008,6 +1023,7 @@ enum bpf_link_type { BPF_LINK_TYPE_NETNS = 5, BPF_LINK_TYPE_XDP = 6, BPF_LINK_TYPE_PERF_EVENT = 7, + BPF_LINK_TYPE_MAP_TRACE = 8, MAX_BPF_LINK_TYPE, }; @@ -1455,6 +1471,12 @@ union bpf_attr { */ __u64 bpf_cookie; } perf_event; + struct { + /* extra bpf_map_trace_link_info */ + __aligned_u64 map_trace_info; + /* map_trace_info length */ + __u32 map_trace_info_len; + }; }; } link_create; diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index 2401fad090c5..e18ddd362052 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -674,7 +674,7 @@ int bpf_link_create(int prog_fd, int target_fd, enum bpf_attach_type attach_type, const struct bpf_link_create_opts *opts) { - __u32 target_btf_id, iter_info_len; + __u32 target_btf_id, iter_info_len, map_trace_info_len; union bpf_attr attr; int fd; @@ -682,13 +682,12 @@ int bpf_link_create(int prog_fd, int target_fd, return libbpf_err(-EINVAL); iter_info_len = OPTS_GET(opts, iter_info_len, 0); + map_trace_info_len = OPTS_GET(opts, map_trace_info_len, 0); target_btf_id = OPTS_GET(opts, target_btf_id, 0); /* validate we don't have unexpected combinations of non-zero fields */ - if (iter_info_len || target_btf_id) { - if (iter_info_len && target_btf_id) - return libbpf_err(-EINVAL); - if (!OPTS_ZEROED(opts, target_btf_id)) + if (iter_info_len || map_trace_info_len || target_btf_id) { + if ((iter_info_len || map_trace_info_len) && target_btf_id) return libbpf_err(-EINVAL); } @@ -713,6 +712,10 @@ int bpf_link_create(int prog_fd, int target_fd, if (!OPTS_ZEROED(opts, perf_event)) return libbpf_err(-EINVAL); break; + case BPF_TRACE_MAP: + attr.link_create.map_trace_info = ptr_to_u64(OPTS_GET(opts, map_trace_info, (void *)0)); + attr.link_create.map_trace_info_len = map_trace_info_len; + break; default: if (!OPTS_ZEROED(opts, flags)) return libbpf_err(-EINVAL); diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h index 6fffb3cdf39b..deb276ad489f 100644 --- a/tools/lib/bpf/bpf.h +++ b/tools/lib/bpf/bpf.h @@ -183,8 +183,10 @@ struct bpf_link_create_opts { } perf_event; }; size_t :0; + struct bpf_map_trace_link_info *map_trace_info; + __u32 map_trace_info_len; }; -#define bpf_link_create_opts__last_field perf_event +#define bpf_link_create_opts__last_field map_trace_info_len LIBBPF_API int bpf_link_create(int prog_fd, int target_fd, enum bpf_attach_type attach_type, diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 1c859b32968d..a82126c0b969 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -7987,6 +7987,7 @@ static struct bpf_link *attach_raw_tp(const struct bpf_program *prog, long cooki static struct bpf_link *attach_trace(const struct bpf_program *prog, long cookie); static struct bpf_link *attach_lsm(const struct bpf_program *prog, long cookie); static struct bpf_link *attach_iter(const struct bpf_program *prog, long cookie); +static struct bpf_link *attach_map_trace(const struct bpf_program *prog, long cookie); static const struct bpf_sec_def section_defs[] = { SEC_DEF("socket", SOCKET_FILTER, 0, SEC_NONE | SEC_SLOPPY_PFX), @@ -8014,6 +8015,7 @@ static const struct bpf_sec_def section_defs[] = { SEC_DEF("lsm/", LSM, BPF_LSM_MAC, SEC_ATTACH_BTF, attach_lsm), SEC_DEF("lsm.s/", LSM, BPF_LSM_MAC, SEC_ATTACH_BTF | SEC_SLEEPABLE, attach_lsm), SEC_DEF("iter/", TRACING, BPF_TRACE_ITER, SEC_ATTACH_BTF, attach_iter), + SEC_DEF("map_trace/", TRACING, BPF_TRACE_MAP, SEC_ATTACH_BTF, attach_map_trace), SEC_DEF("syscall", SYSCALL, 0, SEC_SLEEPABLE), SEC_DEF("xdp_devmap/", XDP, BPF_XDP_DEVMAP, SEC_ATTACHABLE), SEC_DEF("xdp_cpumap/", XDP, BPF_XDP_CPUMAP, SEC_ATTACHABLE), @@ -8311,6 +8313,7 @@ static int bpf_object__collect_st_ops_relos(struct bpf_object *obj, #define BTF_TRACE_PREFIX "btf_trace_" #define BTF_LSM_PREFIX "bpf_lsm_" #define BTF_ITER_PREFIX "bpf_iter_" +#define BTF_MAP_TRACE_PREFIX "bpf_map_trace__BPF_MAP_TRACE_" #define BTF_MAX_NAME_SIZE 128 void btf_get_kernel_prefix_kind(enum bpf_attach_type attach_type, @@ -8329,6 +8332,10 @@ void btf_get_kernel_prefix_kind(enum bpf_attach_type attach_type, *prefix = BTF_ITER_PREFIX; *kind = BTF_KIND_FUNC; break; + case BPF_TRACE_MAP: + *prefix = BTF_MAP_TRACE_PREFIX; + *kind = BTF_KIND_FUNC; + break; default: *prefix = ""; *kind = BTF_KIND_FUNC; @@ -8464,6 +8471,15 @@ static int libbpf_find_attach_btf_id(struct bpf_program *prog, const char *attac __u32 attach_prog_fd = prog->attach_prog_fd; int err = 0; + if (attach_type == BPF_TRACE_MAP) { + while (*attach_name && *attach_name != '/') + ++attach_name; + if (!*attach_name || !*(++attach_name)) { + pr_warn("failed to parse trace type from ELF section name '%s'\n", prog->sec_name); + return -EINVAL; + } + } + /* BPF program's BTF ID */ if (attach_prog_fd) { err = libbpf_find_prog_btf_id(attach_name, attach_prog_fd); @@ -9951,6 +9967,108 @@ static struct bpf_link *attach_iter(const struct bpf_program *prog, long cookie) return bpf_program__attach_iter(prog, NULL); } +struct bpf_link * +bpf_program__attach_map_trace(const struct bpf_program *prog, + const struct bpf_map_trace_attach_opts *opts) +{ + DECLARE_LIBBPF_OPTS(bpf_link_create_opts, link_create_opts); + char errmsg[STRERR_BUFSIZE]; + struct bpf_link *link; + int prog_fd, link_fd; + __u32 target_fd = 0; + + if (!OPTS_VALID(opts, bpf_map_trace_attach_opts)) + return ERR_PTR(-EINVAL); + + link_create_opts.map_trace_info = OPTS_GET(opts, link_info, (void *)0); + link_create_opts.map_trace_info_len = OPTS_GET(opts, link_info_len, 0); + + prog_fd = bpf_program__fd(prog); + if (prog_fd < 0) { + pr_warn("prog '%s': can't attach before loaded\n", prog->name); + return ERR_PTR(-EINVAL); + } + + link = calloc(1, sizeof(*link)); + if (!link) + return ERR_PTR(-ENOMEM); + link->detach = &bpf_link__detach_fd; + + link_fd = bpf_link_create(prog_fd, target_fd, BPF_TRACE_MAP, + &link_create_opts); + if (link_fd < 0) { + link_fd = -errno; + free(link); + pr_warn("prog '%s': failed to attach to map: %s\n", + prog->name, libbpf_strerror_r(link_fd, errmsg, sizeof(errmsg))); + return ERR_PTR(link_fd); + } + link->fd = link_fd; + return link; +} + +static struct bpf_link *attach_map_trace(const struct bpf_program *prog, + long cookie) +{ + struct bpf_map_trace_attach_opts map_trace_opts; + struct bpf_map_trace_link_info link_info; + enum bpf_map_trace_type trace_type; + const char *trace_name = prog->sec_name; + const char *map_name = prog->sec_name; + char *map_name_cstr; + size_t map_name_len; + struct bpf_map *map; + int slash_seen = 0; + + /* + * Map tracing sections are named like this: + * map_trace/map_name/trace_type + * Assign trace_name and map_name to the beginning of their names. + */ + while (*map_name && *trace_name && slash_seen < 2) { + if (slash_seen < 1) + map_name++; + if (slash_seen < 2) + trace_name++; + if (*trace_name == '/') + slash_seen++; + } + if (*map_name) + ++map_name; + if (*trace_name) + ++trace_name; + if (!*map_name || !*trace_name || slash_seen < 2) + return ERR_PTR(-EINVAL); + + if (!strcmp(trace_name, "UPDATE_ELEM")) + trace_type = BPF_MAP_TRACE_UPDATE_ELEM; + else if (!strcmp(trace_name, "DELETE_ELEM")) + trace_type = BPF_MAP_TRACE_DELETE_ELEM; + else + return ERR_PTR(-EINVAL); + + map_name_len = (trace_name - map_name) - 1; + map_name_cstr = malloc(map_name_len + 1); + if (!map_name_cstr) + return ERR_PTR(-ENOMEM); + map_name_cstr[map_name_len] = 0; + strncpy(map_name_cstr, map_name, map_name_len); + pr_warn("map name cstr: %s\n", map_name_cstr); + map = bpf_object__find_map_by_name(prog->obj, map_name_cstr); + free(map_name_cstr); + if (!map) + return ERR_PTR(-EINVAL); + + memset(&link_info, 0, sizeof(link_info)); + link_info.map_fd = bpf_map__fd(map); + link_info.trace_type = trace_type; + memset(&map_trace_opts, 0, sizeof(map_trace_opts)); + map_trace_opts.sz = sizeof(map_trace_opts); + map_trace_opts.link_info = &link_info; + map_trace_opts.link_info_len = sizeof(link_info); + return bpf_program__attach_map_trace(prog, &map_trace_opts); +} + struct bpf_link *bpf_program__attach(const struct bpf_program *prog) { if (!prog->sec_def || !prog->sec_def->attach_fn) diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index e35490c54eb3..418b65918639 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -358,6 +358,17 @@ LIBBPF_API struct bpf_link * bpf_program__attach_iter(const struct bpf_program *prog, const struct bpf_iter_attach_opts *opts); +struct bpf_map_trace_attach_opts { + size_t sz; /* size of this struct for forward/backward compatibility */ + struct bpf_map_trace_link_info *link_info; + __u32 link_info_len; +}; +#define bpf_map_trace_attach_opts__last_field link_info_len + +LIBBPF_API struct bpf_link * +bpf_program__attach_map_trace(const struct bpf_program *prog, + const struct bpf_map_trace_attach_opts *opts); + struct bpf_insn; /* diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index 9e649cf9e771..84f728b6bd4b 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -384,6 +384,7 @@ LIBBPF_0.5.0 { btf__load_module_btf; btf__load_vmlinux_btf; btf_dump__dump_type_data; + bpf_program__attach_map_trace; libbpf_set_strict_mode; } LIBBPF_0.4.0; -- 2.33.0.685.g46640cef36-goog