pub struct Port<'a, L, A, R, C, F: Filter, S = RefCell<PtpInstanceState>> { /* private fields */ }Expand description
A single port of the PTP instance
One of these needs to be created per port of the PTP instance. They are
created by calling PtpInstance::add_port.
§Generics
A Port is generic over:
L: The state of thePort, eitherInBmca, orRunning.A: The type of thePortConfig::acceptable_master_listwhich should implementAcceptableMasterListR: The type of the random number generator (Rng) used to randomize timingC: The type of theClockused by thisPortF: The type of theFilterused by thisPort
§Type States
A Port can be in two states. Either in Running allowing access to
the handle_* methods. Or in InBmca
state where it can be used with a PtpInstance to
run the best master clock algotithm (BMCA).
To transition from InBmca to Running use Port::end_bmca. To
transition from Running to InBmca use Port::start_bmca.
§Example
§Initialization
A Port can be created from a PtpInstance. It requires a
PortConfig, a Filter::Config, a Clock, and a Rng.
use rand::thread_rng;
use statime::config::{AcceptAnyMaster, DelayMechanism, PortConfig, PtpMinorVersion};
use statime::filters::BasicFilter;
use statime::PtpInstance;
use statime::time::Interval;
let mut instance = PtpInstance::<BasicFilter>::new(instance_config, time_properties_ds);
// TODO make these values sensible
let interval = Interval::from_log_2(-2); // 2^(-2)s = 250ms
let port_config = PortConfig {
acceptable_master_list: AcceptAnyMaster,
delay_mechanism: DelayMechanism::E2E { interval },
announce_interval: interval,
announce_receipt_timeout: 0,
sync_interval: interval,
master_only: false,
delay_asymmetry: Default::default(),
minor_ptp_version: PtpMinorVersion::One,
};
let filter_config = 1.0;
let clock = system::Clock {};
let rng = thread_rng();
let port_in_bmca = instance.add_port(port_config, filter_config, clock, rng);
// To handle events for the port it needs to change to running mode
let (running_port, actions) = port_in_bmca.end_bmca();
// This returns the first actions that need to be handled for the port
handle_actions(actions);
§Handling actions
The Port informs the user about any actions it needs the user to handle
via PortActions returned from its methods. The user is responsible for
handling these events in their system specific way.
use statime::port::{PortAction, PortActionIterator, TimestampContext};
use statime::time::Time;
struct MyPortResources {
announce_timer: system::Timer,
sync_timer: system::Timer,
delay_req_timer: system::Timer,
announce_receipt_timer: system::Timer,
filter_update_timer: system::Timer,
time_critical_socket: system::UdpSocket,
general_socket: system::UdpSocket,
send_timestamp: Option<(TimestampContext, Time)>
}
fn handle_actions(resources: &mut MyPortResources, actions: PortActionIterator) {
for action in actions {
match action {
PortAction::SendEvent { context, data, link_local } => {
let timestamp = resources.time_critical_socket.send(data, link_local);
resources.send_timestamp = Some((context, timestamp));
}
PortAction::SendGeneral { data, link_local } => {
resources.general_socket.send(data, link_local);
}
PortAction::ResetAnnounceTimer { duration } => {
resources.announce_timer.expire_in(duration)
}
PortAction::ResetSyncTimer { duration } => resources.sync_timer.expire_in(duration),
PortAction::ResetDelayRequestTimer { duration } => {
resources.delay_req_timer.expire_in(duration)
}
PortAction::ResetAnnounceReceiptTimer { duration } => {
resources.announce_receipt_timer.expire_in(duration)
}
PortAction::ResetFilterUpdateTimer { duration } => {
resources.filter_update_timer.expire_in(duration)
}
PortAction::ForwardTLV { .. } => {}
}
}
}§Handling system events
After the initialization the user has to inform the Port about any
events relevant to it via the handle_*
methods.
use rand::Rng;
use statime::Clock;
use statime::config::AcceptableMasterList;
use statime::filters::Filter;
use statime::port::{NoForwardedTLVs, Port, PortActionIterator, Running};
fn something_happend(resources: &mut MyPortResources, running_port: &mut Port<Running, impl AcceptableMasterList, impl Rng, impl Clock, impl Filter>) {
let actions = if resources.announce_timer.has_expired() {
running_port.handle_announce_timer(&mut NoForwardedTLVs)
} else if resources.sync_timer.has_expired() {
running_port.handle_sync_timer()
} else if resources.delay_req_timer.has_expired() {
running_port.handle_delay_request_timer()
} else if resources.announce_receipt_timer.has_expired() {
running_port.handle_announce_receipt_timer()
} else if resources.filter_update_timer.has_expired() {
running_port.handle_filter_update_timer()
} else if let Some((data, timestamp)) = resources.time_critical_socket.recv() {
running_port.handle_event_receive(data, timestamp)
} else if let Some((data, _timestamp)) = resources.general_socket.recv() {
running_port.handle_general_receive(data)
} else if let Some((context, timestamp)) = resources.send_timestamp.take() {
running_port.handle_send_timestamp(context, timestamp)
} else {
PortActionIterator::empty()
};
handle_actions(resources, actions);
}Implementations§
Source§impl<'a, A: AcceptableMasterList, C: Clock, F: Filter, R: Rng, S: PtpInstanceStateMutex> Port<'a, Running, A, R, C, F, S>
impl<'a, A: AcceptableMasterList, C: Clock, F: Filter, R: Rng, S: PtpInstanceStateMutex> Port<'a, Running, A, R, C, F, S>
Sourcepub fn handle_send_timestamp(
&mut self,
context: TimestampContext,
timestamp: Time,
) -> PortActionIterator<'_> ⓘ
pub fn handle_send_timestamp( &mut self, context: TimestampContext, timestamp: Time, ) -> PortActionIterator<'_> ⓘ
Inform the port about a transmit timestamp being available
context is the handle of the packet that was send from the
PortAction::SendEvent that caused the send.
Sourcepub fn handle_announce_timer(
&mut self,
tlv_provider: &mut impl ForwardedTLVProvider,
) -> PortActionIterator<'_> ⓘ
pub fn handle_announce_timer( &mut self, tlv_provider: &mut impl ForwardedTLVProvider, ) -> PortActionIterator<'_> ⓘ
Handle the announce timer going off
Sourcepub fn handle_sync_timer(&mut self) -> PortActionIterator<'_> ⓘ
pub fn handle_sync_timer(&mut self) -> PortActionIterator<'_> ⓘ
Handle the sync timer going off
Sourcepub fn handle_delay_request_timer(&mut self) -> PortActionIterator<'_> ⓘ
pub fn handle_delay_request_timer(&mut self) -> PortActionIterator<'_> ⓘ
Handle the delay request timer going off
Sourcepub fn handle_announce_receipt_timer(&mut self) -> PortActionIterator<'_> ⓘ
pub fn handle_announce_receipt_timer(&mut self) -> PortActionIterator<'_> ⓘ
Handle the announce receipt timer going off
Sourcepub fn handle_filter_update_timer(&mut self) -> PortActionIterator<'_> ⓘ
pub fn handle_filter_update_timer(&mut self) -> PortActionIterator<'_> ⓘ
Handle the filter update timer going off
Sourcepub fn start_bmca(self) -> Port<'a, InBmca, A, R, C, F, S>
pub fn start_bmca(self) -> Port<'a, InBmca, A, R, C, F, S>
Set this Port into InBmca mode to use it with
PtpInstance::bmca.
Sourcepub fn handle_event_receive<'b>(
&'b mut self,
data: &'b [u8],
timestamp: Time,
) -> PortActionIterator<'b> ⓘ
pub fn handle_event_receive<'b>( &'b mut self, data: &'b [u8], timestamp: Time, ) -> PortActionIterator<'b> ⓘ
Handle a message over the event channel
Sourcepub fn handle_general_receive<'b>(
&'b mut self,
data: &'b [u8],
) -> PortActionIterator<'b> ⓘ
pub fn handle_general_receive<'b>( &'b mut self, data: &'b [u8], ) -> PortActionIterator<'b> ⓘ
Handle a general ptp message
Source§impl<L, A, R, C, F: Filter, S> Port<'_, L, A, R, C, F, S>
impl<L, A, R, C, F: Filter, S> Port<'_, L, A, R, C, F, S>
Sourcepub fn is_steering(&self) -> bool
pub fn is_steering(&self) -> bool
Indicate whether this Port is steering its clock.
Sourcepub fn port_current_ds_contribution(&self) -> Option<FilterEstimate>
pub fn port_current_ds_contribution(&self) -> Option<FilterEstimate>
If this port is in the slave state, this returns the current estimate of the current_ds offset_to_master and mean_delay fields.