blob: 5e8c8ba166ae984359588a228e45433f4dbdc588 [file] [log] [blame]
/*
* 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 <stdbool.h>
#include <zephyr/kernel.h>
#include <zephyr/net/ethernet.h>
#include <zephyr/net/net_ip.h>
#include <zephyr/net/net_pkt.h>
#include <zephyr/net/ptp_time.h>
#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 succesive 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;
/** Refference 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_ */