Skip to content

Commit

Permalink
Introduce AsLibbpfObject trait
Browse files Browse the repository at this point in the history
libbpf-rs aims to be a convenient but thin wrapper around libbpf
functionality. Not all functionality provided of libbpf is exposed
through its API. This can quickly become a blocker if, say, some getter
is not hooked up, but the value required to perform an operation.
In the spirit of being a thin wrapper, it makes sense for us to provide
access to the underlying libbpf objects. When nothing else is available,
these can be used directly in conjunction with libbpf-sys to,
effectively, write Rust-syntax C code.
So far we have provided very ad-hoc accessor methods for retrieving
pointers to the underlying libbpf objects. With this change we formalize
this approach some more, by introducing the AsLibbpfObject trait and
implementing it for major libbpf-rs types.
Using a trait is not the only possible way. We could also continue that
path we were on earlier where relevant types had custom named accessors
without a common trait (e.g., Map::as_libbpf_bpf_map_ptr).
The benefits a trait brings to the table is that it unifies naming and
makes it reasonably easy to get an overview of types that have libbpf
counterparts.
The risk is that we may have to adjust the trait signature in one way or
another if a newly added type has different constraints (e.g., if a
libbpf-rs object has a potentially-NULL libbpf object).

Signed-off-by: Daniel Müller <[email protected]>
  • Loading branch information
d-e-s-o committed Sep 6, 2023
1 parent aacaec1 commit 40e8001
Show file tree
Hide file tree
Showing 13 changed files with 108 additions and 10 deletions.
2 changes: 2 additions & 0 deletions libbpf-rs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Unreleased
- Adjusted `opts` to return a reference to `libbpf_sys::bpf_object_open_opts`
- Removed object name argument from `open_memory` constructor
- Added `pin_root_path` setter
- Added `AsLibbpfObject` trait as a unified way to retrieve `libbpf` equivalents
for `libbpf-rs` objects
- Implemented `Send` for `Link`
- Updated `bitflags` dependency to `2.0`

Expand Down
15 changes: 13 additions & 2 deletions libbpf-rs/src/btf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,16 @@ use std::os::unix::prelude::OwnedFd;
use std::path::Path;
use std::ptr::NonNull;

use num_enum::IntoPrimitive;
use num_enum::TryFromPrimitive;

use crate::libbpf_sys;
use crate::util::create_bpf_entity_checked;
use crate::util::create_bpf_entity_checked_opt;
use crate::util::parse_ret_i32;
use crate::AsLibbpfObject;
use crate::Error;
use crate::Result;
use num_enum::IntoPrimitive;
use num_enum::TryFromPrimitive;

use self::types::Composite;

Expand Down Expand Up @@ -339,6 +341,15 @@ impl<'btf> Btf<'btf> {
}
}

impl AsLibbpfObject for Btf<'_> {
type LibbpfType = libbpf_sys::btf;

/// Retrieve the underlying [`libbpf_sys::btf`] object.
fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
self.ptr
}
}

impl Drop for Btf<'_> {
fn drop(&mut self) {
match self.drop_policy {
Expand Down
1 change: 1 addition & 0 deletions libbpf-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ pub use crate::map::MapHandle;
pub use crate::map::MapInfo;
pub use crate::map::MapType;
pub use crate::map::OpenMap;
pub use crate::object::AsLibbpfObject;
pub use crate::object::Object;
pub use crate::object::ObjectBuilder;
pub use crate::object::OpenObject;
Expand Down
10 changes: 10 additions & 0 deletions libbpf-rs/src/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::ptr::NonNull;

use crate::libbpf_sys;
use crate::util;
use crate::AsLibbpfObject;
use crate::Program;
use crate::Result;

Expand Down Expand Up @@ -105,6 +106,15 @@ impl Link {
}
}

impl AsLibbpfObject for Link {
type LibbpfType = libbpf_sys::bpf_link;

/// Retrieve the underlying [`libbpf_sys::bpf_link`].
fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
self.ptr
}
}

