Skip to content

Commit e9f9be2

Browse files
d-e-s-oinsearchoflosttime
authored andcommitted
libbpf-rs: Add support for tracepoint opts
Similar to what we did in commit a160b60 ("libbpf-rs: Plumb through support for USDT options"), this change adds support for providing additional options when attaching a program to a kernel tracepoint. Closes: #315 Signed-off-by: Daniel Müller <deso@posteo.net>
1 parent ddd1f6c commit e9f9be2

File tree

5 files changed

+130
-19
lines changed

5 files changed

+130
-19
lines changed

libbpf-rs/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ pub use crate::map::{Map, MapFlags, MapType, OpenMap};
9797
pub use crate::object::{Object, ObjectBuilder, OpenObject};
9898
pub use crate::perf_buffer::{PerfBuffer, PerfBufferBuilder};
9999
pub use crate::print::{get_print, set_print, PrintCallback, PrintLevel};
100-
pub use crate::program::{OpenProgram, Program, ProgramAttachType, ProgramType, UsdtOpts};
100+
pub use crate::program::{
101+
OpenProgram, Program, ProgramAttachType, ProgramType, TracepointOpts, UsdtOpts,
102+
};
101103
pub use crate::ringbuf::{RingBuffer, RingBufferBuilder};
102104
pub use crate::tc::{
103105
TcAttachPoint, TcHook, TcHookBuilder, TC_CUSTOM, TC_EGRESS, TC_H_CLSACT, TC_H_INGRESS,

libbpf-rs/src/program.rs

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,29 @@ impl From<UsdtOpts> for libbpf_sys::bpf_usdt_opts {
3232
}
3333
}
3434

35+
/// Options to optionally be provided when attaching to a tracepoint.
36+
#[derive(Clone, Debug, Default)]
37+
pub struct TracepointOpts {
38+
/// Custom user-provided value accessible through `bpf_get_attach_cookie`.
39+
pub cookie: u64,
40+
#[doc(hidden)]
41+
pub _non_exhaustive: (),
42+
}
43+
44+
impl From<TracepointOpts> for libbpf_sys::bpf_tracepoint_opts {
45+
fn from(opts: TracepointOpts) -> Self {
46+
let TracepointOpts {
47+
cookie,
48+
_non_exhaustive,
49+
} = opts;
50+
51+
libbpf_sys::bpf_tracepoint_opts {
52+
sz: mem::size_of::<Self>() as u64,
53+
bpf_cookie: cookie,
54+
}
55+
}
56+
}
57+
3558
/// Represents a parsed but not yet loaded BPF program.
3659
///
3760
/// This object exposes operations that need to happen before the program is loaded.
@@ -428,20 +451,33 @@ impl Program {
428451
}
429452
}
430453

