blob: 70d5a5e8802aec4e64de35b97759538751e56ee7 [file] [log] [blame]
use crate::wire::Ipv6Address;
use super::{lollipop::SequenceCounter, rank::Rank};
use crate::config::RPL_PARENTS_BUFFER_COUNT;
#[derive(Debug, Clone, Copy, PartialEq)]
pub(crate) struct Parent {
rank: Rank,
preference: u8,
version_number: SequenceCounter,
dodag_id: Ipv6Address,
}
impl Parent {
/// Create a new parent.
pub(crate) fn new(
preference: u8,
rank: Rank,
version_number: SequenceCounter,
dodag_id: Ipv6Address,
) -> Self {
Self {
rank,
preference,
version_number,
dodag_id,
}
}
/// Return the Rank of the parent.
pub(crate) fn rank(&self) -> &Rank {
&self.rank
}
}
#[derive(Debug, Default)]
pub(crate) struct ParentSet {
parents: heapless::LinearMap<Ipv6Address, Parent, { RPL_PARENTS_BUFFER_COUNT }>,
}
impl ParentSet {
/// Add a new parent to the parent set. The Rank of the new parent should be lower than the
/// Rank of the node that holds this parent set.
pub(crate) fn add(&mut self, address: Ipv6Address, parent: Parent) {
if let Some(p) = self.parents.get_mut(&address) {
*p = parent;
} else if let Err(p) = self.parents.insert(address, parent) {
if let Some((w_a, w_p)) = self.worst_parent() {
if w_p.rank.dag_rank() > parent.rank.dag_rank() {
self.parents.remove(&w_a.clone()).unwrap();
self.parents.insert(address, parent).unwrap();
} else {
net_debug!("could not add {} to parent set, buffer is full", address);
}
} else {
unreachable!()
}
}
}
/// Find a parent based on its address.
pub(crate) fn find(&self, address: &Ipv6Address) -> Option<&Parent> {
self.parents.get(address)
}
/// Find a mutable parent based on its address.
pub(crate) fn find_mut(&mut self, address: &Ipv6Address) -> Option<&mut Parent> {
self.parents.get_mut(address)
}
/// Return a slice to the parent set.
pub(crate) fn parents(&self) -> impl Iterator<Item = (&Ipv6Address, &Parent)> {
self.parents.iter()
}
/// Find the worst parent that is currently in the parent set.
fn worst_parent(&self) -> Option<(&Ipv6Address, &Parent)> {
self.parents.iter().max_by_key(|(k, v)| v.rank.dag_rank())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn add_parent() {
let mut set = ParentSet::default();
set.add(
Default::default(),
Parent::new(0, Rank::ROOT, Default::default(), Default::default()),
);
assert_eq!(
set.find(&Default::default()),
Some(&Parent::new(
0,
Rank::ROOT,
Default::default(),
Default::default()
))
);
}
#[test]
fn add_more_parents() {
use super::super::consts::DEFAULT_MIN_HOP_RANK_INCREASE;
let mut set = ParentSet::default();
let mut last_address = Default::default();
for i in 0..RPL_PARENTS_BUFFER_COUNT {
let i = i as u16;
let mut address = Ipv6Address::default();
address.0[15] = i as u8;
last_address = address;
set.add(
address,
Parent::new(
0,
Rank::new(256 * i, DEFAULT_MIN_HOP_RANK_INCREASE),
Default::default(),
address,
),
);
assert_eq!(
set.find(&address),
Some(&Parent::new(
0,
Rank::new(256 * i, DEFAULT_MIN_HOP_RANK_INCREASE),
Default::default(),
address,
))
);
}
// This one is not added to the set, because its Rank is worse than any other parent in the
// set.
let mut address = Ipv6Address::default();
address.0[15] = 8;
set.add(
address,
Parent::new(
0,
Rank::new(256 * 8, DEFAULT_MIN_HOP_RANK_INCREASE),
Default::default(),
address,
),
);
assert_eq!(set.find(&address), None);
/// This Parent has a better rank than the last one in the set.
let mut address = Ipv6Address::default();
address.0[15] = 9;
set.add(
address,
Parent::new(
0,
Rank::new(0, DEFAULT_MIN_HOP_RANK_INCREASE),
Default::default(),
address,
),
);
assert_eq!(
set.find(&address),
Some(&Parent::new(
0,
Rank::new(0, DEFAULT_MIN_HOP_RANK_INCREASE),
Default::default(),
address
))
);
assert_eq!(set.find(&last_address), None);
}
}