1*fae6e9adSlinfeng use super::{BpfCallBackFn, BpfMapCommonOps, Result}; 2*fae6e9adSlinfeng use crate::bpf::map::util::BpfMapMeta; 3*fae6e9adSlinfeng use crate::mm::percpu::{PerCpu, PerCpuVar}; 4*fae6e9adSlinfeng use crate::smp::cpu::ProcessorId; 5*fae6e9adSlinfeng use alloc::vec::Vec; 6*fae6e9adSlinfeng use core::fmt::Debug; 7*fae6e9adSlinfeng use core::num::NonZero; 8*fae6e9adSlinfeng use lru::LruCache; 9*fae6e9adSlinfeng use system_error::SystemError; 10*fae6e9adSlinfeng 11*fae6e9adSlinfeng type BpfHashMapKey = Vec<u8>; 12*fae6e9adSlinfeng type BpfHashMapValue = Vec<u8>; 13*fae6e9adSlinfeng /// This map is the LRU (Least Recently Used) variant of the BPF_MAP_TYPE_HASH. 14*fae6e9adSlinfeng /// It is a generic map type that stores a fixed maximum number of key/value pairs. 15*fae6e9adSlinfeng /// When the map starts to get at capacity, the approximately least recently 16*fae6e9adSlinfeng /// used elements is removed to make room for new elements. 17*fae6e9adSlinfeng /// 18*fae6e9adSlinfeng /// See https://docs.ebpf.io/linux/map-type/BPF_MAP_TYPE_LRU_HASH/ 19*fae6e9adSlinfeng #[derive(Debug)] 20*fae6e9adSlinfeng pub struct LruMap { 21*fae6e9adSlinfeng _max_entries: u32, 22*fae6e9adSlinfeng data: LruCache<BpfHashMapKey, BpfHashMapValue>, 23*fae6e9adSlinfeng } 24*fae6e9adSlinfeng 25*fae6e9adSlinfeng impl LruMap { new(attr: &BpfMapMeta) -> Result<Self>26*fae6e9adSlinfeng pub fn new(attr: &BpfMapMeta) -> Result<Self> { 27*fae6e9adSlinfeng if attr.value_size == 0 || attr.max_entries == 0 { 28*fae6e9adSlinfeng return Err(SystemError::EINVAL); 29*fae6e9adSlinfeng } 30*fae6e9adSlinfeng Ok(Self { 31*fae6e9adSlinfeng _max_entries: attr.max_entries, 32*fae6e9adSlinfeng data: LruCache::new( 33*fae6e9adSlinfeng NonZero::new(attr.max_entries as usize).ok_or(SystemError::EINVAL)?, 34*fae6e9adSlinfeng ), 35*fae6e9adSlinfeng }) 36*fae6e9adSlinfeng } 37*fae6e9adSlinfeng } 38*fae6e9adSlinfeng 39*fae6e9adSlinfeng impl BpfMapCommonOps for LruMap { lookup_elem(&mut self, key: &[u8]) -> Result<Option<&[u8]>>40*fae6e9adSlinfeng fn lookup_elem(&mut self, key: &[u8]) -> Result<Option<&[u8]>> { 41*fae6e9adSlinfeng let value = self.data.get(key).map(|v| v.as_slice()); 42*fae6e9adSlinfeng Ok(value) 43*fae6e9adSlinfeng } update_elem(&mut self, key: &[u8], value: &[u8], _flags: u64) -> Result<()>44*fae6e9adSlinfeng fn update_elem(&mut self, key: &[u8], value: &[u8], _flags: u64) -> Result<()> { 45*fae6e9adSlinfeng self.data.put(key.to_vec(), value.to_vec()); 46*fae6e9adSlinfeng Ok(()) 47*fae6e9adSlinfeng } delete_elem(&mut self, key: &[u8]) -> Result<()>48*fae6e9adSlinfeng fn delete_elem(&mut self, key: &[u8]) -> Result<()> { 49*fae6e9adSlinfeng self.data.pop(key); 50*fae6e9adSlinfeng Ok(()) 51*fae6e9adSlinfeng } for_each_elem(&mut self, cb: BpfCallBackFn, ctx: *const u8, flags: u64) -> Result<u32>52*fae6e9adSlinfeng fn for_each_elem(&mut self, cb: BpfCallBackFn, ctx: *const u8, flags: u64) -> Result<u32> { 53*fae6e9adSlinfeng if flags != 0 { 54*fae6e9adSlinfeng return Err(SystemError::EINVAL); 55*fae6e9adSlinfeng } 56*fae6e9adSlinfeng let mut total_used = 0; 57*fae6e9adSlinfeng for (key, value) in self.data.iter() { 58*fae6e9adSlinfeng let res = cb(key, value, ctx); 59*fae6e9adSlinfeng // return value: 0 - continue, 1 - stop and return 60*fae6e9adSlinfeng if res != 0 { 61*fae6e9adSlinfeng break; 62*fae6e9adSlinfeng } 63*fae6e9adSlinfeng total_used += 1; 64*fae6e9adSlinfeng } 65*fae6e9adSlinfeng Ok(total_used) 66*fae6e9adSlinfeng } lookup_and_delete_elem(&mut self, key: &[u8], value: &mut [u8]) -> Result<()>67*fae6e9adSlinfeng fn lookup_and_delete_elem(&mut self, key: &[u8], value: &mut [u8]) -> Result<()> { 68*fae6e9adSlinfeng let v = self 69*fae6e9adSlinfeng .data 70*fae6e9adSlinfeng .get(key) 71*fae6e9adSlinfeng .map(|v| v.as_slice()) 72*fae6e9adSlinfeng .ok_or(SystemError::ENOENT)?; 73*fae6e9adSlinfeng value.copy_from_slice(v); 74*fae6e9adSlinfeng self.data.pop(key); 75*fae6e9adSlinfeng Ok(()) 76*fae6e9adSlinfeng } get_next_key(&self, key: Option<&[u8]>, next_key: &mut [u8]) -> Result<()>77*fae6e9adSlinfeng fn get_next_key(&self, key: Option<&[u8]>, next_key: &mut [u8]) -> Result<()> { 78*fae6e9adSlinfeng let mut iter = self.data.iter(); 79*fae6e9adSlinfeng if let Some(key) = key { 80*fae6e9adSlinfeng for (k, _) in iter.by_ref() { 81*fae6e9adSlinfeng if k.as_slice() == key { 82*fae6e9adSlinfeng break; 83*fae6e9adSlinfeng } 84*fae6e9adSlinfeng } 85*fae6e9adSlinfeng } 86*fae6e9adSlinfeng let res = iter.next(); 87*fae6e9adSlinfeng match res { 88*fae6e9adSlinfeng Some((k, _)) => { 89*fae6e9adSlinfeng next_key.copy_from_slice(k.as_slice()); 90*fae6e9adSlinfeng Ok(()) 91*fae6e9adSlinfeng } 92*fae6e9adSlinfeng None => Err(SystemError::ENOENT), 93*fae6e9adSlinfeng } 94*fae6e9adSlinfeng } 95*fae6e9adSlinfeng } 96*fae6e9adSlinfeng 97*fae6e9adSlinfeng /// See https://ebpf-docs.dylanreimerink.nl/linux/map-type/BPF_MAP_TYPE_LRU_PERCPU_HASH/ 98*fae6e9adSlinfeng pub struct PerCpuLruMap { 99*fae6e9adSlinfeng per_cpu_maps: PerCpuVar<LruMap>, 100*fae6e9adSlinfeng } 101*fae6e9adSlinfeng 102*fae6e9adSlinfeng impl Debug for PerCpuLruMap { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result103*fae6e9adSlinfeng fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 104*fae6e9adSlinfeng f.debug_struct("PerCpuLruMap") 105*fae6e9adSlinfeng .field("maps", &self.per_cpu_maps) 106*fae6e9adSlinfeng .finish() 107*fae6e9adSlinfeng } 108*fae6e9adSlinfeng } 109*fae6e9adSlinfeng 110*fae6e9adSlinfeng impl PerCpuLruMap { new(attr: &BpfMapMeta) -> Result<Self>111*fae6e9adSlinfeng pub fn new(attr: &BpfMapMeta) -> Result<Self> { 112*fae6e9adSlinfeng let num_cpus = PerCpu::MAX_CPU_NUM; 113*fae6e9adSlinfeng let mut data = Vec::with_capacity(num_cpus as usize); 114*fae6e9adSlinfeng for _ in 0..num_cpus { 115*fae6e9adSlinfeng let array_map = LruMap::new(attr)?; 116*fae6e9adSlinfeng data.push(array_map); 117*fae6e9adSlinfeng } 118*fae6e9adSlinfeng let per_cpu_maps = PerCpuVar::new(data).ok_or(SystemError::EINVAL)?; 119*fae6e9adSlinfeng Ok(PerCpuLruMap { per_cpu_maps }) 120*fae6e9adSlinfeng } 121*fae6e9adSlinfeng } 122*fae6e9adSlinfeng 123*fae6e9adSlinfeng impl BpfMapCommonOps for PerCpuLruMap { lookup_elem(&mut self, key: &[u8]) -> Result<Option<&[u8]>>124*fae6e9adSlinfeng fn lookup_elem(&mut self, key: &[u8]) -> Result<Option<&[u8]>> { 125*fae6e9adSlinfeng self.per_cpu_maps.get_mut().lookup_elem(key) 126*fae6e9adSlinfeng } update_elem(&mut self, key: &[u8], value: &[u8], flags: u64) -> Result<()>127*fae6e9adSlinfeng fn update_elem(&mut self, key: &[u8], value: &[u8], flags: u64) -> Result<()> { 128*fae6e9adSlinfeng self.per_cpu_maps.get_mut().update_elem(key, value, flags) 129*fae6e9adSlinfeng } delete_elem(&mut self, key: &[u8]) -> Result<()>130*fae6e9adSlinfeng fn delete_elem(&mut self, key: &[u8]) -> Result<()> { 131*fae6e9adSlinfeng self.per_cpu_maps.get_mut().delete_elem(key) 132*fae6e9adSlinfeng } for_each_elem(&mut self, cb: BpfCallBackFn, ctx: *const u8, flags: u64) -> Result<u32>133*fae6e9adSlinfeng fn for_each_elem(&mut self, cb: BpfCallBackFn, ctx: *const u8, flags: u64) -> Result<u32> { 134*fae6e9adSlinfeng self.per_cpu_maps.get_mut().for_each_elem(cb, ctx, flags) 135*fae6e9adSlinfeng } lookup_and_delete_elem(&mut self, key: &[u8], value: &mut [u8]) -> Result<()>136*fae6e9adSlinfeng fn lookup_and_delete_elem(&mut self, key: &[u8], value: &mut [u8]) -> Result<()> { 137*fae6e9adSlinfeng self.per_cpu_maps 138*fae6e9adSlinfeng .get_mut() 139*fae6e9adSlinfeng .lookup_and_delete_elem(key, value) 140*fae6e9adSlinfeng } lookup_percpu_elem(&mut self, key: &[u8], cpu: u32) -> Result<Option<&[u8]>>141*fae6e9adSlinfeng fn lookup_percpu_elem(&mut self, key: &[u8], cpu: u32) -> Result<Option<&[u8]>> { 142*fae6e9adSlinfeng unsafe { 143*fae6e9adSlinfeng self.per_cpu_maps 144*fae6e9adSlinfeng .force_get_mut(ProcessorId::new(cpu)) 145*fae6e9adSlinfeng .lookup_elem(key) 146*fae6e9adSlinfeng } 147*fae6e9adSlinfeng } get_next_key(&self, key: Option<&[u8]>, next_key: &mut [u8]) -> Result<()>148*fae6e9adSlinfeng fn get_next_key(&self, key: Option<&[u8]>, next_key: &mut [u8]) -> Result<()> { 149*fae6e9adSlinfeng self.per_cpu_maps.get_mut().get_next_key(key, next_key) 150*fae6e9adSlinfeng } 151*fae6e9adSlinfeng } 152