mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-25 10:03:23 +00:00
feat: support tracepoint-based ebpf programs (#1190)
* feat: support tracepoint-based ebpf programs Signed-off-by: Godones <chenlinfeng25@outlook.com> * remove licenses Signed-off-by: Godones <chenlinfeng25@outlook.com> * feat: Supplement tracepoint related files fix some warnings add docs for tracepoint Signed-off-by: Godones <chenlinfeng25@outlook.com> --------- Signed-off-by: Godones <chenlinfeng25@outlook.com> Co-authored-by: longjin <longjin@DragonOS.org>
This commit is contained in:
44
user/apps/test_tracepoint/mytrace/Cargo.toml
Normal file
44
user/apps/test_tracepoint/mytrace/Cargo.toml
Normal file
@ -0,0 +1,44 @@
|
||||
[package]
|
||||
name = "mytrace"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
mytrace-common = { path = "../mytrace-common", features = ["user"] }
|
||||
|
||||
anyhow = { workspace = true, default-features = true }
|
||||
aya = { workspace = true }
|
||||
aya-log = { workspace = true }
|
||||
env_logger = { workspace = true }
|
||||
libc = { workspace = true }
|
||||
log = { workspace = true }
|
||||
tokio = { workspace = true, features = [
|
||||
"macros",
|
||||
"rt",
|
||||
"rt-multi-thread",
|
||||
"net",
|
||||
"signal",
|
||||
"time"
|
||||
] }
|
||||
[build-dependencies]
|
||||
anyhow = { workspace = true }
|
||||
aya-build = { workspace = true }
|
||||
# TODO(https://github.com/rust-lang/cargo/issues/12375): this should be an artifact dependency, but
|
||||
# it's not possible to tell cargo to use `-Z build-std` to build it. We cargo-in-cargo in the build
|
||||
# script to build this, but we want to teach cargo about the dependecy so that cache invalidation
|
||||
# works properly.
|
||||
#
|
||||
# Note also that https://github.com/rust-lang/cargo/issues/10593 occurs when `target = ...` is added
|
||||
# to an artifact dependency; it seems possible to work around that by setting `resolver = "1"` in
|
||||
# Cargo.toml in the workspace root.
|
||||
#
|
||||
# Finally note that *any* usage of `artifact = ...` in *any* Cargo.toml in the workspace breaks
|
||||
# workflows with stable cargo; stable cargo outright refuses to load manifests that use unstable
|
||||
# features.
|
||||
mytrace-ebpf = { path = "../mytrace-ebpf" }
|
||||
|
||||
[[bin]]
|
||||
name = "mytrace"
|
||||
path = "src/main.rs"
|
14
user/apps/test_tracepoint/mytrace/build.rs
Normal file
14
user/apps/test_tracepoint/mytrace/build.rs
Normal file
@ -0,0 +1,14 @@
|
||||
use anyhow::{anyhow, Context as _};
|
||||
use aya_build::cargo_metadata;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let cargo_metadata::Metadata { packages, .. } = cargo_metadata::MetadataCommand::new()
|
||||
.no_deps()
|
||||
.exec()
|
||||
.context("MetadataCommand::exec")?;
|
||||
let ebpf_package = packages
|
||||
.into_iter()
|
||||
.find(|cargo_metadata::Package { name, .. }| name == "mytrace-ebpf")
|
||||
.ok_or_else(|| anyhow!("mytrace-ebpf package not found"))?;
|
||||
aya_build::build_ebpf([ebpf_package])
|
||||
}
|
62
user/apps/test_tracepoint/mytrace/src/main.rs
Normal file
62
user/apps/test_tracepoint/mytrace/src/main.rs
Normal file
@ -0,0 +1,62 @@
|
||||
use aya::programs::TracePoint;
|
||||
#[rustfmt::skip]
|
||||
use log::{debug, warn};
|
||||
use tokio::{signal, task::yield_now, time};
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
// env_logger::init();
|
||||
|
||||
env_logger::builder()
|
||||
.filter_level(log::LevelFilter::Info)
|
||||
.format_timestamp(None)
|
||||
.init();
|
||||
// Bump the memlock rlimit. This is needed for older kernels that don't use the
|
||||
// new memcg based accounting, see https://lwn.net/Articles/837122/
|
||||
let rlim = libc::rlimit {
|
||||
rlim_cur: libc::RLIM_INFINITY,
|
||||
rlim_max: libc::RLIM_INFINITY,
|
||||
};
|
||||
let ret = unsafe { libc::setrlimit(libc::RLIMIT_MEMLOCK, &rlim) };
|
||||
if ret != 0 {
|
||||
debug!("remove limit on locked memory failed, ret is: {ret}");
|
||||
}
|
||||
|
||||
// This will include your eBPF object file as raw bytes at compile-time and load it at
|
||||
// runtime. This approach is recommended for most real-world use cases. If you would
|
||||
// like to specify the eBPF program at runtime rather than at compile-time, you can
|
||||
// reach for `Bpf::load_file` instead.
|
||||
let mut ebpf = aya::Ebpf::load(aya::include_bytes_aligned!(concat!(
|
||||
env!("OUT_DIR"),
|
||||
"/mytrace"
|
||||
)))?;
|
||||
if let Err(e) = aya_log::EbpfLogger::init(&mut ebpf) {
|
||||
// This can happen if you remove all log statements from your eBPF program.
|
||||
warn!("failed to initialize eBPF logger: {e}");
|
||||
}
|
||||
let program: &mut TracePoint = ebpf.program_mut("mytrace").unwrap().try_into()?;
|
||||
program.load()?;
|
||||
program.attach("syscalls", "sys_enter_openat")?;
|
||||
|
||||
tokio::spawn(async move {
|
||||
let mut now = time::Instant::now();
|
||||
loop {
|
||||
let new_now = time::Instant::now();
|
||||
let duration = new_now.duration_since(now);
|
||||
if duration.as_secs() >= 2 {
|
||||
// open a file to trigger the tracepoint
|
||||
log::info!("Triggering tracepoint by opening /bin");
|
||||
let bin = std::fs::File::open("/bin").unwrap();
|
||||
drop(bin);
|
||||
now = new_now;
|
||||
}
|
||||
yield_now().await;
|
||||
}
|
||||
});
|
||||
|
||||
let ctrl_c = signal::ctrl_c();
|
||||
println!("Waiting for Ctrl-C...");
|
||||
ctrl_c.await?;
|
||||
println!("Exiting...");
|
||||
|
||||
Ok(())
|
||||
}
|
Reference in New Issue
Block a user