1 /*
2  * Copyright (c) 2017 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief gPTP message helpers.
10  *
11  * This is not to be included by the application.
12  */
13 
14 #ifndef __GPTP_MESSAGES_H
15 #define __GPTP_MESSAGES_H
16 
17 #include <zephyr/net/net_pkt.h>
18 #include <zephyr/net/ethernet.h>
19 #include <zephyr/net/gptp.h>
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 /* Helpers to access gPTP messages. */
26 #define GPTP_HDR(pkt) gptp_get_hdr(pkt)
27 #define GPTP_ANNOUNCE(pkt) ((struct gptp_announce *)gptp_data(pkt))
28 #define GPTP_SIGNALING(pkt) ((struct gptp_signaling *)gptp_data(pkt))
29 #define GPTP_SYNC(pkt) ((struct gptp_sync *)gptp_data(pkt))
30 #define GPTP_FOLLOW_UP(pkt) ((struct gptp_follow_up *)gptp_data(pkt))
31 #define GPTP_DELAY_REQ(pkt) \
32 	((struct gptp_delay_req *)gptp_data(pkt))
33 #define GPTP_PDELAY_REQ(pkt) \
34 	((struct gptp_pdelay_req *)gptp_data(pkt))
35 #define GPTP_PDELAY_RESP(pkt) \
36 	((struct gptp_pdelay_resp *)gptp_data(pkt))
37 #define GPTP_PDELAY_RESP_FOLLOWUP(pkt) \
38 	((struct gptp_pdelay_resp_follow_up *)gptp_data(pkt))
39 
40 /* Field values. */
41 #define GPTP_TRANSPORT_802_1_AS 0x1
42 #define GPTP_VERSION 0x2
43 
44 /* Message Lengths. */
45 #define GPTP_PACKET_LEN(pkt) net_pkt_get_len(pkt)
46 #define GPTP_VALID_LEN(pkt, len) \
47 	(len > (NET_ETH_MINIMAL_FRAME_SIZE - GPTP_L2_HDR_LEN(pkt)))
48 #define GPTP_L2_HDR_LEN(pkt) \
49 	((long)GPTP_HDR(pkt) - (long)NET_ETH_HDR(pkt))
50 
51 #define GPTP_SYNC_LEN \
52 	(sizeof(struct gptp_hdr) + sizeof(struct gptp_sync))
53 #define GPTP_FOLLOW_UP_LEN \
54 	(sizeof(struct gptp_hdr) + sizeof(struct gptp_follow_up))
55 #define GPTP_PDELAY_REQ_LEN \
56 	(sizeof(struct gptp_hdr) + sizeof(struct gptp_pdelay_req))
57 #define GPTP_PDELAY_RESP_LEN \
58 	(sizeof(struct gptp_hdr) + sizeof(struct gptp_pdelay_resp))
59 #define GPTP_PDELAY_RESP_FUP_LEN \
60 	(sizeof(struct gptp_hdr) + sizeof(struct gptp_pdelay_resp_follow_up))
61 #define GPTP_SIGNALING_LEN \
62 	(sizeof(struct gptp_hdr) + sizeof(struct gptp_signaling))
63 
64 /* For the Announce message, the TLV is variable length. The len field
65  * indicates the length of the TLV not accounting for tlvType and lengthField
66  * which are 4 bytes.
67  */
68 #define GPTP_ANNOUNCE_LEN(pkt) \
69 	(sizeof(struct gptp_hdr) + sizeof(struct gptp_announce) \
70 	 + ntohs(GPTP_ANNOUNCE(pkt)->tlv.len) \
71 	 - sizeof(struct gptp_path_trace_tlv) + 4)
72 
73 #define GPTP_CHECK_LEN(pkt, len) \
74 	((GPTP_PACKET_LEN(pkt) != len) && (GPTP_VALID_LEN(pkt, len)))
75 #define GPTP_ANNOUNCE_CHECK_LEN(pkt) \
76 	((GPTP_PACKET_LEN(pkt) != GPTP_ANNOUNCE_LEN(pkt)) && \
77 	 (GPTP_VALID_LEN(pkt, GPTP_ANNOUNCE_LEN(pkt))))
78 
79 /* Header Flags. Byte 0. */
80 #define GPTP_FLAG_ALT_MASTER        BIT(0)
81 #define GPTP_FLAG_TWO_STEP          BIT(1)
82 #define GPTP_FLAG_UNICAST           BIT(2)
83 #define GPTP_FLAG_PROFILE_SPECIFIC1 BIT(5)
84 #define GPTP_FLAG_PROFILE_SPECIFIC2 BIT(6)
85 
86 /* Header Flags. Byte 1. */
87 #define GPTP_FLAG_LEAP61            BIT(0)
88 #define GPTP_FLAG_LEAP59            BIT(1)
89 #define GPTP_FLAG_CUR_UTC_OFF_VALID BIT(2)
90 #define GPTP_FLAG_PTP_TIMESCALE     BIT(3)
91 #define GPTP_FLAG_TIME_TRACEABLE    BIT(4)
92 #define GPTP_FLAG_FREQ_TRACEABLE    BIT(5)
93 
94 /* Signaling Interval Flags. */
95 #define GPTP_FLAG_COMPUTE_NEIGHBOR_RATE_RATIO 0x1
96 #define GPTP_FLAG_COMPUTE_NEIGHBOR_PROP_DELAY 0x2
97 
98 /* Signaling Interval Values. */
99 #define GPTP_ITV_KEEP               -128
100 #define GPTP_ITV_SET_TO_INIT        126
101 #define GPTP_ITV_STOP               127
102 
103 /* Control. Only set for header compatibility with v1. */
104 #define GPTP_SYNC_CONTROL_VALUE     0x0
105 #define GPTP_FUP_CONTROL_VALUE      0x2
106 #define GPTP_OTHER_CONTROL_VALUE    0x5
107 
108 /* Other default values. */
109 #define GPTP_RESP_LOG_MSG_ITV           0x7F
110 #define GPTP_ANNOUNCE_MSG_PATH_SEQ_TYPE htons(0x8)
111 
112 /* Organization Id used for TLV. */
113 #define GPTP_FUP_TLV_ORG_ID_BYTE_0  0x00
114 #define GPTP_FUP_TLV_ORG_ID_BYTE_1  0x80
115 #define GPTP_FUP_TLV_ORG_ID_BYTE_2  0xC2
116 #define GPTP_FUP_TLV_ORG_SUB_TYPE   0x01
117 
118 /* Organizationally Unique Identifiers */
119 #define OUI_IEEE_802_1_COMMITTEE 0x00, 0x80, 0xC2
120 
121 /**
122  * @brief gPTP Clock Quality
123  *
124  * Defines the quality of a clock.
125  * This is used by the Best Master Clock Algorithm.
126  */
127 struct gptp_clock_quality {
128 	uint8_t clock_class;
129 	uint8_t clock_accuracy;
130 	uint16_t offset_scaled_log_var;
131 } __packed;
132 
133 /**
134  * @brief gPTP Root System Identity
135  *
136  * Defines the Grand Master of a clock.
137  * This is used by the Best Master Clock Algorithm.
138  */
139 struct gptp_root_system_identity {
140 	/** Grand Master priority1 component. */
141 	uint8_t grand_master_prio1;
142 
143 	/** Grand Master clock quality. */
144 	struct gptp_clock_quality clk_quality;
145 
146 	/** Grand Master priority2 component. */
147 	uint8_t grand_master_prio2;
148 
149 	/** Grand Master clock identity. */
150 	uint8_t grand_master_id[GPTP_CLOCK_ID_LEN];
151 } __packed;
152 
153 /* Definition of all message types as defined by IEEE802.1AS. */
154 
155 struct gptp_path_trace_tlv {
156 	/** TLV type: 0x8. */
157 	uint16_t type;
158 
159 	/** Length. Number of TLVs * 8 bytes. */
160 	uint16_t len;
161 
162 	/** ClockIdentity array of the successive time-aware systems. */
163 	uint8_t  path_sequence[1][8];
164 } __packed;
165 
166 struct gptp_announce {
167 	/** Reserved fields. */
168 	uint8_t reserved1[10];
169 
170 	/** Current UTC offset. */
171 	int16_t cur_utc_offset;
172 
173 	/** Reserved field. */
174 	uint8_t reserved2;
175 
176 	/* gmPriorityVector priority 1 of the peer sending the message. */
177 	struct gptp_root_system_identity root_system_id;
178 
179 	/** masterStepsRemoved of the peer sending the message. */
180 	uint16_t steps_removed;
181 
182 	/** timeSource of the peer sending the message. */
183 	uint8_t time_source;
184 
185 	/* Path Trace TLV. This field has a variable length. */
186 	struct gptp_path_trace_tlv tlv;
187 } __packed;
188 
189 struct gptp_sync {
190 	/** Reserved field. This field is used for PTPv2, unused in gPTP. */
191 	uint8_t reserved[10];
192 } __packed;
193 
194 struct gptp_follow_up_tlv_hdr {
195 	/** TLV type: 0x3. */
196 	uint16_t type;
197 
198 	/** Length: 28. */
199 	uint16_t len;
200 } __packed;
201 
202 struct gptp_follow_up_tlv {
203 	/** Organization Id: 00-80-C2. */
204 	uint8_t org_id[3];
205 
206 	/** Organization Sub Type: 1. */
207 	uint8_t org_sub_type[3];
208 
209 	/** Rate ratio relative to the grand master of the peer. */
210 	int32_t cumulative_scaled_rate_offset;
211 
212 	/** Time Base Indicator of the current Grand Master. */
213 	uint16_t gm_time_base_indicator;
214 
215 	/** Difference of the time between the current GM and the previous. */
216 	struct gptp_scaled_ns last_gm_phase_change;
217 
218 	/** Diff of the frequency between the current GM and the previous. */
219 	int32_t scaled_last_gm_freq_change;
220 } __packed;
221 
222 struct gptp_follow_up {
223 	/** Higher 16 bits of the seconds at which the sync was sent. */
224 	uint16_t prec_orig_ts_secs_high;
225 
226 	/** Lower 32 bits of the seconds at which the sync was sent. */
227 	uint32_t prec_orig_ts_secs_low;
228 
229 	/** Nanoseconds at which the sync was sent. */
230 	uint32_t prec_orig_ts_nsecs;
231 
232 	/** Follow up TLV. */
233 	struct gptp_follow_up_tlv_hdr tlv_hdr;
234 	struct gptp_follow_up_tlv tlv;
235 } __packed;
236 
237 struct gptp_pdelay_req {
238 	/** Reserved fields. */
239 	uint8_t reserved1[10];
240 
241 	/** Reserved fields. */
242 	uint8_t reserved2[10];
243 } __packed;
244 
245 struct gptp_pdelay_resp {
246 	/** Higher 16 bits of the seconds at which the request was received. */
247 	uint16_t req_receipt_ts_secs_high;
248 
249 	/** Lower 32 bits of the seconds at which the request was received. */
250 	uint32_t req_receipt_ts_secs_low;
251 
252 	/** Nanoseconds at which the pdelay request was received. */
253 	uint32_t req_receipt_ts_nsecs;
254 
255 	/** Source Port Id of the Path Delay Request. */
256 	struct gptp_port_identity requesting_port_id;
257 } __packed;
258 
259 struct gptp_pdelay_resp_follow_up {
260 	/** Higher 16 bits of the seconds at which the response was sent. */
261 	uint16_t resp_orig_ts_secs_high;
262 
263 	/** Lower 32 bits of the seconds at which the response was sent. */
264 	uint32_t resp_orig_ts_secs_low;
265 
266 	/** Nanoseconds at which the response was received. */
267 	uint32_t resp_orig_ts_nsecs;
268 
269 	/** Source Port Id of the Path Delay Request. */
270 	struct gptp_port_identity requesting_port_id;
271 } __packed;
272 
273 struct gptp_message_itv_req_tlv {
274 	/** TLV type: 0x3. */
275 	uint16_t type;
276 
277 	/** Length field: 12. */
278 	uint16_t len;
279 
280 	/** Organization Id: 00-80-C2. */
281 	uint8_t org_id[3];
282 
283 	/** Organization sub type: 0x2. */
284 	uint8_t org_sub_type[3];
285 
286 	/** Log to base 2 of the mean time interval between pdelay requests. */
287 	int8_t link_delay_itv;
288 
289 	/** Log to base 2 of the mean time interval between syncs. */
290 	int8_t time_sync_itv;
291 
292 	/** Log to base 2 of the mean time interval between announces. */
293 	int8_t announce_itv;
294 
295 	/** Flags (computeNeighborRateRatio and computeNeighborPropDelay). */
296 	union {
297 		struct {
298 		    uint8_t compute_neighbor_rate_ratio : 1;
299 		    uint8_t compute_neighbor_prop_delay : 1;
300 		};
301 		uint8_t flags;
302 	};
303 	/** Reserved fields. */
304 	uint8_t reserved[2];
305 } __packed;
306 
307 struct gptp_signaling {
308 	/** Target Port Identity , always 0xFF. */
309 	struct gptp_port_identity target_port_id;
310 
311 	/** Message Interval TLV. */
312 	struct gptp_message_itv_req_tlv tlv;
313 } __packed;
314 
315 /**
316  * @brief Compute gPTP message location.
317  *
318  * @param pkt Network Buffer containing a gPTP message.
319  *
320  * @return Pointer to the start of the gPTP message inside the packet.
321  */
gptp_data(struct net_pkt * pkt)322 static inline uint8_t *gptp_data(struct net_pkt *pkt)
323 {
324 	return (uint8_t *)GPTP_HDR(pkt) + sizeof(struct gptp_hdr);
325 }
326 
327 /* Functions to prepare messages. */
328 
329 /**
330  * @brief Prepare Sync message.
331  *
332  * @param port gPTP port number.
333  *
334  * @return Pointer to the prepared Network Buffer.
335  */
336 struct net_pkt *gptp_prepare_sync(int port);
337 
338 /**
339  * @brief Prepare Follow Up message.
340  *
341  * @param port gPTP port number.
342  *
343  * @return Pointer to the prepared Network Buffer.
344  */
345 struct net_pkt *gptp_prepare_follow_up(int port, struct net_pkt *sync);
346 
347 /**
348  * @brief Prepare Path Delay Request message.
349  *
350  * @param port gPTP port number.
351  *
352  * @return Pointer to the prepared Network Buffer.
353  */
354 struct net_pkt *gptp_prepare_pdelay_req(int port);
355 
356 /**
357  * @brief Prepare Path Delay Response message.
358  *
359  * @param port gPTP port number.
360  * @param req Path Delay Request to reply to.
361  *
362  * @return Pointer to the prepared Network Buffer.
363  */
364 struct net_pkt *gptp_prepare_pdelay_resp(int port,
365 		struct net_pkt *req);
366 
367 /**
368  * @brief Prepare Announce message.
369  *
370  * @param port gPTP port number.
371  *
372  * @return Pointer to the prepared Network Buffer.
373  */
374 struct net_pkt *gptp_prepare_announce(int port);
375 
376 /**
377  * @brief Prepare Path Delay Response message.
378  *
379  * @param port gPTP port number.
380  * @param resp Related Path Delay Follow Up.
381  *
382  * @return Pointer to the prepared Network Buffer.
383  */
384 struct net_pkt *gptp_prepare_pdelay_follow_up(int port,
385 		struct net_pkt *resp);
386 
387 /* Functions to handle received messages. */
388 
389 /**
390  * @brief Handle Sync message.
391  *
392  * @param port gPTP port number.
393  * @param pkt Network Buffer.
394  */
395 void gptp_handle_sync(int port, struct net_pkt *pkt);
396 
397 /**
398  * @brief Handle Follow Up message.
399  *
400  * @param port gPTP port number.
401  * @param pkt Network Buffer to parse.
402  *
403  * @return 0 if success, Error Code otherwise.
404  */
405 int gptp_handle_follow_up(int port, struct net_pkt *pkt);
406 
407 /**
408  * @brief Handle Path Delay Request message.
409  *
410  * @param port gPTP port number.
411  * @param pkt Network Buffer.
412  */
413 void gptp_handle_pdelay_req(int port, struct net_pkt *pkt);
414 
415 /**
416  * @brief Handle Path Delay Response message.
417  *
418  * @param port gPTP port number.
419  * @param pkt Network Buffer to parse.
420  *
421  * @return 0 if success, Error Code otherwise.
422  */
423 int gptp_handle_pdelay_resp(int port, struct net_pkt *pkt);
424 
425 /**
426  * @brief Handle Path Delay Follow Up message.
427  *
428  * @param port gPTP port number.
429  * @param pkt Network Buffer to parse.
430  *
431  * @return 0 if success, Error Code otherwise.
432  */
433 int gptp_handle_pdelay_follow_up(int port, struct net_pkt *pkt);
434 
435 /**
436  * @brief Handle Signaling message.
437  *
438  * @param port gPTP port number.
439  * @param pkt Network Buffer
440  */
441 void gptp_handle_signaling(int port, struct net_pkt *pkt);
442 
443 /* Functions to send messages. */
444 
445 /**
446  * @brief Send a Sync message.
447  *
448  * @param port gPTP port number.
449  * @param pkt Sync message.
450  */
451 void gptp_send_sync(int port, struct net_pkt *pkt);
452 
453 /**
454  * @brief Send a Follow Up message.
455  *
456  * @param port gPTP port number.
457  * @param pkt Follow Up message.
458  */
459 void gptp_send_follow_up(int port, struct net_pkt *pkt);
460 
461 /**
462  * @brief Send an Announce message.
463  *
464  * @param port gPTP port number.
465  * @param pkt Announce message.
466  */
467 void gptp_send_announce(int port, struct net_pkt *pkt);
468 
469 /**
470  * @brief Send a Path Delay Request on the given port.
471  *
472  * @param port gPTP port number.
473  */
474 void gptp_send_pdelay_req(int port);
475 
476 /**
477  * @brief Send a Path Delay Response for the given Path Delay Request.
478  *
479  * @param port gPTP port number.
480  * @param pkt Network Buffer containing the prepared Path Delay Response.
481  * @param treq Time at which the Path Delay Request was received.
482  */
483 void gptp_send_pdelay_resp(int port, struct net_pkt *pkt,
484 			   struct net_ptp_time *treq);
485 
486 /**
487  * @brief Send a Path Delay Response for the given Path Delay Request.
488  *
489  * @param port gPTP port number.
490  * @param pkt Network Buffer containing the prepared Path Delay Follow Up.
491  * @param tresp Time at which the Path Delay Response was sent.
492  */
493 void gptp_send_pdelay_follow_up(int port, struct net_pkt *pkt,
494 				struct net_ptp_time *tresp);
495 
496 #ifdef __cplusplus
497 }
498 #endif
499 
500 #endif /* __GPTP_MESSAGES_H */
501