@ -11,7 +11,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 network devices.
@ -43,7 +43,12 @@ pub struct DevMap<T> {
impl < T : Borrow < MapData > > DevMap < T > {
pub ( crate ) fn new ( map : T ) -> Result < Self , MapError > {
let data = map . borrow ( ) ;
if FEATURES . devmap_prog_id ( ) {
check_kv_size ::< u32 , bpf_devmap_val > ( data ) ? ;
} else {
check_kv_size ::< u32 , u32 > ( data ) ? ;
}
Ok ( Self { inner : map } )
}
@ -66,19 +71,29 @@ impl<T: Borrow<MapData>> DevMap<T> {
check_bounds ( data , index ) ? ;
let fd = data . fd ;
let value =
bpf_map_lookup_elem ( fd , & index , flags ) . map_err ( | ( _ , io_error ) | SyscallError {
call : "bpf_map_lookup_elem" ,
io_error ,
} ) ? ;
let value : bpf_devmap_val = value . ok_or ( MapError ::KeyNotFound ) ? ;
// SAFETY: map writes use fd, map reads use id.
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/bpf.h#L6136
Ok ( DevMapValue {
let value = if FEATURES . devmap_prog_id ( ) {
bpf_map_lookup_elem ::< _ , bpf_devmap_val > ( fd , & index , flags ) . map ( | value | {
value . map ( | value | DevMapValue {
ifindex : value . ifindex ,
// SAFETY: map writes use fd, map reads use id.
// https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/bpf.h#L6149
prog_id : unsafe { value . bpf_prog . id } ,
} )
} )
} else {
bpf_map_lookup_elem ::< _ , u32 > ( fd , & index , flags ) . map ( | value | {
value . map ( | ifindex | DevMapValue {
ifindex ,
prog_id : 0 ,
} )
} )
} ;
value
. map_err ( | ( _ , io_error ) | SyscallError {
call : "bpf_map_lookup_elem" ,
io_error ,
} ) ?
. ok_or ( MapError ::KeyNotFound )
}
/// An iterator over the elements of the array. The iterator item type is `Result<u32,
@ -104,7 +119,8 @@ impl<T: BorrowMut<MapData>> DevMap<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 ,
index : u32 ,
@ -116,6 +132,7 @@ impl<T: BorrowMut<MapData>> DevMap<T> {
check_bounds ( data , index ) ? ;
let fd = data . fd ;
let res = if FEATURES . devmap_prog_id ( ) {
let value = bpf_devmap_val {
ifindex ,
bpf_prog : bpf_devmap_val__bindgen_ty_1 {
@ -124,11 +141,17 @@ impl<T: BorrowMut<MapData>> DevMap<T> {
. unwrap_or_default ( ) ,
} ,
} ;
bpf_map_update_elem ( fd , Some ( & index ) , & value , flags ) . map_err ( | ( _ , io_error ) | {
SyscallError {
bpf_map_update_elem ( fd , Some ( & index ) , & value , flags )
} else {
if program . is_some ( ) {
return Err ( MapError ::ProgIdNotSupported ) ;
}
bpf_map_update_elem ( fd , Some ( & index ) , & ifindex , flags )
} ;
res . map_err ( | ( _ , io_error ) | SyscallError {
call : "bpf_map_update_elem" ,
io_error ,
}
} ) ? ;
Ok ( ( ) )
}