@ -1,9 +1,12 @@
//! A LPM Trie.
//! A LPM Trie.
use std ::{ marker ::PhantomData , mem , ops ::Deref } ;
use std ::{
convert ::{ AsMut , AsRef } ,
marker ::PhantomData ,
mem ,
} ;
use crate ::{
use crate ::{
generated ::bpf_map_type ::BPF_MAP_TYPE_LPM_TRIE ,
maps ::{ IterableMap , MapData , MapError } ,
maps ::{ IterableMap , Map , MapError , MapRef , MapRefMut } ,
sys ::{ bpf_map_delete_elem , bpf_map_lookup_elem , bpf_map_update_elem } ,
sys ::{ bpf_map_delete_elem , bpf_map_lookup_elem , bpf_map_update_elem } ,
Pod ,
Pod ,
} ;
} ;
@ -17,11 +20,11 @@ use crate::{
/// # Examples
/// # Examples
///
///
/// ```no_run
/// ```no_run
/// # let bpf = aya::Bpf::load(&[])?;
/// # let mut bpf = aya::Bpf::load(&[])?;
/// use aya::maps::lpm_trie::{LpmTrie, Key};
/// use aya::maps::lpm_trie::{LpmTrie, Key};
/// use std::net::Ipv4Addr;
/// use std::net::Ipv4Addr;
///
///
/// let mut trie = LpmTrie::try_from(bpf.map_mut("LPM_TRIE")? )?;
/// let mut trie : LpmTrie<_,u32,u32> = bpf.map_mut("LPM_TRIE")?.try_into( )?;
/// let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
/// let ipaddr = Ipv4Addr::new(8, 8, 8, 8);
/// // The following represents a key for the "8.8.8.8/16" subnet.
/// // The following represents a key for the "8.8.8.8/16" subnet.
/// // The first argument - the prefix length - represents how many bytes should be matched against. The second argument is the actual data to be matched.
/// // The first argument - the prefix length - represents how many bytes should be matched against. The second argument is the actual data to be matched.
@ -43,7 +46,7 @@ use crate::{
/// ```
/// ```
#[ doc(alias = " BPF_MAP_TYPE_LPM_TRIE " ) ]
#[ doc(alias = " BPF_MAP_TYPE_LPM_TRIE " ) ]
pub struct LpmTrie < T : Deref < Target = Map > , K , V > {
pub struct LpmTrie < T , K , V > {
inner : T ,
inner : T ,
_k : PhantomData < K > ,
_k : PhantomData < K > ,
_v : PhantomData < V > ,
_v : PhantomData < V > ,
@ -96,26 +99,21 @@ impl<K: Pod> Clone for Key<K> {
// A Pod impl is required as Key struct is a key for a map.
// A Pod impl is required as Key struct is a key for a map.
unsafe impl < K : Pod > Pod for Key < K > { }
unsafe impl < K : Pod > Pod for Key < K > { }
impl < T : Deref < Target = Map > , K : Pod , V : Pod > LpmTrie < T , K , V > {
impl < T : AsRef < MapData > , K : Pod , V : Pod > LpmTrie < T , K , V > {
pub ( crate ) fn new ( map : T ) -> Result < LpmTrie < T , K , V > , MapError > {
pub ( crate ) fn new ( map : T ) -> Result < LpmTrie < T , K , V > , MapError > {
let map_type = map . obj . map_type ( ) ;
let data = map . as_ref ( ) ;
// validate the map definition
if map_type ! = BPF_MAP_TYPE_LPM_TRIE as u32 {
return Err ( MapError ::InvalidMapType { map_type } ) ;
}
let size = mem ::size_of ::< Key < K > > ( ) ;
let size = mem ::size_of ::< Key < K > > ( ) ;
let expected = map . obj . key_size ( ) as usize ;
let expected = data . obj . key_size ( ) as usize ;
if size ! = expected {
if size ! = expected {
return Err ( MapError ::InvalidKeySize { size , expected } ) ;
return Err ( MapError ::InvalidKeySize { size , expected } ) ;
}
}
let size = mem ::size_of ::< V > ( ) ;
let size = mem ::size_of ::< V > ( ) ;
let expected = map . obj . value_size ( ) as usize ;
let expected = data . obj . value_size ( ) as usize ;
if size ! = expected {
if size ! = expected {
return Err ( MapError ::InvalidValueSize { size , expected } ) ;
return Err ( MapError ::InvalidValueSize { size , expected } ) ;
} ;
} ;
let _ = map . fd_or_err ( ) ? ;
let _ = data . fd_or_err ( ) ? ;
Ok ( LpmTrie {
Ok ( LpmTrie {
inner : map ,
inner : map ,
@ -126,7 +124,7 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> LpmTrie<T, K, V> {
/// Returns a copy of the value associated with the longest prefix matching key in the LpmTrie.
/// Returns a copy of the value associated with the longest prefix matching key in the LpmTrie.
pub fn get ( & self , key : & Key < K > , flags : u64 ) -> Result < V , MapError > {
pub fn get ( & self , key : & Key < K > , flags : u64 ) -> Result < V , MapError > {
let fd = self . inner . de ref( ) . fd_or_err ( ) ? ;
let fd = self . inner . as_ ref( ) . fd_or_err ( ) ? ;
let value = bpf_map_lookup_elem ( fd , key , flags ) . map_err ( | ( _ , io_error ) | {
let value = bpf_map_lookup_elem ( fd , key , flags ) . map_err ( | ( _ , io_error ) | {
MapError ::SyscallError {
MapError ::SyscallError {
call : "bpf_map_lookup_elem" . to_owned ( ) ,
call : "bpf_map_lookup_elem" . to_owned ( ) ,
@ -135,10 +133,12 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> LpmTrie<T, K, V> {
} ) ? ;
} ) ? ;
value . ok_or ( MapError ::KeyNotFound )
value . ok_or ( MapError ::KeyNotFound )
}
}
}
impl < T : AsMut < MapData > , K : Pod , V : Pod > LpmTrie < T , K , V > {
/// Inserts a key value pair into the map.
/// Inserts a key value pair into the map.
pub fn insert ( & self , key : & Key < K > , value : V , flags : u64 ) -> Result < ( ) , MapError > {
pub fn insert ( & mut self , key : & Key < K > , value : V , flags : u64 ) -> Result < ( ) , MapError > {
let fd = self . inner . deref ( ) . fd_or_err ( ) ? ;
let fd = self . inner . as_mut ( ) . fd_or_err ( ) ? ;
bpf_map_update_elem ( fd , Some ( key ) , & value , flags ) . map_err ( | ( _ , io_error ) | {
bpf_map_update_elem ( fd , Some ( key ) , & value , flags ) . map_err ( | ( _ , io_error ) | {
MapError ::SyscallError {
MapError ::SyscallError {
call : "bpf_map_update_elem" . to_owned ( ) ,
call : "bpf_map_update_elem" . to_owned ( ) ,
@ -152,8 +152,8 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> LpmTrie<T, K, V> {
/// Removes an element from the map.
/// Removes an element from the map.
///
///
/// Both the prefix and data must match exactly - this method does not do a longest prefix match.
/// Both the prefix and data must match exactly - this method does not do a longest prefix match.
pub fn remove ( & self , key : & Key < K > ) -> Result < ( ) , MapError > {
pub fn remove ( & mut self , key : & Key < K > ) -> Result < ( ) , MapError > {
let fd = self . inner . deref ( ) . fd_or_err ( ) ? ;
let fd = self . inner . as_mut ( ) . fd_or_err ( ) ? ;
bpf_map_delete_elem ( fd , key )
bpf_map_delete_elem ( fd , key )
. map ( | _ | ( ) )
. map ( | _ | ( ) )
. map_err ( | ( _ , io_error ) | MapError ::SyscallError {
. map_err ( | ( _ , io_error ) | MapError ::SyscallError {
@ -163,9 +163,9 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> LpmTrie<T, K, V> {
}
}
}
}
impl < T : Deref < Target = Map > , K : Pod , V : Pod > IterableMap < K , V > for LpmTrie < T , K , V > {
impl < T : AsRef < MapData > , K : Pod , V : Pod > IterableMap < K , V > for LpmTrie < T , K , V > {
fn map ( & self ) -> & Map {
fn map ( & self ) -> & Map Data {
& self . inner
self . inner . as_ref ( )
}
}
fn get ( & self , key : & K ) -> Result < V , MapError > {
fn get ( & self , key : & K ) -> Result < V , MapError > {
@ -174,38 +174,6 @@ impl<T: Deref<Target = Map>, K: Pod, V: Pod> IterableMap<K, V> for LpmTrie<T, K,
}
}
}
}
impl < K : Pod , V : Pod > TryFrom < MapRef > for LpmTrie < MapRef , K , V > {
type Error = MapError ;
fn try_from ( a : MapRef ) -> Result < LpmTrie < MapRef , K , V > , MapError > {
LpmTrie ::new ( a )
}
}
impl < K : Pod , V : Pod > TryFrom < MapRefMut > for LpmTrie < MapRefMut , K , V > {
type Error = MapError ;
fn try_from ( a : MapRefMut ) -> Result < LpmTrie < MapRefMut , K , V > , MapError > {
LpmTrie ::new ( a )
}
}
impl < ' a , K : Pod , V : Pod > TryFrom < & ' a Map > for LpmTrie < & ' a Map , K , V > {
type Error = MapError ;
fn try_from ( a : & ' a Map ) -> Result < LpmTrie < & ' a Map , K , V > , MapError > {
LpmTrie ::new ( a )
}
}
impl < ' a , K : Pod , V : Pod > TryFrom < & ' a mut Map > for LpmTrie < & ' a mut Map , K , V > {
type Error = MapError ;
fn try_from ( a : & ' a mut Map ) -> Result < LpmTrie < & ' a mut Map , K , V > , MapError > {
LpmTrie ::new ( a )
}
}
#[ cfg(test) ]
#[ cfg(test) ]
mod tests {
mod tests {
use super ::* ;
use super ::* ;
@ -215,6 +183,7 @@ mod tests {
bpf_cmd ,
bpf_cmd ,
bpf_map_type ::{ BPF_MAP_TYPE_LPM_TRIE , BPF_MAP_TYPE_PERF_EVENT_ARRAY } ,
bpf_map_type ::{ BPF_MAP_TYPE_LPM_TRIE , BPF_MAP_TYPE_PERF_EVENT_ARRAY } ,
} ,
} ,
maps ::{ Map , MapData } ,
obj ,
obj ,
sys ::{ override_syscall , SysResult , Syscall } ,
sys ::{ override_syscall , SysResult , Syscall } ,
} ;
} ;
@ -243,7 +212,7 @@ mod tests {
#[ test ]
#[ test ]
fn test_wrong_key_size ( ) {
fn test_wrong_key_size ( ) {
let map = Map {
let map = Map Data {
obj : new_obj_map ( ) ,
obj : new_obj_map ( ) ,
fd : None ,
fd : None ,
pinned : false ,
pinned : false ,
@ -260,7 +229,7 @@ mod tests {
#[ test ]
#[ test ]
fn test_wrong_value_size ( ) {
fn test_wrong_value_size ( ) {
let map = Map {
let map = Map Data {
obj : new_obj_map ( ) ,
obj : new_obj_map ( ) ,
fd : None ,
fd : None ,
pinned : false ,
pinned : false ,
@ -277,7 +246,7 @@ mod tests {
#[ test ]
#[ test ]
fn test_try_from_wrong_map ( ) {
fn test_try_from_wrong_map ( ) {
let map = Map {
let map _data = Map Data {
obj : obj ::Map ::Legacy ( obj ::LegacyMap {
obj : obj ::Map ::Legacy ( obj ::LegacyMap {
def : bpf_map_def {
def : bpf_map_def {
map_type : BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 ,
map_type : BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 ,
@ -296,15 +265,17 @@ mod tests {
pinned : false ,
pinned : false ,
} ;
} ;
let map = Map ::PerfEventArray ( map_data ) ;
assert! ( matches! (
assert! ( matches! (
LpmTrie ::< _ , u32 , u32 > ::try_from ( & map ) ,
LpmTrie ::< _ , u32 , u32 > ::try_from ( & map ) ,
Err ( MapError ::InvalidMapType { .. } )
Err ( MapError ::UnexpectedMapType )
) ) ;
) ) ;
}
}
#[ test ]
#[ test ]
fn test_new_not_created ( ) {
fn test_new_not_created ( ) {
let mut map = Map {
let mut map = Map Data {
obj : new_obj_map ( ) ,
obj : new_obj_map ( ) ,
fd : None ,
fd : None ,
pinned : false ,
pinned : false ,
@ -319,7 +290,7 @@ mod tests {
#[ test ]
#[ test ]
fn test_new_ok ( ) {
fn test_new_ok ( ) {
let mut map = Map {
let mut map = Map Data {
obj : new_obj_map ( ) ,
obj : new_obj_map ( ) ,
fd : Some ( 42 ) ,
fd : Some ( 42 ) ,
pinned : false ,
pinned : false ,
@ -331,12 +302,14 @@ mod tests {
#[ test ]
#[ test ]
fn test_try_from_ok ( ) {
fn test_try_from_ok ( ) {
let map = Map {
let map _data = Map Data {
obj : new_obj_map ( ) ,
obj : new_obj_map ( ) ,
fd : Some ( 42 ) ,
fd : Some ( 42 ) ,
pinned : false ,
pinned : false ,
btf_fd : None ,
btf_fd : None ,
} ;
} ;
let map = Map ::LpmTrie ( map_data ) ;
assert! ( LpmTrie ::< _ , u32 , u32 > ::try_from ( & map ) . is_ok ( ) )
assert! ( LpmTrie ::< _ , u32 , u32 > ::try_from ( & map ) . is_ok ( ) )
}
}
@ -344,13 +317,13 @@ mod tests {
fn test_insert_syscall_error ( ) {
fn test_insert_syscall_error ( ) {
override_syscall ( | _ | sys_error ( EFAULT ) ) ;
override_syscall ( | _ | sys_error ( EFAULT ) ) ;
let mut map = Map {
let mut map = Map Data {
obj : new_obj_map ( ) ,
obj : new_obj_map ( ) ,
fd : Some ( 42 ) ,
fd : Some ( 42 ) ,
pinned : false ,
pinned : false ,
btf_fd : None ,
btf_fd : None ,
} ;
} ;
let trie = LpmTrie ::< _ , u32 , u32 > ::new ( & mut map ) . unwrap ( ) ;
let mut trie = LpmTrie ::< _ , u32 , u32 > ::new ( & mut map ) . unwrap ( ) ;
let ipaddr = Ipv4Addr ::new ( 8 , 8 , 8 , 8 ) ;
let ipaddr = Ipv4Addr ::new ( 8 , 8 , 8 , 8 ) ;
let key = Key ::new ( 16 , u32 ::from ( ipaddr ) . to_be ( ) ) ;
let key = Key ::new ( 16 , u32 ::from ( ipaddr ) . to_be ( ) ) ;
assert! ( matches! (
assert! ( matches! (
@ -369,14 +342,14 @@ mod tests {
_ = > sys_error ( EFAULT ) ,
_ = > sys_error ( EFAULT ) ,
} ) ;
} ) ;
let mut map = Map {
let mut map = Map Data {
obj : new_obj_map ( ) ,
obj : new_obj_map ( ) ,
fd : Some ( 42 ) ,
fd : Some ( 42 ) ,
pinned : false ,
pinned : false ,
btf_fd : None ,
btf_fd : None ,
} ;
} ;
let trie = LpmTrie ::< _ , u32 , u32 > ::new ( & mut map ) . unwrap ( ) ;
let mut trie = LpmTrie ::< _ , u32 , u32 > ::new ( & mut map ) . unwrap ( ) ;
let ipaddr = Ipv4Addr ::new ( 8 , 8 , 8 , 8 ) ;
let ipaddr = Ipv4Addr ::new ( 8 , 8 , 8 , 8 ) ;
let key = Key ::new ( 16 , u32 ::from ( ipaddr ) . to_be ( ) ) ;
let key = Key ::new ( 16 , u32 ::from ( ipaddr ) . to_be ( ) ) ;
assert! ( trie . insert ( & key , 1 , 0 ) . is_ok ( ) ) ;
assert! ( trie . insert ( & key , 1 , 0 ) . is_ok ( ) ) ;
@ -386,13 +359,13 @@ mod tests {
fn test_remove_syscall_error ( ) {
fn test_remove_syscall_error ( ) {
override_syscall ( | _ | sys_error ( EFAULT ) ) ;
override_syscall ( | _ | sys_error ( EFAULT ) ) ;
let mut map = Map {
let mut map = Map Data {
obj : new_obj_map ( ) ,
obj : new_obj_map ( ) ,
fd : Some ( 42 ) ,
fd : Some ( 42 ) ,
pinned : false ,
pinned : false ,
btf_fd : None ,
btf_fd : None ,
} ;
} ;
let trie = LpmTrie ::< _ , u32 , u32 > ::new ( & mut map ) . unwrap ( ) ;
let mut trie = LpmTrie ::< _ , u32 , u32 > ::new ( & mut map ) . unwrap ( ) ;
let ipaddr = Ipv4Addr ::new ( 8 , 8 , 8 , 8 ) ;
let ipaddr = Ipv4Addr ::new ( 8 , 8 , 8 , 8 ) ;
let key = Key ::new ( 16 , u32 ::from ( ipaddr ) . to_be ( ) ) ;
let key = Key ::new ( 16 , u32 ::from ( ipaddr ) . to_be ( ) ) ;
assert! ( matches! (
assert! ( matches! (
@ -411,13 +384,13 @@ mod tests {
_ = > sys_error ( EFAULT ) ,
_ = > sys_error ( EFAULT ) ,
} ) ;
} ) ;
let mut map = Map {
let mut map = Map Data {
obj : new_obj_map ( ) ,
obj : new_obj_map ( ) ,
fd : Some ( 42 ) ,
fd : Some ( 42 ) ,
pinned : false ,
pinned : false ,
btf_fd : None ,
btf_fd : None ,
} ;
} ;
let trie = LpmTrie ::< _ , u32 , u32 > ::new ( & mut map ) . unwrap ( ) ;
let mut trie = LpmTrie ::< _ , u32 , u32 > ::new ( & mut map ) . unwrap ( ) ;
let ipaddr = Ipv4Addr ::new ( 8 , 8 , 8 , 8 ) ;
let ipaddr = Ipv4Addr ::new ( 8 , 8 , 8 , 8 ) ;
let key = Key ::new ( 16 , u32 ::from ( ipaddr ) . to_be ( ) ) ;
let key = Key ::new ( 16 , u32 ::from ( ipaddr ) . to_be ( ) ) ;
assert! ( trie . remove ( & key ) . is_ok ( ) ) ;
assert! ( trie . remove ( & key ) . is_ok ( ) ) ;
@ -426,7 +399,7 @@ mod tests {
#[ test ]
#[ test ]
fn test_get_syscall_error ( ) {
fn test_get_syscall_error ( ) {
override_syscall ( | _ | sys_error ( EFAULT ) ) ;
override_syscall ( | _ | sys_error ( EFAULT ) ) ;
let map = Map {
let map = Map Data {
obj : new_obj_map ( ) ,
obj : new_obj_map ( ) ,
fd : Some ( 42 ) ,
fd : Some ( 42 ) ,
pinned : false ,
pinned : false ,
@ -451,7 +424,7 @@ mod tests {
} = > sys_error ( ENOENT ) ,
} = > sys_error ( ENOENT ) ,
_ = > sys_error ( EFAULT ) ,
_ = > sys_error ( EFAULT ) ,
} ) ;
} ) ;
let map = Map {
let map = Map Data {
obj : new_obj_map ( ) ,
obj : new_obj_map ( ) ,
fd : Some ( 42 ) ,
fd : Some ( 42 ) ,
pinned : false ,
pinned : false ,