Skip to content

Commit

Permalink
Add ability to iterate over lpmtrie key matches
Browse files Browse the repository at this point in the history
  • Loading branch information
FallingSnow committed Dec 8, 2022
1 parent 8fe64ae commit 9a3682e
Showing 1 changed file with 57 additions and 2 deletions.
59 changes: 57 additions & 2 deletions aya/src/maps/lpm_trie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ use std::{
borrow::Borrow,
convert::{AsMut, AsRef},
marker::PhantomData,
mem,
};

use crate::{
maps::{check_kv_size, IterableMap, MapData, MapError, MapIter, MapKeys},
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, bpf_map_get_next_key},
Pod,
};

Expand Down Expand Up @@ -137,6 +136,12 @@ impl<T: AsRef<MapData>, K: Pod, V: Pod> LpmTrie<T, K, V> {
pub fn keys(&self) -> MapKeys<'_, Key<K>> {
MapKeys::new(self.inner.as_ref())
}

/// An iterator visiting all keys matching key. The
/// iterator item type is `Result<Key<K>, MapError>`.
pub fn iter_key(&self, key: Key<K>) -> LpnTrieKeys<'_, K> {
LpnTrieKeys::new(self.inner.as_ref(), key)
}
}

impl<T: AsMut<MapData>, K: Pod, V: Pod> LpmTrie<T, K, V> {
Expand Down Expand Up @@ -182,6 +187,56 @@ impl<T: AsRef<MapData>, K: Pod, V: Pod> IterableMap<Key<K>, V> for LpmTrie<T, K,
}
}

/// Iterator returned by `LpmTrie::iter_key()`.
pub struct LpnTrieKeys<'coll, K: Pod> {
map: &'coll MapData,
err: bool,
key: Key<K>,
}

impl<'coll, K: Pod> LpnTrieKeys<'coll, K> {
fn new(map: &'coll MapData, key: Key<K>) -> LpnTrieKeys<'coll, K> {
LpnTrieKeys {
map,
err: false,
key
}
}
}

impl<K: Pod> Iterator for LpnTrieKeys<'_, K> {
type Item = Result<Key<K>, MapError>;

fn next(&mut self) -> Option<Result<Key<K>, MapError>> {
if self.err {
return None;
}

let fd = match self.map.fd_or_err() {
Ok(fd) => fd,
Err(e) => {
self.err = true;
return Some(Err(e));
}
};

match bpf_map_get_next_key(fd, Some(&self.key)) {
Ok(Some(key)) => {
self.key = key;
Some(Ok(key))
}
Ok(None) => None,
Err((_, io_error)) => {
self.err = true;
Some(Err(MapError::SyscallError {
call: "bpf_map_get_next_key".to_owned(),
io_error,
}))
}
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit 9a3682e

Please sign in to comment.