xref: /openbmc/linux/kernel/bpf/link_iter.c (revision 9f883612)
1*9f883612SDmitrii Dolgov // SPDX-License-Identifier: GPL-2.0-only
2*9f883612SDmitrii Dolgov /* Copyright (c) 2022 Red Hat, Inc. */
3*9f883612SDmitrii Dolgov #include <linux/bpf.h>
4*9f883612SDmitrii Dolgov #include <linux/fs.h>
5*9f883612SDmitrii Dolgov #include <linux/filter.h>
6*9f883612SDmitrii Dolgov #include <linux/kernel.h>
7*9f883612SDmitrii Dolgov #include <linux/btf_ids.h>
8*9f883612SDmitrii Dolgov 
9*9f883612SDmitrii Dolgov struct bpf_iter_seq_link_info {
10*9f883612SDmitrii Dolgov 	u32 link_id;
11*9f883612SDmitrii Dolgov };
12*9f883612SDmitrii Dolgov 
bpf_link_seq_start(struct seq_file * seq,loff_t * pos)13*9f883612SDmitrii Dolgov static void *bpf_link_seq_start(struct seq_file *seq, loff_t *pos)
14*9f883612SDmitrii Dolgov {
15*9f883612SDmitrii Dolgov 	struct bpf_iter_seq_link_info *info = seq->private;
16*9f883612SDmitrii Dolgov 	struct bpf_link *link;
17*9f883612SDmitrii Dolgov 
18*9f883612SDmitrii Dolgov 	link = bpf_link_get_curr_or_next(&info->link_id);
19*9f883612SDmitrii Dolgov 	if (!link)
20*9f883612SDmitrii Dolgov 		return NULL;
21*9f883612SDmitrii Dolgov 
22*9f883612SDmitrii Dolgov 	if (*pos == 0)
23*9f883612SDmitrii Dolgov 		++*pos;
24*9f883612SDmitrii Dolgov 	return link;
25*9f883612SDmitrii Dolgov }
26*9f883612SDmitrii Dolgov 
bpf_link_seq_next(struct seq_file * seq,void * v,loff_t * pos)27*9f883612SDmitrii Dolgov static void *bpf_link_seq_next(struct seq_file *seq, void *v, loff_t *pos)
28*9f883612SDmitrii Dolgov {
29*9f883612SDmitrii Dolgov 	struct bpf_iter_seq_link_info *info = seq->private;
30*9f883612SDmitrii Dolgov 
31*9f883612SDmitrii Dolgov 	++*pos;
32*9f883612SDmitrii Dolgov 	++info->link_id;
33*9f883612SDmitrii Dolgov 	bpf_link_put((struct bpf_link *)v);
34*9f883612SDmitrii Dolgov 	return bpf_link_get_curr_or_next(&info->link_id);
35*9f883612SDmitrii Dolgov }
36*9f883612SDmitrii Dolgov 
37*9f883612SDmitrii Dolgov struct bpf_iter__bpf_link {
38*9f883612SDmitrii Dolgov 	__bpf_md_ptr(struct bpf_iter_meta *, meta);
39*9f883612SDmitrii Dolgov 	__bpf_md_ptr(struct bpf_link *, link);
40*9f883612SDmitrii Dolgov };
41*9f883612SDmitrii Dolgov 
DEFINE_BPF_ITER_FUNC(bpf_link,struct bpf_iter_meta * meta,struct bpf_link * link)42*9f883612SDmitrii Dolgov DEFINE_BPF_ITER_FUNC(bpf_link, struct bpf_iter_meta *meta, struct bpf_link *link)
43*9f883612SDmitrii Dolgov 
44*9f883612SDmitrii Dolgov static int __bpf_link_seq_show(struct seq_file *seq, void *v, bool in_stop)
45*9f883612SDmitrii Dolgov {
46*9f883612SDmitrii Dolgov 	struct bpf_iter__bpf_link ctx;
47*9f883612SDmitrii Dolgov 	struct bpf_iter_meta meta;
48*9f883612SDmitrii Dolgov 	struct bpf_prog *prog;
49*9f883612SDmitrii Dolgov 	int ret = 0;
50*9f883612SDmitrii Dolgov 
51*9f883612SDmitrii Dolgov 	ctx.meta = &meta;
52*9f883612SDmitrii Dolgov 	ctx.link = v;
53*9f883612SDmitrii Dolgov 	meta.seq = seq;
54*9f883612SDmitrii Dolgov 	prog = bpf_iter_get_info(&meta, in_stop);
55*9f883612SDmitrii Dolgov 	if (prog)
56*9f883612SDmitrii Dolgov 		ret = bpf_iter_run_prog(prog, &ctx);
57*9f883612SDmitrii Dolgov 
58*9f883612SDmitrii Dolgov 	return ret;
59*9f883612SDmitrii Dolgov }
60*9f883612SDmitrii Dolgov 
bpf_link_seq_show(struct seq_file * seq,void * v)61*9f883612SDmitrii Dolgov static int bpf_link_seq_show(struct seq_file *seq, void *v)
62*9f883612SDmitrii Dolgov {
63*9f883612SDmitrii Dolgov 	return __bpf_link_seq_show(seq, v, false);
64*9f883612SDmitrii Dolgov }
65*9f883612SDmitrii Dolgov 
bpf_link_seq_stop(struct seq_file * seq,void * v)66*9f883612SDmitrii Dolgov static void bpf_link_seq_stop(struct seq_file *seq, void *v)
67*9f883612SDmitrii Dolgov {
68*9f883612SDmitrii Dolgov 	if (!v)
69*9f883612SDmitrii Dolgov 		(void)__bpf_link_seq_show(seq, v, true);
70*9f883612SDmitrii Dolgov 	else
71*9f883612SDmitrii Dolgov 		bpf_link_put((struct bpf_link *)v);
72*9f883612SDmitrii Dolgov }
73*9f883612SDmitrii Dolgov 
74*9f883612SDmitrii Dolgov static const struct seq_operations bpf_link_seq_ops = {
75*9f883612SDmitrii Dolgov 	.start	= bpf_link_seq_start,
76*9f883612SDmitrii Dolgov 	.next	= bpf_link_seq_next,
77*9f883612SDmitrii Dolgov 	.stop	= bpf_link_seq_stop,
78*9f883612SDmitrii Dolgov 	.show	= bpf_link_seq_show,
79*9f883612SDmitrii Dolgov };
80*9f883612SDmitrii Dolgov 
81*9f883612SDmitrii Dolgov BTF_ID_LIST(btf_bpf_link_id)
82*9f883612SDmitrii Dolgov BTF_ID(struct, bpf_link)
83*9f883612SDmitrii Dolgov 
84*9f883612SDmitrii Dolgov static const struct bpf_iter_seq_info bpf_link_seq_info = {
85*9f883612SDmitrii Dolgov 	.seq_ops		= &bpf_link_seq_ops,
86*9f883612SDmitrii Dolgov 	.init_seq_private	= NULL,
87*9f883612SDmitrii Dolgov 	.fini_seq_private	= NULL,
88*9f883612SDmitrii Dolgov 	.seq_priv_size		= sizeof(struct bpf_iter_seq_link_info),
89*9f883612SDmitrii Dolgov };
90*9f883612SDmitrii Dolgov 
91*9f883612SDmitrii Dolgov static struct bpf_iter_reg bpf_link_reg_info = {
92*9f883612SDmitrii Dolgov 	.target			= "bpf_link",
93*9f883612SDmitrii Dolgov 	.ctx_arg_info_size	= 1,
94*9f883612SDmitrii Dolgov 	.ctx_arg_info		= {
95*9f883612SDmitrii Dolgov 		{ offsetof(struct bpf_iter__bpf_link, link),
96*9f883612SDmitrii Dolgov 		  PTR_TO_BTF_ID_OR_NULL },
97*9f883612SDmitrii Dolgov 	},
98*9f883612SDmitrii Dolgov 	.seq_info		= &bpf_link_seq_info,
99*9f883612SDmitrii Dolgov };
100*9f883612SDmitrii Dolgov 
bpf_link_iter_init(void)101*9f883612SDmitrii Dolgov static int __init bpf_link_iter_init(void)
102*9f883612SDmitrii Dolgov {
103*9f883612SDmitrii Dolgov 	bpf_link_reg_info.ctx_arg_info[0].btf_id = *btf_bpf_link_id;
104*9f883612SDmitrii Dolgov 	return bpf_iter_reg_target(&bpf_link_reg_info);
105*9f883612SDmitrii Dolgov }
106*9f883612SDmitrii Dolgov 
107*9f883612SDmitrii Dolgov late_initcall(bpf_link_iter_init);
108