Skip to content

Commit 45fc1ad

Browse files
committed
Introduce BPF Streams abstraction
Add an abstraction for reading BPF Streams. This commit introduces the wrappers around the libbpf-sys method. Signed-off-by: Emil Tsalapatis <[email protected]>
1 parent e0caff4 commit 45fc1ad

File tree

3 files changed

+65
-5
lines changed

3 files changed

+65
-5
lines changed

libbpf-rs/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ mod program;
8080
pub mod query;
8181
mod ringbuf;
8282
mod skeleton;
83+
mod streams;
8384
mod tc;
8485
mod tracepoint;
8586
mod user_ringbuf;

libbpf-rs/src/program.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::ffi::c_void;
66
use std::ffi::CStr;
77
use std::ffi::CString;
88
use std::ffi::OsStr;
9+
use std::io::Read;
910
use std::marker::PhantomData;
1011
use std::mem;
1112
use std::mem::size_of;
@@ -27,6 +28,7 @@ use std::time::Duration;
2728
use libbpf_sys::bpf_func_id;
2829

2930
use crate::netfilter;
31+
use crate::streams::Stream;
3032
use crate::util;
3133
use crate::util::validate_bpf_ret;
3234
use crate::util::BpfObjectType;
@@ -178,7 +180,6 @@ impl From<PerfEventOpts> for libbpf_sys::bpf_perf_event_opts {
178180
}
179181
}
180182

181-
182183
/// Options used when iterating over a map.
183184
#[derive(Clone, Debug)]
184185
pub struct MapIterOpts<'fd> {
@@ -198,7 +199,6 @@ impl<'fd> MapIterOpts<'fd> {
198199
}
199200
}
200201

201-
202202
/// Iteration order for cgroups.
203203
#[non_exhaustive]
204204
#[repr(u32)]
@@ -239,7 +239,6 @@ impl<'fd> CgroupIterOpts<'fd> {
239239
}
240240
}
241241

242-
243242
/// Options to optionally be provided when attaching to an iterator.
244243
#[non_exhaustive]
245244
#[derive(Clone, Debug)]
@@ -277,7 +276,6 @@ impl From<IterOpts<'_>> for libbpf_sys::bpf_iter_link_info {
277276
}
278277
}
279278

280-
281279
/// An immutable parsed but not yet loaded BPF program.
282280
pub type OpenProgram<'obj> = OpenProgramImpl<'obj>;
283281
/// A mutable parsed but not yet loaded BPF program.
@@ -760,7 +758,6 @@ pub type Program<'obj> = ProgramImpl<'obj>;
760758
/// A mutable loaded BPF program.
761759
pub type ProgramMut<'obj> = ProgramImpl<'obj, Mut>;
762760

763-
764761
/// Represents a loaded [`Program`].
765762
///
766763
/// This struct is not safe to clone because the underlying libbpf resource cannot currently
@@ -1656,6 +1653,16 @@ impl<'obj> ProgramMut<'obj> {
16561653
};
16571654
Ok(output)
16581655
}
1656+
1657+
/// Get the stdout BPF stream of the program.
1658+
pub fn stdout(&self) -> impl Read + '_ {
1659+
Stream::new(self.as_fd(), Stream::BPF_STDOUT)
1660+
}
1661+
1662+
/// Get the stderr BPF stream of the program.
1663+
pub fn stderr(&self) -> impl Read + '_ {
1664+
Stream::new(self.as_fd(), Stream::BPF_STDERR)
1665+
}
16591666
}
16601667

16611668
impl<'obj> Deref for ProgramMut<'obj> {

libbpf-rs/src/streams.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use core::ffi::{c_ulong, c_void};
2+
use std::io;
3+
use std::io::Read;
4+
use std::mem;
5+
use std::os::fd::{self, AsRawFd};
6+
7+
use crate::libbpf_sys::bpf_prog_stream_read_opts;
8+
9+
/// [`Stream`] instances.
10+
///
11+
/// `streams`s are BPF descriptors that provide a character output
12+
/// interface from the BPF program to userspace.
13+
#[derive(Debug)]
14+
pub(crate) struct Stream<'a> {
15+
prog_fd: fd::BorrowedFd<'a>,
16+
stream_id: u32,
17+
}
18+
19+
impl<'a> Stream<'a> {
20+
/// Default BPF stdout stream id.
21+
pub(crate) const BPF_STDOUT: u32 = 1;
22+
/// Default BPF stderr stream id.
23+
pub(crate) const BPF_STDERR: u32 = 2;
24+
25+
/// Create a new Stream instance.
26+
pub(crate) fn new(prog_fd: fd::BorrowedFd<'a>, stream_id: u32) -> Stream<'a> {
27+
Stream { prog_fd, stream_id }
28+
}
29+
}
30+
31+
impl Read for Stream<'_> {
32+
/// Fill in a caller-provided buffer with contents from the stream.
33+
fn read(&mut self, buf: &mut [u8]) -> std::result::Result<usize, std::io::Error> {
34+
let ret = unsafe {
35+
let mut c_opts = bpf_prog_stream_read_opts {
36+
sz: mem::size_of::<bpf_prog_stream_read_opts>() as c_ulong,
37+
};
38+
libbpf_sys::bpf_prog_stream_read(
39+
self.prog_fd.as_raw_fd(),
40+
self.stream_id,
41+
buf.as_mut_ptr() as *mut c_void,
42+
buf.len().try_into().unwrap(),
43+
&mut c_opts as *mut bpf_prog_stream_read_opts,
44+
)
45+
};
46+
if ret < 0 {
47+
return Err(io::Error::last_os_error());
48+
}
49+
50+
Ok(ret as usize)
51+
}
52+
}

0 commit comments

Comments
 (0)