From 554702e63d7a766de65fa8a09bd98574736810a1 Mon Sep 17 00:00:00 2001 From: Luca BRUNO Date: Wed, 25 Jan 2023 10:04:14 +0000 Subject: [PATCH] cargo-generate: add perf_event This adds `perf_event` program type as a template entry. The new entry comes with a skeleton example which register scheduled events on each CPU at 1 HZ, triggered by the kernel (based on clock ticks). The corresponding BPF logic logs each event, and can identify kernel tasks from userland processes. --- .github/workflows/ci.yml | 9 +++++---- cargo-generate.toml | 1 + {{project-name}}-ebpf/src/main.rs | 26 ++++++++++++++++++++++++++ {{project-name}}/src/main.rs | 16 ++++++++++++++++ 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3af968d..288e83e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,14 +29,15 @@ jobs: - socket_filter - sk_msg - xdp - - classifier - cgroup_skb - - cgroup_sysctl - cgroup_sockopt - - tracepoint + - cgroup_sysctl + - classifier - lsm - - tp_btf + - perf_event - raw_tracepoint + - tp_btf + - tracepoint steps: - uses: actions/checkout@v2 diff --git a/cargo-generate.toml b/cargo-generate.toml index 316ac9a..b4c4e31 100644 --- a/cargo-generate.toml +++ b/cargo-generate.toml @@ -15,6 +15,7 @@ choices = [ "kprobe", "kretprobe", "lsm", + "perf_event", "raw_tracepoint", "sk_msg", "sock_ops", diff --git a/{{project-name}}-ebpf/src/main.rs b/{{project-name}}-ebpf/src/main.rs index eee2730..dcc9254 100644 --- a/{{project-name}}-ebpf/src/main.rs +++ b/{{project-name}}-ebpf/src/main.rs @@ -341,6 +341,32 @@ fn try_{{crate_name}}(ctx: RawTracePointContext) -> Result { info!(&ctx, "tracepoint {{tracepoint_name}} called"); Ok(0) } +{%- when "perf_event" %} +use aya_bpf::{ + helpers::bpf_get_smp_processor_id, + macros::perf_event, + programs::PerfEventContext, + BpfContext, +}; +use aya_log_ebpf::info; + +#[perf_event] +pub fn {{crate_name}}(ctx: PerfEventContext) -> u32 { + match try_{{crate_name}}(ctx) { + Ok(ret) => ret, + Err(ret) => ret, + } +} + +fn try_{{crate_name}}(ctx: PerfEventContext) -> Result { + let cpu = unsafe { bpf_get_smp_processor_id() }; + match ctx.pid() { + 0 => info!(&ctx, "perf_event '{{crate_name}}' triggered on CPU {}, running a kernel task", cpu), + pid => info!(&ctx, "perf_event '{{crate_name}}' triggered on CPU {}, running PID {}", cpu, pid), + } + + Ok(0) +} {%- endcase %} #[panic_handler] diff --git a/{{project-name}}/src/main.rs b/{{project-name}}/src/main.rs index f7b403a..07a95fc 100644 --- a/{{project-name}}/src/main.rs +++ b/{{project-name}}/src/main.rs @@ -29,6 +29,9 @@ use aya::programs::CgroupSockopt; use aya::programs::TracePoint; {%- when "lsm" -%} use aya::{programs::Lsm, Btf}; +{%- when "perf_event" -%} +use aya::programs::{perf_event, PerfEvent}; +use aya::util::online_cpus; {%- when "tp_btf" -%} use aya::{programs::BtfTracePoint, Btf}; {%- when "socket_filter" -%} @@ -164,6 +167,19 @@ async fn main() -> Result<(), anyhow::Error> { let cgroup = std::fs::File::open(opt.cgroup_path)?; program.load()?; program.attach(cgroup)?; + {%- when "perf_event" -%} + // This will raise scheduled events on each CPU at 1 HZ, triggered by the kernel based + // on clock ticks. + let program: &mut PerfEvent = bpf.program_mut("{{crate_name}}").unwrap().try_into()?; + program.load()?; + for cpu in online_cpus()? { + program.attach( + perf_event::PerfTypeId::Software, + perf_event::perf_sw_ids::PERF_COUNT_SW_CPU_CLOCK as u64, + perf_event::PerfEventScope::AllProcessesOneCpu { cpu }, + perf_event::SamplePolicy::Frequency(1), + )?; + } {%- when "raw_tracepoint" -%} let program: &mut RawTracePoint = bpf.program_mut("{{crate_name}}").unwrap().try_into()?; program.load()?;