mirror of
https://github.com/smoltcp-rs/smoltcp.git
synced 2025-10-02 07:10:39 +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-64 = []
|
||||||
rpl-relations-buffer-count-128 = []
|
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
|
# END AUTOGENERATED CONFIG FEATURES
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
|
1
build.rs
1
build.rs
@ -19,6 +19,7 @@ static CONFIGS: &[(&str, usize)] = &[
|
|||||||
("DNS_MAX_SERVER_COUNT", 1),
|
("DNS_MAX_SERVER_COUNT", 1),
|
||||||
("DNS_MAX_NAME_SIZE", 255),
|
("DNS_MAX_NAME_SIZE", 255),
|
||||||
("RPL_RELATIONS_BUFFER_COUNT", 16),
|
("RPL_RELATIONS_BUFFER_COUNT", 16),
|
||||||
|
("RPL_PARENTS_BUFFER_COUNT", 8),
|
||||||
// END AUTOGENERATED CONFIG FEATURES
|
// 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_server_count", default=1, min=1, max=32, pow2=4)
|
||||||
feature("dns_max_name_size", default=255, min=64, max=255, pow2=True)
|
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_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
|
# ========= Update Cargo.toml
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
mod consts;
|
mod consts;
|
||||||
mod lollipop;
|
mod lollipop;
|
||||||
|
mod of0;
|
||||||
|
mod parents;
|
||||||
mod rank;
|
mod rank;
|
||||||
mod relations;
|
mod relations;
|
||||||
mod trickle;
|
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)]
|
#[derive(Debug, Clone, Copy, Eq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub struct Rank {
|
pub struct Rank {
|
||||||
value: u16,
|
pub(super) value: u16,
|
||||||
min_hop_rank_increase: u16,
|
pub(super) min_hop_rank_increase: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::fmt::Display for Rank {
|
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
|
/// The `MinHopRankIncrease` is used for calculating the integer part for comparing to other
|
||||||
/// Ranks.
|
/// Ranks.
|
||||||
pub const fn new(value: u16, min_hop_rank_increase: u16) -> Self {
|
pub const fn new(value: u16, min_hop_rank_increase: u16) -> Self {
|
||||||
|
assert!(min_hop_rank_increase > 0);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
value,
|
value,
|
||||||
min_hop_rank_increase,
|
min_hop_rank_increase,
|
||||||
|
@ -145,6 +145,7 @@ mod config {
|
|||||||
pub const REASSEMBLY_BUFFER_COUNT: usize = 4;
|
pub const REASSEMBLY_BUFFER_COUNT: usize = 4;
|
||||||
pub const REASSEMBLY_BUFFER_SIZE: usize = 1500;
|
pub const REASSEMBLY_BUFFER_SIZE: usize = 1500;
|
||||||
pub const RPL_RELATIONS_BUFFER_COUNT: usize = 16;
|
pub const RPL_RELATIONS_BUFFER_COUNT: usize = 16;
|
||||||
|
pub const RPL_PARENTS_BUFFER_COUNT: usize = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user