use crate::error::BccError;
use crate::ring_buf::callback::RingCallback;
use crate::table::Table;
pub struct RingBufBuilder {
table_cb_pairs: Vec<(Table, RingCallback)>,
}
impl RingBufBuilder {
pub fn new(table: Table, rcb: RingCallback) -> Self {
Self {
table_cb_pairs: vec![(table, rcb)],
}
}
pub fn add(mut self, table: Table, rcb: RingCallback) -> Self {
self.table_cb_pairs.push((table, rcb));
self
}
#[cfg(any(
feature = "v0_4_0",
feature = "v0_5_0",
feature = "v0_6_0",
feature = "v0_6_1",
feature = "v0_7_0",
feature = "v0_8_0",
feature = "v0_9_0",
feature = "v0_10_0",
feature = "v0_11_0",
feature = "v0_12_0",
feature = "v0_13_0",
feature = "v0_14_0",
feature = "v0_15_0",
))]
pub fn build(self) -> Result<RingBuf, BccError> {
Err(BccError::BccVersionTooLow {
cause: "ring buffer".to_owned(),
min_version: "0.16.0".to_owned(),
})
}
#[cfg(not(any(
feature = "v0_4_0",
feature = "v0_5_0",
feature = "v0_6_0",
feature = "v0_6_1",
feature = "v0_7_0",
feature = "v0_8_0",
feature = "v0_9_0",
feature = "v0_10_0",
feature = "v0_11_0",
feature = "v0_12_0",
feature = "v0_13_0",
feature = "v0_14_0",
feature = "v0_15_0",
)))]
pub fn build(mut self) -> Result<RingBuf, BccError> {
let ring_buf_manager = self
.table_cb_pairs
.get_mut(0)
.ok_or(BccError::InitializeRingBuf)
.and_then(|(table, rcb)| {
let prcb: *mut _ = rcb;
let rbm = unsafe {
bcc_sys::bccapi::bpf_new_ringbuf(
table.fd(),
Some(super::callback::raw_callback),
prcb as crate::types::MutPointer,
)
} as *mut bcc_sys::bccapi::ring_buffer;
if rbm.is_null() {
Err(BccError::OpenRingBuf {
message: format!("failed to open ring buffer ({})", table.name()),
})
} else {
Ok(rbm)
}
})?;
self.table_cb_pairs
.iter_mut()
.skip(1)
.try_for_each(|(table, rcb)| {
let prcb: *mut _ = rcb;
let add_res = unsafe {
bcc_sys::bccapi::bpf_add_ringbuf(
ring_buf_manager,
table.fd(),
Some(super::callback::raw_callback),
prcb as crate::types::MutPointer,
)
};
if add_res < 0 {
Err(BccError::OpenRingBuf {
message: format!("failed to open ring buffer ({})", table.name()),
})
} else {
Ok(())
}
})?;
Ok(RingBuf {
table_cb_pairs: self.table_cb_pairs,
ring_buf_manager,
})
}
}
pub struct RingBuf {
#[allow(dead_code)]
table_cb_pairs: Vec<(Table, RingCallback)>,
#[cfg(not(any(
feature = "v0_4_0",
feature = "v0_5_0",
feature = "v0_6_0",
feature = "v0_6_1",
feature = "v0_7_0",
feature = "v0_8_0",
feature = "v0_9_0",
feature = "v0_10_0",
feature = "v0_11_0",
feature = "v0_12_0",
feature = "v0_13_0",
feature = "v0_14_0",
feature = "v0_15_0",
)))]
ring_buf_manager: *mut bcc_sys::bccapi::ring_buffer,
}
impl RingBuf {
pub fn consume(&mut self) {
#[cfg(not(any(
feature = "v0_4_0",
feature = "v0_5_0",
feature = "v0_6_0",
feature = "v0_6_1",
feature = "v0_7_0",
feature = "v0_8_0",
feature = "v0_9_0",
feature = "v0_10_0",
feature = "v0_11_0",
feature = "v0_12_0",
feature = "v0_13_0",
feature = "v0_14_0",
feature = "v0_15_0",
)))]
unsafe {
bcc_sys::bccapi::bpf_consume_ringbuf(self.ring_buf_manager)
};
}
pub fn poll(&mut self, timeout_ms: i32) {
#[cfg(not(any(
feature = "v0_4_0",
feature = "v0_5_0",
feature = "v0_6_0",
feature = "v0_6_1",
feature = "v0_7_0",
feature = "v0_8_0",
feature = "v0_9_0",
feature = "v0_10_0",
feature = "v0_11_0",
feature = "v0_12_0",
feature = "v0_13_0",
feature = "v0_14_0",
feature = "v0_15_0",
)))]
unsafe {
bcc_sys::bccapi::bpf_poll_ringbuf(self.ring_buf_manager, timeout_ms)
};
}
}
impl Drop for RingBuf {
fn drop(&mut self) {
#[cfg(not(any(
feature = "v0_4_0",
feature = "v0_5_0",
feature = "v0_6_0",
feature = "v0_6_1",
feature = "v0_7_0",
feature = "v0_8_0",
feature = "v0_9_0",
feature = "v0_10_0",
feature = "v0_11_0",
feature = "v0_12_0",
feature = "v0_13_0",
feature = "v0_14_0",
feature = "v0_15_0",
)))]
unsafe {
bcc_sys::bccapi::bpf_free_ringbuf(self.ring_buf_manager)
}
}
}