1 /*
2  * Copyright (c) 2024 BayLibre SAS
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(ptp_clock, CONFIG_PTP_LOG_LEVEL);
9 
10 #include <stdbool.h>
11 #include <stdlib.h>
12 #include <string.h>
13 
14 #include <zephyr/posix/sys/eventfd.h>
15 
16 #include <zephyr/kernel.h>
17 #include <zephyr/drivers/ptp_clock.h>
18 #include <zephyr/net/ethernet.h>
19 #include <zephyr/net/net_if.h>
20 #include <zephyr/net/socket.h>
21 #include <zephyr/sys/slist.h>
22 
23 #include "btca.h"
24 #include "clock.h"
25 #include "ddt.h"
26 #include "msg.h"
27 #include "port.h"
28 #include "tlv.h"
29 #include "transport.h"
30 
31 #define MIN_NSEC_TO_TIMEINTERVAL (0xFFFF800000000000ULL)
32 #define MAX_NSEC_TO_TIMEINTERVAL (0x00007FFFFFFFFFFFULL)
33 
34 /**
35  * @brief PTP Clock structure.
36  */
37 struct ptp_clock {
38 	const struct device	    *phc;
39 	struct ptp_default_ds	    default_ds;
40 	struct ptp_current_ds	    current_ds;
41 	struct ptp_parent_ds	    parent_ds;
42 	struct ptp_time_prop_ds	    time_prop_ds;
43 	struct ptp_dataset	    dataset;
44 	struct ptp_foreign_tt_clock *best;
45 	sys_slist_t		    ports_list;
46 	struct zsock_pollfd	    pollfd[1 + 2 * CONFIG_PTP_NUM_PORTS];
47 	bool			    pollfd_valid;
48 	bool			    state_decision_event;
49 	uint8_t			    time_src;
50 	struct {
51 		uint64_t	    t1;
52 		uint64_t	    t2;
53 		uint64_t	    t3;
54 		uint64_t	    t4;
55 	} timestamp;			/* latest timestamps in nanoseconds */
56 };
57 
58 __maybe_unused static struct ptp_clock ptp_clk = { 0 };
59 char str_clock_id[] = "FF:FF:FF:FF:FF:FF:FF:FF";
60 
clock_generate_id(ptp_clk_id * clock_id,struct net_if * iface)61 static int clock_generate_id(ptp_clk_id *clock_id, struct net_if *iface)
62 {
63 	struct net_linkaddr *addr = net_if_get_link_addr(iface);
64 
65 	if (addr) {
66 		clock_id->id[0] = addr->addr[0];
67 		clock_id->id[1] = addr->addr[1];
68 		clock_id->id[2] = addr->addr[2];
69 		clock_id->id[3] = 0xFF;
70 		clock_id->id[4] = 0xFE;
71 		clock_id->id[5] = addr->addr[3];
72 		clock_id->id[6] = addr->addr[4];
73 		clock_id->id[7] = addr->addr[5];
74 		return 0;
75 	}
76 	return -1;
77 }
78 
clock_id_str(ptp_clk_id * clock_id)79 static const char *clock_id_str(ptp_clk_id *clock_id)
80 {
81 	uint8_t *cid = clock_id->id;
82 
83 	snprintk(str_clock_id, sizeof(str_clock_id), "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
84 		 cid[0],
85 		 cid[1],
86 		 cid[2],
87 		 cid[3],
88 		 cid[4],
89 		 cid[5],
90 		 cid[6],
91 		 cid[7]);
92 
93 	return str_clock_id;
94 }
95 
clock_ns_to_timeinterval(int64_t val)96 static ptp_timeinterval clock_ns_to_timeinterval(int64_t val)
97 {
98 	if (val < (int64_t)MIN_NSEC_TO_TIMEINTERVAL) {
99 		val = MIN_NSEC_TO_TIMEINTERVAL;
100 	} else if (val > (int64_t)MAX_NSEC_TO_TIMEINTERVAL) {
101 		val = MAX_NSEC_TO_TIMEINTERVAL;
102 	}
103 
104 	return (uint64_t)val << 16;
105 }
106 
clock_forward_msg(struct ptp_port * ingress,struct ptp_port * port,struct ptp_msg * msg,bool * network_byte_order)107 static int clock_forward_msg(struct ptp_port *ingress,
108 			     struct ptp_port *port,
109 			     struct ptp_msg *msg,
110 			     bool *network_byte_order)
111 {
112 	if (ingress == port) {
113 		return 0;
114 	}
115 
116 	if (*network_byte_order == false) {
117 		ptp_msg_pre_send(msg);
118 		*network_byte_order = true;
119 	}
120 
121 	return ptp_transport_send(port, msg, PTP_SOCKET_GENERAL);
122 }
123 
clock_forward_management_msg(struct ptp_port * port,struct ptp_msg * msg)124 static void clock_forward_management_msg(struct ptp_port *port, struct ptp_msg *msg)
125 {
126 	int length;
127 	struct ptp_port *iter;
128 	bool net_byte_ord = false;
129 	enum ptp_port_state state = ptp_port_state(port);
130 
131 	if (ptp_clock_type() != PTP_CLOCK_TYPE_BOUNDARY) {
132 		/* Clocks other than Boundary Clock shouldn't retransmit messages. */
133 		return;
134 	}
135 
136 	if (msg->header.flags[0] & PTP_MSG_UNICAST_FLAG) {
137 		return;
138 	}
139 
140 	if (msg->management.boundary_hops &&
141 	    (state == PTP_PS_GRAND_MASTER ||
142 	     state == PTP_PS_TIME_TRANSMITTER ||
143 	     state == PTP_PS_PRE_TIME_TRANSMITTER ||
144 	     state == PTP_PS_TIME_RECEIVER ||
145 	     state == PTP_PS_UNCALIBRATED)) {
146 		length = msg->header.msg_length;
147 		msg->management.boundary_hops--;
148 
149 		SYS_SLIST_FOR_EACH_CONTAINER(&ptp_clk.ports_list, iter, node) {
150 			if (clock_forward_msg(port, iter, msg, &net_byte_ord)) {
151 				LOG_ERR("Failed to forward message to %d Port",
152 					iter->port_ds.id.port_number);
153 			}
154 		}
155 
156 		if (net_byte_ord) {
157 			ptp_msg_post_recv(port, msg, length);
158 			msg->management.boundary_hops++;
159 		}
160 	}
161 }
162 
clock_management_set(struct ptp_port * port,struct ptp_msg * req,struct ptp_tlv_mgmt * tlv)163 static int clock_management_set(struct ptp_port *port,
164 				struct ptp_msg *req,
165 				struct ptp_tlv_mgmt *tlv)
166 {
167 	bool send_resp = false;
168 
169 	switch (tlv->id) {
170 	case PTP_MGMT_PRIORITY1:
171 		ptp_clk.default_ds.priority1 = *tlv->data;
172 		send_resp = true;
173 		break;
174 	case PTP_MGMT_PRIORITY2:
175 		ptp_clk.default_ds.priority2 = *tlv->data;
176 		send_resp = true;
177 		break;
178 	default:
179 		break;
180 	}
181 
182 	return send_resp ? ptp_port_management_resp(port, req, tlv) : 0;
183 }
184 
clock_update_grandmaster(void)185 static void clock_update_grandmaster(void)
186 {
187 	memset(&ptp_clk.current_ds, 0, sizeof(struct ptp_current_ds));
188 
189 	memcpy(&ptp_clk.parent_ds.port_id.clk_id,
190 	       &ptp_clk.default_ds.clk_id,
191 	       sizeof(ptp_clk_id));
192 	memcpy(&ptp_clk.parent_ds.gm_id,
193 	       &ptp_clk.default_ds.clk_id,
194 	       sizeof(ptp_clk_id));
195 	ptp_clk.parent_ds.port_id.port_number = 0;
196 	ptp_clk.parent_ds.gm_clk_quality = ptp_clk.default_ds.clk_quality;
197 	ptp_clk.parent_ds.gm_priority1 = ptp_clk.default_ds.priority1;
198 	ptp_clk.parent_ds.gm_priority2 = ptp_clk.default_ds.priority2;
199 
200 	ptp_clk.time_prop_ds.current_utc_offset = 37; /* IEEE 1588-2019 9.4 */
201 	ptp_clk.time_prop_ds.time_src = ptp_clk.time_src;
202 	ptp_clk.time_prop_ds.flags = 0;
203 }
204 
clock_update_time_receiver(void)205 static void clock_update_time_receiver(void)
206 {
207 	struct ptp_msg *best_msg = (struct ptp_msg *)k_fifo_peek_tail(&ptp_clk.best->messages);
208 
209 	ptp_clk.current_ds.steps_rm = 1 + ptp_clk.best->dataset.steps_rm;
210 
211 	memcpy(&ptp_clk.parent_ds.gm_id,
212 	       &best_msg->announce.gm_id,
213 	       sizeof(best_msg->announce.gm_id));
214 	memcpy(&ptp_clk.parent_ds.port_id,
215 	       &ptp_clk.best->dataset.sender,
216 	       sizeof(ptp_clk.best->dataset.sender));
217 	ptp_clk.parent_ds.gm_clk_quality = best_msg->announce.gm_clk_quality;
218 	ptp_clk.parent_ds.gm_priority1 = best_msg->announce.gm_priority1;
219 	ptp_clk.parent_ds.gm_priority2 = best_msg->announce.gm_priority2;
220 
221 	ptp_clk.time_prop_ds.current_utc_offset = best_msg->announce.current_utc_offset;
222 	ptp_clk.time_prop_ds.flags = best_msg->header.flags[1];
223 }
224 
clock_check_pollfd(void)225 static void clock_check_pollfd(void)
226 {
227 	struct ptp_port *port;
228 	struct zsock_pollfd *fd = &ptp_clk.pollfd[1];
229 
230 	if (ptp_clk.pollfd_valid) {
231 		return;
232 	}
233 
234 	SYS_SLIST_FOR_EACH_CONTAINER(&ptp_clk.ports_list, port, node) {
235 		for (int i = 0; i < PTP_SOCKET_CNT; i++) {
236 			fd->fd = port->socket[i];
237 			fd->events = ZSOCK_POLLIN | ZSOCK_POLLPRI;
238 			fd++;
239 		}
240 	}
241 
242 	ptp_clk.pollfd_valid = true;
243 }
244 
ptp_clock_init(void)245 const struct ptp_clock *ptp_clock_init(void)
246 {
247 	struct ptp_default_ds *dds = &ptp_clk.default_ds;
248 	struct ptp_parent_ds *pds  = &ptp_clk.parent_ds;
249 	struct net_if *iface = net_if_get_first_by_type(&NET_L2_GET_NAME(ETHERNET));
250 
251 	ptp_clk.time_src = (enum ptp_time_src)PTP_TIME_SRC_INTERNAL_OSC;
252 
253 	/* Initialize Default Dataset. */
254 	int ret = clock_generate_id(&dds->clk_id, iface);
255 
256 	if (ret) {
257 		LOG_ERR("Couldn't assign Clock Identity.");
258 		return NULL;
259 	}
260 
261 	dds->type = (enum ptp_clock_type)CONFIG_PTP_CLOCK_TYPE;
262 	dds->n_ports = 0;
263 	dds->time_receiver_only = IS_ENABLED(CONFIG_PTP_TIME_RECEIVER_ONLY) ? true : false;
264 
265 	dds->clk_quality.class = dds->time_receiver_only ? 255 : 248;
266 	dds->clk_quality.accuracy = CONFIG_PTP_CLOCK_ACCURACY;
267 	/* 0xFFFF means that value has not been computed - IEEE 1588-2019 7.6.3.3 */
268 	dds->clk_quality.offset_scaled_log_variance = 0xFFFF;
269 
270 	dds->max_steps_rm = 255;
271 
272 	dds->priority1 = CONFIG_PTP_PRIORITY1;
273 	dds->priority2 = CONFIG_PTP_PRIORITY2;
274 
275 	/* Initialize Parent Dataset. */
276 	clock_update_grandmaster();
277 	pds->obsreved_parent_offset_scaled_log_variance = 0xFFFF;
278 	pds->obsreved_parent_clk_phase_change_rate = 0x7FFFFFFF;
279 	/* Parent statistics haven't been measured - IEEE 1588-2019 7.6.4.2 */
280 	pds->stats = false;
281 
282 	ptp_clk.phc = net_eth_get_ptp_clock(iface);
283 	if (!ptp_clk.phc) {
284 		LOG_ERR("Couldn't get PTP HW Clock for the interface.");
285 		return NULL;
286 	}
287 
288 	ptp_clk.pollfd[0].fd = eventfd(0, EFD_NONBLOCK);
289 	ptp_clk.pollfd[0].events = ZSOCK_POLLIN;
290 
291 	sys_slist_init(&ptp_clk.ports_list);
292 	LOG_DBG("PTP Clock %s initialized", clock_id_str(&dds->clk_id));
293 	return &ptp_clk;
294 }
295 
ptp_clock_poll_sockets(void)296 struct zsock_pollfd *ptp_clock_poll_sockets(void)
297 {
298 	int ret;
299 
300 	clock_check_pollfd();
301 	ret = zsock_poll(ptp_clk.pollfd, PTP_SOCKET_CNT * ptp_clk.default_ds.n_ports + 1, -1);
302 	if (ret > 0 && ptp_clk.pollfd[0].revents) {
303 		eventfd_t value;
304 
305 		eventfd_read(ptp_clk.pollfd[0].fd, &value);
306 	}
307 
308 	return &ptp_clk.pollfd[1];
309 }
310 
ptp_clock_handle_state_decision_evt(void)311 void ptp_clock_handle_state_decision_evt(void)
312 {
313 	struct ptp_foreign_tt_clock *best = NULL, *foreign;
314 	struct ptp_port *port;
315 	bool tt_changed = false;
316 
317 	if (!ptp_clk.state_decision_event) {
318 		return;
319 	}
320 
321 	SYS_SLIST_FOR_EACH_CONTAINER(&ptp_clk.ports_list, port, node) {
322 		foreign = ptp_port_best_foreign(port);
323 		if (!foreign) {
324 			continue;
325 		}
326 		if (!best || ptp_btca_ds_cmp(&foreign->dataset, &best->dataset)) {
327 			best = foreign;
328 		}
329 	}
330 
331 	ptp_clk.best = best;
332 
333 	SYS_SLIST_FOR_EACH_CONTAINER(&ptp_clk.ports_list, port, node) {
334 		enum ptp_port_state state;
335 		enum ptp_port_event event;
336 
337 		state = ptp_btca_state_decision(port);
338 
339 		switch (state) {
340 		case PTP_PS_LISTENING:
341 			event = PTP_EVT_NONE;
342 			break;
343 		case PTP_PS_GRAND_MASTER:
344 			clock_update_grandmaster();
345 			event = PTP_EVT_RS_GRAND_MASTER;
346 			break;
347 		case PTP_PS_TIME_TRANSMITTER:
348 			event = PTP_EVT_RS_TIME_TRANSMITTER;
349 			break;
350 		case PTP_PS_TIME_RECEIVER:
351 			clock_update_time_receiver();
352 			event = PTP_EVT_RS_TIME_RECEIVER;
353 			break;
354 		case PTP_PS_PASSIVE:
355 			event = PTP_EVT_RS_PASSIVE;
356 			break;
357 		default:
358 			event = PTP_EVT_FAULT_DETECTED;
359 			break;
360 		}
361 
362 		ptp_port_event_handle(port, event, tt_changed);
363 	}
364 
365 	ptp_clk.state_decision_event = false;
366 }
367 
ptp_clock_management_msg_process(struct ptp_port * port,struct ptp_msg * msg)368 int ptp_clock_management_msg_process(struct ptp_port *port, struct ptp_msg *msg)
369 {
370 	static const ptp_clk_id all_ones = {
371 		.id = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
372 	};
373 	int ret;
374 	bool state_decision_required = false;
375 	enum ptp_mgmt_op action = ptp_mgmt_action(msg);
376 	struct ptp_port_id *target_port = &msg->management.target_port_id;
377 	const struct ptp_default_ds *dds = ptp_clock_default_ds();
378 	struct ptp_tlv_mgmt *mgmt = (struct ptp_tlv_mgmt *)msg->management.suffix;
379 	struct ptp_port *iter;
380 
381 	if (!ptp_clock_id_eq(&dds->clk_id, &target_port->clk_id) &&
382 	    !ptp_clock_id_eq(&target_port->clk_id, &all_ones)) {
383 		return state_decision_required;
384 	}
385 
386 	if (sys_slist_len(&msg->tlvs) != 1) {
387 		/* IEEE 1588-2019 15.3.2 - PTP mgmt msg transports single mgmt TLV */
388 		return state_decision_required;
389 	}
390 
391 	clock_forward_management_msg(port, msg);
392 
393 	switch (action) {
394 	case PTP_MGMT_SET:
395 		ret = clock_management_set(port, msg, mgmt);
396 		if (ret < 0) {
397 			return state_decision_required;
398 		}
399 		state_decision_required = ret ? true : false;
400 		break;
401 	case PTP_MGMT_GET:
402 		__fallthrough;
403 	case PTP_MGMT_CMD:
404 		break;
405 	default:
406 		return state_decision_required;
407 	}
408 
409 	switch (mgmt->id) {
410 	case PTP_MGMT_CLOCK_DESCRIPTION:
411 		__fallthrough;
412 	case PTP_MGMT_USER_DESCRIPTION:
413 		__fallthrough;
414 	case PTP_MGMT_SAVE_IN_NON_VOLATILE_STORAGE:
415 		__fallthrough;
416 	case PTP_MGMT_RESET_NON_VOLATILE_STORAGE:
417 		__fallthrough;
418 	case PTP_MGMT_INITIALIZE:
419 		__fallthrough;
420 	case PTP_MGMT_FAULT_LOG:
421 		__fallthrough;
422 	case PTP_MGMT_FAULT_LOG_RESET:
423 		__fallthrough;
424 	case PTP_MGMT_DOMAIN:
425 		__fallthrough;
426 	case PTP_MGMT_TIME_RECEIVER_ONLY:
427 		__fallthrough;
428 	case PTP_MGMT_ANNOUNCE_RECEIPT_TIMEOUT:
429 		__fallthrough;
430 	case PTP_MGMT_VERSION_NUMBER:
431 		__fallthrough;
432 	case PTP_MGMT_ENABLE_PORT:
433 		__fallthrough;
434 	case PTP_MGMT_DISABLE_PORT:
435 		__fallthrough;
436 	case PTP_MGMT_TIME:
437 		__fallthrough;
438 	case PTP_MGMT_CLOCK_ACCURACY:
439 		__fallthrough;
440 	case PTP_MGMT_UTC_PROPERTIES:
441 		__fallthrough;
442 	case PTP_MGMT_TRACEBILITY_PROPERTIES:
443 		__fallthrough;
444 	case PTP_MGMT_TIMESCALE_PROPERTIES:
445 		__fallthrough;
446 	case PTP_MGMT_UNICAST_NEGOTIATION_ENABLE:
447 		__fallthrough;
448 	case PTP_MGMT_PATH_TRACE_LIST:
449 		__fallthrough;
450 	case PTP_MGMT_PATH_TRACE_ENABLE:
451 		__fallthrough;
452 	case PTP_MGMT_GRANDMASTER_CLUSTER_TABLE:
453 		__fallthrough;
454 	case PTP_MGMT_UNICAST_TIME_TRANSMITTER_TABLE:
455 		__fallthrough;
456 	case PTP_MGMT_UNICAST_TIME_TRANSMITTER_MAX_TABLE_SIZE:
457 		__fallthrough;
458 	case PTP_MGMT_ACCEPTABLE_TIME_TRANSMITTER_TABLE:
459 		__fallthrough;
460 	case PTP_MGMT_ACCEPTABLE_TIME_TRANSMITTER_TABLE_ENABLED:
461 		__fallthrough;
462 	case PTP_MGMT_ACCEPTABLE_TIME_TRANSMITTER_MAX_TABLE_SIZE:
463 		__fallthrough;
464 	case PTP_MGMT_ALTERNATE_TIME_TRANSMITTER:
465 		__fallthrough;
466 	case PTP_MGMT_ALTERNATE_TIME_OFFSET_ENABLE:
467 		__fallthrough;
468 	case PTP_MGMT_ALTERNATE_TIME_OFFSET_NAME:
469 		__fallthrough;
470 	case PTP_MGMT_ALTERNATE_TIME_OFFSET_MAX_KEY:
471 		__fallthrough;
472 	case PTP_MGMT_ALTERNATE_TIME_OFFSET_PROPERTIES:
473 		__fallthrough;
474 	case PTP_MGMT_EXTERNAL_PORT_CONFIGURATION_ENABLED:
475 		__fallthrough;
476 	case PTP_MGMT_TIME_TRANSMITTER_ONLY:
477 		__fallthrough;
478 	case PTP_MGMT_HOLDOVER_UPGRADE_ENABLE:
479 		__fallthrough;
480 	case PTP_MGMT_EXT_PORT_CONFIG_PORT_DATA_SET:
481 		__fallthrough;
482 	case PTP_MGMT_TRANSPARENT_CLOCK_DEFAULT_DATA_SET:
483 		__fallthrough;
484 	case PTP_MGMT_TRANSPARENT_CLOCK_PORT_DATA_SET:
485 		__fallthrough;
486 	case PTP_MGMT_PRIMARY_DOMAIN:
487 		__fallthrough;
488 	case PTP_MGMT_DELAY_MECHANISM:
489 		__fallthrough;
490 	case PTP_MGMT_LOG_MIN_PDELAY_REQ_INTERVAL:
491 		ptp_port_management_error(port, msg, PTP_MGMT_ERR_NOT_SUPPORTED);
492 		break;
493 	default:
494 		if (target_port->port_number == port->port_ds.id.port_number) {
495 			ptp_port_management_msg_process(port, port, msg, mgmt);
496 		} else if (target_port->port_number == UINT16_MAX) {
497 			SYS_SLIST_FOR_EACH_CONTAINER(&ptp_clk.ports_list, iter, node) {
498 				if (ptp_port_management_msg_process(iter, port, msg, mgmt)) {
499 					break;
500 				}
501 			}
502 		}
503 		break;
504 	}
505 
506 	return state_decision_required;
507 }
508 
ptp_clock_synchronize(uint64_t ingress,uint64_t egress)509 void ptp_clock_synchronize(uint64_t ingress, uint64_t egress)
510 {
511 	int64_t offset;
512 	uint64_t delay = ptp_clk.current_ds.mean_delay >> 16;
513 
514 	ptp_clk.timestamp.t1 = egress;
515 	ptp_clk.timestamp.t2 = ingress;
516 
517 	if (!ptp_clk.current_ds.mean_delay) {
518 		return;
519 	}
520 
521 	offset = ptp_clk.timestamp.t2 - ptp_clk.timestamp.t1 - delay;
522 
523 	/* If diff is too big, ptp_clk needs to be set first. */
524 	if ((offset > (int64_t)NSEC_PER_SEC) || (offset < -(int64_t)NSEC_PER_SEC)) {
525 		struct net_ptp_time current;
526 
527 		LOG_WRN("Clock offset exceeds 1 second.");
528 
529 		ptp_clock_get(ptp_clk.phc, &current);
530 
531 		current.second -= (uint64_t)(offset / NSEC_PER_SEC);
532 		current.nanosecond -= (uint32_t)(offset % NSEC_PER_SEC);
533 
534 		ptp_clock_set(ptp_clk.phc, &current);
535 		return;
536 	}
537 
538 	LOG_DBG("Offset %lldns", offset);
539 	ptp_clk.current_ds.offset_from_tt = clock_ns_to_timeinterval(offset);
540 
541 	ptp_clock_adjust(ptp_clk.phc, offset);
542 }
543 
ptp_clock_delay(uint64_t egress,uint64_t ingress)544 void ptp_clock_delay(uint64_t egress, uint64_t ingress)
545 {
546 	int64_t delay;
547 
548 	ptp_clk.timestamp.t3 = egress;
549 	ptp_clk.timestamp.t4 = ingress;
550 
551 	delay = ((ptp_clk.timestamp.t2 - ptp_clk.timestamp.t3) +
552 		 (ptp_clk.timestamp.t4 - ptp_clk.timestamp.t1)) / 2;
553 
554 	LOG_DBG("Delay %lldns", delay);
555 	ptp_clk.current_ds.mean_delay = clock_ns_to_timeinterval(delay);
556 }
557 
ptp_clock_ports_list(void)558 sys_slist_t *ptp_clock_ports_list(void)
559 {
560 	return &ptp_clk.ports_list;
561 }
562 
ptp_clock_type(void)563 enum ptp_clock_type ptp_clock_type(void)
564 {
565 	return (enum ptp_clock_type)ptp_clk.default_ds.type;
566 }
567 
ptp_clock_default_ds(void)568 const struct ptp_default_ds *ptp_clock_default_ds(void)
569 {
570 	return &ptp_clk.default_ds;
571 }
572 
ptp_clock_parent_ds(void)573 const struct ptp_parent_ds *ptp_clock_parent_ds(void)
574 {
575 	return &ptp_clk.parent_ds;
576 }
577 
ptp_clock_current_ds(void)578 const struct ptp_current_ds *ptp_clock_current_ds(void)
579 {
580 	return &ptp_clk.current_ds;
581 }
582 
ptp_clock_time_prop_ds(void)583 const struct ptp_time_prop_ds *ptp_clock_time_prop_ds(void)
584 {
585 	return &ptp_clk.time_prop_ds;
586 }
587 
ptp_clock_ds(void)588 const struct ptp_dataset *ptp_clock_ds(void)
589 {
590 	struct ptp_dataset *ds = &ptp_clk.dataset;
591 
592 	ds->priority1		 = ptp_clk.default_ds.priority1;
593 	ds->clk_quality		 = ptp_clk.default_ds.clk_quality;
594 	ds->priority2		 = ptp_clk.default_ds.priority2;
595 	ds->steps_rm		 = 0;
596 	ds->sender.port_number	 = 0;
597 	ds->receiver.port_number = 0;
598 	memcpy(&ds->clk_id, &ptp_clk.default_ds.clk_id, sizeof(ptp_clk_id));
599 	memcpy(&ds->sender.clk_id, &ptp_clk.default_ds.clk_id, sizeof(ptp_clk_id));
600 	memcpy(&ds->receiver.clk_id, &ptp_clk.default_ds.clk_id, sizeof(ptp_clk_id));
601 	return ds;
602 }
603 
ptp_clock_best_foreign_ds(void)604 const struct ptp_dataset *ptp_clock_best_foreign_ds(void)
605 {
606 	return ptp_clk.best ? &ptp_clk.best->dataset : NULL;
607 }
608 
ptp_clock_port_from_iface(struct net_if * iface)609 struct ptp_port *ptp_clock_port_from_iface(struct net_if *iface)
610 {
611 	struct ptp_port *port;
612 
613 	SYS_SLIST_FOR_EACH_CONTAINER(&ptp_clk.ports_list, port, node) {
614 		if (port->iface == iface) {
615 			return port;
616 		}
617 	}
618 
619 	return NULL;
620 }
621 
ptp_clock_pollfd_invalidate(void)622 void ptp_clock_pollfd_invalidate(void)
623 {
624 	ptp_clk.pollfd_valid = false;
625 }
626 
ptp_clock_signal_timeout(void)627 void ptp_clock_signal_timeout(void)
628 {
629 	eventfd_write(ptp_clk.pollfd[0].fd, 1);
630 }
631 
ptp_clock_state_decision_req(void)632 void ptp_clock_state_decision_req(void)
633 {
634 	ptp_clk.state_decision_event = true;
635 }
636 
ptp_clock_port_add(struct ptp_port * port)637 void ptp_clock_port_add(struct ptp_port *port)
638 {
639 	ptp_clk.default_ds.n_ports++;
640 	sys_slist_append(&ptp_clk.ports_list, &port->node);
641 }
642 
ptp_clock_best_time_transmitter(void)643 const struct ptp_foreign_tt_clock *ptp_clock_best_time_transmitter(void)
644 {
645 	return ptp_clk.best;
646 }
647 
ptp_clock_id_eq(const ptp_clk_id * c1,const ptp_clk_id * c2)648 bool ptp_clock_id_eq(const ptp_clk_id *c1, const ptp_clk_id *c2)
649 {
650 	return memcmp(c1, c2, sizeof(ptp_clk_id)) == 0;
651 }
652