Skip to content

Commit 5788b3a

Browse files
yonghong-songAlexei Starovoitov
authored andcommitted
net: bpf: Implement bpf iterator for udp
The bpf iterator for udp is implemented. Both udp4 and udp6 sockets will be traversed. It is up to bpf program to filter for udp4 or udp6 only, or both families of sockets. Signed-off-by: Yonghong Song <yhs@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Martin KaFai Lau <kafai@fb.com> Link: https://lore.kernel.org/bpf/20200623230813.3988404-1-yhs@fb.com
1 parent 9e8ca27 commit 5788b3a

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

net/ipv4/udp.c

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2968,6 +2968,67 @@ int udp4_seq_show(struct seq_file *seq, void *v)
29682968
return 0;
29692969
}
29702970

2971+
#ifdef CONFIG_BPF_SYSCALL
2972+
struct bpf_iter__udp {
2973+
__bpf_md_ptr(struct bpf_iter_meta *, meta);
2974+
__bpf_md_ptr(struct udp_sock *, udp_sk);
2975+
uid_t uid __aligned(8);
2976+
int bucket __aligned(8);
2977+
};
2978+
2979+
static int udp_prog_seq_show(struct bpf_prog *prog, struct bpf_iter_meta *meta,
2980+
struct udp_sock *udp_sk, uid_t uid, int bucket)
2981+
{
2982+
struct bpf_iter__udp ctx;
2983+
2984+
meta->seq_num--; /* skip SEQ_START_TOKEN */
2985+
ctx.meta = meta;
2986+
ctx.udp_sk = udp_sk;
2987+
ctx.uid = uid;
2988+
ctx.bucket = bucket;
2989+
return bpf_iter_run_prog(prog, &ctx);
2990+
}
2991+
2992+
static int bpf_iter_udp_seq_show(struct seq_file *seq, void *v)
2993+
{
2994+
struct udp_iter_state *state = seq->private;
2995+
struct bpf_iter_meta meta;
2996+
struct bpf_prog *prog;
2997+
struct sock *sk = v;
2998+
uid_t uid;
2999+
3000+
if (v == SEQ_START_TOKEN)
3001+
return 0;
3002+
3003+
uid = from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk));
3004+
meta.seq = seq;
3005+
prog = bpf_iter_get_info(&meta, false);
3006+
return udp_prog_seq_show(prog, &meta, v, uid, state->bucket);
3007+
}
3008+
3009+
static void bpf_iter_udp_seq_stop(struct seq_file *seq, void *v)
3010+
{
3011+
struct bpf_iter_meta meta;
3012+
struct bpf_prog *prog;
3013+
3014+
if (!v) {
3015+
meta.seq = seq;
3016+
prog = bpf_iter_get_info(&meta, true);
3017+
if (prog)
3018+
(void)udp_prog_seq_show(prog, &meta, v, 0, 0);
3019+
}
3020+
3021+
udp_seq_stop(seq, v);
3022+
}
3023+
3024+
static const struct seq_operations bpf_iter_udp_seq_ops = {
3025+
.start = udp_seq_start,
3026+
.next = udp_seq_next,
3027+
.stop = bpf_iter_udp_seq_stop,
3028+
.show = bpf_iter_udp_seq_show,
3029+
};
3030+
#endif
3031+
29713032
const struct seq_operations udp_seq_ops = {
29723033
.start = udp_seq_start,
29733034
.next = udp_seq_next,
@@ -3085,6 +3146,57 @@ static struct pernet_operations __net_initdata udp_sysctl_ops = {
30853146
.init = udp_sysctl_init,
30863147
};
30873148

3149+
#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS)
3150+
DEFINE_BPF_ITER_FUNC(udp, struct bpf_iter_meta *meta,
3151+
struct udp_sock *udp_sk, uid_t uid, int bucket)
3152+
3153+
static int bpf_iter_init_udp(void *priv_data)
3154+
{
3155+
struct udp_iter_state *st = priv_data;
3156+
struct udp_seq_afinfo *afinfo;
3157+
int ret;
3158+
3159+
afinfo = kmalloc(sizeof(*afinfo), GFP_USER | __GFP_NOWARN);
3160+
if (!afinfo)
3161+
return -ENOMEM;
3162+
3163+
afinfo->family = AF_UNSPEC;
3164+
afinfo->udp_table = &udp_table;
3165+
st->bpf_seq_afinfo = afinfo;
3166+
ret = bpf_iter_init_seq_net(priv_data);
3167+
if (ret)
3168+
kfree(afinfo);
3169+
return ret;
3170+
}
3171+
3172+
static void bpf_iter_fini_udp(void *priv_data)
3173+
{
3174+
struct udp_iter_state *st = priv_data;
3175+
3176+
kfree(st->bpf_seq_afinfo);
3177+
bpf_iter_fini_seq_net(priv_data);
3178+
}
3179+
3180+
static const struct bpf_iter_reg udp_reg_info = {
3181+
.target = "udp",
3182+
.seq_ops = &bpf_iter_udp_seq_ops,
3183+
.init_seq_private = bpf_iter_init_udp,
3184+
.fini_seq_private = bpf_iter_fini_udp,
3185+
.seq_priv_size = sizeof(struct udp_iter_state),
3186+
.ctx_arg_info_size = 1,
3187+
.ctx_arg_info = {
3188+
{ offsetof(struct bpf_iter__udp, udp_sk),
3189+
PTR_TO_BTF_ID_OR_NULL },
3190+
},
3191+
};
3192+
3193+
static void __init bpf_iter_register(void)
3194+
{
3195+
if (bpf_iter_reg_target(&udp_reg_info))
3196+
pr_warn("Warning: could not register bpf iterator udp\n");
3197+
}
3198+
#endif
3199+
30883200
void __init udp_init(void)
30893201
{
30903202
unsigned long limit;
@@ -3110,4 +3222,8 @@ void __init udp_init(void)
31103222

31113223
if (register_pernet_subsys(&udp_sysctl_ops))
31123224
panic("UDP: failed to init sysctl parameters.\n");
3225+
3226+
#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS)
3227+
bpf_iter_register();
3228+
#endif
31133229
}

0 commit comments

Comments
 (0)