Add objective function and parent set

This commit is contained in:
Thibaut Vandervelden 2023-06-05 13:03:44 +02:00
parent 7b4246d003
commit f68603d8b8
8 changed files with 335 additions and 2 deletions

View File

@ -223,6 +223,12 @@ rpl-relations-buffer-count-32 = []
rpl-relations-buffer-count-64 = []
rpl-relations-buffer-count-128 = []
rpl-parents-buffer-count-2 = []
rpl-parents-buffer-count-4 = []
rpl-parents-buffer-count-8 = [] # Default
rpl-parents-buffer-count-16 = []
rpl-parents-buffer-count-32 = []
# END AUTOGENERATED CONFIG FEATURES
[[example]]

View File

@ -19,6 +19,7 @@ static CONFIGS: &[(&str, usize)] = &[
("DNS_MAX_SERVER_COUNT", 1),
("DNS_MAX_NAME_SIZE", 255),
("RPL_RELATIONS_BUFFER_COUNT", 16),
("RPL_PARENTS_BUFFER_COUNT", 8),
// END AUTOGENERATED CONFIG FEATURES
];

View File

@ -40,6 +40,7 @@ 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)
feature("rpl_parents_buffer_count", default=8, min=2, max=32, pow2=True)
# ========= Update Cargo.toml

View File

@ -2,6 +2,8 @@
mod consts;
mod lollipop;
mod of0;
mod parents;
mod rank;
mod relations;
mod trickle;

131
src/iface/rpl/of0.rs Normal file
View File

@ -0,0 +1,131 @@
use super::parents::*;
use super::rank::Rank;
pub struct ObjectiveFunction0;
pub(crate) trait ObjectiveFunction {
const OCP: u16;
/// Return the new calculated Rank, based on information from the parent.
fn rank(current_rank: Rank, parent_rank: Rank) -> Rank;
/// Return the preferred parent from a given parent set.
fn preferred_parent(parent_set: &ParentSet) -> Option<&Parent>;
}
impl ObjectiveFunction0 {
const OCP: u16 = 0;
const RANK_STRETCH: u16 = 0;
const RANK_FACTOR: u16 = 1;
const RANK_STEP: u16 = 3;
fn rank_increase(parent_rank: Rank) -> u16 {
(Self::RANK_FACTOR * Self::RANK_STEP + Self::RANK_STRETCH)
* parent_rank.min_hop_rank_increase
}
}
impl ObjectiveFunction for ObjectiveFunction0 {
const OCP: u16 = 0;
fn rank(_: Rank, parent_rank: Rank) -> Rank {
assert_ne!(parent_rank, Rank::INFINITE);
Rank::new(
parent_rank.value + Self::rank_increase(parent_rank),
parent_rank.min_hop_rank_increase,
)
}
fn preferred_parent(parent_set: &ParentSet) -> Option<&Parent> {
let mut pref_parent: Option<&Parent> = None;
for parent in parent_set.parents() {
if pref_parent.is_none() || parent.rank() < pref_parent.unwrap().rank() {
pref_parent = Some(parent);
}
}
pref_parent
}
}
#[cfg(test)]
mod tests {
use crate::iface::rpl::consts::DEFAULT_MIN_HOP_RANK_INCREASE;
use super::*;
#[test]
fn rank_increase() {
// 256 (root) + 3 * 256
assert_eq!(
ObjectiveFunction0::rank(Rank::INFINITE, Rank::ROOT),
Rank::new(256 + 3 * 256, DEFAULT_MIN_HOP_RANK_INCREASE)
);
// 1024 + 3 * 256
assert_eq!(
ObjectiveFunction0::rank(
Rank::INFINITE,
Rank::new(1024, DEFAULT_MIN_HOP_RANK_INCREASE)
),
Rank::new(1024 + 3 * 256, DEFAULT_MIN_HOP_RANK_INCREASE)
);
}
#[test]
#[should_panic]
fn rank_increase_infinite() {
assert_eq!(
ObjectiveFunction0::rank(Rank::INFINITE, Rank::INFINITE),
Rank::INFINITE
);
}
#[test]
fn empty_set() {
assert_eq!(
ObjectiveFunction0::preferred_parent(&ParentSet::default()),
None
);
}
#[test]
fn non_empty_set() {
use crate::wire::Ipv6Address;
let mut parents = ParentSet::default();
parents.add(Parent::new(
Ipv6Address::default(),
0,
Rank::ROOT,
Default::default(),
Ipv6Address::default(),
));
let mut address = Ipv6Address::default();
address.0[15] = 1;
parents.add(Parent::new(
address,
0,
Rank::new(1024, DEFAULT_MIN_HOP_RANK_INCREASE),
Default::default(),
Ipv6Address::default(),
));
assert_eq!(
ObjectiveFunction0::preferred_parent(&parents),
Some(&Parent::new(
Ipv6Address::default(),
0,
Rank::ROOT,
Default::default(),
Ipv6Address::default(),
))
);
}
}

