1 /*
2  * Copyright (c) 2024 BayLibre SAS
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file tlv.h
9  * @brief Type, Length, Value extension for PTP
10  *
11  * References are to version 2019 of IEEE 1588, ("PTP")
12  */
13 
14 #ifndef ZEPHYR_INCLUDE_PTP_TLV_H_
15 #define ZEPHYR_INCLUDE_PTP_TLV_H_
16 
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20 
21 #include <stdint.h>
22 
23 #include "ddt.h"
24 #include "msg.h"
25 
26 /**
27  * @brief Type of TLV (type, length, value)
28  *
29  * @note based on IEEE 1588-2019 Section 14.1.1 Table 52
30  */
31 enum ptp_tlv_type {
32 	PTP_TLV_TYPE_MANAGEMENT = 1,
33 	PTP_TLV_TYPE_MANAGEMENT_ERROR_STATUS,
34 	PTP_TLV_TYPE_ORGANIZATION_EXTENSION,
35 	PTP_TLV_TYPE_REQUEST_UNICAST_TRANSMISSION,
36 	PTP_TLV_TYPE_GRANT_UNICAST_TRANSMISSION,
37 	PTP_TLV_TYPE_CANCEL_UNICAST_TRANSMISSION,
38 	PTP_TLV_TYPE_ACKNOWLEDGE_CANCEL_UNICAST_TRANSMISSION,
39 	PTP_TLV_TYPE_PATH_TRACE,
40 	PTP_TLV_TYPE_ORGANIZATION_EXTENSION_PROPAGATE = 0x4000,
41 	PTP_TLV_TYPE_ENHANCED_ACCURACY_METRICS,
42 	PTP_TLV_TYPE_ORGANIZATION_EXTENSION_DO_NOT_PROPAGATE = 0x8000,
43 	PTP_TLV_TYPE_L1_SYNC,
44 	PTP_TLV_TYPE_PORT_COMMUNICATION_AVAILABILITY,
45 	PTP_TLV_TYPE_PROTOCOL_ADDRESS,
46 	PTP_TLV_TYPE_TIME_RECEIVER_RX_SYNC_TIMING_DATA,
47 	PTP_TLV_TYPE_TIME_RECEIVER_RX_SYNC_COMPUTED_DATA,
48 	PTP_TLV_TYPE_TIME_RECEIVER_TX_EVENT_TIMESTAMPS,
49 	PTP_TLV_TYPE_CUMULATIVE_RATE_RATIO,
50 	PTP_TLV_TYPE_PAD,
51 	PTP_TLV_TYPE_AUTHENTICATION,
52 };
53 
54 /**
55  * @brief PTP management message action field
56  *
57  * @note based on IEEE 1588-2019 Section 15.4.1.6 Table 57
58  */
59 enum ptp_mgmt_op {
60 	PTP_MGMT_GET,
61 	PTP_MGMT_SET,
62 	PTP_MGMT_RESP,
63 	PTP_MGMT_CMD,
64 	PTP_MGMT_ACK,
65 };
66 
67 /**
68  * @brief PTP management message ID
69  *
70  * @note based on IEEE 1588-2019 Section 15.5.2.3 Table 59
71  */
72 enum ptp_mgmt_id {
73 	PTP_MGMT_NULL_PTP_MANAGEMENT = 0x0,
74 	PTP_MGMT_CLOCK_DESCRIPTION,
75 	PTP_MGMT_USER_DESCRIPTION,
76 	PTP_MGMT_SAVE_IN_NON_VOLATILE_STORAGE,
77 	PTP_MGMT_RESET_NON_VOLATILE_STORAGE,
78 	PTP_MGMT_INITIALIZE,
79 	PTP_MGMT_FAULT_LOG,
80 	PTP_MGMT_FAULT_LOG_RESET,
81 	PTP_MGMT_DEFAULT_DATA_SET = 0x2000,
82 	PTP_MGMT_CURRENT_DATA_SET,
83 	PTP_MGMT_PARENT_DATA_SET,
84 	PTP_MGMT_TIME_PROPERTIES_DATA_SET,
85 	PTP_MGMT_PORT_DATA_SET,
86 	PTP_MGMT_PRIORITY1,
87 	PTP_MGMT_PRIORITY2,
88 	PTP_MGMT_DOMAIN,
89 	PTP_MGMT_TIME_RECEIVER_ONLY,
90 	PTP_MGMT_LOG_ANNOUNCE_INTERVAL,
91 	PTP_MGMT_ANNOUNCE_RECEIPT_TIMEOUT,
92 	PTP_MGMT_LOG_SYNC_INTERVAL,
93 	PTP_MGMT_VERSION_NUMBER,
94 	PTP_MGMT_ENABLE_PORT,
95 	PTP_MGMT_DISABLE_PORT,
96 	PTP_MGMT_TIME,
97 	PTP_MGMT_CLOCK_ACCURACY,
98 	PTP_MGMT_UTC_PROPERTIES,
99 	PTP_MGMT_TRACEBILITY_PROPERTIES,
100 	PTP_MGMT_TIMESCALE_PROPERTIES,
101 	PTP_MGMT_UNICAST_NEGOTIATION_ENABLE,
102 	PTP_MGMT_PATH_TRACE_LIST,
103 	PTP_MGMT_PATH_TRACE_ENABLE,
104 	PTP_MGMT_GRANDMASTER_CLUSTER_TABLE,
105 	PTP_MGMT_UNICAST_TIME_TRANSMITTER_TABLE,
106 	PTP_MGMT_UNICAST_TIME_TRANSMITTER_MAX_TABLE_SIZE,
107 	PTP_MGMT_ACCEPTABLE_TIME_TRANSMITTER_TABLE,
108 	PTP_MGMT_ACCEPTABLE_TIME_TRANSMITTER_TABLE_ENABLED,
109 	PTP_MGMT_ACCEPTABLE_TIME_TRANSMITTER_MAX_TABLE_SIZE,
110 	PTP_MGMT_ALTERNATE_TIME_TRANSMITTER,
111 	PTP_MGMT_ALTERNATE_TIME_OFFSET_ENABLE,
112 	PTP_MGMT_ALTERNATE_TIME_OFFSET_NAME,
113 	PTP_MGMT_ALTERNATE_TIME_OFFSET_MAX_KEY,
114 	PTP_MGMT_ALTERNATE_TIME_OFFSET_PROPERTIES,
115 	PTP_MGMT_EXTERNAL_PORT_CONFIGURATION_ENABLED = 0x3000,
116 	PTP_MGMT_TIME_TRANSMITTER_ONLY,
117 	PTP_MGMT_HOLDOVER_UPGRADE_ENABLE,
118 	PTP_MGMT_EXT_PORT_CONFIG_PORT_DATA_SET,
119 	PTP_MGMT_TRANSPARENT_CLOCK_DEFAULT_DATA_SET = 0x4000,
120 	PTP_MGMT_TRANSPARENT_CLOCK_PORT_DATA_SET,
121 	PTP_MGMT_PRIMARY_DOMAIN,
122 	PTP_MGMT_DELAY_MECHANISM = 0x6000,
123 	PTP_MGMT_LOG_MIN_PDELAY_REQ_INTERVAL,
124 };
125 
126 /**
127  * @brief Management error ID
128  *
129  * @note based on IEEE 1588-2019 Section 15.5.4.4 Table 109
130  */
131 enum ptp_mgmt_err {
132 	PTP_MGMT_ERR_RESPONSE_TOO_BIG = 0x1,
133 	PTP_MGMT_ERR_NO_SUCH_ID,
134 	PTP_MGMT_ERR_WRONG_LENGTH,
135 	PTP_MGMT_ERR_WRONG_VALUE,
136 	PTP_MGMT_ERR_NOT_SETABLE,
137 	PTP_MGMT_ERR_NOT_SUPPORTED,
138 	PTP_MGMT_ERR_UNPOPULATED,
139 	PTP_MGMT_ERR_GENERAL = 0xFFFE,
140 };
141 
142 /**
143  * @brief PAD TLV - used to increase length of any PTP message.
144  *
145  * @note 14.4.2 - PAD TLV
146  */
147 struct ptp_tlv_pad {
148 	/** Identify type of TLV. */
149 	uint16_t type;
150 	/** Length of pad. */
151 	uint16_t length;
152 	/** Pad. */
153 	uint8_t  pad[];
154 } __packed;
155 
156 /**
157  * @brief Management TLV.
158  *
159  * @note 15.5.2 - MANAGEMENT TLV field format.
160  */
161 struct ptp_tlv_mgmt {
162 	uint16_t type;
163 	uint16_t length;
164 	uint16_t id;
165 	uint8_t  data[];
166 } __packed;
167 
168 /**
169  * @brief Management error status TLV.
170  *
171  * @note 15.5.4 - MANAGEMENT_ERROR_STATUS TLV format.
172  */
173 struct ptp_tlv_mgmt_err {
174 	/** Type of TLV, shall be MANAGEMENT_ERROR_STATUS. */
175 	uint16_t	type;
176 	/** Length of following part of TLV. */
177 	uint16_t	length;
178 	/** Management error ID*/
179 	uint16_t	err_id;
180 	/** Management ID corresponding to the ID of management TLV that caused an error. */
181 	uint16_t	id;
182 	/** @cond INTERNAL_HIDEN */
183 	/** Padding. */
184 	uint32_t	reserved;
185 	/** @endcond */
186 	/** Optional text field to provide human-readable explanation of the error. */
187 	struct ptp_text display_data;
188 } __packed;
189 
190 /**
191  * @brief Structure holding pointers for Clock description send over TLV
192  */
193 struct ptp_tlv_mgmt_clock_desc {
194 	/** Type of PTP Clock. */
195 	uint16_t	     *type;
196 	/** Physical Layer Protocol. */
197 	struct ptp_text	     *phy_protocol;
198 	/** Number of bytes in phy_addr field. */
199 	uint16_t	     *phy_addr_len;
200 	/** Physical address of the PTP Port. */
201 	uint8_t		     *phy_addr;
202 	/** Protocol address of the PTP Port. */
203 	struct ptp_port_addr *protocol_addr;
204 	/** Unique identifier of the manufacturer. */
205 	uint8_t		     *manufacturer_id;
206 	/** Description of the PTP Instance from manufacturer. */
207 	struct ptp_text	     *product_desc;
208 	/** Revision for components of the PTP Instance. */
209 	struct ptp_text	     *revision_data;
210 	/** User defined description. */
211 	struct ptp_text	     *user_desc;
212 	/** PTP Profile implemented by the PTP Port. */
213 	uint8_t		     *profile_id;
214 };
215 
216 /**
217  * @brief Structure holding TLV. It is used as a helper to retrieve TLVs from PTP messages.
218  */
219 struct ptp_tlv_container {
220 	/** Object list. */
221 	sys_snode_t		       node;
222 	/** Pointer to the TLV. */
223 	struct ptp_tlv		       *tlv;
224 	/** Structure holding pointers for Clock description. */
225 	struct ptp_tlv_mgmt_clock_desc clock_desc;
226 };
227 
228 /**
229  * @brief TLV data fields representing defaultDS dataset.
230  */
231 struct ptp_tlv_default_ds {
232 	/** Value of two-step flag and @ref ptp_default_ds.time_receiver_only of the dataset. */
233 	uint8_t		       flags;
234 	/** @cond INTERNAL_HIDEN */
235 	/** Padding. */
236 	uint8_t		       reserved1;
237 	/** @endcond */
238 	/** Value of @ref ptp_default_ds.n_ports of the dataset. */
239 	uint16_t	       n_ports;
240 	/** Value of @ref ptp_default_ds.priority1 of the dataset. */
241 	uint8_t		       priority1;
242 	/** Value of @ref ptp_default_ds.clk_quality of the dataset. */
243 	struct ptp_clk_quality clk_quality;
244 	/** Value of @ref ptp_default_ds.priority2 of the dataset. */
245 	uint8_t		       priority2;
246 	/** Value of @ref ptp_default_ds.clk_id of the dataset. */
247 	ptp_clk_id	       clk_id;
248 	/** Value of @ref ptp_default_ds.domain of the dataset. */
249 	uint8_t		       domain;
250 	/** @cond INTERNAL_HIDEN */
251 	/** Padding. */
252 	uint8_t		       reserved2;
253 	/** @endcond */
254 } __packed;
255 
256 /**
257  * @bref TLV data fields representing currentDS dataset.
258  */
259 struct ptp_tlv_current_ds {
260 	/** Value of @ref ptp_current_ds.steps_rm of the dataset. */
261 	uint16_t	 steps_rm;
262 	/** Value of @ref ptp_current_ds.offset_from_tt of the dataset. */
263 	ptp_timeinterval offset_from_tt;
264 	/** Value of @ref ptp_current_ds.mean_delay of the dataset. */
265 	ptp_timeinterval mean_delay;
266 } __packed;
267 
268 /**
269  * @brief TLV data fields representing parentDS dataset.
270  */
271 struct ptp_tlv_parent_ds {
272 	/** Value of @ref ptp_parent_ds.port_id of the dataset. */
273 	struct ptp_port_id     port_id;
274 	/** Value of @ref ptp_parent_ds.stats of the dataset. */
275 	uint8_t		       flags;
276 	/** @cond INTERNAL_HIDEN */
277 	/** Padding. */
278 	uint8_t		       reserved;
279 	/** @endcond */
280 	/** Value of @ref ptp_parent_ds.obsreved_parent_offset_scaled_log_variance
281 	 * of the dataset.
282 	 */
283 	uint16_t	       obsreved_parent_offset_scaled_log_variance;
284 	/** Value of @ref ptp_parent_ds.obsreved_parent_clk_phase_change_rate of the dataset. */
285 	int32_t		       obsreved_parent_clk_phase_change_rate;
286 	/** Value of @ref ptp_parent_ds.gm_priority1 of the dataset. */
287 	uint8_t		       gm_priority1;
288 	/** Value of @ref ptp_parent_ds.gm_clk_quality of the dataset. */
289 	struct ptp_clk_quality gm_clk_quality;
290 	/** Value of @ref ptp_parent_ds.gm_priority2 of the dataset. */
291 	uint8_t		       gm_priority2;
292 	/** Value of @ref ptp_parent_ds.gm_id of the dataset. */
293 	ptp_clk_id	       gm_id;
294 } __packed;
295 
296 /**
297  * @brief TLV data fields representing time_propertiesDS dataset.
298  */
299 struct ptp_tlv_time_prop_ds {
300 	/** Value of @ref ptp_time_prop_ds.current_utc_offset of the dataset. */
301 	int16_t current_utc_offset;
302 	/** Value of @ref ptp_time_prop_ds.flags of the dataset. */
303 	uint8_t flags;
304 	/** Value of @ref ptp_time_prop_ds.time_src of the dataset. */
305 	uint8_t time_src;
306 } __packed;
307 
308 /**
309  * @brief TLV data fields representing portDS dataset.
310  */
311 struct ptp_tlv_port_ds {
312 	/** Value of @ref ptp_port_ds.id of the dataset. */
313 	struct ptp_port_id id;
314 	/** Value of @ref ptp_port_ds.state of the dataset. */
315 	uint8_t		   state;
316 	/** Value of @ref ptp_port_ds.log_min_delay_req_interval of the dataset. */
317 	int8_t		   log_min_delay_req_interval;
318 	/** Value of @ref ptp_port_ds.mean_link_delay of the dataset. */
319 	ptp_timeinterval   mean_link_delay;
320 	/** Value of @ref ptp_port_ds.log_announce_interval of the dataset. */
321 	int8_t		   log_announce_interval;
322 	/** Value of @ref ptp_port_ds.announce_receipt_timeout of the dataset. */
323 	uint8_t		   announce_receipt_timeout;
324 	/** Value of @ref ptp_port_ds.log_sync_interval of the dataset. */
325 	int8_t		   log_sync_interval;
326 	/** Value of @ref ptp_port_ds.delay_mechanism of the dataset. */
327 	uint8_t		   delay_mechanism;
328 	/** Value of @ref ptp_port_ds.log_min_pdelay_req_interval of the dataset. */
329 	int8_t		   log_min_pdelay_req_interval;
330 	/** Value of @ref ptp_port_ds.version of the dataset. */
331 	uint8_t		   version;
332 } __packed;
333 
334 /**
335  * @brief Function allocating memory for TLV container structure.
336  *
337  * @return Pointer to the TLV container structure.
338  */
339 struct ptp_tlv_container *ptp_tlv_alloc(void);
340 
341 /**
342  * @brief Function freeing memory used by TLV container.
343  *
344  * @param[in] tlv_container Pointer to the TLV container structure.
345  */
346 void ptp_tlv_free(struct ptp_tlv_container *tlv_container);
347 
348 /**
349  * @brief Function for getting type of action to be taken on receipt of the PTP message.
350  *
351  * @param[in] msg Pointer to the PTP message.
352  *
353  * @return Type of action to be taken.
354  */
355 enum ptp_mgmt_op ptp_mgmt_action(struct ptp_msg *msg);
356 
357 /**
358  * @brief Function for getting type of the TLV.
359  *
360  * @param[in] tlv Pointer to the TLV.
361  *
362  * @return Type of TLV message.
363  */
364 enum ptp_tlv_type ptp_tlv_type(struct ptp_tlv *tlv);
365 
366 /**
367  * @brief Function processing TLV after reception, and before processing by PTP stack.
368  *
369  * @param[in] tlv Pointer to the received TLV.
370  *
371  * @return Zero on success, otherwise negative.
372  */
373 int ptp_tlv_post_recv(struct ptp_tlv *tlv);
374 
375 /**
376  * @brief Function preparing TLV to on-wire format before transmitting.
377  *
378  * @param[in] tlv Pointer to the received TLV.
379  */
380 void ptp_tlv_pre_send(struct ptp_tlv *tlv);
381 
382 #ifdef __cplusplus
383 }
384 #endif
385 
386 /**
387  * @}
388  */
389 
390 #endif /* ZEPHYR_INCLUDE_PTP_TLV_H_ */
391