1*fae6e9adSlinfeng //! BPF_MAP_TYPE_ARRAY and BPF_MAP_TYPE_PERCPU_ARRAY 2*fae6e9adSlinfeng //! 3*fae6e9adSlinfeng //! 4*fae6e9adSlinfeng //! See https://docs.kernel.org/bpf/map_array.html 5*fae6e9adSlinfeng 6*fae6e9adSlinfeng use super::super::Result; 7*fae6e9adSlinfeng use crate::bpf::map::util::round_up; 8*fae6e9adSlinfeng use crate::bpf::map::{BpfCallBackFn, BpfMapCommonOps, BpfMapMeta}; 9*fae6e9adSlinfeng use crate::mm::percpu::{PerCpu, PerCpuVar}; 10*fae6e9adSlinfeng use crate::smp::cpu::{smp_cpu_manager, ProcessorId}; 11*fae6e9adSlinfeng use alloc::{vec, vec::Vec}; 12*fae6e9adSlinfeng use core::{ 13*fae6e9adSlinfeng fmt::{Debug, Formatter}, 14*fae6e9adSlinfeng ops::{Index, IndexMut}, 15*fae6e9adSlinfeng }; 16*fae6e9adSlinfeng use log::info; 17*fae6e9adSlinfeng use system_error::SystemError; 18*fae6e9adSlinfeng 19*fae6e9adSlinfeng /// The array map type is a generic map type with no restrictions on the structure of the value. 20*fae6e9adSlinfeng /// Like a normal array, the array map has a numeric key starting at 0 and incrementing. 21*fae6e9adSlinfeng /// 22*fae6e9adSlinfeng /// See https://ebpf-docs.dylanreimerink.nl/linux/map-type/BPF_MAP_TYPE_ARRAY/ 23*fae6e9adSlinfeng #[derive(Debug)] 24*fae6e9adSlinfeng pub struct ArrayMap { 25*fae6e9adSlinfeng max_entries: u32, 26*fae6e9adSlinfeng data: ArrayMapData, 27*fae6e9adSlinfeng } 28*fae6e9adSlinfeng 29*fae6e9adSlinfeng struct ArrayMapData { 30*fae6e9adSlinfeng elem_size: u32, 31*fae6e9adSlinfeng /// The data is stored in a Vec<u8> with the size of elem_size * max_entries. 32*fae6e9adSlinfeng data: Vec<u8>, 33*fae6e9adSlinfeng } 34*fae6e9adSlinfeng 35*fae6e9adSlinfeng impl Debug for ArrayMapData { fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result36*fae6e9adSlinfeng fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { 37*fae6e9adSlinfeng f.debug_struct("ArrayMapData") 38*fae6e9adSlinfeng .field("elem_size", &self.elem_size) 39*fae6e9adSlinfeng .field("data_len", &self.data.len()) 40*fae6e9adSlinfeng .finish() 41*fae6e9adSlinfeng } 42*fae6e9adSlinfeng } 43*fae6e9adSlinfeng 44*fae6e9adSlinfeng impl ArrayMapData { new(elem_size: u32, max_entries: u32) -> Self45*fae6e9adSlinfeng pub fn new(elem_size: u32, max_entries: u32) -> Self { 46*fae6e9adSlinfeng debug_assert!(elem_size % 8 == 0); 47*fae6e9adSlinfeng let total_size = elem_size * max_entries; 48*fae6e9adSlinfeng let data = vec![0; total_size as usize]; 49*fae6e9adSlinfeng ArrayMapData { elem_size, data } 50*fae6e9adSlinfeng } 51*fae6e9adSlinfeng } 52*fae6e9adSlinfeng 53*fae6e9adSlinfeng impl Index<u32> for ArrayMapData { 54*fae6e9adSlinfeng type Output = [u8]; index(&self, index: u32) -> &Self::Output55*fae6e9adSlinfeng fn index(&self, index: u32) -> &Self::Output { 56*fae6e9adSlinfeng let start = index * self.elem_size; 57*fae6e9adSlinfeng &self.data[start as usize..(start + self.elem_size) as usize] 58*fae6e9adSlinfeng } 59*fae6e9adSlinfeng } 60*fae6e9adSlinfeng 61*fae6e9adSlinfeng impl IndexMut<u32> for ArrayMapData { index_mut(&mut self, index: u32) -> &mut Self::Output62*fae6e9adSlinfeng fn index_mut(&mut self, index: u32) -> &mut Self::Output { 63*fae6e9adSlinfeng let start = index * self.elem_size; 64*fae6e9adSlinfeng &mut self.data[start as usize..(start + self.elem_size) as usize] 65*fae6e9adSlinfeng } 66*fae6e9adSlinfeng } 67*fae6e9adSlinfeng 68*fae6e9adSlinfeng impl ArrayMap { new(attr: &BpfMapMeta) -> Result<Self>69*fae6e9adSlinfeng pub fn new(attr: &BpfMapMeta) -> Result<Self> { 70*fae6e9adSlinfeng if attr.value_size == 0 || attr.max_entries == 0 || attr.key_size != 4 { 71*fae6e9adSlinfeng return Err(SystemError::EINVAL); 72*fae6e9adSlinfeng } 73*fae6e9adSlinfeng let elem_size = round_up(attr.value_size as usize, 8); 74*fae6e9adSlinfeng let data = ArrayMapData::new(elem_size as u32, attr.max_entries); 75*fae6e9adSlinfeng Ok(ArrayMap { 76*fae6e9adSlinfeng max_entries: attr.max_entries, 77*fae6e9adSlinfeng data, 78*fae6e9adSlinfeng }) 79*fae6e9adSlinfeng } 80*fae6e9adSlinfeng } 81*fae6e9adSlinfeng 82*fae6e9adSlinfeng impl BpfMapCommonOps for ArrayMap { lookup_elem(&mut self, key: &[u8]) -> Result<Option<&[u8]>>83*fae6e9adSlinfeng fn lookup_elem(&mut self, key: &[u8]) -> Result<Option<&[u8]>> { 84*fae6e9adSlinfeng if key.len() != 4 { 85*fae6e9adSlinfeng return Err(SystemError::EINVAL); 86*fae6e9adSlinfeng } 87*fae6e9adSlinfeng let index = u32::from_ne_bytes(key.try_into().map_err(|_| SystemError::EINVAL)?); 88*fae6e9adSlinfeng if index >= self.max_entries { 89*fae6e9adSlinfeng return Err(SystemError::EINVAL); 90*fae6e9adSlinfeng } 91*fae6e9adSlinfeng let val = self.data.index(index); 92*fae6e9adSlinfeng Ok(Some(val)) 93*fae6e9adSlinfeng } update_elem(&mut self, key: &[u8], value: &[u8], _flags: u64) -> Result<()>94*fae6e9adSlinfeng fn update_elem(&mut self, key: &[u8], value: &[u8], _flags: u64) -> Result<()> { 95*fae6e9adSlinfeng if key.len() != 4 { 96*fae6e9adSlinfeng return Err(SystemError::EINVAL); 97*fae6e9adSlinfeng } 98*fae6e9adSlinfeng let index = u32::from_ne_bytes(key.try_into().map_err(|_| SystemError::EINVAL)?); 99*fae6e9adSlinfeng if index >= self.max_entries { 100*fae6e9adSlinfeng return Err(SystemError::EINVAL); 101*fae6e9adSlinfeng } 102*fae6e9adSlinfeng if value.len() > self.data.elem_size as usize { 103*fae6e9adSlinfeng return Err(SystemError::EINVAL); 104*fae6e9adSlinfeng } 105*fae6e9adSlinfeng let old_value = self.data.index_mut(index); 106*fae6e9adSlinfeng old_value[..value.len()].copy_from_slice(value); 107*fae6e9adSlinfeng Ok(()) 108*fae6e9adSlinfeng } 109*fae6e9adSlinfeng /// For ArrayMap, delete_elem is not supported. delete_elem(&mut self, _key: &[u8]) -> Result<()>110*fae6e9adSlinfeng fn delete_elem(&mut self, _key: &[u8]) -> Result<()> { 111*fae6e9adSlinfeng Err(SystemError::EINVAL) 112*fae6e9adSlinfeng } for_each_elem(&mut self, cb: BpfCallBackFn, ctx: *const u8, flags: u64) -> Result<u32>113*fae6e9adSlinfeng fn for_each_elem(&mut self, cb: BpfCallBackFn, ctx: *const u8, flags: u64) -> Result<u32> { 114*fae6e9adSlinfeng if flags != 0 { 115*fae6e9adSlinfeng return Err(SystemError::EINVAL); 116*fae6e9adSlinfeng } 117*fae6e9adSlinfeng let mut total_used = 0; 118*fae6e9adSlinfeng for i in 0..self.max_entries { 119*fae6e9adSlinfeng let key = i.to_ne_bytes(); 120*fae6e9adSlinfeng let value = self.data.index(i); 121*fae6e9adSlinfeng total_used += 1; 122*fae6e9adSlinfeng let res = cb(&key, value, ctx); 123*fae6e9adSlinfeng // return value: 0 - continue, 1 - stop and return 124*fae6e9adSlinfeng if res != 0 { 125*fae6e9adSlinfeng break; 126*fae6e9adSlinfeng } 127*fae6e9adSlinfeng } 128*fae6e9adSlinfeng Ok(total_used) 129*fae6e9adSlinfeng } 130*fae6e9adSlinfeng lookup_and_delete_elem(&mut self, _key: &[u8], _value: &mut [u8]) -> Result<()>131*fae6e9adSlinfeng fn lookup_and_delete_elem(&mut self, _key: &[u8], _value: &mut [u8]) -> Result<()> { 132*fae6e9adSlinfeng Err(SystemError::EINVAL) 133*fae6e9adSlinfeng } 134*fae6e9adSlinfeng get_next_key(&self, key: Option<&[u8]>, next_key: &mut [u8]) -> Result<()>135*fae6e9adSlinfeng fn get_next_key(&self, key: Option<&[u8]>, next_key: &mut [u8]) -> Result<()> { 136*fae6e9adSlinfeng if let Some(key) = key { 137*fae6e9adSlinfeng if key.len() != 4 { 138*fae6e9adSlinfeng return Err(SystemError::EINVAL); 139*fae6e9adSlinfeng } 140*fae6e9adSlinfeng let index = u32::from_ne_bytes(key.try_into().map_err(|_| SystemError::EINVAL)?); 141*fae6e9adSlinfeng if index == self.max_entries - 1 { 142*fae6e9adSlinfeng return Err(SystemError::ENOENT); 143*fae6e9adSlinfeng } 144*fae6e9adSlinfeng let next_index = index + 1; 145*fae6e9adSlinfeng next_key.copy_from_slice(&next_index.to_ne_bytes()); 146*fae6e9adSlinfeng } else { 147*fae6e9adSlinfeng next_key.copy_from_slice(&0u32.to_ne_bytes()); 148*fae6e9adSlinfeng } 149*fae6e9adSlinfeng Ok(()) 150*fae6e9adSlinfeng } 151*fae6e9adSlinfeng freeze(&self) -> Result<()>152*fae6e9adSlinfeng fn freeze(&self) -> Result<()> { 153*fae6e9adSlinfeng info!("fake freeze done for ArrayMap"); 154*fae6e9adSlinfeng Ok(()) 155*fae6e9adSlinfeng } first_value_ptr(&self) -> Result<*const u8>156*fae6e9adSlinfeng fn first_value_ptr(&self) -> Result<*const u8> { 157*fae6e9adSlinfeng Ok(self.data.data.as_ptr()) 158*fae6e9adSlinfeng } 159*fae6e9adSlinfeng } 160*fae6e9adSlinfeng 161*fae6e9adSlinfeng /// This is the per-CPU variant of the [ArrayMap] map type. 162*fae6e9adSlinfeng /// 163*fae6e9adSlinfeng /// See https://ebpf-docs.dylanreimerink.nl/linux/map-type/BPF_MAP_TYPE_PERCPU_ARRAY/ 164*fae6e9adSlinfeng pub struct PerCpuArrayMap { 165*fae6e9adSlinfeng per_cpu_data: PerCpuVar<ArrayMap>, 166*fae6e9adSlinfeng } 167*fae6e9adSlinfeng 168*fae6e9adSlinfeng impl Debug for PerCpuArrayMap { fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result169*fae6e9adSlinfeng fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { 170*fae6e9adSlinfeng f.debug_struct("PerCpuArrayMap") 171*fae6e9adSlinfeng .field("data", &self.per_cpu_data) 172*fae6e9adSlinfeng .finish() 173*fae6e9adSlinfeng } 174*fae6e9adSlinfeng } 175*fae6e9adSlinfeng 176*fae6e9adSlinfeng impl PerCpuArrayMap { new(attr: &BpfMapMeta) -> Result<Self>177*fae6e9adSlinfeng pub fn new(attr: &BpfMapMeta) -> Result<Self> { 178*fae6e9adSlinfeng let num_cpus = PerCpu::MAX_CPU_NUM; 179*fae6e9adSlinfeng let mut data = Vec::with_capacity(num_cpus as usize); 180*fae6e9adSlinfeng for _ in 0..num_cpus { 181*fae6e9adSlinfeng let array_map = ArrayMap::new(attr)?; 182*fae6e9adSlinfeng data.push(array_map); 183*fae6e9adSlinfeng } 184*fae6e9adSlinfeng let per_cpu_data = PerCpuVar::new(data).ok_or(SystemError::EINVAL)?; 185*fae6e9adSlinfeng Ok(PerCpuArrayMap { per_cpu_data }) 186*fae6e9adSlinfeng } 187*fae6e9adSlinfeng } 188*fae6e9adSlinfeng 189*fae6e9adSlinfeng impl BpfMapCommonOps for PerCpuArrayMap { lookup_elem(&mut self, key: &[u8]) -> Result<Option<&[u8]>>190*fae6e9adSlinfeng fn lookup_elem(&mut self, key: &[u8]) -> Result<Option<&[u8]>> { 191*fae6e9adSlinfeng self.per_cpu_data.get_mut().lookup_elem(key) 192*fae6e9adSlinfeng } update_elem(&mut self, key: &[u8], value: &[u8], flags: u64) -> Result<()>193*fae6e9adSlinfeng fn update_elem(&mut self, key: &[u8], value: &[u8], flags: u64) -> Result<()> { 194*fae6e9adSlinfeng self.per_cpu_data.get_mut().update_elem(key, value, flags) 195*fae6e9adSlinfeng } delete_elem(&mut self, key: &[u8]) -> Result<()>196*fae6e9adSlinfeng fn delete_elem(&mut self, key: &[u8]) -> Result<()> { 197*fae6e9adSlinfeng self.per_cpu_data.get_mut().delete_elem(key) 198*fae6e9adSlinfeng } for_each_elem(&mut self, cb: BpfCallBackFn, ctx: *const u8, flags: u64) -> Result<u32>199*fae6e9adSlinfeng fn for_each_elem(&mut self, cb: BpfCallBackFn, ctx: *const u8, flags: u64) -> Result<u32> { 200*fae6e9adSlinfeng self.per_cpu_data.get_mut().for_each_elem(cb, ctx, flags) 201*fae6e9adSlinfeng } lookup_and_delete_elem(&mut self, _key: &[u8], _value: &mut [u8]) -> Result<()>202*fae6e9adSlinfeng fn lookup_and_delete_elem(&mut self, _key: &[u8], _value: &mut [u8]) -> Result<()> { 203*fae6e9adSlinfeng Err(SystemError::EINVAL) 204*fae6e9adSlinfeng } lookup_percpu_elem(&mut self, key: &[u8], cpu: u32) -> Result<Option<&[u8]>>205*fae6e9adSlinfeng fn lookup_percpu_elem(&mut self, key: &[u8], cpu: u32) -> Result<Option<&[u8]>> { 206*fae6e9adSlinfeng unsafe { 207*fae6e9adSlinfeng self.per_cpu_data 208*fae6e9adSlinfeng .force_get_mut(ProcessorId::new(cpu)) 209*fae6e9adSlinfeng .lookup_elem(key) 210*fae6e9adSlinfeng } 211*fae6e9adSlinfeng } get_next_key(&self, key: Option<&[u8]>, next_key: &mut [u8]) -> Result<()>212*fae6e9adSlinfeng fn get_next_key(&self, key: Option<&[u8]>, next_key: &mut [u8]) -> Result<()> { 213*fae6e9adSlinfeng self.per_cpu_data.get_mut().get_next_key(key, next_key) 214*fae6e9adSlinfeng } first_value_ptr(&self) -> Result<*const u8>215*fae6e9adSlinfeng fn first_value_ptr(&self) -> Result<*const u8> { 216*fae6e9adSlinfeng self.per_cpu_data.get_mut().first_value_ptr() 217*fae6e9adSlinfeng } 218*fae6e9adSlinfeng } 219*fae6e9adSlinfeng 220*fae6e9adSlinfeng /// See https://ebpf-docs.dylanreimerink.nl/linux/map-type/BPF_MAP_TYPE_PERF_EVENT_ARRAY/ 221*fae6e9adSlinfeng pub struct PerfEventArrayMap { 222*fae6e9adSlinfeng // The value is the file descriptor of the perf event. 223*fae6e9adSlinfeng fds: ArrayMapData, 224*fae6e9adSlinfeng } 225*fae6e9adSlinfeng 226*fae6e9adSlinfeng impl Debug for PerfEventArrayMap { fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result227*fae6e9adSlinfeng fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { 228*fae6e9adSlinfeng f.debug_struct("PerfEventArrayMap") 229*fae6e9adSlinfeng .field("fds", &self.fds) 230*fae6e9adSlinfeng .finish() 231*fae6e9adSlinfeng } 232*fae6e9adSlinfeng } 233*fae6e9adSlinfeng 234*fae6e9adSlinfeng impl PerfEventArrayMap { new(attr: &BpfMapMeta) -> Result<Self>235*fae6e9adSlinfeng pub fn new(attr: &BpfMapMeta) -> Result<Self> { 236*fae6e9adSlinfeng let num_cpus = smp_cpu_manager().possible_cpus_count(); 237*fae6e9adSlinfeng if attr.key_size != 4 || attr.value_size != 4 || attr.max_entries != num_cpus { 238*fae6e9adSlinfeng return Err(SystemError::EINVAL); 239*fae6e9adSlinfeng } 240*fae6e9adSlinfeng let fds = ArrayMapData::new(4, num_cpus); 241*fae6e9adSlinfeng Ok(PerfEventArrayMap { fds }) 242*fae6e9adSlinfeng } 243*fae6e9adSlinfeng } 244*fae6e9adSlinfeng 245*fae6e9adSlinfeng impl BpfMapCommonOps for PerfEventArrayMap { lookup_elem(&mut self, key: &[u8]) -> Result<Option<&[u8]>>246*fae6e9adSlinfeng fn lookup_elem(&mut self, key: &[u8]) -> Result<Option<&[u8]>> { 247*fae6e9adSlinfeng let cpu_id = u32::from_ne_bytes(key.try_into().map_err(|_| SystemError::EINVAL)?); 248*fae6e9adSlinfeng let value = self.fds.index(cpu_id); 249*fae6e9adSlinfeng Ok(Some(value)) 250*fae6e9adSlinfeng } update_elem(&mut self, key: &[u8], value: &[u8], _flags: u64) -> Result<()>251*fae6e9adSlinfeng fn update_elem(&mut self, key: &[u8], value: &[u8], _flags: u64) -> Result<()> { 252*fae6e9adSlinfeng assert_eq!(value.len(), 4); 253*fae6e9adSlinfeng let cpu_id = u32::from_ne_bytes(key.try_into().map_err(|_| SystemError::EINVAL)?); 254*fae6e9adSlinfeng let old_value = self.fds.index_mut(cpu_id); 255*fae6e9adSlinfeng old_value.copy_from_slice(value); 256*fae6e9adSlinfeng Ok(()) 257*fae6e9adSlinfeng } delete_elem(&mut self, key: &[u8]) -> Result<()>258*fae6e9adSlinfeng fn delete_elem(&mut self, key: &[u8]) -> Result<()> { 259*fae6e9adSlinfeng let cpu_id = u32::from_ne_bytes(key.try_into().map_err(|_| SystemError::EINVAL)?); 260*fae6e9adSlinfeng self.fds.index_mut(cpu_id).copy_from_slice(&[0; 4]); 261*fae6e9adSlinfeng Ok(()) 262*fae6e9adSlinfeng } for_each_elem(&mut self, cb: BpfCallBackFn, ctx: *const u8, _flags: u64) -> Result<u32>263*fae6e9adSlinfeng fn for_each_elem(&mut self, cb: BpfCallBackFn, ctx: *const u8, _flags: u64) -> Result<u32> { 264*fae6e9adSlinfeng let mut total_used = 0; 265*fae6e9adSlinfeng let num_cpus = smp_cpu_manager().possible_cpus_count(); 266*fae6e9adSlinfeng for i in 0..num_cpus { 267*fae6e9adSlinfeng let key = i.to_ne_bytes(); 268*fae6e9adSlinfeng let value = self.fds.index(i); 269*fae6e9adSlinfeng total_used += 1; 270*fae6e9adSlinfeng let res = cb(&key, value, ctx); 271*fae6e9adSlinfeng if res != 0 { 272*fae6e9adSlinfeng break; 273*fae6e9adSlinfeng } 274*fae6e9adSlinfeng } 275*fae6e9adSlinfeng Ok(total_used) 276*fae6e9adSlinfeng } lookup_and_delete_elem(&mut self, _key: &[u8], _value: &mut [u8]) -> Result<()>277*fae6e9adSlinfeng fn lookup_and_delete_elem(&mut self, _key: &[u8], _value: &mut [u8]) -> Result<()> { 278*fae6e9adSlinfeng Err(SystemError::EINVAL) 279*fae6e9adSlinfeng } first_value_ptr(&self) -> Result<*const u8>280*fae6e9adSlinfeng fn first_value_ptr(&self) -> Result<*const u8> { 281*fae6e9adSlinfeng Ok(self.fds.data.as_ptr()) 282*fae6e9adSlinfeng } 283*fae6e9adSlinfeng } 284