@@ -12,7 +12,7 @@ use aya_ebpf::{
1212 bpf_probe_read_user_buf, bpf_probe_read_user_str_bytes,
1313 } ,
1414 macros:: { map, tracepoint} ,
15- maps:: { HashMap , RingBuf } ,
15+ maps:: { ring_buf :: RingBufEntry , HashMap , PerCpuArray , RingBuf } ,
1616 programs:: TracePointContext ,
1717} ;
1818
@@ -34,6 +34,10 @@ static FILE_EVENTS: RingBuf = RingBuf::with_byte_size(256 * 1024, 0);
3434#[ map]
3535static LLM_EVENTS : RingBuf = RingBuf :: with_byte_size ( 64 * 1024 , 0 ) ;
3636
37+ // Count of events dropped because a ring was full — data-loss visibility under extreme load.
38+ #[ map]
39+ static DROPS : PerCpuArray < u64 > = PerCpuArray :: with_max_entries ( 1 , 0 ) ;
40+
3741// Per-LLM-socket accumulator: (pid<<32|fd) -> running byte/time stats, started at the
3842// ClientHello and flushed on close. Only TLS-to-provider sockets are tracked → stays small.
3943#[ map]
@@ -57,6 +61,20 @@ fn sock_key(pid: u32, fd: u64) -> u64 {
5761 ( ( pid as u64 ) << 32 ) | ( fd & 0xffff_ffff )
5862}
5963
64+ /// Reserve a ring-buffer slot, counting a drop if the ring is full (so userspace can report
65+ /// data loss instead of losing events silently).
66+ fn reserve_or_drop < T > ( ring : & RingBuf ) -> Option < RingBufEntry < T > > {
67+ let entry = ring. reserve :: < T > ( 0 ) ;
68+ if entry. is_none ( ) {
69+ unsafe {
70+ if let Some ( c) = DROPS . get_ptr_mut ( 0 ) {
71+ * c = ( * c) . wrapping_add ( 1 ) ;
72+ }
73+ }
74+ }
75+ entry
76+ }
77+
6078/// Read a `u64` (e.g. a pointer or length) from a user-space address.
6179fn read_user_u64 ( addr : * const u8 ) -> Option < u64 > {
6280 let mut b = [ 0u8 ; 8 ] ;
@@ -75,7 +93,7 @@ pub fn exec(ctx: TracePointContext) -> u32 {
7593}
7694
7795fn try_exec ( ctx : & TracePointContext ) -> Result < u32 , i64 > {
78- let Some ( mut entry) = EVENTS . reserve :: < ExecEvent > ( 0 ) else {
96+ let Some ( mut entry) = reserve_or_drop :: < ExecEvent > ( & EVENTS ) else {
7997 return Ok ( 0 ) ;
8098 } ;
8199 let ev = entry. as_mut_ptr ( ) ;
@@ -146,7 +164,7 @@ fn try_tls(ctx: &TracePointContext) -> Result<u32, i64> {
146164 } ,
147165 0 ,
148166 ) ;
149- let Some ( mut entry) = TLS_EVENTS . reserve :: < TlsEvent > ( 0 ) else {
167+ let Some ( mut entry) = reserve_or_drop :: < TlsEvent > ( & TLS_EVENTS ) else {
150168 return Ok ( 0 ) ;
151169 } ;
152170 let ev = entry. as_mut_ptr ( ) ;
@@ -196,7 +214,7 @@ fn try_connect(ctx: &TracePointContext) -> Result<u32, i64> {
196214 if family != 2 && family != 10 {
197215 return Ok ( 0 ) ; // only AF_INET / AF_INET6
198216 }
199- let Some ( mut entry) = CONNECT_EVENTS . reserve :: < ConnectEvent > ( 0 ) else {
217+ let Some ( mut entry) = reserve_or_drop :: < ConnectEvent > ( & CONNECT_EVENTS ) else {
200218 return Ok ( 0 ) ;
201219 } ;
202220 let ev = entry. as_mut_ptr ( ) ;
@@ -249,7 +267,7 @@ fn try_dns(ctx: &TracePointContext) -> Result<u32, i64> {
249267 if count < 13 {
250268 return Ok ( 0 ) ; // DNS header(12) + >=1 question byte
251269 }
252- let Some ( mut entry) = DNS_EVENTS . reserve :: < DnsEvent > ( 0 ) else {
270+ let Some ( mut entry) = reserve_or_drop :: < DnsEvent > ( & DNS_EVENTS ) else {
253271 return Ok ( 0 ) ;
254272 } ;
255273 let ev = entry. as_mut_ptr ( ) ;
@@ -325,7 +343,7 @@ fn try_dns_msghdr(ctx: &TracePointContext) -> Result<u32, i64> {
325343 if iov_base == 0 || iov_len < 13 {
326344 return Ok ( 0 ) ;
327345 }
328- let Some ( mut entry) = DNS_EVENTS . reserve :: < DnsEvent > ( 0 ) else {
346+ let Some ( mut entry) = reserve_or_drop :: < DnsEvent > ( & DNS_EVENTS ) else {
329347 return Ok ( 0 ) ;
330348 } ;
331349 let ev = entry. as_mut_ptr ( ) ;
@@ -366,7 +384,7 @@ fn try_open(ctx: &TracePointContext) -> Result<u32, i64> {
366384 return Ok ( 0 ) ; // O_RDONLY — skip; keep only O_WRONLY / O_RDWR
367385 }
368386 let filename: * const u8 = unsafe { ctx. read_at ( 24 ) ? } ;
369- let Some ( mut entry) = FILE_EVENTS . reserve :: < FileEvent > ( 0 ) else {
387+ let Some ( mut entry) = reserve_or_drop :: < FileEvent > ( & FILE_EVENTS ) else {
370388 return Ok ( 0 ) ;
371389 } ;
372390 let ev = entry. as_mut_ptr ( ) ;
@@ -455,7 +473,7 @@ pub fn sock_close(ctx: TracePointContext) -> u32 {
455473 return 0 ; // not an LLM socket
456474 } ;
457475 let _ = LLM_SOCKS . remove ( & key) ;
458- if let Some ( mut entry) = LLM_EVENTS . reserve :: < LlmEvent > ( 0 ) {
476+ if let Some ( mut entry) = reserve_or_drop :: < LlmEvent > ( & LLM_EVENTS ) {
459477 let now = unsafe { bpf_ktime_get_ns ( ) } ;
460478 let ev = entry. as_mut_ptr ( ) ;
461479 unsafe {
0 commit comments