@ -12,7 +12,7 @@ use crate::{
maps ::{ check_bounds , check_kv_size , IterableMap , MapData , MapError } ,
programs ::ProgramFd ,
sys ::{ bpf_map_lookup_elem , bpf_map_update_elem , SyscallError } ,
Pod ,
Pod , FEATURES ,
} ;
/// An array of available CPUs.
@ -50,7 +50,12 @@ pub struct CpuMap<T> {
impl < T : Borrow < MapData > > CpuMap < T > {
pub ( crate ) fn new ( map : T ) -> Result < Self , MapError > {
let data = map . borrow ( ) ;
if FEATURES . cpumap_prog_id ( ) {
check_kv_size ::< u32 , bpf_cpumap_val > ( data ) ? ;
} else {
check_kv_size ::< u32 , u32 > ( data ) ? ;
}
Ok ( Self { inner : map } )
}
@ -73,19 +78,29 @@ impl<T: Borrow<MapData>> CpuMap<T> {
check_bounds ( data , cpu_index ) ? ;
let fd = data . fd ( ) . as_fd ( ) ;
let value =
bpf_map_lookup_elem ( fd , & cpu_index , flags ) . map_err ( | ( _ , io_error ) | SyscallError {
call : "bpf_map_lookup_elem" ,
io_error ,
} ) ? ;
let value : bpf_cpumap_val = value . ok_or ( MapError ::KeyNotFound ) ? ;
let value = if FEATURES . cpumap_prog_id ( ) {
bpf_map_lookup_elem ::< _ , bpf_cpumap_val > ( fd , & cpu_index , flags ) . map ( | value | {
value . map ( | value | CpuMapValue {
qsize : value . qsize ,
// SAFETY: map writes use fd, map reads use id.
// https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6241
Ok ( CpuMapValue {
qsize : value . qsize ,
prog_id : NonZeroU32 ::new ( unsafe { value . bpf_prog . id } ) ,
} )
} )
} else {
bpf_map_lookup_elem ::< _ , u32 > ( fd , & cpu_index , flags ) . map ( | value | {
value . map ( | qsize | CpuMapValue {
qsize ,
prog_id : None ,
} )
} )
} ;
value
. map_err ( | ( _ , io_error ) | SyscallError {
call : "bpf_map_lookup_elem" ,
io_error ,
} ) ?
. ok_or ( MapError ::KeyNotFound )
}
/// An iterator over the elements of the map.
@ -111,7 +126,8 @@ impl<T: BorrowMut<MapData>> CpuMap<T> {
/// # Errors
///
/// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`]
/// if `bpf_map_update_elem` fails.
/// if `bpf_map_update_elem` fails, [`MapError::ProgIdNotSupported`] if the kernel does not
/// support program ids and one is provided.
pub fn set (
& mut self ,
cpu_index : u32 ,
@ -123,6 +139,7 @@ impl<T: BorrowMut<MapData>> CpuMap<T> {
check_bounds ( data , cpu_index ) ? ;
let fd = data . fd ( ) . as_fd ( ) ;
let res = if FEATURES . cpumap_prog_id ( ) {
let value = bpf_cpumap_val {
qsize : queue_size ,
bpf_prog : bpf_cpumap_val__bindgen_ty_1 {
@ -133,11 +150,17 @@ impl<T: BorrowMut<MapData>> CpuMap<T> {
. unwrap_or_default ( ) ,
} ,
} ;
bpf_map_update_elem ( fd , Some ( & cpu_index ) , & value , flags ) . map_err ( | ( _ , io_error ) | {
SyscallError {
bpf_map_update_elem ( fd , Some ( & cpu_index ) , & value , flags )
} else {
if program . is_some ( ) {
return Err ( MapError ::ProgIdNotSupported ) ;
}
bpf_map_update_elem ( fd , Some ( & cpu_index ) , & queue_size , flags )
} ;
res . map_err ( | ( _ , io_error ) | SyscallError {
call : "bpf_map_update_elem" ,
io_error ,
}
} ) ? ;
Ok ( ( ) )
}