Skip to content

Commit bc159f9

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 bc159f9

File tree

3 files changed

+68
-1
lines changed

3 files changed

+68
-1
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: 13 additions & 1 deletion
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;
@@ -283,6 +285,7 @@ pub type OpenProgram<'obj> = OpenProgramImpl<'obj>;
283285
/// A mutable parsed but not yet loaded BPF program.
284286
pub type OpenProgramMut<'obj> = OpenProgramImpl<'obj, Mut>;
285287

288+
286289
/// Represents a parsed but not yet loaded BPF program.
287290
///
288291
/// This object exposes operations that need to happen before the program is loaded.
@@ -760,7 +763,6 @@ pub type Program<'obj> = ProgramImpl<'obj>;
760763
/// A mutable loaded BPF program.
761764
pub type ProgramMut<'obj> = ProgramImpl<'obj, Mut>;
762765

763-
764766
/// Represents a loaded [`Program`].
765767
///
766768
/// This struct is not safe to clone because the underlying libbpf resource cannot currently
@@ -1656,6 +1658,16 @@ impl<'obj> ProgramMut<'obj> {
16561658
};
16571659
Ok(output)
16581660
}
1661+
1662+
/// Get the stdout BPF stream of the program.
1663+
pub fn stdout(&self) -> impl Read + '_ {
1664+
Stream::new(self.as_fd(), Stream::BPF_STDOUT)
1665+
}
1666+
1667+
/// Get the stderr BPF stream of the program.
1668+
pub fn stderr(&self) -> impl Read + '_ {
1669+
Stream::new(self.as_fd(), Stream::BPF_STDERR)
1670+
}
16591671
}
16601672

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

libbpf-rs/src/streams.rs

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

0 commit comments

Comments
 (0)