431-
/// Attach this program to a [kernel
432-
/// tracepoint](https://www.kernel.org/doc/html/latest/trace/tracepoints.html).
433-
pub fn attach_tracepoint(
454+
fn attach_tracepoint_impl(
434455
&mut self,
435-
tp_category: impl AsRef<str>,
436-
tp_name: impl AsRef<str>,
456+
tp_category: &str,
457+
tp_name: &str,
458+
tp_opts: Option<TracepointOpts>,
437459
) -> Result<Link> {
438-
let tp_category = util::str_to_cstring(tp_category.as_ref())?;
460+
let tp_category = util::str_to_cstring(tp_category)?;
439461
let tp_category_ptr = tp_category.as_ptr();
440-
let tp_name = util::str_to_cstring(tp_name.as_ref())?;
462+
let tp_name = util::str_to_cstring(tp_name)?;
441463
let tp_name_ptr = tp_name.as_ptr();
442-
let ptr = unsafe {
443-
libbpf_sys::bpf_program__attach_tracepoint(self.ptr, tp_category_ptr, tp_name_ptr)
464+
465+
let ptr = if let Some(tp_opts) = tp_opts {
466+
let tp_opts = libbpf_sys::bpf_tracepoint_opts::from(tp_opts);
467+
unsafe {
468+
libbpf_sys::bpf_program__attach_tracepoint_opts(
469+
self.ptr,
470+
tp_category_ptr,
471+
tp_name_ptr,
472+
&tp_opts as *const _,
473+
)
474+
}
475+
} else {
476+
unsafe {
477+
libbpf_sys::bpf_program__attach_tracepoint(self.ptr, tp_category_ptr, tp_name_ptr)
478+
}
444479
};
480+
445481
let err = unsafe { libbpf_sys::libbpf_get_error(ptr as *const _) };
446482
if err != 0 {
447483
Err(Error::System(err as i32))
@@ -450,6 +486,28 @@ impl Program {
450486
}
451487
}
452488

489+
/// Attach this program to a [kernel
490+
/// tracepoint](https://www.kernel.org/doc/html/latest/trace/tracepoints.html).
491+
pub fn attach_tracepoint(
492+
&mut self,
493+
tp_category: impl AsRef<str>,
494+
tp_name: impl AsRef<str>,
495+
) -> Result<Link> {
496+
self.attach_tracepoint_impl(tp_category.as_ref(), tp_name.as_ref(), None)
497+
}
498+
499+
/// Attach this program to a [kernel
500+
/// tracepoint](https://www.kernel.org/doc/html/latest/trace/tracepoints.html),
501+
/// providing additional options.
502+
pub fn attach_tracepoint_with_opts(
503+
&mut self,
504+
tp_category: impl AsRef<str>,
505+
tp_name: impl AsRef<str>,
506+
tp_opts: TracepointOpts,
507+
) -> Result<Link> {
508+
self.attach_tracepoint_impl(tp_category.as_ref(), tp_name.as_ref(), Some(tp_opts))
509+
}
510+
453511
/// Attach this program to a [raw kernel
454512
/// tracepoint](https://lwn.net/Articles/748352/).
455513
pub fn attach_raw_tracepoint<T: AsRef<str>>(&mut self, tp_name: T) -> Result<Link> {

libbpf-rs/tests/bin/src/tracepoint.bpf.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,18 @@ int handle__tracepoint(void *ctx)
2323
return 0;
2424
}
2525

26+
SEC("tracepoint/syscalls/sys_enter_getpid")
27+
int handle__tracepoint_with_cookie(void *ctx)
28+
{
29+
int *value;
30+
31+
value = bpf_ringbuf_reserve(&ringbuf, sizeof(int), 0);
32+
if (value) {
33+
*value = bpf_get_attach_cookie(ctx);
34+
bpf_ringbuf_submit(value, 0);
35+
}
36+
37+
return 0;
38+
}
39+
2640
char LICENSE[] SEC("license") = "GPL";

libbpf-rs/tests/bin/tracepoint.bpf.o

1.03 KB
Binary file not shown.

libbpf-rs/tests/test.rs

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use scopeguard::defer;
1414

1515
use libbpf_rs::{
1616
num_possible_cpus, Iter, Map, MapFlags, MapType, Object, ObjectBuilder, OpenObject,
17-
ProgramType, UsdtOpts,
17+
ProgramType, TracepointOpts, UsdtOpts,
1818
};
1919

2020
fn get_test_object_path(filename: &str) -> PathBuf {
@@ -661,14 +661,7 @@ fn test_object_map_create_and_pin() {
661661
let opts = libbpf_sys::bpf_map_create_opts {
662662
sz: std::mem::size_of::<libbpf_sys::bpf_map_create_opts>() as libbpf_sys::size_t,
663663
map_flags: libbpf_sys::BPF_F_NO_PREALLOC,
664-
btf_fd: 0,
665-
btf_key_type_id: 0,
666-
btf_value_type_id: 0,
667-
btf_vmlinux_value_type_id: 0,
668-
inner_map_fd: 0,
669-
map_extra: 0,
670-
numa_node: 0,
671-
map_ifindex: 0,
664+
..Default::default()
672665
};
673666

674667
let mut map = Map::create(
@@ -936,3 +929,47 @@ fn test_object_tracepoint() {
936929

937930
unsafe { assert_eq!(V, 1) };
938931
}
932+
933+
/// Check that we can attach a BPF program to a kernel tracepoint, providing
934+
/// additional options.
935+
#[test]
936+
fn test_object_tracepoint_with_opts() {
937+
bump_rlimit_mlock();
938+
939+
let cookie_val = 42u16;
940+
let mut obj = get_test_object("tracepoint.bpf.o");
941+
let prog = obj
942+
.prog_mut("handle__tracepoint_with_cookie")
943+
.expect("Failed to find program");
944+
945+
let opts = TracepointOpts {
946+
cookie: cookie_val.into(),
947+
..TracepointOpts::default()
948+
};
949+
let _link = prog
950+
.attach_tracepoint_with_opts("syscalls", "sys_enter_getpid", opts)
951+
.expect("Failed to attach prog");
952+
953+
let mut builder = libbpf_rs::RingBufferBuilder::new();
954+
let map = obj.map("ringbuf").expect("Failed to get ringbuf map");
955+
956+
static mut V: i32 = 0;
957+
fn callback(data: &[u8]) -> i32 {
958+
let mut value: i32 = 0;
959+
plain::copy_from_bytes(&mut value, data).expect("Wrong size");
960+
961+
unsafe {
962+
V = value;
963+
}
964+
965+
0
966+
}
967+
968+
builder.add(map, callback).expect("Failed to add ringbuf");
969+
let mgr = builder.build().expect("Failed to build");
970+
971+
let _pid = unsafe { libc::getpid() };
972+
mgr.consume().expect("Failed to consume ringbuf");
973+
974+
unsafe { assert_eq!(V, cookie_val.into()) };
975+
}

0 commit comments

Comments
 (0)