From a9d8d041da721a45268ae9de4f0978e68df0e5cd Mon Sep 17 00:00:00 2001 From: Teodor Wozniak Date: Thu, 1 Aug 2024 19:28:15 +0200 Subject: [PATCH 01/10] implemented virtual system clock --- Cargo.lock | 12 +++ statime-linux/src/clock/mod.rs | 30 +++++- statime-linux/src/config/mod.rs | 3 + statime-linux/src/main.rs | 175 ++++++++++++++++++++------------ statime/Cargo.toml | 1 + statime/src/clock.rs | 21 ++++ statime/src/lib.rs | 6 ++ statime/src/overlay_clock.rs | 67 ++++++++++++ statime/src/shared_clock.rs | 40 ++++++++ 9 files changed, 288 insertions(+), 67 deletions(-) create mode 100644 statime/src/overlay_clock.rs create mode 100644 statime/src/shared_clock.rs diff --git a/Cargo.lock b/Cargo.lock index 40c757a1d..b5518bd30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,6 +75,17 @@ dependencies = [ "serde", ] +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "az" version = "1.2.1" @@ -503,6 +514,7 @@ name = "statime" version = "0.2.1" dependencies = [ "arrayvec", + "auto_impl", "az", "fixed", "libm", diff --git a/statime-linux/src/clock/mod.rs b/statime-linux/src/clock/mod.rs index 36627eaf2..9ffce696d 100644 --- a/statime-linux/src/clock/mod.rs +++ b/statime-linux/src/clock/mod.rs @@ -6,7 +6,7 @@ use clock_steering::{unix::UnixClock, TimeOffset}; use statime::{ config::{LeapIndicator, TimePropertiesDS}, time::{Duration, Time}, - Clock, + Clock, OverlayClock, SharedClock, }; #[derive(Debug, Clone)] @@ -172,3 +172,31 @@ impl Clock for LinuxClock { pub fn libc_timespec_into_instant(spec: libc::timespec) -> Time { Time::from_fixed_nanos(spec.tv_sec as i128 * 1_000_000_000i128 + spec.tv_nsec as i128) } + + +pub trait PortTimestampToTime { + fn port_timestamp_to_time(&self, ts: timestamped_socket::socket::Timestamp) -> Time; +} + +impl PortTimestampToTime for LinuxClock { + fn port_timestamp_to_time(&self, mut ts: timestamped_socket::socket::Timestamp) -> Time { + // get_tai gives zero if this is a hardware clock, and the needed + // correction when this port uses software timestamping + ts.seconds += self.get_tai_offset().expect("Unable to get tai offset") as libc::time_t; + Time::from_fixed_nanos(ts.seconds as i128 * 1_000_000_000i128 + ts.nanos as i128) + } +} + +impl PortTimestampToTime for OverlayClock { + fn port_timestamp_to_time(&self, ts: timestamped_socket::socket::Timestamp) -> Time { + let roclock_time = self.underlying().port_timestamp_to_time(ts); + //log::debug!("port_timestamp_to_time for OverlayClock called"); + self.time_from_underlying(roclock_time) + } +} + +impl PortTimestampToTime for SharedClock> { + fn port_timestamp_to_time(&self, ts: timestamped_socket::socket::Timestamp) -> Time { + self.0.lock().unwrap().port_timestamp_to_time(ts) + } +} diff --git a/statime-linux/src/config/mod.rs b/statime-linux/src/config/mod.rs index 01216b8e0..bb8eeda6e 100644 --- a/statime-linux/src/config/mod.rs +++ b/statime-linux/src/config/mod.rs @@ -36,6 +36,8 @@ pub struct Config { pub ports: Vec, #[serde(default)] pub observability: ObservabilityConfig, + #[serde(default)] + pub virtual_system_clock: bool, } #[derive(Deserialize, Debug, Clone, PartialEq, Eq)] @@ -285,6 +287,7 @@ interface = "enp0s31f6" path_trace: false, ports: vec![expected_port], observability: ObservabilityConfig::default(), + virtual_system_clock: false, }; let actual = toml::from_str(MINIMAL_CONFIG).unwrap(); diff --git a/statime-linux/src/main.rs b/statime-linux/src/main.rs index dbbc26907..a2a9ad2ac 100644 --- a/statime-linux/src/main.rs +++ b/statime-linux/src/main.rs @@ -16,15 +16,15 @@ use statime::{ TimestampContext, MAX_DATA_LEN, }, time::Time, - PtpInstance, PtpInstanceState, + PtpInstance, Clock, OverlayClock, SharedClock, PtpInstanceState, }; use statime_linux::{ - clock::LinuxClock, + clock::{LinuxClock, PortTimestampToTime}, initialize_logging_parse_config, observer::ObservableInstanceState, socket::{ open_ethernet_socket, open_ipv4_event_socket, open_ipv4_general_socket, - open_ipv6_event_socket, open_ipv6_general_socket, timestamp_to_time, PtpTargetAddress, + open_ipv6_event_socket, open_ipv6_general_socket, PtpTargetAddress, }, tlvforwarder::TlvForwarder, }; @@ -38,6 +38,16 @@ use tokio::{ time::Sleep, }; +trait PortClock: Clock::Error> + PortTimestampToTime {} +impl PortClock for LinuxClock { +} +impl PortClock for SharedClock> { +} +type BoxedClock = Box; +//type SharedBoxedClock = SharedClock; +type SharedOverlayClock = SharedClock>; + + #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] pub struct Args { @@ -93,6 +103,20 @@ impl Future for Timer { } } +#[derive(Debug, Clone)] +enum SystemClock { + Linux(LinuxClock), + Overlay(SharedOverlayClock) +} +impl SystemClock { + fn clone_boxed(&self) -> BoxedClock { + match self { + Self::Linux(clock) => Box::new(clock.clone()), + Self::Overlay(clock) => Box::new(clock.clone()) + } + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] enum ClockSyncMode { #[default] @@ -100,16 +124,25 @@ enum ClockSyncMode { ToSystem, } -fn start_clock_task(clock: LinuxClock) -> tokio::sync::watch::Sender { +fn start_clock_task(clock: LinuxClock, system_clock: SystemClock) -> tokio::sync::watch::Sender { let (mode_sender, mode_receiver) = tokio::sync::watch::channel(ClockSyncMode::FromSystem); - tokio::spawn(clock_task(clock, mode_receiver)); + match system_clock { + SystemClock::Linux(system_clock) => { + tokio::spawn(clock_task(clock, system_clock, None, mode_receiver)); + }, + SystemClock::Overlay(overlay_clock) => { + tokio::spawn(clock_task(clock, overlay_clock.clone(), Some(overlay_clock), mode_receiver)); + } + } mode_sender } -async fn clock_task( - clock: LinuxClock, +async fn clock_task>( + mut clock: LinuxClock, + mut system_clock: C, + system_clock_overlay: Option, mut mode_receiver: tokio::sync::watch::Receiver, ) { let mut measurement_timer = pin!(Timer::new()); @@ -120,14 +153,17 @@ async fn clock_task( let mut filter = KalmanFilter::new(KalmanConfiguration::default()); let mut current_mode = *mode_receiver.borrow_and_update(); - let mut filter_clock = match current_mode { - ClockSyncMode::FromSystem => clock.clone(), - ClockSyncMode::ToSystem => LinuxClock::CLOCK_TAI, - }; loop { tokio::select! { () = &mut measurement_timer => { - let (t1, t2, t3) = clock.system_offset().expect("Unable to determine offset from system clock"); + let (raw_t1, t2, raw_t3) = clock.system_offset().expect("Unable to determine offset from system clock"); + let (t1, t3) = match &system_clock_overlay { + Some(shared) => { + let overlay = shared.0.lock().expect("shared clock lock is tainted"); + (overlay.time_from_underlying(raw_t1), overlay.time_from_underlying(raw_t3)) + }, + None => (raw_t1, raw_t3) + }; log::debug!("Interclock measurement: {} {} {}", t1, t2, t3); @@ -135,26 +171,31 @@ async fn clock_task( let offset_a = t2 - t1; let offset_b = t3 - t2; - let m = match current_mode { - ClockSyncMode::FromSystem => Measurement { - event_time: t2, - offset: Some(offset_a - delay), - delay: Some(delay), - peer_delay: None, - raw_sync_offset: Some(offset_a), - raw_delay_offset: Some(-offset_b), + let update = match current_mode { + ClockSyncMode::FromSystem => { + let m = Measurement { + event_time: t2, + offset: Some(offset_a - delay), + delay: Some(delay), + peer_delay: None, + raw_sync_offset: Some(offset_a), + raw_delay_offset: Some(-offset_b), + }; + filter.measurement(m, &mut clock) }, - ClockSyncMode::ToSystem => Measurement { - event_time: t1+delay, - offset: Some(offset_b - delay), - delay: Some(delay), - peer_delay: None, - raw_sync_offset: Some(offset_b), - raw_delay_offset: Some(-offset_a), + ClockSyncMode::ToSystem => { + let m = Measurement { + event_time: t1+delay, + offset: Some(offset_b - delay), + delay: Some(delay), + peer_delay: None, + raw_sync_offset: Some(offset_b), + raw_delay_offset: Some(-offset_a), + }; + filter.measurement(m, &mut system_clock) }, }; - let update = filter.measurement(m, &mut filter_clock); if let Some(timeout) = update.next_update { update_timer.as_mut().reset(timeout); } @@ -162,7 +203,10 @@ async fn clock_task( measurement_timer.as_mut().reset(std::time::Duration::from_millis(250)); } () = &mut update_timer => { - let update = filter.update(&mut filter_clock); + let update = match current_mode { + ClockSyncMode::FromSystem => filter.update(&mut clock), + ClockSyncMode::ToSystem => filter.update(&mut system_clock), + }; if let Some(timeout) = update.next_update { update_timer.as_mut().reset(timeout); } @@ -172,11 +216,10 @@ async fn clock_task( if new_mode != current_mode { let mut new_filter = KalmanFilter::new(KalmanConfiguration::default()); std::mem::swap(&mut filter, &mut new_filter); - new_filter.demobilize(&mut filter_clock); - match new_mode { - ClockSyncMode::FromSystem => filter_clock = clock.clone(), - ClockSyncMode::ToSystem => filter_clock = LinuxClock::CLOCK_TAI, - } + match current_mode { + ClockSyncMode::FromSystem => new_filter.demobilize(&mut clock), + ClockSyncMode::ToSystem => new_filter.demobilize(&mut system_clock) + }; current_mode = new_mode; } } @@ -217,6 +260,12 @@ async fn actual_main() { let time_properties_ds = TimePropertiesDS::new_arbitrary_time(false, false, TimeSource::InternalOscillator); + let system_clock = if config.virtual_system_clock { + SystemClock::Overlay(SharedClock::new(OverlayClock::new(LinuxClock::CLOCK_TAI))) + } else { + SystemClock::Linux(LinuxClock::CLOCK_TAI) + }; + // Leak to get a static reference, the ptp instance will be around for the rest // of the program anyway let instance = Box::leak(Box::new(PtpInstance::new( @@ -252,7 +301,7 @@ async fn actual_main() { for port_config in config.ports { let interface = port_config.interface; let network_mode = port_config.network_mode; - let (port_clock, timestamping) = match port_config.hardware_clock { + let (port_clock, port_clock2, timestamping) = match port_config.hardware_clock { Some(idx) => { let mut clock = LinuxClock::open_idx(idx).expect("Unable to open clock"); if let Some(id) = clock_name_map.get(&idx) { @@ -262,13 +311,21 @@ async fn actual_main() { let id = internal_sync_senders.len(); clock_port_map.push(Some(id)); clock_name_map.insert(idx, id); - internal_sync_senders.push(start_clock_task(clock.clone())); + internal_sync_senders.push(start_clock_task(clock.clone(), system_clock.clone())); } - (clock, InterfaceTimestampMode::HardwarePTPAll) + ( + Box::new(clock.clone()) as BoxedClock, + Box::new(clock) as BoxedClock, + InterfaceTimestampMode::HardwarePTPAll + ) } None => { clock_port_map.push(None); - (LinuxClock::CLOCK_TAI, InterfaceTimestampMode::SoftwareAll) + ( + system_clock.clone_boxed(), + system_clock.clone_boxed(), + InterfaceTimestampMode::SoftwareAll + ) } }; @@ -277,7 +334,7 @@ async fn actual_main() { let port = instance.add_port( port_config.into(), KalmanConfiguration::default(), - port_clock.clone(), + port_clock2, rng, ); @@ -444,7 +501,7 @@ type BmcaPort = Port< InBmca, Option>, StdRng, - LinuxClock, + BoxedClock, KalmanFilter, RwLock, >; @@ -462,7 +519,7 @@ async fn port_task( mut general_socket: Socket, mut bmca_notify: tokio::sync::watch::Receiver, mut tlv_forwarder: TlvForwarder, - clock: LinuxClock, + clock: BoxedClock, ) { let mut timers = Timers { port_sync_timer: pin!(Timer::new()), @@ -510,12 +567,9 @@ async fn port_task( if !is_message_buffer_compatible(&event_buffer[..packet.bytes_read]) { // do not spam with missing timestamp error in mixed-version PTPv1+v2 networks PortActionIterator::empty() - } else if let Some(mut timestamp) = packet.timestamp { - // get_tai gives zero if this is a hardware clock, and the needed - // correction when this port uses software timestamping - timestamp.seconds += clock.get_tai_offset().expect("Unable to get tai offset") as i64; + } else if let Some(timestamp) = packet.timestamp { log::trace!("Recv timestamp: {:?}", packet.timestamp); - port.handle_event_receive(&event_buffer[..packet.bytes_read], timestamp_to_time(timestamp)) + port.handle_event_receive(&event_buffer[..packet.bytes_read], clock.port_timestamp_to_time(timestamp)) } else { log::error!("Missing recv timestamp"); PortActionIterator::empty() @@ -585,7 +639,7 @@ async fn ethernet_port_task( mut socket: Socket, mut bmca_notify: tokio::sync::watch::Receiver, mut tlv_forwarder: TlvForwarder, - clock: LinuxClock, + clock: BoxedClock, ) { let mut timers = Timers { port_sync_timer: pin!(Timer::new()), @@ -635,12 +689,9 @@ async fn ethernet_port_task( let mut actions = tokio::select! { result = socket.recv(&mut event_buffer) => match result { Ok(packet) => { - if let Some(mut timestamp) = packet.timestamp { - // get_tai gives zero if this is a hardware clock, and the needed - // correction when this port uses software timestamping - timestamp.seconds += clock.get_tai_offset().expect("Unable to get tai offset") as i64; + if let Some(timestamp) = packet.timestamp { log::trace!("Recv timestamp: {:?}", packet.timestamp); - port.handle_event_receive(&event_buffer[..packet.bytes_read], timestamp_to_time(timestamp)) + port.handle_event_receive(&event_buffer[..packet.bytes_read], clock.port_timestamp_to_time(timestamp)) } else { port.handle_general_receive(&event_buffer[..packet.bytes_read]) } @@ -706,7 +757,7 @@ async fn handle_actions( general_socket: &mut Socket, timers: &mut Timers<'_>, tlv_forwarder: &TlvForwarder, - clock: &LinuxClock, + clock: &BoxedClock, ) -> Option<(TimestampContext, Time)> { let mut pending_timestamp = None; @@ -731,13 +782,9 @@ async fn handle_actions( .expect("Failed to send event message"); // anything we send later will have a later pending (send) timestamp - if let Some(mut time) = time { - // get_tai gives zero if this is a hardware clock, and the needed - // correction when this port uses software timestamping - time.seconds += - clock.get_tai_offset().expect("Unable to get tai offset") as i64; + if let Some(time) = time { log::trace!("Send timestamp {:?}", time); - pending_timestamp = Some((context, timestamp_to_time(time))); + pending_timestamp = Some((context, clock.port_timestamp_to_time(time))); } else { log::error!("Missing send timestamp"); } @@ -785,7 +832,7 @@ async fn handle_actions_ethernet( socket: &mut Socket, timers: &mut Timers<'_>, tlv_forwarder: &TlvForwarder, - clock: &LinuxClock, + clock: &BoxedClock, ) -> Option<(TimestampContext, Time)> { let mut pending_timestamp = None; @@ -818,13 +865,9 @@ async fn handle_actions_ethernet( .expect("Failed to send event message"); // anything we send later will have a later pending (send) timestamp - if let Some(mut time) = time { - // get_tai gives zero if this is a hardware clock, and the needed - // correction when this port uses software timestamping - time.seconds += - clock.get_tai_offset().expect("Unable to get tai offset") as i64; + if let Some(time) = time { log::trace!("Send timestamp {:?}", time); - pending_timestamp = Some((context, timestamp_to_time(time))); + pending_timestamp = Some((context, clock.port_timestamp_to_time(time))); } else { log::error!("Missing send timestamp"); } diff --git a/statime/Cargo.toml b/statime/Cargo.toml index a8eeb2b92..431e92e2d 100644 --- a/statime/Cargo.toml +++ b/statime/Cargo.toml @@ -19,6 +19,7 @@ serde = ["dep:serde", "arrayvec/serde"] [dependencies] arrayvec.workspace = true +auto_impl = "1.2.0" az.workspace = true fixed.workspace = true libm.workspace = true diff --git a/statime/src/clock.rs b/statime/src/clock.rs index 81402e536..d604ae17e 100644 --- a/statime/src/clock.rs +++ b/statime/src/clock.rs @@ -1,5 +1,6 @@ //! Definitions and implementations of the abstract clock types +use auto_impl::auto_impl; use crate::{ datastructures::datasets::TimePropertiesDS, time::{Duration, Time}, @@ -16,6 +17,7 @@ use crate::{ /// Note that the clock implementation is responsible for handling leap seconds. /// On most operating systems, this will be provided for by the OS, but on some /// platforms this may require extra logic. +#[auto_impl(Box)] pub trait Clock { /// Type of the error the methods of this [`Clock`] may return type Error: core::fmt::Debug; @@ -47,3 +49,22 @@ pub trait Clock { /// system. fn set_properties(&mut self, time_properties_ds: &TimePropertiesDS) -> Result<(), Self::Error>; } + +/* #[cfg(feature = "std")] +use std::boxed::Box; +#[cfg(feature = "std")] +impl Clock for Box + Send + Sync + '_> { + type Error = E; + fn now(&self) -> Time { + self.as_ref().now() + } + fn step_clock(&mut self, offset: Duration) -> Result { + self.as_mut().step_clock(offset) + } + fn set_frequency(&mut self, ppm: f64) -> Result { + self.as_mut().set_frequency(ppm) + } + fn set_properties(&mut self, time_properties_ds: &TimePropertiesDS) -> Result<(), Self::Error> { + self.as_mut().set_properties(time_properties_ds) + } +} */ \ No newline at end of file diff --git a/statime/src/lib.rs b/statime/src/lib.rs index 568c3aefa..619eae3ab 100644 --- a/statime/src/lib.rs +++ b/statime/src/lib.rs @@ -85,6 +85,9 @@ extern crate std; mod bmc; mod clock; +mod overlay_clock; +#[cfg(feature = "std")] +mod shared_clock; pub mod config; pub(crate) mod datastructures; pub mod filters; @@ -96,6 +99,9 @@ pub mod time; pub use clock::Clock; pub use ptp_instance::{PtpInstance, PtpInstanceState, PtpInstanceStateMutex}; +pub use overlay_clock::OverlayClock; +#[cfg(feature = "std")] +pub use shared_clock::SharedClock; /// Helper types used for fuzzing /// diff --git a/statime/src/overlay_clock.rs b/statime/src/overlay_clock.rs new file mode 100644 index 000000000..26cc7786e --- /dev/null +++ b/statime/src/overlay_clock.rs @@ -0,0 +1,67 @@ +use crate::{time::Time, time::Duration, Clock}; + + +/// An overlay over other, read-only clock, frequency-locked to it. +/// In other words, a virtual clock which can be tuned in software without affecting +/// the underlying system or hardware clock. +#[derive(Debug)] +pub struct OverlayClock { + roclock: C, + last_sync: Time, + shift: Duration, + freq_scale_ppm_diff: f64 +} + +impl OverlayClock { + /// Creates new OverlayClock based on given clock + pub fn new(underlying_clock: C) -> Self { + let now = underlying_clock.now(); + Self { + roclock: underlying_clock, + last_sync: now, + shift: Duration::from_fixed_nanos(0), + freq_scale_ppm_diff: 0.0, + } + } + + /// Converts (shifts and scales) `Time` in underlying clock's timescale to overlay clock timescale + pub fn time_from_underlying(&self, roclock_time: Time) -> Time { + let elapsed = roclock_time - self.last_sync; + let corr = elapsed * self.freq_scale_ppm_diff / 1_000_000; + + roclock_time + self.shift + corr + // equals self.last_sync + self.shift + elapsed + corr + } + + /// Returns reference to underlying clock + pub fn underlying(&self) -> &C { + &self.roclock + } +} + +impl Clock for OverlayClock { + type Error = C::Error; + fn now(&self) -> Time { + self.time_from_underlying(self.roclock.now()) + } + fn set_frequency(&mut self, ppm: f64) -> Result { + // save current shift: + let now_roclock = self.roclock.now(); + let now_local = self.time_from_underlying(now_roclock); + self.shift = now_local - now_roclock; + self.last_sync = now_roclock; + + self.freq_scale_ppm_diff = ppm; + debug_assert_eq!(self.time_from_underlying(self.last_sync), now_local); + Ok(now_local) + } + fn step_clock(&mut self, offset: Duration) -> Result { + self.last_sync = self.roclock.now(); + self.shift += offset; + Ok(self.time_from_underlying(self.last_sync)) + } + fn set_properties(&mut self, _time_properties_ds: &crate::config::TimePropertiesDS) -> Result<(), Self::Error> { + // we can ignore the properies - they are just metadata + Ok(()) + } +} diff --git a/statime/src/shared_clock.rs b/statime/src/shared_clock.rs new file mode 100644 index 000000000..61685369f --- /dev/null +++ b/statime/src/shared_clock.rs @@ -0,0 +1,40 @@ +use std::sync::Mutex; +use std::sync::Arc; +use crate::time::Duration; +use crate::time::Time; +use crate::Clock; + +/// A wrapper for stateful `statime::Clock` implementations to make them behave +/// like e.g. `statime_linux::LinuxClock` - clones share state with each other +#[derive(Debug)] +pub struct SharedClock(pub Arc>) where C: Clock; + +impl SharedClock { + /// Take given clock and make it a `SharedClock` + pub fn new(clock: C) -> Self { + Self(Arc::new(Mutex::new(clock))) + } +} + +impl Clone for SharedClock { + /// Clone the shared reference to the clock (behaviour consistent with `statime_linux::LinuxClock`) + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +impl Clock for SharedClock { + type Error = C::Error; + fn now(&self) -> Time { + self.0.lock().unwrap().now() + } + fn set_frequency(&mut self, ppm: f64) -> Result { + self.0.lock().unwrap().set_frequency(ppm) + } + fn step_clock(&mut self, offset: Duration) -> Result { + self.0.lock().unwrap().step_clock(offset) + } + fn set_properties(&mut self, time_properties_ds: &crate::config::TimePropertiesDS) -> Result<(), Self::Error> { + self.0.lock().unwrap().set_properties(time_properties_ds) + } +} From 5d698464cf47131d30fbb09ec9c9e1131c997210 Mon Sep 17 00:00:00 2001 From: Teodor Wozniak Date: Thu, 15 Aug 2024 00:43:42 +0200 Subject: [PATCH 02/10] export clock using usrvclock protocol (not tested yet) --- Cargo.lock | 42 +++++++++++ Cargo.toml | 1 + statime-linux/Cargo.toml | 3 + statime-linux/src/clock/mod.rs | 6 +- statime-linux/src/config/mod.rs | 10 +++ statime-linux/src/main.rs | 26 +++++-- statime/Cargo.toml | 2 +- statime/src/lib.rs | 3 +- statime/src/overlay_clock.rs | 124 ++++++++++++++++++++++++++------ 9 files changed, 186 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b5518bd30..e576a2eee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,6 +107,12 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + [[package]] name = "bytemuck" version = "1.18.0" @@ -131,6 +137,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "clap" version = "4.5.17" @@ -192,6 +204,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "custom_error" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f8a51dd197fa6ba5b4dc98a990a43cc13693c23eb0089ebb0fcc1f04152bca6" + [[package]] name = "equivalent" version = "1.0.1" @@ -334,6 +352,18 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -531,6 +561,7 @@ dependencies = [ "arrayvec", "clap", "clock-steering", + "fixed", "hex", "libc", "log", @@ -545,6 +576,7 @@ dependencies = [ "tracing", "tracing-log", "tracing-subscriber", + "usrvclock", ] [[package]] @@ -715,6 +747,16 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +[[package]] +name = "usrvclock" +version = "0.1.0" +source = "git+https://gitlab.com/lumifaza/usrvclock-rs#0039099ced600f635928299db3a9adbb0a8db5f0" +dependencies = [ + "custom_error", + "nix", + "tokio", +] + [[package]] name = "utf8parse" version = "0.2.2" diff --git a/Cargo.toml b/Cargo.toml index f781d342f..54fad756e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,6 +46,7 @@ serde_test = { version = "1.0.176" } az = "1.2.1" fixed = "1.24" libm = "0.2.8" +auto_impl = "1.2.0" clock-steering = "0.2.0" timestamped-socket = "0.2.4" diff --git a/statime-linux/Cargo.toml b/statime-linux/Cargo.toml index da08fe135..728f67d71 100644 --- a/statime-linux/Cargo.toml +++ b/statime-linux/Cargo.toml @@ -23,6 +23,7 @@ path = "bin/statime-metrics-exporter.rs" statime.workspace = true arrayvec.workspace = true +fixed.workspace = true clap.workspace = true tracing.workspace = true tracing-log.workspace = true @@ -37,6 +38,8 @@ rand = { workspace = true, default-features = false, features = ["std", "std_rng serde.workspace = true serde_json.workspace = true +usrvclock = { git = "https://gitlab.com/lumifaza/usrvclock-rs", version = "0.1.0" } + clock-steering.workspace = true timestamped-socket.workspace = true diff --git a/statime-linux/src/clock/mod.rs b/statime-linux/src/clock/mod.rs index 9ffce696d..1358f360e 100644 --- a/statime-linux/src/clock/mod.rs +++ b/statime-linux/src/clock/mod.rs @@ -6,7 +6,7 @@ use clock_steering::{unix::UnixClock, TimeOffset}; use statime::{ config::{LeapIndicator, TimePropertiesDS}, time::{Duration, Time}, - Clock, OverlayClock, SharedClock, + Clock, SharedClock, overlay_clock::{OverlayClock, ClockOverlayExporter} }; #[derive(Debug, Clone)] @@ -187,7 +187,7 @@ impl PortTimestampToTime for LinuxClock { } } -impl PortTimestampToTime for OverlayClock { +impl PortTimestampToTime for OverlayClock { fn port_timestamp_to_time(&self, ts: timestamped_socket::socket::Timestamp) -> Time { let roclock_time = self.underlying().port_timestamp_to_time(ts); //log::debug!("port_timestamp_to_time for OverlayClock called"); @@ -195,7 +195,7 @@ impl PortTimestampToTime for OverlayClock { } } -impl PortTimestampToTime for SharedClock> { +impl PortTimestampToTime for SharedClock> { fn port_timestamp_to_time(&self, ts: timestamped_socket::socket::Timestamp) -> Time { self.0.lock().unwrap().port_timestamp_to_time(ts) } diff --git a/statime-linux/src/config/mod.rs b/statime-linux/src/config/mod.rs index bb8eeda6e..dbe5ffe28 100644 --- a/statime-linux/src/config/mod.rs +++ b/statime-linux/src/config/mod.rs @@ -38,6 +38,10 @@ pub struct Config { pub observability: ObservabilityConfig, #[serde(default)] pub virtual_system_clock: bool, + #[serde(default)] + pub usrvclock_export: bool, + #[serde(default = "default_usrvclock_path")] + pub usrvclock_path: PathBuf, } #[derive(Deserialize, Debug, Clone, PartialEq, Eq)] @@ -210,6 +214,10 @@ fn default_priority2() -> u8 { 128 } +fn default_usrvclock_path() -> PathBuf { + usrvclock::DEFAULT_SERVER_SOCKET_PATH.into() +} + fn default_delay_asymmetry() -> i64 { 0 } @@ -288,6 +296,8 @@ interface = "enp0s31f6" ports: vec![expected_port], observability: ObservabilityConfig::default(), virtual_system_clock: false, + usrvclock_export: false, + usrvclock_path: usrvclock::DEFAULT_SERVER_SOCKET_PATH.into(), }; let actual = toml::from_str(MINIMAL_CONFIG).unwrap(); diff --git a/statime-linux/src/main.rs b/statime-linux/src/main.rs index a2a9ad2ac..85c497c85 100644 --- a/statime-linux/src/main.rs +++ b/statime-linux/src/main.rs @@ -16,7 +16,7 @@ use statime::{ TimestampContext, MAX_DATA_LEN, }, time::Time, - PtpInstance, Clock, OverlayClock, SharedClock, PtpInstanceState, + PtpInstance, Clock, overlay_clock::{OverlayClock, CallbackExporter}, SharedClock, PtpInstanceState, }; use statime_linux::{ clock::{LinuxClock, PortTimestampToTime}, @@ -41,11 +41,11 @@ use tokio::{ trait PortClock: Clock::Error> + PortTimestampToTime {} impl PortClock for LinuxClock { } -impl PortClock for SharedClock> { +impl PortClock for SharedClock> { } type BoxedClock = Box; //type SharedBoxedClock = SharedClock; -type SharedOverlayClock = SharedClock>; +type SharedOverlayClock = SharedClock>; #[derive(Parser, Debug)] @@ -261,7 +261,25 @@ async fn actual_main() { TimePropertiesDS::new_arbitrary_time(false, false, TimeSource::InternalOscillator); let system_clock = if config.virtual_system_clock { - SystemClock::Overlay(SharedClock::new(OverlayClock::new(LinuxClock::CLOCK_TAI))) + let exporter = if config.usrvclock_export { + let mut server = usrvclock::Server::new(config.usrvclock_path.clone()).expect("failed to create usrvclock server"); + CallbackExporter::from(move |overlay: &statime::overlay_clock::ClockOverlay| { + use fixed::traits::LossyInto; + let last_sync: i128 = overlay.last_sync.nanos().lossy_into(); + let shift: i128 = overlay.shift.nanos().lossy_into(); + let to_share = usrvclock::ClockOverlay { + clock_id: libc::CLOCK_TAI as i64, + last_sync: last_sync as i64, + shift: shift as i64, + freq_scale: overlay.freq_scale + }; + server.send(to_share) + }) + } else { + CallbackExporter::from(|_: &statime::overlay_clock::ClockOverlay| {}) + }; + let overlay_clock = OverlayClock::new(LinuxClock::CLOCK_TAI, exporter); + SystemClock::Overlay(SharedClock::new(overlay_clock)) } else { SystemClock::Linux(LinuxClock::CLOCK_TAI) }; diff --git a/statime/Cargo.toml b/statime/Cargo.toml index 431e92e2d..0f36e1530 100644 --- a/statime/Cargo.toml +++ b/statime/Cargo.toml @@ -19,7 +19,7 @@ serde = ["dep:serde", "arrayvec/serde"] [dependencies] arrayvec.workspace = true -auto_impl = "1.2.0" +auto_impl.workspace = true az.workspace = true fixed.workspace = true libm.workspace = true diff --git a/statime/src/lib.rs b/statime/src/lib.rs index 619eae3ab..9db3f7c2b 100644 --- a/statime/src/lib.rs +++ b/statime/src/lib.rs @@ -85,7 +85,7 @@ extern crate std; mod bmc; mod clock; -mod overlay_clock; +pub mod overlay_clock; #[cfg(feature = "std")] mod shared_clock; pub mod config; @@ -99,7 +99,6 @@ pub mod time; pub use clock::Clock; pub use ptp_instance::{PtpInstance, PtpInstanceState, PtpInstanceStateMutex}; -pub use overlay_clock::OverlayClock; #[cfg(feature = "std")] pub use shared_clock::SharedClock; diff --git a/statime/src/overlay_clock.rs b/statime/src/overlay_clock.rs index 26cc7786e..77f9177a9 100644 --- a/statime/src/overlay_clock.rs +++ b/statime/src/overlay_clock.rs @@ -1,35 +1,107 @@ +//! Virtual (overlay) clock and utilities related to it + use crate::{time::Time, time::Duration, Clock}; +/// Clock overlay values +#[derive(Debug, Clone)] +pub struct ClockOverlay { + /// underlying clock's timestamp of the last synchronization + pub last_sync: Time, + /// value to add to the OS clock's timestamp to obtain the virtual clock's timestamp + pub shift: Duration, + /// frequency correction factor, positive numbers accelerate the virtual clock relative to OS clock, negative make is slower + pub freq_scale: f64, +} + +/// Trait used for exporting the changes of the overlay from overlay clock to a third-party +pub trait ClockOverlayExporter { + /// Called when overlay is updated. + /// It doesn't make sense to export clock from more than 1 ClockOverlay, hence this method is mutable + fn export(&mut self, overlay: &ClockOverlay); +} + +/// Dummy exporter, does not forward clock overlay changes anywhere +#[derive(Debug)] +pub struct DoNotExport { +} +impl ClockOverlayExporter for DoNotExport { + fn export(&mut self, _: &ClockOverlay) { + // no-op + } +} + +#[cfg(feature = "std")] +/// Calls specified callback when overlay changes +pub struct CallbackExporter (std::boxed::Box); + +#[cfg(feature = "std")] +impl ClockOverlayExporter for CallbackExporter { + fn export(&mut self, overlay: &ClockOverlay) { + (self.0)(overlay); + } +} + +#[cfg(feature = "std")] +impl core::fmt::Debug for CallbackExporter { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "CallbackExporter") + } +} + +#[cfg(feature = "std")] +impl From for CallbackExporter { + fn from(cb: F) -> Self { + Self(std::boxed::Box::new(cb)) + } +} + +/* #[cfg(feature = "std")] +impl From> for CallbackExporter { + fn from(cb: std::boxed::Box) -> Self { + Self(cb) + } +} */ + +impl ClockOverlayExporter for Option { + fn export(&mut self, overlay: &ClockOverlay) { + if let Some(v) = self { + v.export(overlay); + } + } +} + /// An overlay over other, read-only clock, frequency-locked to it. /// In other words, a virtual clock which can be tuned in software without affecting /// the underlying system or hardware clock. #[derive(Debug)] -pub struct OverlayClock { +pub struct OverlayClock { roclock: C, - last_sync: Time, - shift: Duration, - freq_scale_ppm_diff: f64 + overlay: ClockOverlay, + exporter: E, } -impl OverlayClock { - /// Creates new OverlayClock based on given clock - pub fn new(underlying_clock: C) -> Self { +impl OverlayClock { + /// Creates new OverlayClock based on given clock. Specify `DoNotExport` as `exporter` if you don't need to export the overlay. + pub fn new(underlying_clock: C, exporter: E) -> Self { let now = underlying_clock.now(); Self { roclock: underlying_clock, - last_sync: now, - shift: Duration::from_fixed_nanos(0), - freq_scale_ppm_diff: 0.0, + overlay: ClockOverlay { + last_sync: now, + shift: Duration::from_fixed_nanos(0), + freq_scale: 0.0, + }, + exporter } } /// Converts (shifts and scales) `Time` in underlying clock's timescale to overlay clock timescale pub fn time_from_underlying(&self, roclock_time: Time) -> Time { - let elapsed = roclock_time - self.last_sync; - let corr = elapsed * self.freq_scale_ppm_diff / 1_000_000; + let elapsed = roclock_time - self.overlay.last_sync; + let corr = elapsed * self.overlay.freq_scale; - roclock_time + self.shift + corr + roclock_time + self.overlay.shift + corr // equals self.last_sync + self.shift + elapsed + corr } @@ -37,9 +109,13 @@ impl OverlayClock { pub fn underlying(&self) -> &C { &self.roclock } + + fn export(&mut self) { + self.exporter.export(&self.overlay); + } } -impl Clock for OverlayClock { +impl Clock for OverlayClock { type Error = C::Error; fn now(&self) -> Time { self.time_from_underlying(self.roclock.now()) @@ -48,17 +124,23 @@ impl Clock for OverlayClock { // save current shift: let now_roclock = self.roclock.now(); let now_local = self.time_from_underlying(now_roclock); - self.shift = now_local - now_roclock; - self.last_sync = now_roclock; - self.freq_scale_ppm_diff = ppm; - debug_assert_eq!(self.time_from_underlying(self.last_sync), now_local); + self.overlay = ClockOverlay { + last_sync: now_roclock, + shift: now_local - now_roclock, + freq_scale: ppm / 1_000_000f64 + }; + debug_assert_eq!(self.time_from_underlying(self.overlay.last_sync), now_local); + + self.export(); Ok(now_local) } fn step_clock(&mut self, offset: Duration) -> Result { - self.last_sync = self.roclock.now(); - self.shift += offset; - Ok(self.time_from_underlying(self.last_sync)) + self.overlay.last_sync = self.roclock.now(); + self.overlay.shift += offset; + + self.export(); + Ok(self.time_from_underlying(self.overlay.last_sync)) } fn set_properties(&mut self, _time_properties_ds: &crate::config::TimePropertiesDS) -> Result<(), Self::Error> { // we can ignore the properies - they are just metadata From 8cb7575f00ab9d7a1128b1da7e572148c7cb8e6e Mon Sep 17 00:00:00 2001 From: Teodor Wozniak Date: Wed, 28 Aug 2024 17:56:57 +0200 Subject: [PATCH 03/10] Revert "export clock using usrvclock protocol (not tested yet)" This reverts commit 93ccc5781144e14c7f7d8265845d9a6069828000. --- Cargo.lock | 42 ----------- Cargo.toml | 1 - statime-linux/Cargo.toml | 3 - statime-linux/src/clock/mod.rs | 6 +- statime-linux/src/config/mod.rs | 10 --- statime-linux/src/main.rs | 26 ++----- statime/Cargo.toml | 2 +- statime/src/lib.rs | 3 +- statime/src/overlay_clock.rs | 124 ++++++-------------------------- 9 files changed, 31 insertions(+), 186 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e576a2eee..b5518bd30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,12 +107,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" - [[package]] name = "bytemuck" version = "1.18.0" @@ -137,12 +131,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - [[package]] name = "clap" version = "4.5.17" @@ -204,12 +192,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -[[package]] -name = "custom_error" -version = "1.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f8a51dd197fa6ba5b4dc98a990a43cc13693c23eb0089ebb0fcc1f04152bca6" - [[package]] name = "equivalent" version = "1.0.1" @@ -352,18 +334,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags", - "cfg-if", - "cfg_aliases", - "libc", -] - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -561,7 +531,6 @@ dependencies = [ "arrayvec", "clap", "clock-steering", - "fixed", "hex", "libc", "log", @@ -576,7 +545,6 @@ dependencies = [ "tracing", "tracing-log", "tracing-subscriber", - "usrvclock", ] [[package]] @@ -747,16 +715,6 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" -[[package]] -name = "usrvclock" -version = "0.1.0" -source = "git+https://gitlab.com/lumifaza/usrvclock-rs#0039099ced600f635928299db3a9adbb0a8db5f0" -dependencies = [ - "custom_error", - "nix", - "tokio", -] - [[package]] name = "utf8parse" version = "0.2.2" diff --git a/Cargo.toml b/Cargo.toml index 54fad756e..f781d342f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,6 @@ serde_test = { version = "1.0.176" } az = "1.2.1" fixed = "1.24" libm = "0.2.8" -auto_impl = "1.2.0" clock-steering = "0.2.0" timestamped-socket = "0.2.4" diff --git a/statime-linux/Cargo.toml b/statime-linux/Cargo.toml index 728f67d71..da08fe135 100644 --- a/statime-linux/Cargo.toml +++ b/statime-linux/Cargo.toml @@ -23,7 +23,6 @@ path = "bin/statime-metrics-exporter.rs" statime.workspace = true arrayvec.workspace = true -fixed.workspace = true clap.workspace = true tracing.workspace = true tracing-log.workspace = true @@ -38,8 +37,6 @@ rand = { workspace = true, default-features = false, features = ["std", "std_rng serde.workspace = true serde_json.workspace = true -usrvclock = { git = "https://gitlab.com/lumifaza/usrvclock-rs", version = "0.1.0" } - clock-steering.workspace = true timestamped-socket.workspace = true diff --git a/statime-linux/src/clock/mod.rs b/statime-linux/src/clock/mod.rs index 1358f360e..9ffce696d 100644 --- a/statime-linux/src/clock/mod.rs +++ b/statime-linux/src/clock/mod.rs @@ -6,7 +6,7 @@ use clock_steering::{unix::UnixClock, TimeOffset}; use statime::{ config::{LeapIndicator, TimePropertiesDS}, time::{Duration, Time}, - Clock, SharedClock, overlay_clock::{OverlayClock, ClockOverlayExporter} + Clock, OverlayClock, SharedClock, }; #[derive(Debug, Clone)] @@ -187,7 +187,7 @@ impl PortTimestampToTime for LinuxClock { } } -impl PortTimestampToTime for OverlayClock { +impl PortTimestampToTime for OverlayClock { fn port_timestamp_to_time(&self, ts: timestamped_socket::socket::Timestamp) -> Time { let roclock_time = self.underlying().port_timestamp_to_time(ts); //log::debug!("port_timestamp_to_time for OverlayClock called"); @@ -195,7 +195,7 @@ impl PortTimestampToTime for Overlay } } -impl PortTimestampToTime for SharedClock> { +impl PortTimestampToTime for SharedClock> { fn port_timestamp_to_time(&self, ts: timestamped_socket::socket::Timestamp) -> Time { self.0.lock().unwrap().port_timestamp_to_time(ts) } diff --git a/statime-linux/src/config/mod.rs b/statime-linux/src/config/mod.rs index dbe5ffe28..bb8eeda6e 100644 --- a/statime-linux/src/config/mod.rs +++ b/statime-linux/src/config/mod.rs @@ -38,10 +38,6 @@ pub struct Config { pub observability: ObservabilityConfig, #[serde(default)] pub virtual_system_clock: bool, - #[serde(default)] - pub usrvclock_export: bool, - #[serde(default = "default_usrvclock_path")] - pub usrvclock_path: PathBuf, } #[derive(Deserialize, Debug, Clone, PartialEq, Eq)] @@ -214,10 +210,6 @@ fn default_priority2() -> u8 { 128 } -fn default_usrvclock_path() -> PathBuf { - usrvclock::DEFAULT_SERVER_SOCKET_PATH.into() -} - fn default_delay_asymmetry() -> i64 { 0 } @@ -296,8 +288,6 @@ interface = "enp0s31f6" ports: vec![expected_port], observability: ObservabilityConfig::default(), virtual_system_clock: false, - usrvclock_export: false, - usrvclock_path: usrvclock::DEFAULT_SERVER_SOCKET_PATH.into(), }; let actual = toml::from_str(MINIMAL_CONFIG).unwrap(); diff --git a/statime-linux/src/main.rs b/statime-linux/src/main.rs index 85c497c85..a2a9ad2ac 100644 --- a/statime-linux/src/main.rs +++ b/statime-linux/src/main.rs @@ -16,7 +16,7 @@ use statime::{ TimestampContext, MAX_DATA_LEN, }, time::Time, - PtpInstance, Clock, overlay_clock::{OverlayClock, CallbackExporter}, SharedClock, PtpInstanceState, + PtpInstance, Clock, OverlayClock, SharedClock, PtpInstanceState, }; use statime_linux::{ clock::{LinuxClock, PortTimestampToTime}, @@ -41,11 +41,11 @@ use tokio::{ trait PortClock: Clock::Error> + PortTimestampToTime {} impl PortClock for LinuxClock { } -impl PortClock for SharedClock> { +impl PortClock for SharedClock> { } type BoxedClock = Box; //type SharedBoxedClock = SharedClock; -type SharedOverlayClock = SharedClock>; +type SharedOverlayClock = SharedClock>; #[derive(Parser, Debug)] @@ -261,25 +261,7 @@ async fn actual_main() { TimePropertiesDS::new_arbitrary_time(false, false, TimeSource::InternalOscillator); let system_clock = if config.virtual_system_clock { - let exporter = if config.usrvclock_export { - let mut server = usrvclock::Server::new(config.usrvclock_path.clone()).expect("failed to create usrvclock server"); - CallbackExporter::from(move |overlay: &statime::overlay_clock::ClockOverlay| { - use fixed::traits::LossyInto; - let last_sync: i128 = overlay.last_sync.nanos().lossy_into(); - let shift: i128 = overlay.shift.nanos().lossy_into(); - let to_share = usrvclock::ClockOverlay { - clock_id: libc::CLOCK_TAI as i64, - last_sync: last_sync as i64, - shift: shift as i64, - freq_scale: overlay.freq_scale - }; - server.send(to_share) - }) - } else { - CallbackExporter::from(|_: &statime::overlay_clock::ClockOverlay| {}) - }; - let overlay_clock = OverlayClock::new(LinuxClock::CLOCK_TAI, exporter); - SystemClock::Overlay(SharedClock::new(overlay_clock)) + SystemClock::Overlay(SharedClock::new(OverlayClock::new(LinuxClock::CLOCK_TAI))) } else { SystemClock::Linux(LinuxClock::CLOCK_TAI) }; diff --git a/statime/Cargo.toml b/statime/Cargo.toml index 0f36e1530..431e92e2d 100644 --- a/statime/Cargo.toml +++ b/statime/Cargo.toml @@ -19,7 +19,7 @@ serde = ["dep:serde", "arrayvec/serde"] [dependencies] arrayvec.workspace = true -auto_impl.workspace = true +auto_impl = "1.2.0" az.workspace = true fixed.workspace = true libm.workspace = true diff --git a/statime/src/lib.rs b/statime/src/lib.rs index 9db3f7c2b..619eae3ab 100644 --- a/statime/src/lib.rs +++ b/statime/src/lib.rs @@ -85,7 +85,7 @@ extern crate std; mod bmc; mod clock; -pub mod overlay_clock; +mod overlay_clock; #[cfg(feature = "std")] mod shared_clock; pub mod config; @@ -99,6 +99,7 @@ pub mod time; pub use clock::Clock; pub use ptp_instance::{PtpInstance, PtpInstanceState, PtpInstanceStateMutex}; +pub use overlay_clock::OverlayClock; #[cfg(feature = "std")] pub use shared_clock::SharedClock; diff --git a/statime/src/overlay_clock.rs b/statime/src/overlay_clock.rs index 77f9177a9..26cc7786e 100644 --- a/statime/src/overlay_clock.rs +++ b/statime/src/overlay_clock.rs @@ -1,107 +1,35 @@ -//! Virtual (overlay) clock and utilities related to it - use crate::{time::Time, time::Duration, Clock}; -/// Clock overlay values -#[derive(Debug, Clone)] -pub struct ClockOverlay { - /// underlying clock's timestamp of the last synchronization - pub last_sync: Time, - /// value to add to the OS clock's timestamp to obtain the virtual clock's timestamp - pub shift: Duration, - /// frequency correction factor, positive numbers accelerate the virtual clock relative to OS clock, negative make is slower - pub freq_scale: f64, -} - -/// Trait used for exporting the changes of the overlay from overlay clock to a third-party -pub trait ClockOverlayExporter { - /// Called when overlay is updated. - /// It doesn't make sense to export clock from more than 1 ClockOverlay, hence this method is mutable - fn export(&mut self, overlay: &ClockOverlay); -} - -/// Dummy exporter, does not forward clock overlay changes anywhere -#[derive(Debug)] -pub struct DoNotExport { -} -impl ClockOverlayExporter for DoNotExport { - fn export(&mut self, _: &ClockOverlay) { - // no-op - } -} - -#[cfg(feature = "std")] -/// Calls specified callback when overlay changes -pub struct CallbackExporter (std::boxed::Box); - -#[cfg(feature = "std")] -impl ClockOverlayExporter for CallbackExporter { - fn export(&mut self, overlay: &ClockOverlay) { - (self.0)(overlay); - } -} - -#[cfg(feature = "std")] -impl core::fmt::Debug for CallbackExporter { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "CallbackExporter") - } -} - -#[cfg(feature = "std")] -impl From for CallbackExporter { - fn from(cb: F) -> Self { - Self(std::boxed::Box::new(cb)) - } -} - -/* #[cfg(feature = "std")] -impl From> for CallbackExporter { - fn from(cb: std::boxed::Box) -> Self { - Self(cb) - } -} */ - -impl ClockOverlayExporter for Option { - fn export(&mut self, overlay: &ClockOverlay) { - if let Some(v) = self { - v.export(overlay); - } - } -} - /// An overlay over other, read-only clock, frequency-locked to it. /// In other words, a virtual clock which can be tuned in software without affecting /// the underlying system or hardware clock. #[derive(Debug)] -pub struct OverlayClock { +pub struct OverlayClock { roclock: C, - overlay: ClockOverlay, - exporter: E, + last_sync: Time, + shift: Duration, + freq_scale_ppm_diff: f64 } -impl OverlayClock { - /// Creates new OverlayClock based on given clock. Specify `DoNotExport` as `exporter` if you don't need to export the overlay. - pub fn new(underlying_clock: C, exporter: E) -> Self { +impl OverlayClock { + /// Creates new OverlayClock based on given clock + pub fn new(underlying_clock: C) -> Self { let now = underlying_clock.now(); Self { roclock: underlying_clock, - overlay: ClockOverlay { - last_sync: now, - shift: Duration::from_fixed_nanos(0), - freq_scale: 0.0, - }, - exporter + last_sync: now, + shift: Duration::from_fixed_nanos(0), + freq_scale_ppm_diff: 0.0, } } /// Converts (shifts and scales) `Time` in underlying clock's timescale to overlay clock timescale pub fn time_from_underlying(&self, roclock_time: Time) -> Time { - let elapsed = roclock_time - self.overlay.last_sync; - let corr = elapsed * self.overlay.freq_scale; + let elapsed = roclock_time - self.last_sync; + let corr = elapsed * self.freq_scale_ppm_diff / 1_000_000; - roclock_time + self.overlay.shift + corr + roclock_time + self.shift + corr // equals self.last_sync + self.shift + elapsed + corr } @@ -109,13 +37,9 @@ impl OverlayClock { pub fn underlying(&self) -> &C { &self.roclock } - - fn export(&mut self) { - self.exporter.export(&self.overlay); - } } -impl Clock for OverlayClock { +impl Clock for OverlayClock { type Error = C::Error; fn now(&self) -> Time { self.time_from_underlying(self.roclock.now()) @@ -124,23 +48,17 @@ impl Clock for OverlayCloc // save current shift: let now_roclock = self.roclock.now(); let now_local = self.time_from_underlying(now_roclock); + self.shift = now_local - now_roclock; + self.last_sync = now_roclock; - self.overlay = ClockOverlay { - last_sync: now_roclock, - shift: now_local - now_roclock, - freq_scale: ppm / 1_000_000f64 - }; - debug_assert_eq!(self.time_from_underlying(self.overlay.last_sync), now_local); - - self.export(); + self.freq_scale_ppm_diff = ppm; + debug_assert_eq!(self.time_from_underlying(self.last_sync), now_local); Ok(now_local) } fn step_clock(&mut self, offset: Duration) -> Result { - self.overlay.last_sync = self.roclock.now(); - self.overlay.shift += offset; - - self.export(); - Ok(self.time_from_underlying(self.overlay.last_sync)) + self.last_sync = self.roclock.now(); + self.shift += offset; + Ok(self.time_from_underlying(self.last_sync)) } fn set_properties(&mut self, _time_properties_ds: &crate::config::TimePropertiesDS) -> Result<(), Self::Error> { // we can ignore the properies - they are just metadata From 31186628ef9ffba8da0a86899586582f7d6a670b Mon Sep 17 00:00:00 2001 From: Teodor Wozniak Date: Wed, 28 Aug 2024 18:36:42 +0200 Subject: [PATCH 04/10] removed auto_impl dependency --- Cargo.lock | 12 ------------ statime/Cargo.toml | 1 - statime/src/clock.rs | 10 +++------- 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b5518bd30..40c757a1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,17 +75,6 @@ dependencies = [ "serde", ] -[[package]] -name = "auto_impl" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "az" version = "1.2.1" @@ -514,7 +503,6 @@ name = "statime" version = "0.2.1" dependencies = [ "arrayvec", - "auto_impl", "az", "fixed", "libm", diff --git a/statime/Cargo.toml b/statime/Cargo.toml index 431e92e2d..a8eeb2b92 100644 --- a/statime/Cargo.toml +++ b/statime/Cargo.toml @@ -19,7 +19,6 @@ serde = ["dep:serde", "arrayvec/serde"] [dependencies] arrayvec.workspace = true -auto_impl = "1.2.0" az.workspace = true fixed.workspace = true libm.workspace = true diff --git a/statime/src/clock.rs b/statime/src/clock.rs index d604ae17e..ac0d4f83f 100644 --- a/statime/src/clock.rs +++ b/statime/src/clock.rs @@ -1,6 +1,5 @@ //! Definitions and implementations of the abstract clock types -use auto_impl::auto_impl; use crate::{ datastructures::datasets::TimePropertiesDS, time::{Duration, Time}, @@ -17,7 +16,6 @@ use crate::{ /// Note that the clock implementation is responsible for handling leap seconds. /// On most operating systems, this will be provided for by the OS, but on some /// platforms this may require extra logic. -#[auto_impl(Box)] pub trait Clock { /// Type of the error the methods of this [`Clock`] may return type Error: core::fmt::Debug; @@ -50,11 +48,9 @@ pub trait Clock { fn set_properties(&mut self, time_properties_ds: &TimePropertiesDS) -> Result<(), Self::Error>; } -/* #[cfg(feature = "std")] -use std::boxed::Box; #[cfg(feature = "std")] -impl Clock for Box + Send + Sync + '_> { - type Error = E; +impl Clock for std::boxed::Box { + type Error = T::Error; fn now(&self) -> Time { self.as_ref().now() } @@ -67,4 +63,4 @@ impl Clock for Box + Send + Sync + '_> { fn set_properties(&mut self, time_properties_ds: &TimePropertiesDS) -> Result<(), Self::Error> { self.as_mut().set_properties(time_properties_ds) } -} */ \ No newline at end of file +} From 565c2de067950987a7fc28becdd7fd2d925885cf Mon Sep 17 00:00:00 2001 From: Teodor Wozniak Date: Wed, 28 Aug 2024 18:41:47 +0200 Subject: [PATCH 05/10] cargo fmt --- statime-linux/src/clock/mod.rs | 1 - statime-linux/src/main.rs | 34 ++++++++++++++++++++-------------- statime/src/lib.rs | 8 ++++---- statime/src/overlay_clock.rs | 10 ++++++---- statime/src/shared_clock.rs | 13 +++++++++---- 5 files changed, 39 insertions(+), 27 deletions(-) diff --git a/statime-linux/src/clock/mod.rs b/statime-linux/src/clock/mod.rs index 9ffce696d..f2482b0f8 100644 --- a/statime-linux/src/clock/mod.rs +++ b/statime-linux/src/clock/mod.rs @@ -173,7 +173,6 @@ pub fn libc_timespec_into_instant(spec: libc::timespec) -> Time { Time::from_fixed_nanos(spec.tv_sec as i128 * 1_000_000_000i128 + spec.tv_nsec as i128) } - pub trait PortTimestampToTime { fn port_timestamp_to_time(&self, ts: timestamped_socket::socket::Timestamp) -> Time; } diff --git a/statime-linux/src/main.rs b/statime-linux/src/main.rs index a2a9ad2ac..58a925494 100644 --- a/statime-linux/src/main.rs +++ b/statime-linux/src/main.rs @@ -16,7 +16,7 @@ use statime::{ TimestampContext, MAX_DATA_LEN, }, time::Time, - PtpInstance, Clock, OverlayClock, SharedClock, PtpInstanceState, + Clock, OverlayClock, PtpInstance, PtpInstanceState, SharedClock, }; use statime_linux::{ clock::{LinuxClock, PortTimestampToTime}, @@ -39,15 +39,12 @@ use tokio::{ }; trait PortClock: Clock::Error> + PortTimestampToTime {} -impl PortClock for LinuxClock { -} -impl PortClock for SharedClock> { -} +impl PortClock for LinuxClock {} +impl PortClock for SharedClock> {} type BoxedClock = Box; //type SharedBoxedClock = SharedClock; type SharedOverlayClock = SharedClock>; - #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] pub struct Args { @@ -106,13 +103,13 @@ impl Future for Timer { #[derive(Debug, Clone)] enum SystemClock { Linux(LinuxClock), - Overlay(SharedOverlayClock) + Overlay(SharedOverlayClock), } impl SystemClock { fn clone_boxed(&self) -> BoxedClock { match self { Self::Linux(clock) => Box::new(clock.clone()), - Self::Overlay(clock) => Box::new(clock.clone()) + Self::Overlay(clock) => Box::new(clock.clone()), } } } @@ -124,15 +121,23 @@ enum ClockSyncMode { ToSystem, } -fn start_clock_task(clock: LinuxClock, system_clock: SystemClock) -> tokio::sync::watch::Sender { +fn start_clock_task( + clock: LinuxClock, + system_clock: SystemClock, +) -> tokio::sync::watch::Sender { let (mode_sender, mode_receiver) = tokio::sync::watch::channel(ClockSyncMode::FromSystem); match system_clock { SystemClock::Linux(system_clock) => { tokio::spawn(clock_task(clock, system_clock, None, mode_receiver)); - }, + } SystemClock::Overlay(overlay_clock) => { - tokio::spawn(clock_task(clock, overlay_clock.clone(), Some(overlay_clock), mode_receiver)); + tokio::spawn(clock_task( + clock, + overlay_clock.clone(), + Some(overlay_clock), + mode_receiver, + )); } } @@ -311,12 +316,13 @@ async fn actual_main() { let id = internal_sync_senders.len(); clock_port_map.push(Some(id)); clock_name_map.insert(idx, id); - internal_sync_senders.push(start_clock_task(clock.clone(), system_clock.clone())); + internal_sync_senders + .push(start_clock_task(clock.clone(), system_clock.clone())); } ( Box::new(clock.clone()) as BoxedClock, Box::new(clock) as BoxedClock, - InterfaceTimestampMode::HardwarePTPAll + InterfaceTimestampMode::HardwarePTPAll, ) } None => { @@ -324,7 +330,7 @@ async fn actual_main() { ( system_clock.clone_boxed(), system_clock.clone_boxed(), - InterfaceTimestampMode::SoftwareAll + InterfaceTimestampMode::SoftwareAll, ) } }; diff --git a/statime/src/lib.rs b/statime/src/lib.rs index 619eae3ab..d4a3539ce 100644 --- a/statime/src/lib.rs +++ b/statime/src/lib.rs @@ -85,21 +85,21 @@ extern crate std; mod bmc; mod clock; -mod overlay_clock; -#[cfg(feature = "std")] -mod shared_clock; pub mod config; pub(crate) mod datastructures; pub mod filters; mod float_polyfill; pub mod observability; +mod overlay_clock; pub mod port; mod ptp_instance; +#[cfg(feature = "std")] +mod shared_clock; pub mod time; pub use clock::Clock; -pub use ptp_instance::{PtpInstance, PtpInstanceState, PtpInstanceStateMutex}; pub use overlay_clock::OverlayClock; +pub use ptp_instance::{PtpInstance, PtpInstanceState, PtpInstanceStateMutex}; #[cfg(feature = "std")] pub use shared_clock::SharedClock; diff --git a/statime/src/overlay_clock.rs b/statime/src/overlay_clock.rs index 26cc7786e..273d9b6d8 100644 --- a/statime/src/overlay_clock.rs +++ b/statime/src/overlay_clock.rs @@ -1,5 +1,4 @@ -use crate::{time::Time, time::Duration, Clock}; - +use crate::{time::Duration, time::Time, Clock}; /// An overlay over other, read-only clock, frequency-locked to it. /// In other words, a virtual clock which can be tuned in software without affecting @@ -9,7 +8,7 @@ pub struct OverlayClock { roclock: C, last_sync: Time, shift: Duration, - freq_scale_ppm_diff: f64 + freq_scale_ppm_diff: f64, } impl OverlayClock { @@ -60,7 +59,10 @@ impl Clock for OverlayClock { self.shift += offset; Ok(self.time_from_underlying(self.last_sync)) } - fn set_properties(&mut self, _time_properties_ds: &crate::config::TimePropertiesDS) -> Result<(), Self::Error> { + fn set_properties( + &mut self, + _time_properties_ds: &crate::config::TimePropertiesDS, + ) -> Result<(), Self::Error> { // we can ignore the properies - they are just metadata Ok(()) } diff --git a/statime/src/shared_clock.rs b/statime/src/shared_clock.rs index 61685369f..1006a6623 100644 --- a/statime/src/shared_clock.rs +++ b/statime/src/shared_clock.rs @@ -1,13 +1,15 @@ -use std::sync::Mutex; -use std::sync::Arc; use crate::time::Duration; use crate::time::Time; use crate::Clock; +use std::sync::Arc; +use std::sync::Mutex; /// A wrapper for stateful `statime::Clock` implementations to make them behave /// like e.g. `statime_linux::LinuxClock` - clones share state with each other #[derive(Debug)] -pub struct SharedClock(pub Arc>) where C: Clock; +pub struct SharedClock(pub Arc>) +where + C: Clock; impl SharedClock { /// Take given clock and make it a `SharedClock` @@ -34,7 +36,10 @@ impl Clock for SharedClock { fn step_clock(&mut self, offset: Duration) -> Result { self.0.lock().unwrap().step_clock(offset) } - fn set_properties(&mut self, time_properties_ds: &crate::config::TimePropertiesDS) -> Result<(), Self::Error> { + fn set_properties( + &mut self, + time_properties_ds: &crate::config::TimePropertiesDS, + ) -> Result<(), Self::Error> { self.0.lock().unwrap().set_properties(time_properties_ds) } } From 4178fef066866ba5281157fed973dbbc4ef069e1 Mon Sep 17 00:00:00 2001 From: Teodor Wozniak Date: Fri, 30 Aug 2024 11:53:38 +0200 Subject: [PATCH 06/10] fix OverlayClock::step_clock offset timescale --- statime/src/overlay_clock.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/statime/src/overlay_clock.rs b/statime/src/overlay_clock.rs index 273d9b6d8..48d9780ab 100644 --- a/statime/src/overlay_clock.rs +++ b/statime/src/overlay_clock.rs @@ -56,7 +56,9 @@ impl Clock for OverlayClock { } fn step_clock(&mut self, offset: Duration) -> Result { self.last_sync = self.roclock.now(); - self.shift += offset; + let multiplier = 1_000_000f64 + self.freq_scale_ppm_diff; + let reciprocal = 1_000_000f64 / multiplier; + self.shift += offset * reciprocal; Ok(self.time_from_underlying(self.last_sync)) } fn set_properties( From adfc0d2e432e5949a93cd364f73b7827b0710a36 Mon Sep 17 00:00:00 2001 From: Teodor Wozniak Date: Fri, 30 Aug 2024 11:53:58 +0200 Subject: [PATCH 07/10] removed commented out & dead code --- statime-linux/src/clock/mod.rs | 1 - statime-linux/src/main.rs | 1 - statime-linux/src/socket.rs | 5 ----- 3 files changed, 7 deletions(-) diff --git a/statime-linux/src/clock/mod.rs b/statime-linux/src/clock/mod.rs index f2482b0f8..958a6ca4c 100644 --- a/statime-linux/src/clock/mod.rs +++ b/statime-linux/src/clock/mod.rs @@ -189,7 +189,6 @@ impl PortTimestampToTime for LinuxClock { impl PortTimestampToTime for OverlayClock { fn port_timestamp_to_time(&self, ts: timestamped_socket::socket::Timestamp) -> Time { let roclock_time = self.underlying().port_timestamp_to_time(ts); - //log::debug!("port_timestamp_to_time for OverlayClock called"); self.time_from_underlying(roclock_time) } } diff --git a/statime-linux/src/main.rs b/statime-linux/src/main.rs index 58a925494..e26fea7e5 100644 --- a/statime-linux/src/main.rs +++ b/statime-linux/src/main.rs @@ -42,7 +42,6 @@ trait PortClock: Clock::Error> + PortTimestampToTi impl PortClock for LinuxClock {} impl PortClock for SharedClock> {} type BoxedClock = Box; -//type SharedBoxedClock = SharedClock; type SharedOverlayClock = SharedClock>; #[derive(Parser, Debug)] diff --git a/statime-linux/src/socket.rs b/statime-linux/src/socket.rs index 94bfa2a1c..c9cc430c5 100644 --- a/statime-linux/src/socket.rs +++ b/statime-linux/src/socket.rs @@ -4,7 +4,6 @@ use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6}; -use statime::time::Time; use timestamped_socket::{ interface::InterfaceName, networkaddress::{EthernetAddress, MacAddress}, @@ -118,7 +117,3 @@ pub fn open_ethernet_socket( socket.join_multicast(EthernetAddress::PDELAY_EVENT, interface)?; Ok(socket) } - -pub fn timestamp_to_time(ts: timestamped_socket::socket::Timestamp) -> Time { - Time::from_fixed_nanos(ts.seconds as i128 * 1_000_000_000i128 + ts.nanos as i128) -} From 4623dc5b6f2f61916bc5f9d6596f22de572906dd Mon Sep 17 00:00:00 2001 From: Teodor Wozniak Date: Sat, 31 Aug 2024 01:57:26 +0200 Subject: [PATCH 08/10] simplified cloning --- statime-linux/src/main.rs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/statime-linux/src/main.rs b/statime-linux/src/main.rs index e26fea7e5..688e67001 100644 --- a/statime-linux/src/main.rs +++ b/statime-linux/src/main.rs @@ -38,10 +38,20 @@ use tokio::{ time::Sleep, }; -trait PortClock: Clock::Error> + PortTimestampToTime {} -impl PortClock for LinuxClock {} -impl PortClock for SharedClock> {} -type BoxedClock = Box; +trait PortClock: Clock::Error> + PortTimestampToTime + Send + Sync { + fn clone_box(&self) -> Box; +} +impl PortClock for LinuxClock { + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } +} +impl PortClock for SharedClock> { + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } +} +type BoxedClock = Box; type SharedOverlayClock = SharedClock>; #[derive(Parser, Debug)] @@ -305,7 +315,7 @@ async fn actual_main() { for port_config in config.ports { let interface = port_config.interface; let network_mode = port_config.network_mode; - let (port_clock, port_clock2, timestamping) = match port_config.hardware_clock { + let (port_clock, timestamping) = match port_config.hardware_clock { Some(idx) => { let mut clock = LinuxClock::open_idx(idx).expect("Unable to open clock"); if let Some(id) = clock_name_map.get(&idx) { @@ -319,7 +329,6 @@ async fn actual_main() { .push(start_clock_task(clock.clone(), system_clock.clone())); } ( - Box::new(clock.clone()) as BoxedClock, Box::new(clock) as BoxedClock, InterfaceTimestampMode::HardwarePTPAll, ) @@ -327,7 +336,6 @@ async fn actual_main() { None => { clock_port_map.push(None); ( - system_clock.clone_boxed(), system_clock.clone_boxed(), InterfaceTimestampMode::SoftwareAll, ) @@ -339,7 +347,7 @@ async fn actual_main() { let port = instance.add_port( port_config.into(), KalmanConfiguration::default(), - port_clock2, + port_clock.clone_box(), rng, ); From 499fd510348d068d2bd3fb8125f610d2a0f96892 Mon Sep 17 00:00:00 2001 From: Ruben Nijveld Date: Fri, 20 Sep 2024 15:43:29 +0200 Subject: [PATCH 09/10] Fixed style issue --- statime-linux/src/main.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/statime-linux/src/main.rs b/statime-linux/src/main.rs index 688e67001..dbce7992c 100644 --- a/statime-linux/src/main.rs +++ b/statime-linux/src/main.rs @@ -38,7 +38,9 @@ use tokio::{ time::Sleep, }; -trait PortClock: Clock::Error> + PortTimestampToTime + Send + Sync { +trait PortClock: + Clock::Error> + PortTimestampToTime + Send + Sync +{ fn clone_box(&self) -> Box; } impl PortClock for LinuxClock { From 49a2d474e530d610acfcb273b377144d107a88fc Mon Sep 17 00:00:00 2001 From: Ruben Nijveld Date: Fri, 20 Sep 2024 15:49:21 +0200 Subject: [PATCH 10/10] Add entry in manual page for statime-linux config --- docs/man/statime.toml.5.md | 3 +++ docs/precompiled/man/statime.8 | 2 +- docs/precompiled/man/statime.toml.5 | 5 ++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/man/statime.toml.5.md b/docs/man/statime.toml.5.md index 71f63fb97..eca2a118d 100644 --- a/docs/man/statime.toml.5.md +++ b/docs/man/statime.toml.5.md @@ -41,6 +41,9 @@ will be indicated by each configuration setting shown. `path-trace` = *bool* : The instance uses the path trace option. This allows detecting clock loops when enabled on all instances in the network. +`virtual-system-clock` = *bool* (**false**) +: Use a virtual overlay clock instead of adjusting the system clock. + ## `[[port]]` `interface` = *interface name* diff --git a/docs/precompiled/man/statime.8 b/docs/precompiled/man/statime.8 index 05ecea1f1..4807a6212 100644 --- a/docs/precompiled/man/statime.8 +++ b/docs/precompiled/man/statime.8 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 3.2 +.\" Automatically generated by Pandoc 3.4 .\" .TH "STATIME" "8" "" "statime 0.2.1" "statime" .SH NAME diff --git a/docs/precompiled/man/statime.toml.5 b/docs/precompiled/man/statime.toml.5 index 41ec6068c..8ecc021c7 100644 --- a/docs/precompiled/man/statime.toml.5 +++ b/docs/precompiled/man/statime.toml.5 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 3.2 +.\" Automatically generated by Pandoc 3.4 .\" .TH "STATIME.TOML" "5" "" "statime 0.2.1" "statime" .SH NAME @@ -42,6 +42,9 @@ A tie breaker for the best master clock algorithm in the range A tie breaker for the best master clock algorithm in the range \f[CR]0..256\f[R]. \f[CR]0\f[R] being highest priority an \f[CR]255\f[R] the lowest. +.TP +\f[CR]virtual\-system\-clock\f[R] = \f[I]bool\f[R] (\f[B]false\f[R]) +Use a virtual overlay clock instead of adjusting the system clock. .SS \f[CR][[port]]\f[R] .TP \f[CR]interface\f[R] = \f[I]interface name\f[R]