lpm_trie.rs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. use core::{cell::UnsafeCell, marker::PhantomData, mem, ptr::NonNull};
  2. use aya_bpf_cty::{c_long, c_void};
  3. use crate::{
  4. bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_LPM_TRIE},
  5. helpers::{bpf_map_delete_elem, bpf_map_lookup_elem, bpf_map_update_elem},
  6. maps::PinningType,
  7. };
  8. #[repr(transparent)]
  9. pub struct LpmTrie<K, V> {
  10. def: UnsafeCell<bpf_map_def>,
  11. _k: PhantomData<K>,
  12. _v: PhantomData<V>,
  13. }
  14. unsafe impl<K: Sync, V: Sync> Sync for LpmTrie<K, V> {}
  15. #[repr(packed)]
  16. pub struct Key<K> {
  17. /// Represents the number of bytes matched against.
  18. pub prefix_len: u32,
  19. /// Represents arbitrary data stored in the LpmTrie.
  20. pub data: K,
  21. }
  22. impl<K> Key<K> {
  23. pub fn new(prefix_len: u32, data: K) -> Self {
  24. Self { prefix_len, data }
  25. }
  26. }
  27. impl<K, V> LpmTrie<K, V> {
  28. pub const fn with_max_entries(max_entries: u32, flags: u32) -> LpmTrie<K, V> {
  29. LpmTrie {
  30. def: UnsafeCell::new(build_def::<K, V>(
  31. BPF_MAP_TYPE_LPM_TRIE,
  32. max_entries,
  33. flags,
  34. PinningType::None,
  35. )),
  36. _k: PhantomData,
  37. _v: PhantomData,
  38. }
  39. }
  40. pub const fn pinned(max_entries: u32, flags: u32) -> LpmTrie<K, V> {
  41. LpmTrie {
  42. def: UnsafeCell::new(build_def::<K, V>(
  43. BPF_MAP_TYPE_LPM_TRIE,
  44. max_entries,
  45. flags,
  46. PinningType::ByName,
  47. )),
  48. _k: PhantomData,
  49. _v: PhantomData,
  50. }
  51. }
  52. #[inline]
  53. pub fn get(&self, key: &Key<K>) -> Option<&V> {
  54. unsafe {
  55. let value =
  56. bpf_map_lookup_elem(self.def.get() as *mut _, key as *const _ as *const c_void);
  57. // FIXME: alignment
  58. NonNull::new(value as *mut V).map(|p| p.as_ref())
  59. }
  60. }
  61. #[inline]
  62. pub fn insert(&self, key: &Key<K>, value: &V, flags: u64) -> Result<(), c_long> {
  63. let ret = unsafe {
  64. bpf_map_update_elem(
  65. self.def.get() as *mut _,
  66. key as *const _ as *const _,
  67. value as *const _ as *const _,
  68. flags,
  69. )
  70. };
  71. (ret == 0).then_some(()).ok_or(ret)
  72. }
  73. #[inline]
  74. pub fn remove(&self, key: &Key<K>) -> Result<(), c_long> {
  75. let ret = unsafe {
  76. bpf_map_delete_elem(self.def.get() as *mut _, key as *const _ as *const c_void)
  77. };
  78. (ret == 0).then_some(()).ok_or(ret)
  79. }
  80. }
  81. const fn build_def<K, V>(ty: u32, max_entries: u32, flags: u32, pin: PinningType) -> bpf_map_def {
  82. bpf_map_def {
  83. type_: ty,
  84. key_size: mem::size_of::<Key<K>>() as u32,
  85. value_size: mem::size_of::<V>() as u32,
  86. max_entries,
  87. map_flags: flags,
  88. id: 0,
  89. pinning: pin as u32,
  90. }
  91. }