ring_buf.rs 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. #![no_std]
  2. #![no_main]
  3. use aya_ebpf::{
  4. macros::{map, uprobe},
  5. maps::{PerCpuArray, RingBuf},
  6. programs::ProbeContext,
  7. };
  8. use integration_common::ring_buf::Registers;
  9. #[map]
  10. static RING_BUF: RingBuf = RingBuf::with_byte_size(0, 0);
  11. // Use a PerCpuArray to store the registers so that we can update the values from multiple CPUs
  12. // without needing synchronization. Atomics exist [1], but aren't exposed.
  13. //
  14. // [1]: https://lwn.net/Articles/838884/
  15. #[map]
  16. static REGISTERS: PerCpuArray<Registers> = PerCpuArray::with_max_entries(1, 0);
  17. #[uprobe]
  18. pub fn ring_buf_test(ctx: ProbeContext) {
  19. let Registers { dropped, rejected } = match REGISTERS.get_ptr_mut(0) {
  20. Some(regs) => unsafe { &mut *regs },
  21. None => return,
  22. };
  23. let mut entry = match RING_BUF.reserve::<u64>(0) {
  24. Some(entry) => entry,
  25. None => {
  26. *dropped += 1;
  27. return;
  28. }
  29. };
  30. // Write the first argument to the function back out to RING_BUF if it is even,
  31. // otherwise increment the counter in REJECTED. This exercises discarding data.
  32. let arg: u64 = match ctx.arg(0) {
  33. Some(arg) => arg,
  34. None => return,
  35. };
  36. if arg % 2 == 0 {
  37. entry.write(arg);
  38. entry.submit(0);
  39. } else {
  40. *rejected += 1;
  41. entry.discard(0);
  42. }
  43. }
  44. #[cfg(not(test))]
  45. #[panic_handler]
  46. fn panic(_info: &core::panic::PanicInfo) -> ! {
  47. loop {}
  48. }