1 /*
2  * Copyright (c) 2024 BayLibre SAS
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file msg.h
9  * @brief PTP messages definition.
10  *
11  * References are to version 2019 of IEEE 1588, ("PTP")
12  */
13 
14 #ifndef ZEPHYR_INCLUDE_PTP_MSG_H_
15 #define ZEPHYR_INCLUDE_PTP_MSG_H_
16 
17 #include <stdbool.h>
18 
19 #include <zephyr/kernel.h>
20 #include <zephyr/net/ethernet.h>
21 #include <zephyr/net/net_ip.h>
22 #include <zephyr/net/net_pkt.h>
23 #include <zephyr/net/ptp_time.h>
24 
25 #include "ddt.h"
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 /* values of the bits of the flagField array for PTP message */
32 #define PTP_MSG_ALT_TIME_TRANSMITTER_FLAG BIT(0)
33 #define PTP_MSG_TWO_STEP_FLAG		  BIT(1)
34 #define PTP_MSG_UNICAST_FLAG		  BIT(2)
35 
36 /**
37  * @brief PTP message type.
38  */
39 enum ptp_msg_type {
40 	/* PTP event message types */
41 	PTP_MSG_SYNC = 0,
42 	PTP_MSG_DELAY_REQ,
43 	PTP_MSG_PDELAY_REQ,
44 	PTP_MSG_PDELAY_RESP,
45 	/* General PTP message types */
46 	PTP_MSG_FOLLOW_UP = 8,
47 	PTP_MSG_DELAY_RESP,
48 	PTP_MSG_PDELAY_RESP_FOLLOW_UP,
49 	PTP_MSG_ANNOUNCE,
50 	PTP_MSG_SIGNALING,
51 	PTP_MSG_MANAGEMENT,
52 };
53 
54 /**
55  * @brief Common PTP message header.
56  */
57 struct ptp_header {
58 	/** PTP message type and most significant 4 bytes of SdoId. */
59 	uint8_t		   type_major_sdo_id;
60 	/** PTP version. */
61 	uint8_t		   version;
62 	/** Number of bytes in the message. */
63 	uint16_t	   msg_length;
64 	/** ID number of an instance in a domain. */
65 	uint8_t		   domain_number;
66 	/** Minor SdoId. */
67 	uint8_t		   minor_sdo_id;
68 	/** Array of message flags. */
69 	uint8_t		   flags[2];
70 	/** Value of correction in nanoseconds multiplied by 2^16. */
71 	int64_t		   correction;
72 	/** @cond INTERNAL_HIDDEN */
73 	/** Padding. */
74 	uint32_t	   reserved;
75 	/** @endcond */
76 	/** PTP Port ID of the sender. */
77 	struct ptp_port_id src_port_id;
78 	/** unique ID number of the message. */
79 	uint16_t	   sequence_id;
80 	/** @cond INTERNAL_HIDDEN */
81 	/** Obsolete, used for padding. */
82 	uint8_t		   control;
83 	/** @endcond */
84 	/** Logarithm base of 2 of message interval. */
85 	int8_t		   log_msg_interval;
86 } __packed;
87 
88 /**
89  * @brief PTP Announce message header.
90  */
91 struct ptp_announce_msg {
92 	/** PTP message header. */
93 	struct ptp_header      hdr;
94 	/** Estimate of the PTP Instance Time of an originating Instance
95 	 * when message was transmitted.
96 	 */
97 	struct ptp_timestamp   origin_timestamp;
98 	/** Value of @ref ptp_time_prop_ds.current_utc_offset . */
99 	uint16_t	       current_utc_offset;
100 	/** @cond INTERNAL_HIDDEN */
101 	/** Padding. */
102 	uint8_t		       reserved;
103 	/** @endcond */
104 	/** Value of @ref ptp_parent_ds.gm_priority1 of transmitter. */
105 	uint8_t		       gm_priority1;
106 	/** Value of @ref ptp_parent_ds.gm_clk_quality of transmitter. */
107 	struct ptp_clk_quality gm_clk_quality;
108 	/** Value of @ref ptp_parent_ds.gm_priority2 of transmitter. */
109 	uint8_t		       gm_priority2;
110 	/** Value of @ref ptp_parent_ds.gm_id of transmitter. */
111 	ptp_clk_id	       gm_id;
112 	/** Value of @ref ptp_current_ds.steps_rm of transmitter. */
113 	uint16_t	       steps_rm;
114 	/** Time source of a clock of the sender. */
115 	uint8_t		       time_src;
116 	/** Flexible array of zero or more TLV entities. */
117 	uint8_t		       suffix[];
118 } __packed;
119 
120 /**
121  * @brief PTP Sync message header.
122  */
123 struct ptp_sync_msg {
124 	/** PTP message header. */
125 	struct ptp_header    hdr;
126 	/** PTP Instance Time of an originating PTP Instance when message was transmitted. */
127 	struct ptp_timestamp origin_timestamp;
128 	/** Flexible array of zero or more TLV entities. */
129 	uint8_t		     suffix[];
130 } __packed;
131 
132 /**
133  * @brief PTP Delay_Req message header.
134  */
135 struct ptp_delay_req_msg {
136 	/** PTP message header. */
137 	struct ptp_header    hdr;
138 	/** PTP Instance Time of an originating PTP Instance when message was transmitted. */
139 	struct ptp_timestamp origin_timestamp;
140 	/** Flexible array of zero or more TLV entities. */
141 	uint8_t		     suffix[];
142 } __packed;
143 
144 /**
145  * @brief PTP Follow_Up message header.
146  */
147 struct ptp_follow_up_msg {
148 	/** PTP message header. */
149 	struct ptp_header    hdr;
150 	/** Precise timestamp of Sync message corresponding to that message. */
151 	struct ptp_timestamp precise_origin_timestamp;
152 	/** Flexible array of zero or more TLV entities. */
153 	uint8_t		     suffix[];
154 } __packed;
155 
156 /**
157  * @brief PTP Delay_Resp message header.
158  */
159 struct ptp_delay_resp_msg {
160 	/** PTP message header. */
161 	struct ptp_header    hdr;
162 	/** Ingress timestamp of Delay_Req message. */
163 	struct ptp_timestamp receive_timestamp;
164 	/** Port's ID of the sender of Delay_Req message. */
165 	struct ptp_port_id   req_port_id;
166 	/** Flexible array of zero or more TLV entities. */
167 	uint8_t		     suffix[];
168 } __packed;
169 
170 /**
171  * @brief PTP Pdelay_Req message header.
172  */
173 struct ptp_pdelay_req_msg {
174 	/** PTP message header. */
175 	struct ptp_header    hdr;
176 	/** PTP Instance Time of an originating PTP Instance when message was transmitted. */
177 	struct ptp_timestamp origin_timestamp;
178 	/** @cond INTERNAL_HIDDEN */
179 	/** Padding. */
180 	struct ptp_port_id   reserved; /* make it the same length as ptp_pdelay_resp */
181 	/** @endcond */
182 	/** Flexible array of zero or more TLV entities. */
183 	uint8_t		     suffix[];
184 } __packed;
185 
186 /**
187  * @brief PTP Pdelay_Resp message header.
188  */
189 struct ptp_pdelay_resp_msg {
190 	/** PTP message header. */
191 	struct ptp_header    hdr;
192 	/** Ingress timestamp of Pdelay_Req message. */
193 	struct ptp_timestamp req_receipt_timestamp;
194 	/** Port's ID of the sender of Pdelay_Req message. */
195 	struct ptp_port_id   req_port_id;
196 	/** Flexible array of zero or more TLV entities. */
197 	uint8_t		     suffix[];
198 } __packed;
199 
200 /**
201  * @brief PTP Pdelay_Resp_Follow_Up message header.
202  */
203 struct ptp_pdelay_resp_follow_up_msg {
204 	/** PTP message header. */
205 	struct ptp_header    hdr;
206 	/** Precise timestamp of Pdelay_Resp message corresponding to that message. */
207 	struct ptp_timestamp resp_origin_timestamp;
208 	/** Port's ID of the sender of Pdelay_Req message. */
209 	struct ptp_port_id   req_port_id;
210 	/** Flexible array of zero or more TLV entities. */
211 	uint8_t		     suffix[];
212 } __packed;
213 
214 /**
215  * @brief PTP Signaling message header.
216  */
217 struct ptp_signaling_msg {
218 	/** PTP message header. */
219 	struct ptp_header  hdr;
220 	/** Port's ID to which this message is addressed. */
221 	struct ptp_port_id target_port_id;
222 	/** Flexible array of zero or more TLV entities. */
223 	uint8_t		   suffix[];
224 } __packed;
225 
226 /**
227  * @brief PTP Management message header.
228  */
229 struct ptp_management_msg {
230 	/** PTP message header. */
231 	struct ptp_header  hdr;
232 	/** Port's ID to which this message is addressed. */
233 	struct ptp_port_id target_port_id;
234 	/** For response it should be computed from starting_boundary_hops and boundary_hops
235 	 * of the requesting message.
236 	 */
237 	uint8_t		   starting_boundary_hops;
238 	/** Number of successive retransmissions of the message
239 	 * by Boundary Clocks receiving message.
240 	 */
241 	uint8_t		   boundary_hops;
242 	/** Action to be taken on receipt of the message */
243 	uint8_t		   action:5;
244 	/** @cond INTERNAL_HIDDEN */
245 	/** Padding. */
246 	uint8_t		   reserved;
247 	/** @endcond */
248 	/** Flexible array of zero or more TLV entities. */
249 	uint8_t		   suffix[];
250 } __packed;
251 
252 /**
253  * @brief Generic PTP message structure.
254  */
255 struct ptp_msg {
256 	union {
257 		/** General PTP message header. */
258 		struct ptp_header		     header;
259 		/** Announce message. */
260 		struct ptp_announce_msg		     announce;
261 		/** Sync message. */
262 		struct ptp_sync_msg		     sync;
263 		/** Delay_Req message. */
264 		struct ptp_delay_req_msg	     delay_req;
265 		/** Follow_Up message. */
266 		struct ptp_follow_up_msg	     follow_up;
267 		/** Delay_Resp message. */
268 		struct ptp_delay_resp_msg	     delay_resp;
269 		/** Pdelay_Req message. */
270 		struct ptp_pdelay_req_msg	     pdelay_req;
271 		/** Pdelay_Resp message. */
272 		struct ptp_pdelay_resp_msg	     pdelay_resp;
273 		/** Pdelay_Resp_Follow_Up message. */
274 		struct ptp_pdelay_resp_follow_up_msg pdelay_resp_follow_up;
275 		/** Signaling message. */
276 		struct ptp_signaling_msg	     signaling;
277 		/** Management message. */
278 		struct ptp_management_msg	     management;
279 		/** @cond INTERNAL_HIDEN */
280 		/** MTU. */
281 		uint8_t				     mtu[NET_ETH_MTU];
282 		/** @endcond */
283 	} __packed;
284 	struct {
285 		/**
286 		 * Timestamp extracted from the message in a host binary format.
287 		 * Depending on the message type the value comes from different
288 		 * field of the message.
289 		 */
290 		struct net_ptp_time protocol;
291 		 /** Ingress timestamp on the host side. */
292 		struct net_ptp_time host;
293 
294 	} timestamp;
295 	/** Reference counter. */
296 	atomic_t ref;
297 	/** List object. */
298 	sys_snode_t node;
299 	/** Single-linked list of TLVs attached to the message. */
300 	sys_slist_t tlvs;
301 	/** Protocol address of the sender/receiver of the message. */
302 	struct sockaddr addr;
303 };
304 
305 /**
306  * @brief Function allocating space for a new PTP message.
307  *
308  * @return Pointer to the new PTP Message.
309  */
310 struct ptp_msg *ptp_msg_alloc(void);
311 
312 /**
313  * @brief Function removing reference to the PTP message.
314  *
315  * @note If the message is not referenced anywhere, the memory space is cleared.
316  *
317  * @param[in] msg Pointer to the PTP message.
318  */
319 void ptp_msg_unref(struct ptp_msg *msg);
320 
321 /**
322  * @brief Function incrementing reference count for the PTP message.
323  *
324  * @param[in] msg Pointer to the PTP message.
325  */
326 void ptp_msg_ref(struct ptp_msg *msg);
327 
328 /**
329  * @brief Function extracting message type from it.
330  *
331  * @param[in] msg Pointer to the message.
332  *
333  * @return Type of the message.
334  */
335 enum ptp_msg_type ptp_msg_type(const struct ptp_msg *msg);
336 
337 /**
338  * @brief Function extracting PTP message from network packet.
339  *
340  * @param[in] pkt Pointer to the network packet.
341  *
342  * @note Returned message has all data in the network byte order.
343  *
344  * @return Pointer to a PTP message.
345  */
346 struct ptp_msg *ptp_msg_from_pkt(struct net_pkt *pkt);
347 
348 /**
349  * @brief Function preparing message right before transmission.
350  *
351  * @param[in] msg Pointer to the prepared PTP message.
352  */
353 void ptp_msg_pre_send(struct ptp_msg *msg);
354 
355 /**
356  * @brief Function preparing message for further processing after reception.
357  *
358  * @param[in] port Pointer to the PTP Port instance.
359  * @param[in] msg  Pointer to the received PTP message.
360  * @param[in] cnt  Length of the message in bytes.
361  *
362  * @return 0 on success, negative otherwise.
363  */
364 int ptp_msg_post_recv(struct ptp_port *port, struct ptp_msg *msg, int cnt);
365 
366 /**
367  * @brief Function adding TLV of specified length to the message.
368  *
369  * @param[in] msg    Pointer to the message that will have TLV added.
370  * @param[in] length Length of the TLV.
371  *
372  * @return Pointer to the TLV or NULL if there was no space to append TLV to the message.
373  */
374 struct ptp_tlv *ptp_msg_add_tlv(struct ptp_msg *msg, int length);
375 
376 /**
377  * @brief Function compering content of two PTP Announce messages.
378  *
379  * @param[in] m1 Pointer to the Announce message to be compared.
380  * @param[in] m2 Pointer to the Announce message to be compared.
381  *
382  * @return Negative if m1 < m2, 0 if equal, else positive
383  */
384 int ptp_msg_announce_cmp(const struct ptp_announce_msg *m1, const struct ptp_announce_msg *m2);
385 
386 /**
387  * @brief Function checking if given message comes from current PTP Port's
388  * TimeTransmitter PTP instance.
389  *
390  * @param[in] msg  Pointer to the message.
391  *
392  * @return True if the message is received from the current PTP Port's TimeTransmitter,
393  * false otherwise.
394  */
395 bool ptp_msg_current_parent(const struct ptp_msg *msg);
396 
397 #ifdef __cplusplus
398 }
399 #endif
400 
401 /**
402  * @}
403  */
404 
405 #endif /* ZEPHYR_INCLUDE_PTP_MSG_H_ */
406