// SAFETY: `bpf_link` objects can safely be sent to a different thread.
unsafe impl Send for Link {}

Expand Down
12 changes: 11 additions & 1 deletion libbpf-rs/src/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ use std::path::Path;
use std::ptr::null_mut;
use std::ptr::NonNull;

use crate::util;
use crate::util::path_to_cstring;
use crate::util::{self};
use crate::AsLibbpfObject;
use crate::Error;
use crate::Result;

Expand Down Expand Up @@ -62,6 +63,15 @@ impl Linker {
}
}

impl AsLibbpfObject for Linker {
type LibbpfType = libbpf_sys::bpf_linker;

/// Retrieve the underlying [`libbpf_sys::bpf_linker`].
fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
self.linker
}
}

// SAFETY: `bpf_linker` can be sent to a different thread.
unsafe impl Send for Linker {}

Expand Down
16 changes: 15 additions & 1 deletion libbpf-rs/src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use strum_macros::Display;

use crate::util;
use crate::util::parse_ret_i32;
use crate::AsLibbpfObject;
use crate::Error;
use crate::Link;
use crate::Result;
Expand Down Expand Up @@ -170,6 +171,15 @@ impl OpenMap {
}
}

impl AsLibbpfObject for OpenMap {
type LibbpfType = libbpf_sys::bpf_map;

/// Retrieve the underlying [`libbpf_sys::bpf_map`].
fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
self.ptr
}
}

#[derive(Debug)]
enum MapFd {
Owned(OwnedFd),
Expand Down Expand Up @@ -302,9 +312,13 @@ impl Map {
Link::new(ptr)
})
}
}

impl AsLibbpfObject for Map {
type LibbpfType = libbpf_sys::bpf_map;

/// Retrieve the underlying [`libbpf_sys::bpf_map`].
pub fn as_libbpf_bpf_map_ptr(&self) -> NonNull<libbpf_sys::bpf_map> {
fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
self.ptr
}
}
Expand Down
28 changes: 26 additions & 2 deletions libbpf-rs/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use std::ffi::CStr;
use std::ffi::CString;
use std::mem;
use std::path::Path;
use std::ptr;
use std::ptr::NonNull;
use std::ptr::{self};

use crate::libbpf_sys;
use crate::set_print;
Expand All @@ -19,6 +19,26 @@ use crate::PrintLevel;
use crate::Program;
use crate::Result;

/// A trait implemented for types that are thin wrappers around `libbpf` types.
///
/// The trait provides access to the underlying `libbpf` (or `libbpf-sys`)
/// object. In many cases, this enables direct usage of `libbpf-sys`
/// functionality when higher-level bindings are not yet provided by this crate.
pub trait AsLibbpfObject {
/// The underlying `libbpf` type.
type LibbpfType;

/// Retrieve the underlying `libbpf` object.
///
/// # Warning
/// By virtue of working with a mutable raw pointer this method effectively
/// circumvents mutability and liveness checks. While by-design, usage is
/// meant as an escape-hatch more than anything else. If you find yourself
/// making use of it, please consider discussing your workflow with crate
/// maintainers to see if it would make sense to provide safer wrappers.
fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType>;
}

/// Builder for creating an [`OpenObject`]. Typically the entry point into libbpf-rs.
#[derive(Debug)]
pub struct ObjectBuilder {
Expand Down Expand Up @@ -430,9 +450,13 @@ impl Object {
pub fn progs_iter_mut(&mut self) -> impl Iterator<Item = &mut Program> {
self.progs.values_mut()
}
}

impl AsLibbpfObject for Object {
type LibbpfType = libbpf_sys::bpf_object;

/// Retrieve the underlying [`libbpf_sys::bpf_object`].
pub fn as_libbpf_bpf_object_ptr(&self) -> NonNull<libbpf_sys::bpf_object> {
fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
self.ptr
}
}
Expand Down
7 changes: 6 additions & 1 deletion libbpf-rs/src/perf_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use std::time::Duration;

use crate::libbpf_sys;
use crate::util;
use crate::AsLibbpfObject;
use crate::Error;
use crate::Map;
use crate::MapType;
Expand Down Expand Up @@ -227,9 +228,13 @@ impl PerfBuffer<'_> {
};
util::parse_ret_i32(ret)
}
}

