瀏覽代碼

Add objective function and parent set

Thibaut Vandervelden 1 年之前
父節點
當前提交
f68603d8b8
共有 8 個文件被更改,包括 335 次插入2 次删除
  1. 6 0
      Cargo.toml
  2. 1 0
      build.rs
  3. 1 0
      gen_config.py
  4. 2 0
      src/iface/rpl/mod.rs
  5. 131 0
      src/iface/rpl/of0.rs
  6. 189 0
      src/iface/rpl/parents.rs
  7. 4 2
      src/iface/rpl/rank.rs
  8. 1 0
      src/lib.rs

+ 6 - 0
Cargo.toml

@@ -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 - 0
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
 ];
 

+ 1 - 0
gen_config.py

@@ -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 - 0
src/iface/rpl/mod.rs

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

+ 131 - 0
src/iface/rpl/of0.rs

@@ -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 - 0
src/iface/rpl/parents.rs

@@ -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);
+    }
+}

+ 4 - 2
src/iface/rpl/rank.rs

@@ -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,

+ 1 - 0
src/lib.rs

@@ -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))]