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, ¤t);
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, ¤t);
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