mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-09 06:04:05 +08:00
Merge branch 'link_query-bpf_iter'
Yonghong Song says: ==================== "link" has been an important concept for bpf ecosystem to connect bpf program with other properties. Currently, the information related information can be queried from userspace through bpf command BPF_LINK_GET_NEXT_ID, BPF_LINK_GET_FD_BY_ID and BPF_OBJ_GET_INFO_BY_FD. The information is also available by "cating" /proc/<pid>/fdinfo/<link_fd>. Raw_tracepoint, tracing, cgroup, netns and xdp links are already supported in the kernel and bpftool. This patch added support for bpf iterator. Patch #1 added generic support for link querying interface. Patch #2 implemented callback functions for map element bpf iterators. Patch #3 added bpftool support. Changelogs: v3 -> v4: . return target specific link_info even if target_name buffer is empty. (Andrii) v2 -> v3: . remove extra '\t' when fdinfo prints map_id to make parsing consistent. (Andrii) v1 -> v2: . fix checkpatch.pl warnings. (Jakub) ==================== Acked-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
commit
ad8edd0d76
@ -1218,12 +1218,18 @@ typedef int (*bpf_iter_attach_target_t)(struct bpf_prog *prog,
|
||||
union bpf_iter_link_info *linfo,
|
||||
struct bpf_iter_aux_info *aux);
|
||||
typedef void (*bpf_iter_detach_target_t)(struct bpf_iter_aux_info *aux);
|
||||
typedef void (*bpf_iter_show_fdinfo_t) (const struct bpf_iter_aux_info *aux,
|
||||
struct seq_file *seq);
|
||||
typedef int (*bpf_iter_fill_link_info_t)(const struct bpf_iter_aux_info *aux,
|
||||
struct bpf_link_info *info);
|
||||
|
||||
#define BPF_ITER_CTX_ARG_MAX 2
|
||||
struct bpf_iter_reg {
|
||||
const char *target;
|
||||
bpf_iter_attach_target_t attach_target;
|
||||
bpf_iter_detach_target_t detach_target;
|
||||
bpf_iter_show_fdinfo_t show_fdinfo;
|
||||
bpf_iter_fill_link_info_t fill_link_info;
|
||||
u32 ctx_arg_info_size;
|
||||
struct bpf_ctx_arg_aux ctx_arg_info[BPF_ITER_CTX_ARG_MAX];
|
||||
const struct bpf_iter_seq_info *seq_info;
|
||||
@ -1250,6 +1256,10 @@ int bpf_iter_new_fd(struct bpf_link *link);
|
||||
bool bpf_link_is_iter(struct bpf_link *link);
|
||||
struct bpf_prog *bpf_iter_get_info(struct bpf_iter_meta *meta, bool in_stop);
|
||||
int bpf_iter_run_prog(struct bpf_prog *prog, void *ctx);
|
||||
void bpf_iter_map_show_fdinfo(const struct bpf_iter_aux_info *aux,
|
||||
struct seq_file *seq);
|
||||
int bpf_iter_map_fill_link_info(const struct bpf_iter_aux_info *aux,
|
||||
struct bpf_link_info *info);
|
||||
|
||||
int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value);
|
||||
int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value);
|
||||
|
@ -4071,6 +4071,13 @@ struct bpf_link_info {
|
||||
__u64 cgroup_id;
|
||||
__u32 attach_type;
|
||||
} cgroup;
|
||||
struct {
|
||||
__aligned_u64 target_name; /* in/out: target_name buffer ptr */
|
||||
__u32 target_name_len; /* in/out: target_name buffer len */
|
||||
union {
|
||||
__u32 map_id;
|
||||
} map;
|
||||
} iter;
|
||||
struct {
|
||||
__u32 netns_ino;
|
||||
__u32 attach_type;
|
||||
|
@ -377,10 +377,68 @@ out_unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bpf_iter_link_show_fdinfo(const struct bpf_link *link,
|
||||
struct seq_file *seq)
|
||||
{
|
||||
struct bpf_iter_link *iter_link =
|
||||
container_of(link, struct bpf_iter_link, link);
|
||||
bpf_iter_show_fdinfo_t show_fdinfo;
|
||||
|
||||
seq_printf(seq,
|
||||
"target_name:\t%s\n",
|
||||
iter_link->tinfo->reg_info->target);
|
||||
|
||||
show_fdinfo = iter_link->tinfo->reg_info->show_fdinfo;
|
||||
if (show_fdinfo)
|
||||
show_fdinfo(&iter_link->aux, seq);
|
||||
}
|
||||
|
||||
static int bpf_iter_link_fill_link_info(const struct bpf_link *link,
|
||||
struct bpf_link_info *info)
|
||||
{
|
||||
struct bpf_iter_link *iter_link =
|
||||
container_of(link, struct bpf_iter_link, link);
|
||||
char __user *ubuf = u64_to_user_ptr(info->iter.target_name);
|
||||
bpf_iter_fill_link_info_t fill_link_info;
|
||||
u32 ulen = info->iter.target_name_len;
|
||||
const char *target_name;
|
||||
u32 target_len;
|
||||
|
||||
if (!ulen ^ !ubuf)
|
||||
return -EINVAL;
|
||||
|
||||
target_name = iter_link->tinfo->reg_info->target;
|
||||
target_len = strlen(target_name);
|
||||
info->iter.target_name_len = target_len + 1;
|
||||
|
||||
if (ubuf) {
|
||||
if (ulen >= target_len + 1) {
|
||||
if (copy_to_user(ubuf, target_name, target_len + 1))
|
||||
return -EFAULT;
|
||||
} else {
|
||||
char zero = '\0';
|
||||
|
||||
if (copy_to_user(ubuf, target_name, ulen - 1))
|
||||
return -EFAULT;
|
||||
if (put_user(zero, ubuf + ulen - 1))
|
||||
return -EFAULT;
|
||||
return -ENOSPC;
|
||||
}
|
||||
}
|
||||
|
||||
fill_link_info = iter_link->tinfo->reg_info->fill_link_info;
|
||||
if (fill_link_info)
|
||||
return fill_link_info(&iter_link->aux, info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct bpf_link_ops bpf_iter_link_lops = {
|
||||
.release = bpf_iter_link_release,
|
||||
.dealloc = bpf_iter_link_dealloc,
|
||||
.update_prog = bpf_iter_link_replace,
|
||||
.show_fdinfo = bpf_iter_link_show_fdinfo,
|
||||
.fill_link_info = bpf_iter_link_fill_link_info,
|
||||
};
|
||||
|
||||
bool bpf_link_is_iter(struct bpf_link *link)
|
||||
|
@ -149,6 +149,19 @@ static void bpf_iter_detach_map(struct bpf_iter_aux_info *aux)
|
||||
bpf_map_put_with_uref(aux->map);
|
||||
}
|
||||
|
||||
void bpf_iter_map_show_fdinfo(const struct bpf_iter_aux_info *aux,
|
||||
struct seq_file *seq)
|
||||
{
|
||||
seq_printf(seq, "map_id:\t%u\n", aux->map->id);
|
||||
}
|
||||
|
||||
int bpf_iter_map_fill_link_info(const struct bpf_iter_aux_info *aux,
|
||||
struct bpf_link_info *info)
|
||||
{
|
||||
info->iter.map.map_id = aux->map->id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_BPF_ITER_FUNC(bpf_map_elem, struct bpf_iter_meta *meta,
|
||||
struct bpf_map *map, void *key, void *value)
|
||||
|
||||
@ -156,6 +169,8 @@ static const struct bpf_iter_reg bpf_map_elem_reg_info = {
|
||||
.target = "bpf_map_elem",
|
||||
.attach_target = bpf_iter_attach_map,
|
||||
.detach_target = bpf_iter_detach_map,
|
||||
.show_fdinfo = bpf_iter_map_show_fdinfo,
|
||||
.fill_link_info = bpf_iter_map_fill_link_info,
|
||||
.ctx_arg_info_size = 2,
|
||||
.ctx_arg_info = {
|
||||
{ offsetof(struct bpf_iter__bpf_map_elem, key),
|
||||
|
@ -1437,6 +1437,8 @@ static struct bpf_iter_reg bpf_sk_storage_map_reg_info = {
|
||||
.target = "bpf_sk_storage_map",
|
||||
.attach_target = bpf_iter_attach_map,
|
||||
.detach_target = bpf_iter_detach_map,
|
||||
.show_fdinfo = bpf_iter_map_show_fdinfo,
|
||||
.fill_link_info = bpf_iter_map_fill_link_info,
|
||||
.ctx_arg_info_size = 2,
|
||||
.ctx_arg_info = {
|
||||
{ offsetof(struct bpf_iter__bpf_sk_storage_map, sk),
|
||||
|
@ -77,6 +77,22 @@ static void show_link_attach_type_json(__u32 attach_type, json_writer_t *wtr)
|
||||
jsonw_uint_field(wtr, "attach_type", attach_type);
|
||||
}
|
||||
|
||||
static bool is_iter_map_target(const char *target_name)
|
||||
{
|
||||
return strcmp(target_name, "bpf_map_elem") == 0 ||
|
||||
strcmp(target_name, "bpf_sk_storage_map") == 0;
|
||||
}
|
||||
|
||||
static void show_iter_json(struct bpf_link_info *info, json_writer_t *wtr)
|
||||
{
|
||||
const char *target_name = u64_to_ptr(info->iter.target_name);
|
||||
|
||||
jsonw_string_field(wtr, "target_name", target_name);
|
||||
|
||||
if (is_iter_map_target(target_name))
|
||||
jsonw_uint_field(wtr, "map_id", info->iter.map.map_id);
|
||||
}
|
||||
|
||||
static int get_prog_info(int prog_id, struct bpf_prog_info *info)
|
||||
{
|
||||
__u32 len = sizeof(*info);
|
||||
@ -128,6 +144,9 @@ static int show_link_close_json(int fd, struct bpf_link_info *info)
|
||||
info->cgroup.cgroup_id);
|
||||
show_link_attach_type_json(info->cgroup.attach_type, json_wtr);
|
||||
break;
|
||||
case BPF_LINK_TYPE_ITER:
|
||||
show_iter_json(info, json_wtr);
|
||||
break;
|
||||
case BPF_LINK_TYPE_NETNS:
|
||||
jsonw_uint_field(json_wtr, "netns_ino",
|
||||
info->netns.netns_ino);
|
||||
@ -175,6 +194,16 @@ static void show_link_attach_type_plain(__u32 attach_type)
|
||||
printf("attach_type %u ", attach_type);
|
||||
}
|
||||
|
||||
static void show_iter_plain(struct bpf_link_info *info)
|
||||
{
|
||||
const char *target_name = u64_to_ptr(info->iter.target_name);
|
||||
|
||||
printf("target_name %s ", target_name);
|
||||
|
||||
if (is_iter_map_target(target_name))
|
||||
printf("map_id %u ", info->iter.map.map_id);
|
||||
}
|
||||
|
||||
static int show_link_close_plain(int fd, struct bpf_link_info *info)
|
||||
{
|
||||
struct bpf_prog_info prog_info;
|
||||
@ -204,6 +233,9 @@ static int show_link_close_plain(int fd, struct bpf_link_info *info)
|
||||
printf("\n\tcgroup_id %zu ", (size_t)info->cgroup.cgroup_id);
|
||||
show_link_attach_type_plain(info->cgroup.attach_type);
|
||||
break;
|
||||
case BPF_LINK_TYPE_ITER:
|
||||
show_iter_plain(info);
|
||||
break;
|
||||
case BPF_LINK_TYPE_NETNS:
|
||||
printf("\n\tnetns_ino %u ", info->netns.netns_ino);
|
||||
show_link_attach_type_plain(info->netns.attach_type);
|
||||
@ -231,7 +263,7 @@ static int do_show_link(int fd)
|
||||
{
|
||||
struct bpf_link_info info;
|
||||
__u32 len = sizeof(info);
|
||||
char raw_tp_name[256];
|
||||
char buf[256];
|
||||
int err;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
@ -245,8 +277,14 @@ again:
|
||||
}
|
||||
if (info.type == BPF_LINK_TYPE_RAW_TRACEPOINT &&
|
||||
!info.raw_tracepoint.tp_name) {
|
||||
info.raw_tracepoint.tp_name = (unsigned long)&raw_tp_name;
|
||||
info.raw_tracepoint.tp_name_len = sizeof(raw_tp_name);
|
||||
info.raw_tracepoint.tp_name = (unsigned long)&buf;
|
||||
info.raw_tracepoint.tp_name_len = sizeof(buf);
|
||||
goto again;
|
||||
}
|
||||
if (info.type == BPF_LINK_TYPE_ITER &&
|
||||
!info.iter.target_name) {
|
||||
info.iter.target_name = (unsigned long)&buf;
|
||||
info.iter.target_name_len = sizeof(buf);
|
||||
goto again;
|
||||
}
|
||||
|
||||
|
@ -4071,6 +4071,13 @@ struct bpf_link_info {
|
||||
__u64 cgroup_id;
|
||||
__u32 attach_type;
|
||||
} cgroup;
|
||||
struct {
|
||||
__aligned_u64 target_name; /* in/out: target_name buffer ptr */
|
||||
__u32 target_name_len; /* in/out: target_name buffer len */
|
||||
union {
|
||||
__u32 map_id;
|
||||
} map;
|
||||
} iter;
|
||||
struct {
|
||||
__u32 netns_ino;
|
||||
__u32 attach_type;
|
||||
|
Loading…
Reference in New Issue
Block a user