Skip to content

Commit dbab0e6

Browse files
committed
rex: add support for PERF_EVENT_ARRAY
Signed-off-by: MinhPhan8803 <[email protected]>
1 parent e8c9f47 commit dbab0e6

File tree

4 files changed

+113
-4
lines changed

4 files changed

+113
-4
lines changed

rex/librexstub/lib.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ KSYM_FUNC(bpf_spin_unlock)
2222
KSYM_FUNC(just_return_func)
2323
KSYM_FUNC(bpf_get_stackid_pe)
2424
KSYM_FUNC(bpf_perf_prog_read_value)
25+
KSYM_FUNC(bpf_perf_event_output_tp)
26+
KSYM_FUNC(bpf_perf_event_read_value)
27+
KSYM_FUNC(bpf_skb_event_output)
28+
KSYM_FUNC(bpf_xdp_event_output)
2529
KSYM_FUNC(bpf_xdp_adjust_head)
2630
KSYM_FUNC(bpf_xdp_adjust_tail)
2731
KSYM_FUNC(bpf_clone_redirect)

rex/src/ffi.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,53 @@ unsafe extern "C" {
132132
size: u32,
133133
) -> i64;
134134

135+
/// `long bpf_perf_event_output_tp(void *tp_buff, struct bpf_map *map, u64
136+
/// flags, void *data, u64 size)`
137+
pub(crate) fn bpf_perf_event_output_tp(
138+
tp_buff: *const (),
139+
map: *mut (),
140+
flags: u64,
141+
data: *const (),
142+
size: u64,
143+
) -> i64;
144+
145+
/// `long bpf_perf_event_read_value(struct bpf_map *map, u64 flags,
146+
/// struct bpf_perf_event_value *buf, u32 buf_size)`
147+
/// same reason for use of improper_ctypes as bpf_perf_prog_read_value
148+
#[allow(improper_ctypes)]
149+
pub(crate) fn bpf_perf_event_read_value(
150+
map: *mut (),
151+
flags: u64,
152+
buf: &mut bpf_perf_event_value,
153+
buf_size: u32,
154+
) -> i64;
155+
156+
/// `long bpf_skb_event_output(struct sk_buff *skb, struct bpf_map *map, u64 flags,
157+
/// void *meta, u64 meta_size)`
158+
/// The compiler complains about some non-FFI safe type, but since the
159+
/// kernel is using it fine it should be safe for an FFI call using C ABI
160+
#[allow(improper_ctypes)]
161+
pub(crate) fn bpf_skb_event_output(
162+
skb: *const sk_buff,
163+
map: *mut (),
164+
flags: u64,
165+
meta: *const (),
166+
meta_size: u64,
167+
) -> i64;
168+
169+
/// `long bpf_xdp_event_output(struct xdp_buff *xdp, struct bpf_map *map, u64 flags,
170+
/// void *meta, u64 meta_size)`
171+
/// The compiler complains about some non-FFI safe type, but since the
172+
/// kernel is using it fine it should be safe for an FFI call using C ABI
173+
#[allow(improper_ctypes)]
174+
pub(crate) fn bpf_xdp_event_output(
175+
xdp: *const xdp_buff,
176+
map: *mut (),
177+
flags: u64,
178+
meta: *const (),
179+
meta_size: u64,
180+
) -> i64;
181+
135182
/// `long bpf_xdp_adjust_head(struct xdp_buff *xdp, int offset)`
136183
///
137184
/// The compiler complains about some non-FFI safe type, but since the

