/* * Copyright (c) 2024 BayLibre SAS * * SPDX-License-Identifier: Apache-2.0 */ /** * @file msg.h * @brief PTP messages definition. * * References are to version 2019 of IEEE 1588, ("PTP") */ #ifndef ZEPHYR_INCLUDE_PTP_MSG_H_ #define ZEPHYR_INCLUDE_PTP_MSG_H_ #include #include #include #include #include #include #include "ddt.h" #ifdef __cplusplus extern "C" { #endif /* values of the bits of the flagField array for PTP message */ #define PTP_MSG_ALT_TIME_TRANSMITTER_FLAG BIT(0) #define PTP_MSG_TWO_STEP_FLAG BIT(1) #define PTP_MSG_UNICAST_FLAG BIT(2) /** * @brief PTP message type. */ enum ptp_msg_type { /* PTP event message types */ PTP_MSG_SYNC = 0, PTP_MSG_DELAY_REQ, PTP_MSG_PDELAY_REQ, PTP_MSG_PDELAY_RESP, /* General PTP message types */ PTP_MSG_FOLLOW_UP = 8, PTP_MSG_DELAY_RESP, PTP_MSG_PDELAY_RESP_FOLLOW_UP, PTP_MSG_ANNOUNCE, PTP_MSG_SIGNALING, PTP_MSG_MANAGEMENT, }; /** * @brief Common PTP message header. */ struct ptp_header { /** PTP message type and most significant 4 bytes of SdoId. */ uint8_t type_major_sdo_id; /** PTP version. */ uint8_t version; /** Number of bytes in the message. */ uint16_t msg_length; /** ID number of an instance in a domain. */ uint8_t domain_number; /** Minor SdoId. */ uint8_t minor_sdo_id; /** Array of message flags. */ uint8_t flags[2]; /** Value of correction in nanoseconds multiplied by 2^16. */ int64_t correction; /** @cond INTERNAL_HIDDEN */ /** Padding. */ uint32_t reserved; /** @endcond */ /** PTP Port ID of the sender. */ struct ptp_port_id src_port_id; /** unique ID number of the message. */ uint16_t sequence_id; /** @cond INTERNAL_HIDDEN */ /** Obsolete, used for padding. */ uint8_t control; /** @endcond */ /** Logarithm base of 2 of message interval. */ int8_t log_msg_interval; } __packed; /** * @brief PTP Announce message header. */ struct ptp_announce_msg { /** PTP message header. */ struct ptp_header hdr; /** Estimate of the PTP Instance Time of an originating Instance * when message was transmitted. */ struct ptp_timestamp origin_timestamp; /** Value of @ref ptp_time_prop_ds.current_utc_offset . */ uint16_t current_utc_offset; /** @cond INTERNAL_HIDDEN */ /** Padding. */ uint8_t reserved; /** @endcond */ /** Value of @ref ptp_parent_ds.gm_priority1 of transmitter. */ uint8_t gm_priority1; /** Value of @ref ptp_parent_ds.gm_clk_quality of transmitter. */ struct ptp_clk_quality gm_clk_quality; /** Value of @ref ptp_parent_ds.gm_priority2 of transmitter. */ uint8_t gm_priority2; /** Value of @ref ptp_parent_ds.gm_id of transmitter. */ ptp_clk_id gm_id; /** Value of @ref ptp_current_ds.steps_rm of transmitter. */ uint16_t steps_rm; /** Time source of a clock of the sender. */ uint8_t time_src; /** Flexible array of zero or more TLV entities. */ uint8_t suffix[]; } __packed; /** * @brief PTP Sync message header. */ struct ptp_sync_msg { /** PTP message header. */ struct ptp_header hdr; /** PTP Instance Time of an originating PTP Instance when message was transmitted. */ struct ptp_timestamp origin_timestamp; /** Flexible array of zero or more TLV entities. */ uint8_t suffix[]; } __packed; /** * @brief PTP Delay_Req message header. */ struct ptp_delay_req_msg { /** PTP message header. */ struct ptp_header hdr; /** PTP Instance Time of an originating PTP Instance when message was transmitted. */ struct ptp_timestamp origin_timestamp; /** Flexible array of zero or more TLV entities. */ uint8_t suffix[]; } __packed; /** * @brief PTP Follow_Up message header. */ struct ptp_follow_up_msg { /** PTP message header. */ struct ptp_header hdr; /** Precise timestamp of Sync message corresponding to that message. */ struct ptp_timestamp precise_origin_timestamp; /** Flexible array of zero or more TLV entities. */ uint8_t suffix[]; } __packed; /** * @brief PTP Delay_Resp message header. */ struct ptp_delay_resp_msg { /** PTP message header. */ struct ptp_header hdr; /** Ingress timestamp of Delay_Req message. */ struct ptp_timestamp receive_timestamp; /** Port's ID of the sender of Delay_Req message. */ struct ptp_port_id req_port_id; /** Flexible array of zero or more TLV entities. */ uint8_t suffix[]; } __packed; /** * @brief PTP Pdelay_Req message header. */ struct ptp_pdelay_req_msg { /** PTP message header. */ struct ptp_header hdr; /** PTP Instance Time of an originating PTP Instance when message was transmitted. */ struct ptp_timestamp origin_timestamp; /** @cond INTERNAL_HIDDEN */ /** Padding. */ struct ptp_port_id reserved; /* make it the same length as ptp_pdelay_resp */ /** @endcond */ /** Flexible array of zero or more TLV entities. */ uint8_t suffix[]; } __packed; /** * @brief PTP Pdelay_Resp message header. */ struct ptp_pdelay_resp_msg { /** PTP message header. */ struct ptp_header hdr; /** Ingress timestamp of Pdelay_Req message. */ struct ptp_timestamp req_receipt_timestamp; /** Port's ID of the sender of Pdelay_Req message. */ struct ptp_port_id req_port_id; /** Flexible array of zero or more TLV entities. */ uint8_t suffix[]; } __packed; /** * @brief PTP Pdelay_Resp_Follow_Up message header. */ struct ptp_pdelay_resp_follow_up_msg { /** PTP message header. */ struct ptp_header hdr; /** Precise timestamp of Pdelay_Resp message corresponding to that message. */ struct ptp_timestamp resp_origin_timestamp; /** Port's ID of the sender of Pdelay_Req message. */ struct ptp_port_id req_port_id; /** Flexible array of zero or more TLV entities. */ uint8_t suffix[]; } __packed; /** * @brief PTP Signaling message header. */ struct ptp_signaling_msg { /** PTP message header. */ struct ptp_header hdr; /** Port's ID to which this message is addressed. */ struct ptp_port_id target_port_id; /** Flexible array of zero or more TLV entities. */ uint8_t suffix[]; } __packed; /** * @brief PTP Management message header. */ struct ptp_management_msg { /** PTP message header. */ struct ptp_header hdr; /** Port's ID to which this message is addressed. */ struct ptp_port_id target_port_id; /** For response it should be computed from starting_boundary_hops and boundary_hops * of the requesting message. */ uint8_t starting_boundary_hops; /** Number of successive retransmissions of the message * by Boundary Clocks receiving message. */ uint8_t boundary_hops; /** Action to be taken on receipt of the message */ uint8_t action:5; /** @cond INTERNAL_HIDDEN */ /** Padding. */ uint8_t reserved; /** @endcond */ /** Flexible array of zero or more TLV entities. */ uint8_t suffix[]; } __packed; /** * @brief Generic PTP message structure. */ struct ptp_msg { union { /** General PTP message header. */ struct ptp_header header; /** Announce message. */ struct ptp_announce_msg announce; /** Sync message. */ struct ptp_sync_msg sync; /** Delay_Req message. */ struct ptp_delay_req_msg delay_req; /** Follow_Up message. */ struct ptp_follow_up_msg follow_up; /** Delay_Resp message. */ struct ptp_delay_resp_msg delay_resp; /** Pdelay_Req message. */ struct ptp_pdelay_req_msg pdelay_req; /** Pdelay_Resp message. */ struct ptp_pdelay_resp_msg pdelay_resp; /** Pdelay_Resp_Follow_Up message. */ struct ptp_pdelay_resp_follow_up_msg pdelay_resp_follow_up; /** Signaling message. */ struct ptp_signaling_msg signaling; /** Management message. */ struct ptp_management_msg management; /** @cond INTERNAL_HIDEN */ /** MTU. */ uint8_t mtu[NET_ETH_MTU]; /** @endcond */ } __packed; struct { /** * Timestamp extracted from the message in a host binary format. * Depending on the message type the value comes from different * field of the message. */ struct net_ptp_time protocol; /** Ingress timestamp on the host side. */ struct net_ptp_time host; } timestamp; /** Reference counter. */ atomic_t ref; /** List object. */ sys_snode_t node; /** Single-linked list of TLVs attached to the message. */ sys_slist_t tlvs; /** Protocol address of the sender/receiver of the message. */ struct sockaddr addr; }; /** * @brief Function allocating space for a new PTP message. * * @return Pointer to the new PTP Message. */ struct ptp_msg *ptp_msg_alloc(void); /** * @brief Function removing reference to the PTP message. * * @note If the message is not referenced anywhere, the memory space is cleared. * * @param[in] msg Pointer to the PTP message. */ void ptp_msg_unref(struct ptp_msg *msg); /** * @brief Function incrementing reference count for the PTP message. * * @param[in] msg Pointer to the PTP message. */ void ptp_msg_ref(struct ptp_msg *msg); /** * @brief Function extracting message type from it. * * @param[in] msg Pointer to the message. * * @return Type of the message. */ enum ptp_msg_type ptp_msg_type(const struct ptp_msg *msg); /** * @brief Function extracting PTP message from network packet. * * @param[in] pkt Pointer to the network packet. * * @note Returned message has all data in the network byte order. * * @return Pointer to a PTP message. */ struct ptp_msg *ptp_msg_from_pkt(struct net_pkt *pkt); /** * @brief Function preparing message right before transmission. * * @param[in] msg Pointer to the prepared PTP message. */ void ptp_msg_pre_send(struct ptp_msg *msg); /** * @brief Function preparing message for further processing after reception. * * @param[in] port Pointer to the PTP Port instance. * @param[in] msg Pointer to the received PTP message. * @param[in] cnt Length of the message in bytes. * * @return 0 on success, negative otherwise. */ int ptp_msg_post_recv(struct ptp_port *port, struct ptp_msg *msg, int cnt); /** * @brief Function adding TLV of specified length to the message. * * @param[in] msg Pointer to the message that will have TLV added. * @param[in] length Length of the TLV. * * @return Pointer to the TLV or NULL if there was no space to append TLV to the message. */ struct ptp_tlv *ptp_msg_add_tlv(struct ptp_msg *msg, int length); /** * @brief Function compering content of two PTP Announce messages. * * @param[in] m1 Pointer to the Announce message to be compared. * @param[in] m2 Pointer to the Announce message to be compared. * * @return Negative if m1 < m2, 0 if equal, else positive */ int ptp_msg_announce_cmp(const struct ptp_announce_msg *m1, const struct ptp_announce_msg *m2); /** * @brief Function checking if given message comes from current PTP Port's * TimeTransmitter PTP instance. * * @param[in] msg Pointer to the message. * * @return True if the message is received from the current PTP Port's TimeTransmitter, * false otherwise. */ bool ptp_msg_current_parent(const struct ptp_msg *msg); #ifdef __cplusplus } #endif /** * @} */ #endif /* ZEPHYR_INCLUDE_PTP_MSG_H_ */