mirror of
https://github.com/smoltcp-rs/smoltcp.git
synced 2025-09-30 22:31:25 +00:00
Merge pull request #790 from thvdveld/rpl-relations-buffer
Add RPL relations table
This commit is contained in:
commit
7b4246d003
@ -214,6 +214,15 @@ dns-max-name-size-64 = []
|
||||
dns-max-name-size-128 = []
|
||||
dns-max-name-size-255 = [] # Default
|
||||
|
||||
rpl-relations-buffer-count-1 = []
|
||||
rpl-relations-buffer-count-2 = []
|
||||
rpl-relations-buffer-count-4 = []
|
||||
rpl-relations-buffer-count-8 = []
|
||||
rpl-relations-buffer-count-16 = [] # Default
|
||||
rpl-relations-buffer-count-32 = []
|
||||
rpl-relations-buffer-count-64 = []
|
||||
rpl-relations-buffer-count-128 = []
|
||||
|
||||
# END AUTOGENERATED CONFIG FEATURES
|
||||
|
||||
[[example]]
|
||||
|
1
build.rs
1
build.rs
@ -18,6 +18,7 @@ static CONFIGS: &[(&str, usize)] = &[
|
||||
("DNS_MAX_RESULT_COUNT", 1),
|
||||
("DNS_MAX_SERVER_COUNT", 1),
|
||||
("DNS_MAX_NAME_SIZE", 255),
|
||||
("RPL_RELATIONS_BUFFER_COUNT", 16),
|
||||
// END AUTOGENERATED CONFIG FEATURES
|
||||
];
|
||||
|
||||
|
@ -39,6 +39,7 @@ feature("reassembly_buffer_count", default=1, min=1, max=32, pow2=4)
|
||||
feature("dns_max_result_count", default=1, min=1, max=32, pow2=4)
|
||||
feature("dns_max_server_count", default=1, min=1, max=32, pow2=4)
|
||||
feature("dns_max_name_size", default=255, min=64, max=255, pow2=True)
|
||||
feature("rpl_relations_buffer_count", default=16, min=1, max=128, pow2=True)
|
||||
|
||||
# ========= Update Cargo.toml
|
||||
|
||||
|
@ -3,4 +3,5 @@
|
||||
mod consts;
|
||||
mod lollipop;
|
||||
mod rank;
|
||||
mod relations;
|
||||
mod trickle;
|
||||
|
162
src/iface/rpl/relations.rs
Normal file
162
src/iface/rpl/relations.rs
Normal file
@ -0,0 +1,162 @@
|
||||
use crate::time::Instant;
|
||||
use crate::wire::Ipv6Address;
|
||||
|
||||
use crate::config::RPL_RELATIONS_BUFFER_COUNT;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Relation {
|
||||
destination: Ipv6Address,
|
||||
next_hop: Ipv6Address,
|
||||
expiration: Instant,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Relations {
|
||||
relations: heapless::Vec<Relation, { RPL_RELATIONS_BUFFER_COUNT }>,
|
||||
}
|
||||
|
||||
impl Relations {
|
||||
/// Add a new relation to the buffer. If there was already a relation in the buffer, then
|
||||
/// update it.
|
||||
pub fn add_relation(
|
||||
&mut self,
|
||||
destination: Ipv6Address,
|
||||
next_hop: Ipv6Address,
|
||||
expiration: Instant,
|
||||
) {
|
||||
if let Some(r) = self
|
||||
.relations
|
||||
.iter_mut()
|
||||
.find(|r| r.destination == destination)
|
||||
{
|
||||
r.next_hop = next_hop;
|
||||
r.expiration = expiration;
|
||||
} else {
|
||||
let relation = Relation {
|
||||
destination,
|
||||
next_hop,
|
||||
expiration,
|
||||
};
|
||||
|
||||
if let Err(e) = self.relations.push(relation) {
|
||||
net_debug!("Unable to add relation, buffer is full");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove all relation entries for a specific destination.
|
||||
pub fn remove_relation(&mut self, destination: Ipv6Address) {
|
||||
self.relations.retain(|r| r.destination != destination)
|
||||
}
|
||||
|
||||
/// Return the next hop for a specific IPv6 address, if there is one.
|
||||
pub fn find_next_hop(&mut self, destination: Ipv6Address) -> Option<Ipv6Address> {
|
||||
self.relations.iter().find_map(|r| {
|
||||
if r.destination == destination {
|
||||
Some(r.next_hop)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Purge expired relations.
|
||||
pub fn purge(&mut self, now: Instant) {
|
||||
self.relations.retain(|r| r.expiration > now)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::time::Duration;
|
||||
|
||||
fn addresses(count: usize) -> Vec<Ipv6Address> {
|
||||
(0..count)
|
||||
.map(|i| {
|
||||
let mut ip = Ipv6Address::default();
|
||||
ip.0[0] = i as u8;
|
||||
ip
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_relation() {
|
||||
let addrs = addresses(2);
|
||||
|
||||
let mut relations = Relations::default();
|
||||
relations.add_relation(addrs[0], addrs[1], Instant::now());
|
||||
assert_eq!(relations.relations.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_relations_full_buffer() {
|
||||
let addrs = addresses(crate::config::RPL_RELATIONS_BUFFER_COUNT + 1);
|
||||
|
||||
// Try to add RPL_RELATIONS_BUFFER_COUNT + 1 to the buffer.
|
||||
// The size of the buffer should still be RPL_RELATIONS_BUFFER_COUNT.
|
||||
let mut relations = Relations::default();
|
||||
for a in addrs {
|
||||
relations.add_relation(a, a, Instant::now());
|
||||
}
|
||||
|
||||
assert_eq!(relations.relations.len(), RPL_RELATIONS_BUFFER_COUNT);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_relation() {
|
||||
let addrs = addresses(3);
|
||||
|
||||
let mut relations = Relations::default();
|
||||
relations.add_relation(addrs[0], addrs[1], Instant::now());
|
||||
assert_eq!(relations.relations.len(), 1);
|
||||
|
||||
relations.add_relation(addrs[0], addrs[2], Instant::now());
|
||||
assert_eq!(relations.relations.len(), 1);
|
||||
|
||||
assert_eq!(relations.find_next_hop(addrs[0]), Some(addrs[2]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn find_next_hop() {
|
||||
let addrs = addresses(3);
|
||||
|
||||
let mut relations = Relations::default();
|
||||
relations.add_relation(addrs[0], addrs[1], Instant::now());
|
||||
assert_eq!(relations.relations.len(), 1);
|
||||
assert_eq!(relations.find_next_hop(addrs[0]), Some(addrs[1]));
|
||||
|
||||
relations.add_relation(addrs[0], addrs[2], Instant::now());
|
||||
assert_eq!(relations.relations.len(), 1);
|
||||
assert_eq!(relations.find_next_hop(addrs[0]), Some(addrs[2]));
|
||||
|
||||
// Find the next hop of a destination not in the buffer.
|
||||
assert_eq!(relations.find_next_hop(addrs[1]), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_relation() {
|
||||
let addrs = addresses(2);
|
||||
|
||||
let mut relations = Relations::default();
|
||||
relations.add_relation(addrs[0], addrs[1], Instant::now());
|
||||
assert_eq!(relations.relations.len(), 1);
|
||||
|
||||
relations.remove_relation(addrs[0]);
|
||||
assert!(relations.relations.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn purge_relation() {
|
||||
let addrs = addresses(2);
|
||||
|
||||
let mut relations = Relations::default();
|
||||
relations.add_relation(addrs[0], addrs[1], Instant::now() - Duration::from_secs(1));
|
||||
|
||||
assert_eq!(relations.relations.len(), 1);
|
||||
|
||||
relations.purge(Instant::now());
|
||||
assert!(relations.relations.is_empty());
|
||||
}
|
||||
}
|
@ -144,6 +144,7 @@ mod config {
|
||||
pub const IFACE_NEIGHBOR_CACHE_COUNT: usize = 3;
|
||||
pub const REASSEMBLY_BUFFER_COUNT: usize = 4;
|
||||
pub const REASSEMBLY_BUFFER_SIZE: usize = 1500;
|
||||
pub const RPL_RELATIONS_BUFFER_COUNT: usize = 16;
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
|
Loading…
x
Reference in New Issue
Block a user