bpf/virtcmdlatency.c (53 lines of code) (raw):
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
// +build ignore
#include <vmlinux.h>
#include <bpf_helpers.h>
#include <bpf_tracing.h>
#define VIRTCMDLAT_THRESH 10000000
struct insp_virtcmdlat_event_t {
u32 pid;
u32 cpu;
u64 latency;
};
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
} insp_virtcmdlat_events SEC(".maps");
struct insp_virtcmdlat_event_t *unused_event __attribute__((unused));
static inline int report_virtcmdlat_events(void *ctx, u64 latency)
{
struct insp_virtcmdlat_event_t event = {0};
event.pid = bpf_get_current_pid_tgid() >> 32;
event.cpu = bpf_get_smp_processor_id();
event.latency = latency;
bpf_perf_event_output(ctx, &insp_virtcmdlat_events, BPF_F_CURRENT_CPU, &event, sizeof(event));
return 0;
}
struct {
__uint(type, BPF_MAP_TYPE_PERCPU_HASH);
__uint(max_entries, 1024);
__type(key, u32);
__type(value, u64);
} insp_virtcmdlat SEC(".maps");
SEC("kprobe/virtnet_send_command")
int trace_virtcmd()
{
u32 key = bpf_get_current_pid_tgid();
u64 ts = bpf_ktime_get_ns();
bpf_map_update_elem(&insp_virtcmdlat, &key, &ts, BPF_ANY);
return 0;
}
SEC("kretprobe/virtnet_send_command")
int trace_virtcmdret(struct pt_regs * ctx)
{
u32 key = bpf_get_current_pid_tgid();
u64 ts = bpf_ktime_get_ns();
u64 *tsp;
tsp = bpf_map_lookup_elem(&insp_virtcmdlat, &key);
if (tsp) {
u64 latency = ts - *tsp;
if (latency > VIRTCMDLAT_THRESH) {
report_virtcmdlat_events(ctx,latency);
}
bpf_map_delete_elem(&insp_virtcmdlat,&key);
}
return 0;
}
char LICENSE[] SEC("license") = "Dual BSD/GPL";