forked from ccfos/huatuo
77 lines
1.6 KiB
C
77 lines
1.6 KiB
C
#include "vmlinux.h"
|
|
|
|
#include <bpf/bpf_core_read.h>
|
|
#include <bpf/bpf_helpers.h>
|
|
#include <bpf/bpf_tracing.h>
|
|
|
|
#include "bpf_common.h"
|
|
|
|
enum lat_zone {
|
|
LAT_ZONE0 = 0, // 0 ~ 10us
|
|
LAT_ZONE1, // 10us ~ 100us
|
|
LAT_ZONE2, // 100us ~ 1ms
|
|
LAT_ZONE3, // 1ms ~ inf
|
|
LAT_ZONE_MAX,
|
|
};
|
|
|
|
struct tp_softirq {
|
|
unsigned long long pad;
|
|
unsigned int vec;
|
|
};
|
|
|
|
struct softirq_lat {
|
|
u64 timestamp;
|
|
u64 total_latency[LAT_ZONE_MAX];
|
|
};
|
|
|
|
struct {
|
|
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
|
|
__uint(key_size, sizeof(u32));
|
|
__uint(value_size, sizeof(struct softirq_lat));
|
|
__uint(max_entries, NR_SOFTIRQS_MAX);
|
|
} softirq_percpu_lats SEC(".maps");
|
|
|
|
SEC("tracepoint/irq/softirq_raise")
|
|
int probe_softirq_raise(struct tp_softirq *ctx)
|
|
{
|
|
struct softirq_lat lat = {
|
|
.timestamp = bpf_ktime_get_ns(),
|
|
};
|
|
u32 vec = ctx->vec;
|
|
|
|
if (vec >= NR_SOFTIRQS)
|
|
return 0;
|
|
|
|
bpf_map_update_elem(&softirq_percpu_lats, &vec, &lat, COMPAT_BPF_ANY);
|
|
return 0;
|
|
}
|
|
|
|
SEC("tracepoint/irq/softirq_entry")
|
|
int probe_softirq_entry(struct tp_softirq *ctx)
|
|
{
|
|
struct softirq_lat *lat;
|
|
u32 vec = ctx->vec;
|
|
|
|
if (vec >= NR_SOFTIRQS)
|
|
return 0;
|
|
|
|
lat = bpf_map_lookup_elem(&softirq_percpu_lats, &vec);
|
|
if (!lat)
|
|
return 0;
|
|
|
|
u64 latency = bpf_ktime_get_ns() - lat->timestamp;
|
|
|
|
if (latency < 10 * NSEC_PER_USEC) {
|
|
__sync_fetch_and_add(&lat->total_latency[LAT_ZONE0], 1);
|
|
} else if (latency < 100 * NSEC_PER_USEC) {
|
|
__sync_fetch_and_add(&lat->total_latency[LAT_ZONE1], 1);
|
|
} else if (latency < 1 * NSEC_PER_MSEC) {
|
|
__sync_fetch_and_add(&lat->total_latency[LAT_ZONE2], 1);
|
|
} else {
|
|
__sync_fetch_and_add(&lat->total_latency[LAT_ZONE3], 1);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
char __license[] SEC("license") = "Dual MIT/GPL";
|