Skip to main content

xarxa_driver/
meta.rs

1//! Per-packet metadata.
2//!
3//! A [`PacketMeta`] is a small set of attributes that travels together with a packet
4//! all the way through the stack.
5//!
6//! Every field has a corresponding Cargo feature. When none are enabled `PacketMeta` is zero-sized.
7//!
8//! Use cases:
9//!
10//! * **Tagging.** [`PacketMeta::id`] (`packetmeta-id`) is an opaque number you
11//!   can use to correlate packets between the driver and sockets.
12//! * **Receive timestamping.** [`PacketMeta::timestamp`] (`packetmeta-timestamp`)
13//!   contains the time the packet was received, measured by the driver's own clock.
14//! * **Transmit timestamping.** [`PacketMeta::request_timestamp`] asks the driver to
15//!   timestamp a packet as it goes out. The result comes back through
16//!   [`Driver::poll_tx_timestamp`](crate::Driver::poll_tx_timestamp), as a
17//!   [`TxTimestamp`] tagged with the packet's `id`.
18
19/// A reading of a device's own clock.
20///
21/// This is *different* from the clock the stack is polled with. Do not mix
22/// `Timestamp` values with readings of that clock.
23///
24/// This is typically a higher-precision clock in the MAC.
25#[cfg(feature = "packetmeta-timestamp")]
26#[cfg_attr(feature = "defmt", derive(defmt::Format))]
27#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
28pub struct Timestamp {
29    /// Whole seconds.
30    pub seconds: u32,
31    /// Fraction of a second, in units of 0.25 nanoseconds.
32    ///
33    /// Always less than `4_000_000_000`, i.e. less than one whole second. The quarter
34    /// nanosecond is the resolution of the sub-second counter in common PTP hardware.
35    pub quarter_nanos: u32,
36}
37
38#[cfg(feature = "packetmeta-timestamp")]
39impl Timestamp {
40    /// Construct a timestamp from whole seconds and nanoseconds.
41    pub const fn from_seconds_and_nanos(seconds: u32, nanos: u32) -> Self {
42        Self {
43            seconds,
44            quarter_nanos: nanos << 2,
45        }
46    }
47
48    /// The fraction of a second, in whole nanoseconds, rounded down.
49    pub const fn nanos(&self) -> u32 {
50        self.quarter_nanos >> 2
51    }
52}
53
54/// Metadata associated with a packet.
55///
56/// This struct is `#[non_exhaustive]`. Start from [`Default`] and set what you
57/// care about:
58///
59/// ```
60/// let mut meta = xarxa_driver::PacketMeta::default();
61/// # #[cfg(feature = "packetmeta-id")] {
62/// meta.id = 15;
63/// # }
64/// ```
65#[cfg_attr(feature = "defmt", derive(defmt::Format))]
66#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, Default)]
67#[non_exhaustive]
68pub struct PacketMeta {
69    /// An opaque identifier for this packet.
70    ///
71    /// On received packets it is set by the driver. On packets to transmit it is set
72    /// by the application and handed to the driver untouched. It is also used
73    /// to correlates a transmit timestamp back to the packet that produced it, see
74    /// [`Driver::poll_tx_timestamp`](crate::Driver::poll_tx_timestamp).
75    ///
76    /// Defaults to `0`.
77    #[cfg(feature = "packetmeta-id")]
78    pub id: u32,
79
80    /// The time at which this packet was received, as measured by the device.
81    ///
82    /// `None` if the device did not timestamp this packet. Devices commonly timestamp
83    /// only a subset of received packets, e.g. only PTP event messages.
84    ///
85    /// Meaningful on received packets only. It is ignored on packets to transmit.
86    #[cfg(feature = "packetmeta-timestamp")]
87    pub timestamp: Option<Timestamp>,
88
89    /// Request that the device timestamp this packet as it is transmitted.
90    ///
91    /// The timestamp is reported back later, out of band, by
92    /// [`Driver::poll_tx_timestamp`](crate::Driver::poll_tx_timestamp),
93    /// tagged with this packet's [`id`](Self::id).
94    ///
95    /// Meaningful on packets to transmit only, ignored on received packets.
96    ///
97    /// Timestamping is opt-in per packet because hardware typically has only a handful
98    /// of transmit timestamp slots: requesting one for every packet will cause most of
99    /// them to be dropped.
100    #[cfg(feature = "packetmeta-timestamp")]
101    pub request_timestamp: bool,
102}
103
104/// The timestamp of a transmitted packet, reported by
105/// [`Driver::poll_tx_timestamp`](crate::Driver::poll_tx_timestamp).
106#[cfg(feature = "packetmeta-timestamp")]
107#[cfg_attr(feature = "defmt", derive(defmt::Format))]
108#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
109pub struct TxTimestamp {
110    /// The [`PacketMeta::id`] of the packet this timestamp belongs to.
111    pub id: u32,
112
113    /// The time at which the packet was transmitted, as measured by the device.
114    pub timestamp: Timestamp,
115}