bpf: Add missed stats for kprobes
Jiri Olsa
reviewerv3 cover bpf: Add missed stats for kprobes
hi,
at the moment we can't retrieve the number of missed kprobe executions and subsequent execution of BPF programs.
This patchset adds:
- counting of missed execution on attach layer for:
. kprobes attached through perf link (kprobe/ftrace) . kprobes attached through kprobe.multi link (fprobe)
- counting of recursion_misses for BPF kprobe programs
It's still technically possible to create kprobe without perf link (using SET_BPF perf ioctl) in which case we don't have a way to retrieve the kprobe's 'missed' count. However both libbpf and cilium/ebpf libraries use perf link if it's available, and for old kernels without perf link support we can use BPF program to retrieve the kprobe missed count.
v3 changes:
- added acks [Song]
- make test_missed not serial [Andrii]
Also available at:
https://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
bpf/missed_stats
thanks,
jirka
---
Jiri Olsa (9):
bpf: Count stats for kprobe_multi programs
bpf: Add missed value to kprobe_multi link info
bpf: Add missed value to kprobe perf link info
bpf: Count missed stats in trace_call_bpf
bpftool: Display missed count for kprobe_multi link
bpftool: Display missed count for kprobe perf link selftests/bpf: Add test for missed counts of perf event link kprobe selftests/bpf: Add test for recursion counts of perf event link kprobe selftests/bpf: Add test for recursion counts of perf event link tracepoint
include/linux/bpf.h | 16 +++++++++++ include/linux/trace_events.h | 6 ++-- include/uapi/linux/bpf.h | 2 ++ kernel/bpf/syscall.c | 14 ++++++---- kernel/trace/bpf_trace.c | 10 +++++-- kernel/trace/trace_kprobe.c | 14 ++++++++-- tools/bpf/bpftool/link.c | 6 ++++ tools/include/uapi/linux/bpf.h | 2 ++ tools/testing/selftests/bpf/DENYLIST.aarch64 | 1 + tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c | 5 ++++ tools/testing/selftests/bpf/bpf_testmod/bpf_testmod_kfunc.h | 2 ++ tools/testing/selftests/bpf/prog_tests/missed.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/testing/selftests/bpf/progs/missed_kprobe.c | 30 ++++++++++++++++++++ tools/testing/selftests/bpf/progs/missed_kprobe_recursion.c | 48 ++++++++++++++++++++++++++++++++ tools/testing/selftests/bpf/progs/missed_tp_recursion.c | 41 +++++++++++++++++++++++++++ 15 files changed, 322 insertions(+), 13 deletions(-) create mode 100644 tools/testing/selftests/bpf/prog_tests/missed.c create mode 100644 tools/testing/selftests/bpf/progs/missed_kprobe.c create mode 100644 tools/testing/selftests/bpf/progs/missed_kprobe_recursion.c create mode 100644 tools/testing/selftests/bpf/progs/missed_tp_recursion.c
Jiri Olsa
reviewerPATCH v3 1/9 bpf: Count stats for kprobe_multi programs
Adding support to gather missed stats for kprobe_multi programs due to bpf_prog_active protection.
--- kernel/trace/bpf_trace.c | 1 + 1 file changed, 1 insertion(+)
kernel/trace/bpf_trace.c +1 -0
@@ -2710,6 +2710,7 @@ kprobe_multi_link_prog_run(struct bpf_kprobe_multi_link *link,int err;if (unlikely (__this_cpu_inc_return (bpf_prog_active) !=1 )) { +bpf_prog_inc_misses_counter (link->link.prog); err =0 ; goto out; }
Signature · 1 line
2.41.0
Jiri Olsa
reviewerPATCH v3 2/9 bpf: Add missed value to kprobe_multi link info
In reply to Jiri OlsaAdd missed value to kprobe_multi link info to hold the stats of missed kprobe_multi probe.
The missed counter gets incremented when fprobe fails the recursion check or there's no rethook available for return probe. In either case the attached bpf program is not executed.
--- include/uapi/linux/bpf.h | 1 + kernel/trace/bpf_trace.c | 1 + tools/include/uapi/linux/bpf.h | 1 + 3 files changed, 3 insertions(+)
include/uapi/linux/bpf.h +1 -0
@@ -6530,6 +6530,7 @@ struct bpf_link_info {__aligned_u64 addrs;__u32 count;/* in/out: kprobe_multi function count */ __u32 flags; +__u64 missed; } kprobe_multi;struct {__u32 type;/* enum bpf_perf_event_type */
kernel/trace/bpf_trace.c +1 -0
@@ -2614,6 +2614,7 @@ static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link, kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link); info->kprobe_multi.count = kmulti_link->cnt; info->kprobe_multi.flags = kmulti_link->flags; + info->kprobe_multi.missed = kmulti_link->fp.nmissed;if (!uaddrs)return 0 ;
tools/include/uapi/linux/bpf.h +1 -0
@@ -6530,6 +6530,7 @@ struct bpf_link_info {__aligned_u64 addrs;__u32 count;/* in/out: kprobe_multi function count */ __u32 flags; +__u64 missed; } kprobe_multi;struct {__u32 type;/* enum bpf_perf_event_type */
Signature · 1 line
2.41.0
Song Liu
maintainerRe: [PATCHv3 bpf-next 2/9] bpf: Add missed value to kprobe_multi link info
Quoted 22 lines · Jiri Olsa
Add missed value to
kprobe_multilink info to hold the stats of missedkprobe_multiprobe.The missed counter gets incremented when fprobe fails the recursion check or there's no rethook available for return probe. In either case the attached bpf program is not executed.
Acked-by Hou Tao <[email protected]>Reviewed-and-tested-by Song Liu <[email protected]>Signed-off-by Jiri Olsa <[email protected]>--- include/uapi/linux/bpf.h | 1 + kernel/trace/bpf_trace.c | 1 + tools/include/uapi/linux/bpf.h | 1 + 3 files changed, 3 insertions(+)include/uapi/linux/bpf.h +0
-0
include/uapi/linux/bpf.h struct bpf_link_info { · line 6533
Quoted 4 lines
include/uapi/linux/bpf.h +1
-0@@ -6530,6 +6530,7 @@ struct bpf_link_info {__aligned_u64 addrs;__u32 count;/* in/out: kprobe_multi function count */ __u32 flags; +__u64 missed;
This does not make bpf_link_info bigger. So if we use newer user space on older kernel, the user space cannot tell whether missed == 0 or the kernel doesn't support "missed". Right?
Thanks,
Song
Quoted 31 lines
include/uapi/linux/bpf.h +0
-0} kprobe_multi;struct {__u32 type;/* enum bpf_perf_event_type */ kernel/trace/bpf_trace.c +1
-0@@ -2614,6 +2614,7 @@ static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link, kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link); info->kprobe_multi.count = kmulti_link->cnt; info->kprobe_multi.flags = kmulti_link->flags; + info->kprobe_multi.missed = kmulti_link->fp.nmissed;if (!uaddrs)return 0 ;tools/include/uapi/linux/bpf.h +1
-1@@ -6530,6 +6530,7 @@ struct bpf_link_info {__aligned_u64 addrs;__u32 count;/* in/out: kprobe_multi function count */ __u32 flags; +__u64 missed; } kprobe_multi;struct {__u32 type;/* enum bpf_perf_event_type */ --2.41.0
Re: [PATCHv3 bpf-next 2/9] bpf: Add missed value to kprobe_multi link info
Quoted 18 lines · Song Liu
Quoted 17 lines · Jiri Olsa
Add missed value to
kprobe_multilink info to hold the stats of missedkprobe_multiprobe.The missed counter gets incremented when fprobe fails the recursion check or there's no rethook available for return probe. In either case the attached bpf program is not executed.
Acked-by Hou Tao <[email protected]>Reviewed-and-tested-by Song Liu <[email protected]>Signed-off-by Jiri Olsa <[email protected]>--- include/uapi/linux/bpf.h | 1 + kernel/trace/bpf_trace.c | 1 + tools/include/uapi/linux/bpf.h | 1 + 3 files changed, 3 insertions(+)
Quoted 13 lines
include/uapi/linux/bpf.h struct bpf_link_info { · line 6533
Quoted 9 lines
include/uapi/linux/bpf.h +1
-0@@ -6530,6 +6530,7 @@ struct bpf_link_info {__aligned_u64 addrs;__u32 count;/* in/out: kprobe_multi function count */ __u32 flags; +__u64 missed;This does not make
bpf_link_infobigger. So if we use newer user space on older kernel, the user space cannot tell whether missed == 0 or the kernel doesn't support "missed". Right?
hum, I think that's right.. but I think that would be the case even if it did make bpf_link_info bigger, because we'd need to pass zeroed value in 'missed' field and it'd not be changed by older kernel
user space could maybe check if there's 'missed field in bpf_link_info.perf_event.kprobe.missed ?
jirka
Quoted 35 lines
Thanks,
SongQuoted 31 lines
include/uapi/linux/bpf.h +0
-0} kprobe_multi;struct {__u32 type;/* enum bpf_perf_event_type */ kernel/trace/bpf_trace.c +1
-0@@ -2614,6 +2614,7 @@ static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link, kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link); info->kprobe_multi.count = kmulti_link->cnt; info->kprobe_multi.flags = kmulti_link->flags; + info->kprobe_multi.missed = kmulti_link->fp.nmissed;if (!uaddrs)return 0 ;tools/include/uapi/linux/bpf.h +1
-1@@ -6530,6 +6530,7 @@ struct bpf_link_info {__aligned_u64 addrs;__u32 count;/* in/out: kprobe_multi function count */ __u32 flags; +__u64 missed; } kprobe_multi;struct {__u32 type;/* enum bpf_perf_event_type */ --2.41.0
Jiri Olsa
reviewerPATCH v3 3/9 bpf: Add missed value to kprobe perf link info
In reply to Jiri OlsaAdd missed value to kprobe attached through perf link info to hold the stats of missed kprobe handler execution.
The kprobe's missed counter gets incremented when kprobe handler is not executed due to another kprobe running on the same cpu.
--- include/linux/trace_events.h | 6 ++++-- include/uapi/linux/bpf.h | 1 + kernel/bpf/syscall.c | 14 ++++++++------ kernel/trace/bpf_trace.c | 5 +++-- kernel/trace/trace_kprobe.c | 14 +++++++++++--- tools/include/uapi/linux/bpf.h | 1 + 6 files changed, 28 insertions(+), 13 deletions(-)
include/linux/trace_events.h +4 -2
@@ -761,7 +761,8 @@ struct bpf_raw_event_map *bpf_get_raw_tracepoint(const char *name);void bpf_put_raw_tracepoint (struct bpf_raw_event_map *btp);int bpf_get_perf_event_info (const struct perf_event *event,u32 *prog_id,u32 *fd_type,const char **buf, -u64 *probe_offset,u64 *probe_addr); +u64 *probe_offset,u64 *probe_addr, +unsigned long *missed);int bpf_kprobe_multi_link_attach (const union bpf_attr *attr,struct bpf_prog *prog);int bpf_uprobe_multi_link_attach (const union bpf_attr *attr,struct bpf_prog *prog);#else
@@ -801,7 +802,7 @@ static inline void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp)static inline int bpf_get_perf_event_info (const struct perf_event *event,u32 *prog_id,u32 *fd_type,const char **buf,u64 *probe_offset, -u64 *probe_addr) +u64 *probe_addr,unsigned long *missed) {return -EOPNOTSUPP ; }
@@ -877,6 +878,7 @@ extern void perf_kprobe_destroy(struct perf_event *event);extern int bpf_get_kprobe_info (const struct perf_event *event,u32 *fd_type,const char **symbol,u64 *probe_offset,u64 *probe_addr, +unsigned long *missed,bool perf_type_tracepoint);#endif #ifdef CONFIG_UPROBE_EVENTS
include/uapi/linux/bpf.h +1 -0
@@ -6546,6 +6546,7 @@ struct bpf_link_info {__u32 name_len;__u32 offset;/* offset from func_name */ __u64 addr; +__u64 missed; } kprobe;/* BPF_PERF_EVENT_KPROBE, BPF_PERF_EVENT_KRETPROBE */ struct {__aligned_u64 tp_name;/* in/out */
kernel/bpf/syscall.c +8 -6
@@ -3374,7 +3374,7 @@ static void bpf_perf_link_dealloc(struct bpf_link *link)static int bpf_perf_link_fill_common (const struct perf_event *event,char __user *uname,u32 ulen,u64 *probe_offset,u64 *probe_addr, -u32 *fd_type) +u32 *fd_type,unsigned long *missed) {const char *buf;u32 prog_id;
@@ -3385,7 +3385,7 @@ static int bpf_perf_link_fill_common(const struct perf_event *event,return -EINVAL ; err =bpf_get_perf_event_info (event, &prog_id, fd_type, &buf, - probe_offset, probe_addr); + probe_offset, probe_addr, missed);if (err)return err;if (!uname)
@@ -3408,6 +3408,7 @@ static int bpf_perf_link_fill_common(const struct perf_event *event,static int bpf_perf_link_fill_kprobe (const struct perf_event *event,struct bpf_link_info *info) { +unsigned long missed;char __user *uname;u64 addr, offset;u32 ulen, type;
@@ -3416,7 +3417,7 @@ static int bpf_perf_link_fill_kprobe(const struct perf_event *event, uname =u64_to_user_ptr (info->perf_event.kprobe.func_name); ulen = info->perf_event.kprobe.name_len; err =bpf_perf_link_fill_common (event, uname, ulen, &offset, &addr, - &type); + &type, &missed);if (err)return err;if (type ==BPF_FD_TYPE_KRETPROBE )
@@ -3425,6 +3426,7 @@ static int bpf_perf_link_fill_kprobe(const struct perf_event *event, info->perf_event.type =BPF_PERF_EVENT_KPROBE ; info->perf_event.kprobe.offset = offset; + info->perf_event.kprobe.missed = missed;if (!kallsyms_show_value (current_cred ())) addr =0 ; info->perf_event.kprobe.addr = addr;
@@ -3444,7 +3446,7 @@ static int bpf_perf_link_fill_uprobe(const struct perf_event *event, uname =u64_to_user_ptr (info->perf_event.uprobe.file_name); ulen = info->perf_event.uprobe.name_len; err =bpf_perf_link_fill_common (event, uname, ulen, &offset, &addr, - &type); + &type,NULL );if (err)return err;
@@ -3480,7 +3482,7 @@ static int bpf_perf_link_fill_tracepoint(const struct perf_event *event, uname =u64_to_user_ptr (info->perf_event.tracepoint.tp_name); ulen = info->perf_event.tracepoint.name_len; info->perf_event.type =BPF_PERF_EVENT_TRACEPOINT ; -return bpf_perf_link_fill_common (event, uname, ulen,NULL ,NULL ,NULL ); +return bpf_perf_link_fill_common (event, uname, ulen,NULL ,NULL ,NULL ,NULL ); } static int bpf_perf_link_fill_perf_event(const struct perf_event *event,
@@ -4813,7 +4815,7 @@ static int bpf_task_fd_query(const union bpf_attr *attr, err =bpf_get_perf_event_info (event, &prog_id, &fd_type, &buf, &probe_offset, - &probe_addr); + &probe_addr,NULL );if (!err) err = bpf_task_fd_query_copy(attr, uattr, prog_id, fd_type, buf,
kernel/trace/bpf_trace.c +3 -2
@@ -2384,7 +2384,8 @@ int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *prog)int bpf_get_perf_event_info (const struct perf_event *event,u32 *prog_id,u32 *fd_type,const char **buf, -u64 *probe_offset,u64 *probe_addr) +u64 *probe_offset,u64 *probe_addr, +unsigned long *missed) {bool is_tracepoint, is_syscall_tp;struct bpf_prog *prog;
@@ -2419,7 +2420,7 @@ int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,#ifdef CONFIG_KPROBE_EVENTS if (flags &TRACE_EVENT_FL_KPROBE ) err =bpf_get_kprobe_info (event, fd_type, buf, - probe_offset, probe_addr, + probe_offset, probe_addr, missed, event->attr.type ==PERF_TYPE_TRACEPOINT );#endif #ifdef CONFIG_UPROBE_EVENTS
kernel/trace/trace_kprobe.c +11 -3
@@ -1189,6 +1189,12 @@ static const struct file_operations kprobe_events_ops = { .write = probes_write, }; +static unsigned long trace_kprobe_missed (struct trace_kprobe *tk) +{ +return trace_kprobe_is_return (tk) ? + tk->rp.kp.nmissed + tk->rp.nmissed : tk->rp.kp.nmissed; +} +/* Probes profiling interfaces */ static int probes_profile_seq_show (struct seq_file *m,void *v) {
@@ -1200,8 +1206,7 @@ static int probes_profile_seq_show(struct seq_file *m, void *v)return 0 ; tk =to_trace_kprobe (ev); - nmissed =trace_kprobe_is_return (tk) ? - tk->rp.kp.nmissed + tk->rp.nmissed : tk->rp.kp.nmissed; + nmissed =trace_kprobe_missed (tk); seq_printf(m, " %-44s %15lu %15lu\n", trace_probe_name(&tk->tp), trace_kprobe_nhit(tk),
@@ -1547,7 +1552,8 @@ NOKPROBE_SYMBOL(kretprobe_perf_func);int bpf_get_kprobe_info (const struct perf_event *event,u32 *fd_type,const char **symbol,u64 *probe_offset, -u64 *probe_addr,bool perf_type_tracepoint) +u64 *probe_addr,unsigned long *missed, +bool perf_type_tracepoint) {const char *pevent =trace_event_name (event->tp_event);const char *group = event->tp_event->class->system;
@@ -1566,6 +1572,8 @@ int bpf_get_kprobe_info(const struct perf_event *event, u32 *fd_type, *probe_addr =kallsyms_show_value (current_cred ()) ? (unsigned long )tk->rp.kp.addr :0 ; *symbol = tk->symbol; +if (missed) + *missed =trace_kprobe_missed (tk); return 0; }#endif /* CONFIG_PERF_EVENTS */
tools/include/uapi/linux/bpf.h +1 -0
@@ -6546,6 +6546,7 @@ struct bpf_link_info {__u32 name_len;__u32 offset;/* offset from func_name */ __u64 addr; +__u64 missed; } kprobe;/* BPF_PERF_EVENT_KPROBE, BPF_PERF_EVENT_KRETPROBE */ struct {__aligned_u64 tp_name;/* in/out */
Signature · 1 line
2.41.0
Jiri Olsa
reviewerPATCH v3 4/9 bpf: Count missed stats in trace_call_bpf
In reply to Jiri OlsaIncrease misses stats in case bpf array execution is skipped because of recursion check in trace_call_bpf.
Adding bpf_prog_inc_misses_counters that increase misses counts for all bpf programs in bpf_prog_array.
--- include/linux/bpf.h | 16 ++++++++++++++++ kernel/trace/bpf_trace.c | 3 +++ 2 files changed, 19 insertions(+)
include/linux/bpf.h +16 -0
@@ -2922,6 +2922,22 @@ static inline int sock_map_bpf_prog_query(const union bpf_attr *attr,#endif /* CONFIG_BPF_SYSCALL */ #endif /* CONFIG_NET && CONFIG_BPF_SYSCALL */ +static __always_inline void +bpf_prog_inc_misses_counters (const struct bpf_prog_array *array) +{ +const struct bpf_prog_array_item *item; +struct bpf_prog *prog; + +if (unlikely (!array)) +return ; + + item = &array->items[0 ]; +while ((prog =READ_ONCE (item->prog))) { +bpf_prog_inc_misses_counter (prog); + item++; + } +} +#if defined(CONFIG_INET ) && defined(CONFIG_BPF_SYSCALL )void bpf_sk_reuseport_detach (struct sock *sk); int bpf_fd_reuseport_array_lookup_elem(struct bpf_map *map, void *key,
kernel/trace/bpf_trace.c +3 -0
@@ -117,6 +117,9 @@ unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx)* and don't send kprobe event into ring-buffer, * so return zero here */ +rcu_read_lock (); +bpf_prog_inc_misses_counters (rcu_dereference (call->prog_array)); +rcu_read_unlock (); ret =0 ; goto out; }
Signature · 1 line
2.41.0
Jiri Olsa
reviewerPATCH v3 5/9 bpftool: Display missed count for kprobe_multi link
In reply to Jiri OlsaAdding 'missed' field to display missed counts for kprobes attached by kprobe multi link, like:
# bpftool link
5: kprobe_multi prog 76
kprobe.multi func_cnt 1 missed 1
addr func [module]
ffffffffa039c030 fp3_test [fprobe_test] # bpftool link -jp
[{
"id": 5,
"type": "kprobe_multi",
"prog_id": 76,
"retprobe": false,
"func_cnt": 1,
"missed": 1,
"funcs": [{
"addr": 18446744072102723632,
"func": "fp3_test",
"module": "fprobe_test"
}
]
}
]--- tools/bpf/bpftool/link.c | 3 +++ 1 file changed, 3 insertions(+)
tools/bpf/bpftool/link.c +3 -0
@@ -265,6 +265,7 @@ show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)jsonw_bool_field (json_wtr,"retprobe" , info->kprobe_multi.flags &BPF_F_KPROBE_MULTI_RETURN );jsonw_uint_field (json_wtr,"func_cnt" , info->kprobe_multi.count); +jsonw_uint_field (json_wtr,"missed" , info->kprobe_multi.missed);jsonw_name (json_wtr,"funcs" );jsonw_start_array (json_wtr); addrs =u64_to_ptr (info->kprobe_multi.addrs);
@@ -641,6 +642,8 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)else printf ("\n\tkprobe.multi " );printf ("func_cnt %u " , info->kprobe_multi.count); +if (info->kprobe_multi.missed) +printf ("missed %llu " , info->kprobe_multi.missed); addrs = (__u64 *)u64_to_ptr (info->kprobe_multi.addrs);qsort (addrs, info->kprobe_multi.count,sizeof (__u64), cmp_u64);
Signature · 1 line
2.41.0
Jiri Olsa
reviewerPATCH v3 6/9 bpftool: Display missed count for kprobe perf link
In reply to Jiri OlsaAdding 'missed' field to display missed counts for kprobes attached by perf event link, like:
# bpftool link
5: perf_event prog 82
kprobe ffffffff815203e0 ksys_write
6: perf_event prog 83
kprobe ffffffff811d1e50 scheduler_tick missed 682217 # bpftool link -jp
[{
"id": 5,
"type": "perf_event",
"prog_id": 82,
"retprobe": false,
"addr": 18446744071584220128,
"func": "ksys_write",
"offset": 0,
"missed": 0
},{
"id": 6,
"type": "perf_event",
"prog_id": 83,
"retprobe": false,
"addr": 18446744071580753488,
"func": "scheduler_tick",
"offset": 0,
"missed": 693469
}
]--- tools/bpf/bpftool/link.c | 3 +++ 1 file changed, 3 insertions(+)
tools/bpf/bpftool/link.c +3 -0
@@ -302,6 +302,7 @@ show_perf_event_kprobe_json(struct bpf_link_info *info, json_writer_t *wtr)jsonw_string_field (wtr,"func" ,u64_to_ptr (info->perf_event.kprobe.func_name));jsonw_uint_field (wtr,"offset" , info->perf_event.kprobe.offset); +jsonw_uint_field (wtr,"missed" , info->perf_event.kprobe.missed); } static void
@@ -686,6 +687,8 @@ static void show_perf_event_kprobe_plain(struct bpf_link_info *info)printf ("%s" , buf);if (info->perf_event.kprobe.offset)printf ("+%#x" , info->perf_event.kprobe.offset); +if (info->perf_event.kprobe.missed) +printf (" missed %llu" , info->perf_event.kprobe.missed);printf (" " ); }
Signature · 1 line
2.41.0
Jiri Olsa
reviewerPATCH v3 7/9 selftests/bpf: Add test for missed counts of perf event link kprobe
In reply to Jiri OlsaAdding test that puts kprobe on bpf_fentry_test1 that calls bpf_kfunc_common_test kfunc, which has also kprobe on.
The latter won't get triggered due to kprobe recursion check and kprobe missed counter is incremented.
--- .../selftests/bpf/bpf_testmod/bpf_testmod.c | 5 ++ .../bpf/bpf_testmod/bpf_testmod_kfunc.h | 2 + .../testing/selftests/bpf/prog_tests/missed.c | 47 +++++++++++++++++++ .../selftests/bpf/progs/missed_kprobe.c | 30 ++++++++++++ 4 files changed, 84 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/missed.c create mode 100644 tools/testing/selftests/bpf/progs/missed_kprobe.c
tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c +5 -0
@@ -138,6 +138,10 @@ __bpf_kfunc void bpf_iter_testmod_seq_destroy(struct bpf_iter_testmod_seq *it) it->cnt =0 ; } +__bpf_kfunc void bpf_kfunc_common_test(void) +{ +} +struct bpf_testmod_btf_type_tag_1 {int a; };
@@ -343,6 +347,7 @@ BTF_SET8_START(bpf_testmod_common_kfunc_ids) BTF_ID_FLAGS(func, bpf_iter_testmod_seq_new, KF_ITER_NEW) BTF_ID_FLAGS(func, bpf_iter_testmod_seq_next, KF_ITER_NEXT | KF_RET_NULL) BTF_ID_FLAGS(func, bpf_iter_testmod_seq_destroy, KF_ITER_DESTROY) +BTF_ID_FLAGS(func, bpf_kfunc_common_test)BTF_SET8_END (bpf_testmod_common_kfunc_ids) static const struct btf_kfunc_id_set bpf_testmod_common_kfunc_set = {
tools/testing/selftests/bpf/bpf_testmod/bpf_testmod_kfunc.h +2 -0
@@ -104,4 +104,6 @@ void bpf_kfunc_call_test_fail1(struct prog_test_fail1 *p);void bpf_kfunc_call_test_fail2 (struct prog_test_fail2 *p);void bpf_kfunc_call_test_fail3 (struct prog_test_fail3 *p);void bpf_kfunc_call_test_mem_len_fail1 (void *mem,int len); + +void bpf_kfunc_common_test(void) __ksym;#endif /* _BPF_TESTMOD_KFUNC_H */
tools/testing/selftests/bpf/prog_tests/missed.c new file +47 -0
47 lines not on this page · raw message
tools/testing/selftests/bpf/progs/missed_kprobe.c new file +30 -0
@@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "vmlinux.h" +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> +#include "../bpf_testmod/bpf_testmod_kfunc.h" + +char _license[] SEC("license") = "GPL"; + +/* +* No tests in here, just to trigger 'bpf_fentry_test*' +* through tracing test_run +*/ +SEC("fentry/bpf_modify_return_test") +int BPF_PROG (trigger ) +{ +return 0 ; +} + +SEC("kprobe/bpf_fentry_test1") +int test1 (struct pt_regs *ctx) +{ +bpf_kfunc_common_test (); +return 0 ; +} + +SEC("kprobe/bpf_kfunc_common_test") +int test2 (struct pt_regs *ctx) +{ +return 0 ; +}
Signature · 1 line
2.41.0
Jiri Olsa
reviewerPATCH v3 8/9 selftests/bpf: Add test for recursion counts of perf event link kprobe
In reply to Jiri OlsaAdding selftest that puts kprobe.multi on bpf_fentry_test1 that calls bpf_kfunc_common_test kfunc which has 3 perf event kprobes and 1 kprobe.multi attached.
Because fprobe (kprobe.multi attach layear) does not have strict recursion check the kprobe's bpf_prog_active check is hit for test2-5.
Disabling this test for arm64, because there's no fprobe support yet.
--- tools/testing/selftests/bpf/DENYLIST.aarch64 | 1 + .../testing/selftests/bpf/prog_tests/missed.c | 51 +++++++++++++++++++ .../bpf/progs/missed_kprobe_recursion.c | 48 +++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/missed_kprobe_recursion.c
tools/testing/selftests/bpf/DENYLIST.aarch64 +1 -0
@@ -16,3 +16,4 @@ fexit_test/fexit_many_args # fexit_many_args:FAIL:fexit_ma fill_link_info/kprobe_multi_link_info # bpf_program__attach_kprobe_multi_opts unexpected error: -95 fill_link_info/kretprobe_multi_link_info # bpf_program__attach_kprobe_multi_opts unexpected error: -95 fill_link_info/kprobe_multi_invalid_ubuff # bpf_program__attach_kprobe_multi_opts unexpected error: -95 +missed/kprobe_recursion # missed_kprobe_recursion__attach unexpected error: -95 (errno 95)
tools/testing/selftests/bpf/prog_tests/missed.c +51 -0
65 lines not on this page · raw message
tools/testing/selftests/bpf/progs/missed_kprobe_recursion.c new file +48 -0
48 lines not on this page · raw message
Signature · 1 line
2.41.0
Jiri Olsa
reviewerPATCH v3 9/9 selftests/bpf: Add test for recursion counts of perf event link tracepoint
In reply to Jiri OlsaAdding selftest that puts kprobe on bpf_fentry_test1 that calls bpf_printk and invokes bpf_trace_printk tracepoint. The bpf_trace_printk tracepoint has test[234] programs attached to it.
Because kprobe execution goes through bpf_prog_active check, programs attached to the tracepoint will fail the recursion check and increment the recursion_misses stats.
--- .../testing/selftests/bpf/prog_tests/missed.c | 40 ++++++++++++++++++ .../selftests/bpf/progs/missed_tp_recursion.c | 41 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/missed_tp_recursion.c
tools/testing/selftests/bpf/prog_tests/missed.c +40 -0
@@ -2,6 +2,7 @@#include <test_progs.h> #include "missed_kprobe.skel.h" #include "missed_kprobe_recursion.skel.h" +#include "missed_tp_recursion.skel.h" /* * Putting kprobe on bpf_fentry_test1 that calls bpf_kfunc_common_test
@@ -89,10 +90,49 @@ static void test_missed_kprobe_recursion(void)missed_kprobe_recursion__destroy (skel); } +/* +* Putting kprobe on bpf_fentry_test1 that calls bpf_printk and invokes +* bpf_trace_printk tracepoint. The bpf_trace_printk tracepoint has test[234] +* programs attached to it. +* +* Because kprobe execution goes through bpf_prog_active check, programs +* attached to the tracepoint will fail the recursion check and increment +* the recursion_misses stats. +*/ +static void test_missed_tp_recursion (void ) +{ +LIBBPF_OPTS (bpf_test_run_opts, topts); +struct missed_tp_recursion *skel; +int err, prog_fd; + + skel =missed_tp_recursion__open_and_load (); +if (!ASSERT_OK_PTR (skel,"missed_tp_recursion__open_and_load" )) + goto cleanup; + + err =missed_tp_recursion__attach (skel); +if (!ASSERT_OK (err,"missed_tp_recursion__attach" )) + goto cleanup; + + prog_fd =bpf_program__fd (skel->progs.trigger); + err =bpf_prog_test_run_opts (prog_fd, &topts); +ASSERT_OK (err,"test_run" ); +ASSERT_EQ (topts.retval,0 ,"test_run" ); + +ASSERT_EQ (get_missed_count (bpf_program__fd (skel->progs.test1)),0 ,"test1_recursion_misses" ); +ASSERT_EQ (get_missed_count (bpf_program__fd (skel->progs.test2)),1 ,"test2_recursion_misses" ); +ASSERT_EQ (get_missed_count (bpf_program__fd (skel->progs.test3)),1 ,"test3_recursion_misses" ); +ASSERT_EQ (get_missed_count (bpf_program__fd (skel->progs.test4)),1 ,"test4_recursion_misses" ); + +cleanup: +missed_tp_recursion__destroy (skel); +} +void test_missed (void ) {if (test__start_subtest ("perf_kprobe" ))test_missed_perf_kprobe ();if (test__start_subtest ("kprobe_recursion" ))test_missed_kprobe_recursion (); +if (test__start_subtest ("tp_recursion" )) +test_missed_tp_recursion (); }
tools/testing/selftests/bpf/progs/missed_tp_recursion.c new file +41 -0
41 lines not on this page · raw message
Signature · 1 line
2.41.0
This series was applied to bpf/bpf-next.git (master) by Andrii Nakryiko <[email protected]>:
Hello:
This series was applied to bpf/bpf-next.git (master) by Andrii Nakryiko <[email protected]>:
Quoted 11 lines · On Wed, 20 Sep 2023 23:31:36 +0200 you wrote:
hi,
at the moment we can't retrieve the number of missed kprobe executions and subsequent execution of BPF programs.This patchset adds:
- counting of missed execution on attach layer for:
. kprobes attached through perf link (kprobe/ftrace) . kprobes attached through kprobe.multi link (fprobe)
- counting ofrecursion_missesfor BPF kprobe programs[...]
Here is the summary with links:
- [PATCHv3,bpf-next,1/9] bpf: Count stats for kprobe_multi programs
https://git.kernel.org/bpf/bpf-next/c/f915fcb38553 - [PATCHv3,bpf-next,2/9] bpf: Add missed value to kprobe_multi link info https://git.kernel.org/bpf/bpf-next/c/e2b2cd592adb - [PATCHv3,bpf-next,3/9] bpf: Add missed value to kprobe perf link info https://git.kernel.org/bpf/bpf-next/c/3acf8ace6823 - [PATCHv3,bpf-next,4/9] bpf: Count missed stats in trace_call_bpf https://git.kernel.org/bpf/bpf-next/c/dd8657894c11 - [PATCHv3,bpf-next,5/9] bpftool: Display missed count for kprobe_multi link https://git.kernel.org/bpf/bpf-next/c/b24fc35521b0 - [PATCHv3,bpf-next,6/9] bpftool: Display missed count for kprobe perf link https://git.kernel.org/bpf/bpf-next/c/b563b9bae8c3 - [PATCHv3,bpf-next,7/9] selftests/bpf: Add test for missed counts of perf event link kprobe https://git.kernel.org/bpf/bpf-next/c/01e4ae474e39 - [PATCHv3,bpf-next,8/9] selftests/bpf: Add test for recursion counts of perf event link kprobe https://git.kernel.org/bpf/bpf-next/c/59e83c0187c5 - [PATCHv3,bpf-next,9/9] selftests/bpf: Add test for recursion counts of perf event link tracepoint https://git.kernel.org/bpf/bpf-next/c/85981e0f9e9f
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html