statime/config/port.rs
1use rand::Rng;
2
3use crate::time::{Duration, Interval};
4#[cfg(doc)]
5use crate::{config::AcceptableMasterList, port::Port};
6
7/// Which delay mechanism a port is using.
8///
9/// Currently, statime only supports the end to end (E2E) delay mechanism.
10#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
11pub enum DelayMechanism {
12 /// End to end delay mechanism. Delay measurement is done directly to the
13 /// chosen master, across potential transparent nodes in between.
14 E2E {
15 /// The time between sending two delay requests
16 interval: Interval,
17 },
18 /// Peer to peer delay mechanism. Delay measurement is done on the
19 /// individaul links.
20 P2P {
21 /// The time between sending two peer delay requests
22 interval: Interval,
23 },
24 // No support for other delay mechanisms
25}
26
27#[repr(u8)]
28#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, PartialOrd, Ord)]
29/// Minor version to be used in PTP protocol messages
30pub enum PtpMinorVersion {
31 /// 0
32 Zero = 0,
33 /// 1
34 One = 1,
35}
36
37impl TryFrom<u8> for PtpMinorVersion {
38 type Error = &'static str;
39
40 fn try_from(value: u8) -> Result<Self, Self::Error> {
41 match value {
42 0 => Ok(PtpMinorVersion::Zero),
43 1 => Ok(PtpMinorVersion::One),
44 _ => Err(""),
45 }
46 }
47}
48
49impl From<PtpMinorVersion> for u8 {
50 fn from(value: PtpMinorVersion) -> Self {
51 value as u8
52 }
53}
54
55/// Configuration items of the PTP PortDS dataset. Dynamical fields are kept
56/// as part of [crate::port::Port].
57#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
58pub struct PortConfig<A> {
59 /// A list that contains all nodes that this [`Port`] will accept as a
60 /// master.
61 ///
62 /// This should implement the [`AcceptableMasterList`] trait.
63 pub acceptable_master_list: A,
64
65 /// The mechanism used to measure the delay at this [`Port`].
66 pub delay_mechanism: DelayMechanism,
67
68 /// The time between announcements.
69 pub announce_interval: Interval,
70
71 /// Specifies how many [`announce_interval`](`Self::announce_interval`)s to
72 /// wait until the announce message expires.
73 pub announce_receipt_timeout: u8,
74
75 /// Time between two sync messages when this [`Port`] is in master mode.
76 pub sync_interval: Interval,
77
78 /// Never let this [`Port`] become a slave.
79 pub master_only: bool,
80
81 /// The estimated asymmetry in the link connected to this [`Port`]
82 pub delay_asymmetry: Duration,
83
84 /// Minor version number to use.
85 pub minor_ptp_version: PtpMinorVersion,
86 // Notes:
87 // Fields specific for delay mechanism are kept as part of [DelayMechanism].
88 // Major version is always 2, so not stored (versionNumber)
89}
90
91impl<A> PortConfig<A> {
92 /// Minimum time between two delay request messages
93 pub fn min_delay_req_interval(&self) -> Interval {
94 match self.delay_mechanism {
95 DelayMechanism::E2E { interval } => interval,
96 DelayMechanism::P2P { interval } => interval,
97 }
98 }
99
100 /// Time between two announce messages
101 ///
102 /// For more information see *IEEE1588-2019 section 9.2.6.12*
103 pub fn announce_duration(&self, rng: &mut impl Rng) -> core::time::Duration {
104 // add some randomness so that not all timers expire at the same time
105 let factor = 1.0 + rng.sample::<f64, _>(rand::distributions::Open01);
106 let duration = self.announce_interval.as_core_duration();
107
108 duration.mul_f64(factor * self.announce_receipt_timeout as u32 as f64)
109 }
110}