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_list
which should implementAcceptableMasterList
R
: The type of the random number generator (Rng
) used to randomize timingC
: The type of theClock
used by thisPort
F
: The type of theFilter
used 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};
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(),
};
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 PortAction
s 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