189
src/iface/rpl/parents.rs Normal file
View File

@ -0,0 +1,189 @@
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,
address: Ipv6Address,
preference: u8,
version_number: SequenceCounter,
dodag_id: Ipv6Address,
}
impl Parent {
/// Create a new parent.
pub(crate) fn new(
address: Ipv6Address,
preference: u8,
rank: Rank,
version_number: SequenceCounter,
dodag_id: Ipv6Address,
) -> Self {
Self {
rank,
address,
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::Vec<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, parent: Parent) {
if let Some(p) = self.find_mut(parent.address) {
// Update information
*p = parent;
} else if let Err(p) = self.parents.push(parent) {
// Look for the worst parent
if let Some(worst) = self.worst_parent() {
if worst.rank().dag_rank() > parent.rank().dag_rank() {
*worst = parent;
} else {
net_debug!("could not add parent");
}
} else {
// WARNING: there should be a worst parent, since the list of parents is not empty
unreachable!();
}
}
}
/// Find a parent based on its address.
pub(crate) fn find(&self, address: Ipv6Address) -> Option<&Parent> {
self.parents.iter().find(|p| p.address == address)
}
/// Find a mutable parent based on its address.
pub(crate) fn find_mut(&mut self, address: Ipv6Address) -> Option<&mut Parent> {
self.parents.iter_mut().find(|p| p.address == address)
}
/// Return a slice to the parent set.
pub(crate) fn parents(&self) -> &[Parent] {
&self.parents
}
/// Find the worst parent that is currently in the parent set.
fn worst_parent(&mut self) -> Option<&mut Parent> {
let mut worst: Option<&mut Parent> = None;
for p in self.parents.iter_mut() {
if worst.is_none() || worst.as_mut().unwrap().rank.dag_rank() < p.rank.dag_rank() {
worst = Some(p);
}
}
worst
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn add_parent() {
let mut set = ParentSet::default();
set.add(Parent::new(
Default::default(),
0,
Rank::ROOT,
Default::default(),
Default::default(),
));
assert_eq!(
set.find(Default::default()),
Some(&Parent::new(
Default::default(),
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(Parent::new(
address,
0,
Rank::new(256 * i, DEFAULT_MIN_HOP_RANK_INCREASE),
Default::default(),
address,
));
assert_eq!(
set.find(address),
Some(&Parent::new(
address,
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(Parent::new(
address,
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(Parent::new(
address,
0,
Rank::new(0, DEFAULT_MIN_HOP_RANK_INCREASE),
Default::default(),
address,
));
assert_eq!(
set.find(address),
Some(&Parent::new(
address,
0,
Rank::new(0, DEFAULT_MIN_HOP_RANK_INCREASE),
Default::default(),
address
))
);
assert_eq!(set.find(last_address), None);
}
}

View File

@ -25,8 +25,8 @@ use super::consts::DEFAULT_MIN_HOP_RANK_INCREASE;
#[derive(Debug, Clone, Copy, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Rank {
value: u16,
min_hop_rank_increase: u16,
pub(super) value: u16,
pub(super) min_hop_rank_increase: u16,
}
impl core::fmt::Display for Rank {
@ -46,6 +46,8 @@ impl Rank {
/// The `MinHopRankIncrease` is used for calculating the integer part for comparing to other
/// Ranks.
pub const fn new(value: u16, min_hop_rank_increase: u16) -> Self {
assert!(min_hop_rank_increase > 0);
Self {
value,
min_hop_rank_increase,

View File

@ -145,6 +145,7 @@ mod config {
pub const REASSEMBLY_BUFFER_COUNT: usize = 4;
pub const REASSEMBLY_BUFFER_SIZE: usize = 1500;
pub const RPL_RELATIONS_BUFFER_COUNT: usize = 16;
pub const RPL_PARENTS_BUFFER_COUNT: usize = 8;
}
#[cfg(not(test))]