Struct statime::port::Port

source ·
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:

§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 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>

source

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.

source

pub fn handle_announce_timer( &mut self, tlv_provider: &mut impl ForwardedTLVProvider, ) -> PortActionIterator<'_>

Handle the announce timer going off

source

pub fn handle_sync_timer(&mut self) -> PortActionIterator<'_>

Handle the sync timer going off

source

pub fn handle_delay_request_timer(&mut self) -> PortActionIterator<'_>

Handle the delay request timer going off

source

pub fn handle_announce_receipt_timer(&mut self) -> PortActionIterator<'_>

Handle the announce receipt timer going off

source

pub fn handle_filter_update_timer(&mut self) -> PortActionIterator<'_>

Handle the filter update timer going off

source

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.

source

pub fn handle_event_receive<'b>( &'b mut self, data: &'b [u8], timestamp: Time, ) -> PortActionIterator<'b>

Handle a message over the event channel

source

pub fn handle_general_receive<'b>( &'b mut self, data: &'b [u8], ) -> PortActionIterator<'b>

Handle a general ptp message

source§

impl<'a, A, C, F: Filter, R, S> Port<'a, InBmca, A, R, C, F, S>

source

pub fn end_bmca( self, ) -> (Port<'a, Running, A, R, C, F, S>, PortActionIterator<'static>)

End a BMCA cycle and make the handle_* methods available again

source§

impl<L, A, R, C, F: Filter, S> Port<'_, L, A, R, C, F, S>

source

pub fn is_steering(&self) -> bool

Indicate whether this Port is steering its clock.

source

pub fn is_master(&self) -> bool

Indicate whether this Port is in the master state.

Trait Implementations§

source§

impl<'a, L: Debug, A: Debug, R: Debug, C: Debug, F: Debug + Filter, S: Debug> Debug for Port<'a, L, A, R, C, F, S>
where F::Config: Debug,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a, L, A, R, C, F, S> Freeze for Port<'a, L, A, R, C, F, S>
where <F as Filter>::Config: Freeze, C: Freeze, L: Freeze, R: Freeze, F: Freeze, A: Freeze,

§

impl<'a, L, A, R, C, F, S> RefUnwindSafe for Port<'a, L, A, R, C, F, S>

§

impl<'a, L, A, R, C, F, S> Send for Port<'a, L, A, R, C, F, S>
where <F as Filter>::Config: Send, C: Send, L: Send, R: Send, F: Send, S: Sync, A: Send,

§

impl<'a, L, A, R, C, F, S> Sync for Port<'a, L, A, R, C, F, S>
where <F as Filter>::Config: Sync, C: Sync, L: Sync, R: Sync, F: Sync, S: Sync, A: Sync,

§

impl<'a, L, A, R, C, F, S> Unpin for Port<'a, L, A, R, C, F, S>
where <F as Filter>::Config: Unpin, C: Unpin, L: Unpin, R: Unpin, F: Unpin, A: Unpin,

§

impl<'a, L, A, R, C, F, S> UnwindSafe for Port<'a, L, A, R, C, F, S>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.