rex/src/map.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,15 @@ use crate::base_helper::{
1111
use crate::ffi;
1212
use crate::linux::bpf::{
1313
bpf_map_type, BPF_ANY, BPF_EXIST, BPF_MAP_TYPE_ARRAY, BPF_MAP_TYPE_HASH,
14-
BPF_MAP_TYPE_PERCPU_ARRAY, BPF_MAP_TYPE_QUEUE, BPF_MAP_TYPE_RINGBUF,
15-
BPF_MAP_TYPE_STACK, BPF_MAP_TYPE_STACK_TRACE, BPF_NOEXIST,
16-
BPF_RB_AVAIL_DATA, BPF_RB_CONS_POS, BPF_RB_PROD_POS, BPF_RB_RING_SIZE,
14+
BPF_MAP_TYPE_PERCPU_ARRAY, BPF_MAP_TYPE_PERF_EVENT_ARRAY,
15+
BPF_MAP_TYPE_QUEUE, BPF_MAP_TYPE_RINGBUF, BPF_MAP_TYPE_STACK,
16+
BPF_MAP_TYPE_STACK_TRACE, BPF_NOEXIST, BPF_RB_AVAIL_DATA, BPF_RB_CONS_POS,
17+
BPF_RB_PROD_POS, BPF_RB_RING_SIZE,
1718
};
1819
use crate::linux::errno::EINVAL;
19-
use crate::utils::{to_result, NoRef, Result};
20+
use crate::utils::{
21+
to_result, NoRef, PerfEventMaskedCPU, PerfEventStreamer, Result,
22+
};
2023

2124
/// Rex equivalent to be used for map APIs in place of the `struct bpf_map`.
2225
/// The key and the value type are encoded as generics types `K` and `V`.
@@ -66,6 +69,8 @@ unsafe impl<const MT: bpf_map_type, K, V> Sync for RexMapHandle<MT, K, V> where
6669

6770
pub type RexStackTrace<K, V> = RexMapHandle<BPF_MAP_TYPE_STACK_TRACE, K, V>;
6871
pub type RexPerCPUArrayMap<V> = RexMapHandle<BPF_MAP_TYPE_PERCPU_ARRAY, u32, V>;
72+
pub type RexPerfEventArray<V> =
73+
RexMapHandle<BPF_MAP_TYPE_PERF_EVENT_ARRAY, u32, V>;
6974
pub type RexArrayMap<V> = RexMapHandle<BPF_MAP_TYPE_ARRAY, u32, V>;
7075
pub type RexHashMap<K, V> = RexMapHandle<BPF_MAP_TYPE_HASH, K, V>;
7176
pub type RexStack<V> = RexMapHandle<BPF_MAP_TYPE_STACK, (), V>;
@@ -114,6 +119,21 @@ where
114119
}
115120
}
116121

122+
impl<V> RexPerfEventArray<V>
123+
where
124+
V: Copy + NoRef,
125+
{
126+
pub fn output<P: PerfEventStreamer>(
127+
&'static self,
128+
program: &P,
129+
ctx: &P::Context,
130+
data: &V,
131+
cpu: PerfEventMaskedCPU,
132+
) -> Result {
133+
program.output_event(ctx, self, data, cpu)
134+
}
135+
}
136+
117137
impl<V> RexStack<V>
118138
where
119139
V: Copy + NoRef,

rex/src/utils.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use crate::bindings::uapi::linux::bpf::{BPF_F_CURRENT_CPU, BPF_F_INDEX_MASK};
2+
use crate::map::RexPerfEventArray;
13
use core::ffi::{c_int, c_uchar};
24
use core::mem;
35
use core::ops::{Deref, DerefMut, Drop};
@@ -286,3 +288,39 @@ macro_rules! read_field {
286288
)
287289
}};
288290
}
291+
292+
// For implementers, see tp_impl.rs for how to implement
293+
// this trait
294+
/// Programs that can stream data through a
295+
/// RexPerfEventArray will implement this trait
296+
pub trait PerfEventStreamer {
297+
type Context;
298+
fn output_event<T: Copy + NoRef>(
299+
&self,
300+
ctx: &Self::Context,
301+
map: &'static RexPerfEventArray<T>,
302+
data: &T,
303+
cpu: PerfEventMaskedCPU,
304+
) -> Result;
305+
}
306+
307+
/// Newtype for a cpu for perf event output to ensure
308+
/// type safety since the cpu must be masked with
309+
/// BPF_F_INDEX_MASK
310+
#[derive(Debug, Copy, Clone)]
311+
pub struct PerfEventMaskedCPU {
312+
pub(crate) masked_cpu: u64,
313+
}
314+
315+
impl PerfEventMaskedCPU {
316+
pub fn current_cpu() -> Self {
317+
PerfEventMaskedCPU {
318+
masked_cpu: BPF_F_CURRENT_CPU,
319+
}
320+
}
321+
pub fn any_cpu(cpu: u64) -> Self {
322+
PerfEventMaskedCPU {
323+
masked_cpu: cpu & BPF_F_INDEX_MASK,
324+
}
325+
}
326+
}

0 commit comments

Comments
 (0)