mirror of
https://github.com/smoltcp-rs/smoltcp.git
synced 2025-09-30 14:20:52 +00:00
Add objective function and parent set
This commit is contained in:
parent
7b4246d003
commit
f68603d8b8
@ -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]]
|
||||
|
1
build.rs
1
build.rs
@ -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
|
||||
];
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
131
src/iface/rpl/of0.rs
Normal 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
189
src/iface/rpl/parents.rs
Normal 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);
|
||||
}
|
||||
}
|
@ -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,
|
||||
|
@ -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))]
|
||||
|
Loading…
x
Reference in New Issue
Block a user