impl AsLibbpfObject for PerfBuffer<'_> {
type LibbpfType = libbpf_sys::perf_buffer;

/// Retrieve the underlying [`libbpf_sys::perf_buffer`].
pub fn as_libbpf_perf_buffer_ptr(&self) -> NonNull<libbpf_sys::perf_buffer> {
fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
self.ptr
}
}
Expand Down
2 changes: 1 addition & 1 deletion libbpf-rs/src/print.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::libbpf_sys;
use lazy_static::lazy_static;
use std::io;
use std::io::Write;
use std::io::{self};
use std::os::raw::c_char;
use std::sync::Mutex;

Expand Down
10 changes: 10 additions & 0 deletions libbpf-rs/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use strum_macros::Display;

use crate::libbpf_sys;
use crate::util;
use crate::AsLibbpfObject;
use crate::Error;
use crate::Link;
use crate::Result;
Expand Down Expand Up @@ -231,6 +232,15 @@ impl OpenProgram {
}
}

impl AsLibbpfObject for Program {
type LibbpfType = libbpf_sys::bpf_program;

/// Retrieve the underlying [`libbpf_sys::bpf_program`].
fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
self.ptr
}
}

/// Type of a [`Program`]. Maps to `enum bpf_prog_type` in kernel uapi.
#[non_exhaustive]
#[repr(u32)]
Expand Down
10 changes: 10 additions & 0 deletions libbpf-rs/src/ringbuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use std::time::Duration;

use crate::libbpf_sys;
use crate::util;
use crate::AsLibbpfObject;
use crate::Error;
use crate::MapHandle;
use crate::MapType;
Expand Down Expand Up @@ -182,6 +183,15 @@ impl RingBuffer<'_> {
}
}

impl AsLibbpfObject for RingBuffer<'_> {
type LibbpfType = libbpf_sys::ring_buffer;

/// Retrieve the underlying [`libbpf_sys::ring_buffer`].
fn as_libbpf_object(&self) -> NonNull<Self::LibbpfType> {
self.ptr
}
}

// SAFETY: `ring_buffer` objects can safely be polled from any thread.
unsafe impl Send for RingBuffer<'_> {}

Expand Down
2 changes: 1 addition & 1 deletion libbpf-rs/src/skeleton.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use std::ffi::CString;
use std::mem::size_of;
use std::os::raw::c_char;
use std::os::raw::c_ulong;
use std::ptr;
use std::ptr::NonNull;
use std::ptr::{self};

use libbpf_sys::bpf_link;
use libbpf_sys::bpf_map;
Expand Down
3 changes: 2 additions & 1 deletion libbpf-rs/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use std::ptr;
use tempfile::NamedTempFile;

use libbpf_rs::num_possible_cpus;
use libbpf_rs::AsLibbpfObject;
use libbpf_rs::Iter;
use libbpf_rs::Linker;
use libbpf_rs::Map;
Expand Down Expand Up @@ -1430,7 +1431,7 @@ fn test_object_link_files() {

/// Get access to the underlying per-cpu ring buffer data.
fn buffer<'a>(perf: &'a libbpf_rs::PerfBuffer, buf_idx: usize) -> &'a [u8] {
let perf_buff_ptr = perf.as_libbpf_perf_buffer_ptr();
let perf_buff_ptr = perf.as_libbpf_object();
let mut buffer_data_ptr: *mut c_void = ptr::null_mut();
let mut buffer_size: usize = 0;
let ret = unsafe {
Expand Down

0 comments on commit 40e8001

Please sign in to comment.