11573Srgrimes// SPDX-License-Identifier: GPL-2.0-only 21573Srgrimes/* Copyright (c) 2022 Red Hat, Inc. */ 31573Srgrimes#include <linux/bpf.h> 41573Srgrimes#include <linux/fs.h> 51573Srgrimes#include <linux/filter.h> 61573Srgrimes#include <linux/kernel.h> 71573Srgrimes#include <linux/btf_ids.h> 8227753Stheraven 9227753Stheravenstruct bpf_iter_seq_link_info { 10227753Stheraven u32 link_id; 11227753Stheraven}; 12227753Stheraven 131573Srgrimesstatic void *bpf_link_seq_start(struct seq_file *seq, loff_t *pos) 141573Srgrimes{ 151573Srgrimes struct bpf_iter_seq_link_info *info = seq->private; 161573Srgrimes struct bpf_link *link; 171573Srgrimes 181573Srgrimes link = bpf_link_get_curr_or_next(&info->link_id); 191573Srgrimes if (!link) 201573Srgrimes return NULL; 21249808Semaste 221573Srgrimes if (*pos == 0) 231573Srgrimes ++*pos; 241573Srgrimes return link; 251573Srgrimes} 261573Srgrimes 271573Srgrimesstatic void *bpf_link_seq_next(struct seq_file *seq, void *v, loff_t *pos) 281573Srgrimes{ 291573Srgrimes struct bpf_iter_seq_link_info *info = seq->private; 301573Srgrimes 311573Srgrimes ++*pos; 321573Srgrimes ++info->link_id; 331573Srgrimes bpf_link_put((struct bpf_link *)v); 341573Srgrimes return bpf_link_get_curr_or_next(&info->link_id); 351573Srgrimes} 361573Srgrimes 371573Srgrimesstruct bpf_iter__bpf_link { 381573Srgrimes __bpf_md_ptr(struct bpf_iter_meta *, meta); 391573Srgrimes __bpf_md_ptr(struct bpf_link *, link); 401573Srgrimes}; 4192986Sobrien 4292986SobrienDEFINE_BPF_ITER_FUNC(bpf_link, struct bpf_iter_meta *meta, struct bpf_link *link) 431573Srgrimes 441573Srgrimesstatic int __bpf_link_seq_show(struct seq_file *seq, void *v, bool in_stop) 451573Srgrimes{ 461573Srgrimes struct bpf_iter__bpf_link ctx; 47227753Stheraven struct bpf_iter_meta meta; 481573Srgrimes struct bpf_prog *prog; 491573Srgrimes int ret = 0; 5013545Sjulian 51104989Smike ctx.meta = &meta; 521573Srgrimes ctx.link = v; 531573Srgrimes meta.seq = seq; 541573Srgrimes prog = bpf_iter_get_info(&meta, in_stop); 551573Srgrimes if (prog) 561573Srgrimes ret = bpf_iter_run_prog(prog, &ctx); 57200800Sdelphij 581573Srgrimes return ret; 591573Srgrimes} 601573Srgrimes 61227753Stheravenstatic int bpf_link_seq_show(struct seq_file *seq, void *v) 62227753Stheraven{ 63227753Stheraven return __bpf_link_seq_show(seq, v, false); 64227753Stheraven} 65227753Stheraven 66227753Stheravenstatic void bpf_link_seq_stop(struct seq_file *seq, void *v) 67227753Stheraven{ 68227753Stheraven if (!v) 69227753Stheraven (void)__bpf_link_seq_show(seq, v, true); 70227753Stheraven else 71227753Stheraven bpf_link_put((struct bpf_link *)v); 72227753Stheraven} 73 74static const struct seq_operations bpf_link_seq_ops = { 75 .start = bpf_link_seq_start, 76 .next = bpf_link_seq_next, 77 .stop = bpf_link_seq_stop, 78 .show = bpf_link_seq_show, 79}; 80 81BTF_ID_LIST(btf_bpf_link_id) 82BTF_ID(struct, bpf_link) 83 84static const struct bpf_iter_seq_info bpf_link_seq_info = { 85 .seq_ops = &bpf_link_seq_ops, 86 .init_seq_private = NULL, 87 .fini_seq_private = NULL, 88 .seq_priv_size = sizeof(struct bpf_iter_seq_link_info), 89}; 90 91static struct bpf_iter_reg bpf_link_reg_info = { 92 .target = "bpf_link", 93 .ctx_arg_info_size = 1, 94 .ctx_arg_info = { 95 { offsetof(struct bpf_iter__bpf_link, link), 96 PTR_TO_BTF_ID_OR_NULL }, 97 }, 98 .seq_info = &bpf_link_seq_info, 99}; 100 101static int __init bpf_link_iter_init(void) 102{ 103 bpf_link_reg_info.ctx_arg_info[0].btf_id = *btf_bpf_link_id; 104 return bpf_iter_reg_target(&bpf_link_reg_info); 105} 106 107late_initcall(bpf_link_iter_init); 108