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_port, CONFIG_PTP_LOG_LEVEL);
9
10 #include <zephyr/kernel.h>
11 #include <zephyr/net/net_if.h>
12 #include <zephyr/net/ptp.h>
13 #include <zephyr/net/ptp_time.h>
14 #include <zephyr/random/random.h>
15
16 #include "btca.h"
17 #include "clock.h"
18 #include "port.h"
19 #include "msg.h"
20 #include "tlv.h"
21 #include "transport.h"
22
23 #define DEFAULT_LOG_MSG_INTERVAL (0x7F)
24
25 #define PORT_DELAY_REQ_CLEARE_TO (3 * NSEC_PER_SEC)
26
27 #define PORT_LINK_UP BIT(0)
28 #define PORT_LINK_DOWN BIT(1)
29 #define PORT_LINK_CHANGED BIT(2)
30 #define PORT_LINK_EVENT_MASK (NET_EVENT_IF_DOWN | NET_EVENT_IF_UP)
31
32 static struct ptp_port ports[CONFIG_PTP_NUM_PORTS];
33 static struct k_mem_slab foreign_tts_slab;
34 #if CONFIG_PTP_FOREIGN_TIME_TRANSMITTER_FEATURE
35 BUILD_ASSERT(CONFIG_PTP_FOREIGN_TIME_TRANSMITTER_RECORD_SIZE >= 5 * CONFIG_PTP_NUM_PORTS,
36 "PTP_FOREIGN_TIME_TRANSMITTER_RECORD_SIZE is smaller than expected!");
37
38 K_MEM_SLAB_DEFINE_STATIC(foreign_tts_slab,
39 sizeof(struct ptp_foreign_tt_clock),
40 CONFIG_PTP_FOREIGN_TIME_TRANSMITTER_RECORD_SIZE,
41 8);
42 #endif
43
44 char str_port_id[] = "FF:FF:FF:FF:FF:FF:FF:FF-FFFF";
45
port_id_str(struct ptp_port_id * port_id)46 const char *port_id_str(struct ptp_port_id *port_id)
47 {
48 uint8_t *pid = port_id->clk_id.id;
49
50 snprintk(str_port_id, sizeof(str_port_id), "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X-%04X",
51 pid[0],
52 pid[1],
53 pid[2],
54 pid[3],
55 pid[4],
56 pid[5],
57 pid[6],
58 pid[7],
59 port_id->port_number);
60
61 return str_port_id;
62 }
63
port_state_str(enum ptp_port_state state)64 static const char *port_state_str(enum ptp_port_state state)
65 {
66 const static char * const states[] = {
67 [PTP_PS_INITIALIZING] = "INITIALIZING",
68 [PTP_PS_FAULTY] = "FAULTY",
69 [PTP_PS_DISABLED] = "DISABLED",
70 [PTP_PS_LISTENING] = "LISTENING",
71 [PTP_PS_PRE_TIME_TRANSMITTER] = "PRE TIME TRANSMITTER",
72 [PTP_PS_TIME_TRANSMITTER] = "TIME TRANSMITTER",
73 [PTP_PS_GRAND_MASTER] = "GRAND MASTER",
74 [PTP_PS_PASSIVE] = "PASSIVE",
75 [PTP_PS_UNCALIBRATED] = "UNCALIBRATED",
76 [PTP_PS_TIME_RECEIVER] = "TIME RECEIVER",
77 };
78
79 return states[state];
80 }
81
port_msg_send(struct ptp_port * port,struct ptp_msg * msg,enum ptp_socket idx)82 static int port_msg_send(struct ptp_port *port, struct ptp_msg *msg, enum ptp_socket idx)
83 {
84 ptp_msg_pre_send(msg);
85
86 return ptp_transport_send(port, msg, idx);
87 }
88
port_timer_set_timeout(struct k_timer * timer,uint8_t factor,int8_t log_seconds)89 static void port_timer_set_timeout(struct k_timer *timer, uint8_t factor, int8_t log_seconds)
90 {
91 uint64_t timeout = log_seconds < 0 ?
92 (uint64_t)((NSEC_PER_SEC * factor) >> (log_seconds * -1)) :
93 (uint64_t)((NSEC_PER_SEC * factor) << log_seconds);
94
95 k_timer_start(timer, K_NSEC(timeout), K_NO_WAIT);
96 }
97
port_timer_set_timeout_random(struct k_timer * timer,int min_factor,int span,int log_seconds)98 static void port_timer_set_timeout_random(struct k_timer *timer,
99 int min_factor,
100 int span,
101 int log_seconds)
102 {
103 uint64_t timeout, random_ns;
104
105 if (log_seconds < 0) {
106 timeout = (uint64_t)((NSEC_PER_SEC * min_factor) >> -log_seconds);
107 random_ns = (uint64_t)(NSEC_PER_SEC >> -log_seconds);
108 } else {
109 timeout = (uint64_t)((NSEC_PER_SEC * min_factor) << log_seconds);
110 random_ns = (uint64_t)((span * NSEC_PER_SEC) << log_seconds);
111 }
112
113 timeout = (uint64_t)(timeout + (random_ns * (sys_rand32_get() % (1 << 15) + 1) >> 15));
114 k_timer_start(timer, K_NSEC(timeout), K_NO_WAIT);
115 }
116
port_synchronize(struct ptp_port * port,struct net_ptp_time ingress_ts,struct net_ptp_time origin_ts,ptp_timeinterval correction1,ptp_timeinterval correction2)117 static void port_synchronize(struct ptp_port *port,
118 struct net_ptp_time ingress_ts,
119 struct net_ptp_time origin_ts,
120 ptp_timeinterval correction1,
121 ptp_timeinterval correction2)
122 {
123 uint64_t t1, t2, t1c;
124
125 t1 = origin_ts.second * NSEC_PER_SEC + origin_ts.nanosecond;
126 t2 = ingress_ts.second * NSEC_PER_SEC + ingress_ts.nanosecond;
127 t1c = t1 + (correction1 >> 16) + (correction2 >> 16);
128
129 ptp_clock_synchronize(t2, t1c);
130
131 port_timer_set_timeout(&port->timers.sync,
132 port->port_ds.announce_receipt_timeout,
133 port->port_ds.log_sync_interval);
134 }
135
port_ds_init(struct ptp_port * port)136 static void port_ds_init(struct ptp_port *port)
137 {
138 struct ptp_port_ds *ds = &port->port_ds;
139 const struct ptp_default_ds *dds = ptp_clock_default_ds();
140
141 memcpy(&ds->id.clk_id, &dds->clk_id, sizeof(ptp_clk_id));
142 ds->id.port_number = dds->n_ports + 1;
143
144 ds->state = PTP_PS_INITIALIZING;
145 ds->log_min_delay_req_interval = CONFIG_PTP_MIN_DELAY_REQ_LOG_INTERVAL;
146 ds->log_announce_interval = CONFIG_PTP_ANNOUNCE_LOG_INTERVAL;
147 ds->announce_receipt_timeout = CONFIG_PTP_ANNOUNCE_RECV_TIMEOUT;
148 ds->log_sync_interval = CONFIG_PTP_SYNC_LOG_INTERVAL;
149 ds->delay_mechanism = PTP_DM_E2E;
150 ds->log_min_pdelay_req_interval = CONFIG_PTP_MIN_PDELAY_REQ_LOG_INTERVAL;
151 ds->version = PTP_VERSION;
152 ds->delay_asymmetry = 0;
153 }
154
port_delay_req_timestamp_cb(struct net_pkt * pkt)155 static void port_delay_req_timestamp_cb(struct net_pkt *pkt)
156 {
157 struct ptp_port *port = ptp_clock_port_from_iface(pkt->iface);
158 struct ptp_msg *req, *msg = ptp_msg_from_pkt(pkt);
159 sys_snode_t *iter, *last = NULL;
160
161 if (!port || !msg) {
162 return;
163 }
164
165 msg->header.src_port_id.port_number = ntohs(msg->header.src_port_id.port_number);
166
167 if (!ptp_port_id_eq(&port->port_ds.id, &msg->header.src_port_id) ||
168 ptp_msg_type(msg) != PTP_MSG_DELAY_REQ) {
169 return;
170 }
171
172 for (iter = sys_slist_peek_head(&port->delay_req_list);
173 iter;
174 iter = sys_slist_peek_next(iter), last = iter) {
175
176 req = CONTAINER_OF(iter, struct ptp_msg, node);
177
178 if (req->header.sequence_id != msg->header.sequence_id) {
179 continue;
180 }
181
182 if (pkt->timestamp.second == UINT64_MAX ||
183 (pkt->timestamp.second == 0 && pkt->timestamp.nanosecond == 0)) {
184 net_if_unregister_timestamp_cb(&port->delay_req_ts_cb);
185 sys_slist_remove(&port->delay_req_list, last, iter);
186 ptp_msg_unref(req);
187 return;
188 }
189
190 req->timestamp.host._sec.high = pkt->timestamp._sec.high;
191 req->timestamp.host._sec.low = pkt->timestamp._sec.low;
192 req->timestamp.host.nanosecond = pkt->timestamp.nanosecond;
193
194 LOG_DBG("Port %d registered timestamp for %d Delay_Req",
195 port->port_ds.id.port_number,
196 ntohs(msg->header.sequence_id));
197
198 if (iter == sys_slist_peek_tail(&port->delay_req_list)) {
199 net_if_unregister_timestamp_cb(&port->delay_req_ts_cb);
200 }
201 }
202 }
203
port_sync_timestamp_cb(struct net_pkt * pkt)204 static void port_sync_timestamp_cb(struct net_pkt *pkt)
205 {
206 struct ptp_port *port = ptp_clock_port_from_iface(pkt->iface);
207 struct ptp_msg *msg = ptp_msg_from_pkt(pkt);
208
209 if (!port || !msg) {
210 return;
211 }
212
213 msg->header.src_port_id.port_number = ntohs(msg->header.src_port_id.port_number);
214
215 if (ptp_port_id_eq(&port->port_ds.id, &msg->header.src_port_id) &&
216 ptp_msg_type(msg) == PTP_MSG_SYNC) {
217
218 const struct ptp_default_ds *dds = ptp_clock_default_ds();
219 const struct ptp_time_prop_ds *tpds = ptp_clock_time_prop_ds();
220 struct ptp_msg *resp = ptp_msg_alloc();
221
222 if (!resp) {
223 return;
224 }
225
226 resp->header.type_major_sdo_id = PTP_MSG_FOLLOW_UP;
227 resp->header.version = PTP_VERSION;
228 resp->header.msg_length = sizeof(struct ptp_follow_up_msg);
229 resp->header.domain_number = dds->domain;
230 resp->header.flags[1] = tpds->flags;
231 resp->header.src_port_id = port->port_ds.id;
232 resp->header.sequence_id = port->seq_id.sync++;
233 resp->header.log_msg_interval = port->port_ds.log_sync_interval;
234
235 resp->follow_up.precise_origin_timestamp.seconds_high = pkt->timestamp._sec.high;
236 resp->follow_up.precise_origin_timestamp.seconds_low = pkt->timestamp._sec.low;
237 resp->follow_up.precise_origin_timestamp.nanoseconds = pkt->timestamp.nanosecond;
238
239 net_if_unregister_timestamp_cb(&port->sync_ts_cb);
240
241 port_msg_send(port, resp, PTP_SOCKET_GENERAL);
242 ptp_msg_unref(resp);
243
244 LOG_DBG("Port %d sends Follow_Up message", port->port_ds.id.port_number);
245 }
246 }
247
port_announce_msg_transmit(struct ptp_port * port)248 static int port_announce_msg_transmit(struct ptp_port *port)
249 {
250 const struct ptp_parent_ds *pds = ptp_clock_parent_ds();
251 const struct ptp_current_ds *cds = ptp_clock_current_ds();
252 const struct ptp_default_ds *dds = ptp_clock_default_ds();
253 const struct ptp_time_prop_ds *tpds = ptp_clock_time_prop_ds();
254 struct ptp_msg *msg = ptp_msg_alloc();
255 int ret;
256
257 if (!msg) {
258 return -ENOMEM;
259 }
260
261 msg->header.type_major_sdo_id = PTP_MSG_ANNOUNCE;
262 msg->header.version = PTP_VERSION;
263 msg->header.msg_length = sizeof(struct ptp_announce_msg);
264 msg->header.domain_number = dds->domain;
265 msg->header.flags[1] = tpds->flags;
266 msg->header.src_port_id = port->port_ds.id;
267 msg->header.sequence_id = port->seq_id.announce++;
268 msg->header.log_msg_interval = port->port_ds.log_sync_interval;
269
270 msg->announce.current_utc_offset = tpds->current_utc_offset;
271 msg->announce.gm_priority1 = pds->gm_priority1;
272 msg->announce.gm_clk_quality = pds->gm_clk_quality;
273 msg->announce.gm_priority2 = pds->gm_priority2;
274 msg->announce.gm_id = pds->gm_id;
275 msg->announce.steps_rm = cds->steps_rm;
276 msg->announce.time_src = tpds->time_src;
277
278 ret = port_msg_send(port, msg, PTP_SOCKET_GENERAL);
279 ptp_msg_unref(msg);
280
281 if (ret < 0) {
282 return -EFAULT;
283 }
284
285 LOG_DBG("Port %d sends Announce message", port->port_ds.id.port_number);
286 return 0;
287 }
288
port_delay_req_msg_transmit(struct ptp_port * port)289 static int port_delay_req_msg_transmit(struct ptp_port *port)
290 {
291 const struct ptp_default_ds *dds = ptp_clock_default_ds();
292 struct ptp_msg *msg = ptp_msg_alloc();
293 int ret;
294
295 if (!msg) {
296 return -ENOMEM;
297 }
298
299 msg->header.type_major_sdo_id = PTP_MSG_DELAY_REQ;
300 msg->header.version = PTP_VERSION;
301 msg->header.msg_length = sizeof(struct ptp_delay_req_msg);
302 msg->header.domain_number = dds->domain;
303 msg->header.src_port_id = port->port_ds.id;
304 msg->header.sequence_id = port->seq_id.delay++;
305 msg->header.log_msg_interval = DEFAULT_LOG_MSG_INTERVAL;
306
307 net_if_register_timestamp_cb(&port->delay_req_ts_cb,
308 NULL,
309 port->iface,
310 port_delay_req_timestamp_cb);
311
312 ret = port_msg_send(port, msg, PTP_SOCKET_EVENT);
313 if (ret < 0) {
314 ptp_msg_unref(msg);
315 return -EFAULT;
316 }
317
318 sys_slist_append(&port->delay_req_list, &msg->node);
319
320 LOG_DBG("Port %d sends Delay_Req message", port->port_ds.id.port_number);
321 return 0;
322 }
323
port_sync_msg_transmit(struct ptp_port * port)324 static int port_sync_msg_transmit(struct ptp_port *port)
325 {
326 const struct ptp_default_ds *dds = ptp_clock_default_ds();
327 const struct ptp_time_prop_ds *tpds = ptp_clock_time_prop_ds();
328 struct ptp_msg *msg = ptp_msg_alloc();
329 int ret;
330
331 if (!msg) {
332 return -ENOMEM;
333 }
334
335 msg->header.type_major_sdo_id = PTP_MSG_SYNC;
336 msg->header.version = PTP_VERSION;
337 msg->header.msg_length = sizeof(struct ptp_sync_msg);
338 msg->header.domain_number = dds->domain;
339 msg->header.flags[0] = PTP_MSG_TWO_STEP_FLAG;
340 msg->header.flags[1] = tpds->flags;
341 msg->header.src_port_id = port->port_ds.id;
342 msg->header.sequence_id = port->seq_id.sync;
343 msg->header.log_msg_interval = port->port_ds.log_sync_interval;
344
345 net_if_register_timestamp_cb(&port->sync_ts_cb,
346 NULL,
347 port->iface,
348 port_sync_timestamp_cb);
349
350 ret = port_msg_send(port, msg, PTP_SOCKET_EVENT);
351 ptp_msg_unref(msg);
352
353 if (ret < 0) {
354 return -EFAULT;
355 }
356 LOG_DBG("Port %d sends Sync message", port->port_ds.id.port_number);
357 return 0;
358 }
359
port_timer_init(struct k_timer * timer,k_timer_expiry_t timeout_fn,void * user_data)360 static void port_timer_init(struct k_timer *timer, k_timer_expiry_t timeout_fn, void *user_data)
361 {
362 k_timer_init(timer, timeout_fn, NULL);
363 k_timer_user_data_set(timer, user_data);
364 }
365
port_timer_to_handler(struct k_timer * timer)366 static void port_timer_to_handler(struct k_timer *timer)
367 {
368 struct ptp_port *port = (struct ptp_port *)k_timer_user_data_get(timer);
369
370 if (timer == &port->timers.announce) {
371 atomic_set_bit(&port->timeouts, PTP_PORT_TIMER_ANNOUNCE_TO);
372 } else if (timer == &port->timers.sync) {
373 atomic_set_bit(&port->timeouts, PTP_PORT_TIMER_SYNC_TO);
374 } else if (timer == &port->timers.delay) {
375 atomic_set_bit(&port->timeouts, PTP_PORT_TIMER_DELAY_TO);
376 } else if (timer == &port->timers.qualification) {
377 atomic_set_bit(&port->timeouts, PTP_PORT_TIMER_QUALIFICATION_TO);
378 }
379
380 ptp_clock_signal_timeout();
381 }
382
foreign_clock_cleanup(struct ptp_foreign_tt_clock * foreign)383 static void foreign_clock_cleanup(struct ptp_foreign_tt_clock *foreign)
384 {
385 struct ptp_msg *msg;
386 int64_t timestamp, timeout, current = k_uptime_get() * NSEC_PER_MSEC;
387
388 while (foreign->messages_count > FOREIGN_TIME_TRANSMITTER_THRESHOLD) {
389 msg = (struct ptp_msg *)k_fifo_get(&foreign->messages, K_NO_WAIT);
390 ptp_msg_unref(msg);
391 foreign->messages_count--;
392 }
393
394 /* Remove messages that don't arrived at
395 * FOREIGN_TIME_TRANSMITTER_TIME_WINDOW (4 * announce interval) - IEEE 1588-2019 9.3.2.4.5
396 */
397 while (!k_fifo_is_empty(&foreign->messages)) {
398 msg = (struct ptp_msg *)k_fifo_peek_head(&foreign->messages);
399
400 if (msg->header.log_msg_interval <= -31) {
401 timeout = 0;
402 } else if (msg->header.log_msg_interval >= 31) {
403 timeout = INT64_MAX;
404 } else if (msg->header.log_msg_interval > 0) {
405 timeout = FOREIGN_TIME_TRANSMITTER_TIME_WINDOW_MUL *
406 (1 << msg->header.log_msg_interval) * NSEC_PER_SEC;
407 } else {
408 timeout = FOREIGN_TIME_TRANSMITTER_TIME_WINDOW_MUL * NSEC_PER_SEC /
409 (1 << (-msg->header.log_msg_interval));
410 }
411
412 timestamp = msg->timestamp.host.second * NSEC_PER_SEC +
413 msg->timestamp.host.nanosecond;
414
415 if (current - timestamp < timeout) {
416 /* Remaining messages are within time window */
417 break;
418 }
419
420 msg = (struct ptp_msg *)k_fifo_get(&foreign->messages, K_NO_WAIT);
421 ptp_msg_unref(msg);
422 foreign->messages_count--;
423 }
424 }
425
port_clear_foreign_clock_records(struct ptp_foreign_tt_clock * foreign)426 static void port_clear_foreign_clock_records(struct ptp_foreign_tt_clock *foreign)
427 {
428 struct ptp_msg *msg;
429
430 while (!k_fifo_is_empty(&foreign->messages)) {
431 msg = (struct ptp_msg *)k_fifo_get(&foreign->messages, K_NO_WAIT);
432 ptp_msg_unref(msg);
433 foreign->messages_count--;
434 }
435 }
436
port_delay_req_cleanup(struct ptp_port * port)437 static void port_delay_req_cleanup(struct ptp_port *port)
438 {
439 sys_snode_t *prev = NULL;
440 struct ptp_msg *msg;
441 int64_t timestamp, current = k_uptime_get() * NSEC_PER_MSEC;
442
443 SYS_SLIST_FOR_EACH_CONTAINER(&port->delay_req_list, msg, node) {
444 timestamp = msg->timestamp.host.second * NSEC_PER_SEC +
445 msg->timestamp.host.nanosecond;
446
447 if (current - timestamp < PORT_DELAY_REQ_CLEARE_TO) {
448 break;
449 }
450
451 ptp_msg_unref(msg);
452 sys_slist_remove(&port->delay_req_list, prev, &msg->node);
453 prev = &msg->node;
454 }
455 }
456
port_clear_delay_req(struct ptp_port * port)457 static void port_clear_delay_req(struct ptp_port *port)
458 {
459 sys_snode_t *prev = NULL;
460 struct ptp_msg *msg;
461
462 SYS_SLIST_FOR_EACH_CONTAINER(&port->delay_req_list, msg, node) {
463 ptp_msg_unref(msg);
464 sys_slist_remove(&port->delay_req_list, prev, &msg->node);
465 prev = &msg->node;
466 }
467 }
468
port_sync_fup_ooo_handle(struct ptp_port * port,struct ptp_msg * msg)469 static void port_sync_fup_ooo_handle(struct ptp_port *port, struct ptp_msg *msg)
470 {
471 struct ptp_msg *last = port->last_sync_fup;
472
473 if (ptp_msg_type(msg) != PTP_MSG_FOLLOW_UP &&
474 ptp_msg_type(msg) != PTP_MSG_SYNC) {
475 return;
476 }
477
478 if (!last) {
479 port->last_sync_fup = msg;
480 ptp_msg_ref(msg);
481 return;
482 }
483
484 if (ptp_msg_type(last) == PTP_MSG_SYNC &&
485 ptp_msg_type(msg) == PTP_MSG_FOLLOW_UP &&
486 msg->header.sequence_id == last->header.sequence_id) {
487
488 port_synchronize(port,
489 last->timestamp.host,
490 msg->timestamp.protocol,
491 last->header.correction,
492 msg->header.correction);
493
494 ptp_msg_unref(port->last_sync_fup);
495 port->last_sync_fup = NULL;
496 } else if (ptp_msg_type(last) == PTP_MSG_FOLLOW_UP &&
497 ptp_msg_type(msg) == PTP_MSG_SYNC &&
498 msg->header.sequence_id == last->header.sequence_id) {
499
500 port_synchronize(port,
501 msg->timestamp.host,
502 last->timestamp.protocol,
503 msg->header.correction,
504 last->header.correction);
505
506 ptp_msg_unref(port->last_sync_fup);
507 port->last_sync_fup = NULL;
508 } else {
509 ptp_msg_unref(port->last_sync_fup);
510 port->last_sync_fup = msg;
511 ptp_msg_ref(msg);
512 }
513 }
514
port_announce_msg_process(struct ptp_port * port,struct ptp_msg * msg)515 static int port_announce_msg_process(struct ptp_port *port, struct ptp_msg *msg)
516 {
517 int ret = 0;
518 const struct ptp_default_ds *dds = ptp_clock_default_ds();
519
520 if (msg->announce.steps_rm >= dds->max_steps_rm) {
521 return ret;
522 }
523
524 switch (ptp_port_state(port)) {
525 case PTP_PS_INITIALIZING:
526 __fallthrough;
527 case PTP_PS_DISABLED:
528 __fallthrough;
529 case PTP_PS_FAULTY:
530 break;
531 case PTP_PS_LISTENING:
532 __fallthrough;
533 case PTP_PS_PRE_TIME_TRANSMITTER:
534 __fallthrough;
535 case PTP_PS_TIME_TRANSMITTER:
536 __fallthrough;
537 case PTP_PS_GRAND_MASTER:
538 #if CONFIG_PTP_FOREIGN_TIME_TRANSMITTER_FEATURE
539 ret = ptp_port_add_foreign_tt(port, msg);
540 break;
541 #else
542 __fallthrough;
543 #endif
544 case PTP_PS_TIME_RECEIVER:
545 __fallthrough;
546 case PTP_PS_UNCALIBRATED:
547 __fallthrough;
548 case PTP_PS_PASSIVE:
549 ret = ptp_port_update_current_time_transmitter(port, msg);
550 break;
551 default:
552 break;
553 }
554
555 return ret;
556 }
557
port_sync_msg_process(struct ptp_port * port,struct ptp_msg * msg)558 static void port_sync_msg_process(struct ptp_port *port, struct ptp_msg *msg)
559 {
560 enum ptp_port_state state = ptp_port_state(port);
561
562 if (state != PTP_PS_TIME_RECEIVER && state != PTP_PS_UNCALIBRATED) {
563 return;
564 }
565
566 if (!ptp_msg_current_parent(msg)) {
567 return;
568 }
569
570 if (port->port_ds.log_sync_interval != msg->header.log_msg_interval) {
571 port->port_ds.log_sync_interval = msg->header.log_msg_interval;
572 }
573
574 msg->header.correction += port->port_ds.delay_asymmetry;
575
576 if (!(msg->header.flags[0] & PTP_MSG_TWO_STEP_FLAG)) {
577 port_synchronize(port,
578 msg->timestamp.host,
579 msg->timestamp.protocol,
580 msg->header.correction,
581 0);
582
583 if (port->last_sync_fup) {
584 ptp_msg_unref(port->last_sync_fup);
585 port->last_sync_fup = NULL;
586 }
587
588 return;
589 }
590
591 port_sync_fup_ooo_handle(port, msg);
592 }
593
port_follow_up_msg_process(struct ptp_port * port,struct ptp_msg * msg)594 static void port_follow_up_msg_process(struct ptp_port *port, struct ptp_msg *msg)
595 {
596 enum ptp_port_state state = ptp_port_state(port);
597
598 if (state != PTP_PS_TIME_RECEIVER && state != PTP_PS_UNCALIBRATED) {
599 return;
600 }
601
602 if (!ptp_msg_current_parent(msg)) {
603 return;
604 }
605
606 port_sync_fup_ooo_handle(port, msg);
607 }
608
port_delay_req_msg_process(struct ptp_port * port,struct ptp_msg * msg)609 static int port_delay_req_msg_process(struct ptp_port *port, struct ptp_msg *msg)
610 {
611 int ret;
612 struct ptp_msg *resp;
613 enum ptp_port_state state = ptp_port_state(port);
614 const struct ptp_default_ds *dds = ptp_clock_default_ds();
615
616 if (state != PTP_PS_TIME_TRANSMITTER && state != PTP_PS_GRAND_MASTER) {
617 return 0;
618 }
619
620 resp = ptp_msg_alloc();
621 if (!resp) {
622 return -ENOMEM;
623 }
624
625 resp->header.type_major_sdo_id = PTP_MSG_DELAY_RESP;
626 resp->header.version = PTP_VERSION;
627 resp->header.msg_length = sizeof(struct ptp_delay_resp_msg);
628 resp->header.domain_number = dds->domain;
629 resp->header.correction = msg->header.correction;
630 resp->header.src_port_id = port->port_ds.id;
631 resp->header.sequence_id = msg->header.sequence_id;
632 resp->header.log_msg_interval = port->port_ds.log_min_delay_req_interval;
633
634 resp->delay_resp.receive_timestamp.seconds_high = msg->timestamp.host._sec.high;
635 resp->delay_resp.receive_timestamp.seconds_low = msg->timestamp.host._sec.low;
636 resp->delay_resp.receive_timestamp.nanoseconds = msg->timestamp.host.nanosecond;
637 resp->delay_resp.req_port_id = msg->header.src_port_id;
638
639 if (msg->header.flags[0] & PTP_MSG_UNICAST_FLAG) {
640 /* TODO handle unicast messages */
641 resp->header.flags[0] |= PTP_MSG_UNICAST_FLAG;
642 }
643
644 ret = port_msg_send(port, resp, PTP_SOCKET_EVENT);
645 ptp_msg_unref(resp);
646
647 if (ret < 0) {
648 return -EFAULT;
649 }
650
651 LOG_DBG("Port %d responds to Delay_Req message", port->port_ds.id.port_number);
652 return 0;
653 }
654
port_delay_resp_msg_process(struct ptp_port * port,struct ptp_msg * msg)655 static void port_delay_resp_msg_process(struct ptp_port *port, struct ptp_msg *msg)
656 {
657 uint64_t t3, t4, t4c;
658 sys_snode_t *prev = NULL;
659 struct ptp_msg *req;
660 enum ptp_port_state state = ptp_port_state(port);
661
662 if (state != PTP_PS_TIME_RECEIVER && state != PTP_PS_UNCALIBRATED) {
663 return;
664 }
665
666 if (!ptp_port_id_eq(&msg->delay_resp.req_port_id, &port->port_ds.id)) {
667 /* Message is not meant for this PTP Port */
668 return;
669 }
670
671 SYS_SLIST_FOR_EACH_CONTAINER(&port->delay_req_list, req, node) {
672 if (msg->header.sequence_id == ntohs(req->header.sequence_id)) {
673 break;
674 }
675 prev = &req->node;
676 }
677
678 if (!req) {
679 return;
680 }
681
682 t3 = req->timestamp.host.second * NSEC_PER_SEC + req->timestamp.host.nanosecond;
683 t4 = msg->timestamp.protocol.second * NSEC_PER_SEC + msg->timestamp.protocol.nanosecond;
684 t4c = t4 - (msg->header.correction >> 16);
685
686 ptp_clock_delay(t3, t4c);
687
688 sys_slist_remove(&port->delay_req_list, prev, &req->node);
689 ptp_msg_unref(req);
690
691 port->port_ds.log_min_delay_req_interval = msg->header.log_msg_interval;
692 }
693
port_management_resp_prepare(struct ptp_port * port,struct ptp_msg * req)694 static struct ptp_msg *port_management_resp_prepare(struct ptp_port *port, struct ptp_msg *req)
695 {
696 struct ptp_msg *resp = ptp_msg_alloc();
697 const struct ptp_default_ds *dds = ptp_clock_default_ds();
698
699 if (!resp) {
700 return NULL;
701 }
702
703 resp->header.type_major_sdo_id = PTP_MSG_MANAGEMENT;
704 resp->header.version = PTP_VERSION;
705 resp->header.msg_length = sizeof(struct ptp_management_msg);
706 resp->header.domain_number = dds->domain;
707 resp->header.src_port_id = port->port_ds.id;
708 resp->header.sequence_id = req->header.sequence_id;
709 resp->header.log_msg_interval = port->port_ds.log_min_delay_req_interval;
710
711 if (req->management.action == PTP_MGMT_GET ||
712 req->management.action == PTP_MGMT_SET) {
713 resp->management.action = PTP_MGMT_RESP;
714 } else if (req->management.action == PTP_MGMT_CMD) {
715 resp->management.action = PTP_MGMT_ACK;
716 }
717
718 memcpy(&resp->management.target_port_id,
719 &req->header.src_port_id,
720 sizeof(struct ptp_port_id));
721
722 resp->management.starting_boundary_hops = req->management.starting_boundary_hops -
723 req->management.boundary_hops;
724 resp->management.boundary_hops = resp->management.starting_boundary_hops;
725
726 return resp;
727 }
728
port_management_resp_tlv_fill(struct ptp_port * port,struct ptp_msg * req,struct ptp_msg * resp,struct ptp_tlv_mgmt * req_mgmt)729 static int port_management_resp_tlv_fill(struct ptp_port *port,
730 struct ptp_msg *req,
731 struct ptp_msg *resp,
732 struct ptp_tlv_mgmt *req_mgmt)
733 {
734 int length = 0;
735 struct ptp_tlv_mgmt *mgmt;
736 struct ptp_tlv_default_ds *tlv_dds;
737 struct ptp_tlv_parent_ds *tlv_pds;
738 const struct ptp_parent_ds *pds = ptp_clock_parent_ds();
739 const struct ptp_current_ds *cds = ptp_clock_current_ds();
740 const struct ptp_default_ds *dds = ptp_clock_default_ds();
741 const struct ptp_time_prop_ds *tpds = ptp_clock_time_prop_ds();
742 struct ptp_tlv_container *container = ptp_tlv_alloc();
743
744 if (!container) {
745 return -ENOMEM;
746 }
747
748 container->tlv = (struct ptp_tlv *)resp->management.suffix;
749 mgmt = (struct ptp_tlv_mgmt *)container->tlv;
750 mgmt->type = PTP_TLV_TYPE_MANAGEMENT;
751 mgmt->id = req_mgmt->id;
752
753 switch (mgmt->id) {
754 case PTP_MGMT_DEFAULT_DATA_SET:
755 tlv_dds = (struct ptp_tlv_default_ds *)mgmt->data;
756
757 length = sizeof(struct ptp_tlv_default_ds);
758 tlv_dds->flags = 0x1 | (dds->time_receiver_only << 1);
759 tlv_dds->n_ports = dds->n_ports;
760 tlv_dds->priority1 = dds->priority1;
761 tlv_dds->priority2 = dds->priority2;
762 tlv_dds->domain = dds->domain;
763 memcpy(&tlv_dds->clk_id, &dds->clk_id, sizeof(tlv_dds->clk_id));
764 memcpy(&tlv_dds->clk_quality, &dds->clk_quality, sizeof(tlv_dds->clk_quality));
765 break;
766 case PTP_MGMT_CURRENT_DATA_SET:
767 length = sizeof(struct ptp_tlv_current_ds);
768 memcpy(mgmt->data, cds, sizeof(struct ptp_tlv_current_ds));
769 break;
770 case PTP_MGMT_PARENT_DATA_SET:
771 tlv_pds = (struct ptp_tlv_parent_ds *)mgmt->data;
772
773 length = sizeof(struct ptp_tlv_parent_ds);
774
775 tlv_pds->obsreved_parent_offset_scaled_log_variance =
776 pds->obsreved_parent_offset_scaled_log_variance;
777 tlv_pds->obsreved_parent_clk_phase_change_rate =
778 pds->obsreved_parent_clk_phase_change_rate;
779 tlv_pds->gm_priority1 = pds->gm_priority1;
780 tlv_pds->gm_priority2 = pds->gm_priority2;
781 memcpy(&tlv_pds->port_id, &pds->port_id, sizeof(tlv_pds->port_id));
782 memcpy(&tlv_pds->gm_id, &pds->gm_id, sizeof(tlv_pds->gm_id));
783 memcpy(&tlv_pds->gm_clk_quality,
784 &pds->gm_clk_quality,
785 sizeof(tlv_pds->gm_clk_quality));
786
787 break;
788 case PTP_MGMT_TIME_PROPERTIES_DATA_SET:
789 length = sizeof(struct ptp_tlv_time_prop_ds);
790 memcpy(mgmt->data, tpds, sizeof(struct ptp_tlv_time_prop_ds));
791 break;
792 case PTP_MGMT_PORT_DATA_SET:
793 length = sizeof(struct ptp_tlv_port_ds);
794 memcpy(mgmt->data, &port->port_ds, sizeof(struct ptp_tlv_port_ds));
795 break;
796 case PTP_MGMT_PRIORITY1:
797 length = sizeof(dds->priority1);
798 *mgmt->data = dds->priority1;
799 break;
800 case PTP_MGMT_PRIORITY2:
801 length = sizeof(dds->priority2);
802 *mgmt->data = dds->priority2;
803 break;
804 case PTP_MGMT_DOMAIN:
805 length = sizeof(dds->domain);
806 *mgmt->data = dds->domain;
807 break;
808 case PTP_MGMT_TIME_RECEIVER_ONLY:
809 length = sizeof(dds->time_receiver_only);
810 *mgmt->data = dds->time_receiver_only;
811 break;
812 case PTP_MGMT_LOG_ANNOUNCE_INTERVAL:
813 length = sizeof(port->port_ds.log_announce_interval);
814 *mgmt->data = port->port_ds.log_announce_interval;
815 break;
816 case PTP_MGMT_LOG_SYNC_INTERVAL:
817 length = sizeof(port->port_ds.log_sync_interval);
818 *mgmt->data = port->port_ds.log_sync_interval;
819 break;
820 case PTP_MGMT_VERSION_NUMBER:
821 length = sizeof(port->port_ds.version);
822 *mgmt->data = port->port_ds.version;
823 break;
824 case PTP_MGMT_CLOCK_ACCURACY:
825 length = sizeof(dds->clk_quality.accuracy);
826 *mgmt->data = dds->clk_quality.accuracy;
827 break;
828 case PTP_MGMT_DELAY_MECHANISM:
829 length = sizeof(port->port_ds.delay_mechanism);
830 *(uint16_t *)mgmt->data = port->port_ds.delay_mechanism;
831 break;
832 default:
833 ptp_tlv_free(container);
834 return -EINVAL;
835 }
836
837 /* Management TLV length shall be an even number */
838 if (length % 2) {
839 mgmt->data[length] = 0;
840 length++;
841 }
842
843 container->tlv->length = sizeof(mgmt->id) + length;
844 resp->header.msg_length += sizeof(*container->tlv) + container->tlv->length;
845 sys_slist_append(&resp->tlvs, &container->node);
846
847 return 0;
848 }
849
port_management_set(struct ptp_port * port,struct ptp_msg * req,struct ptp_tlv_mgmt * tlv)850 static int port_management_set(struct ptp_port *port,
851 struct ptp_msg *req,
852 struct ptp_tlv_mgmt *tlv)
853 {
854 bool send_resp = false;
855
856 switch (tlv->id) {
857 case PTP_MGMT_LOG_ANNOUNCE_INTERVAL:
858 port->port_ds.log_announce_interval = *tlv->data;
859 send_resp = true;
860 break;
861 case PTP_MGMT_LOG_SYNC_INTERVAL:
862 port->port_ds.log_sync_interval = *tlv->data;
863 send_resp = true;
864 break;
865 case PTP_MGMT_UNICAST_NEGOTIATION_ENABLE:
866 /* TODO unicast */
867 break;
868 default:
869 break;
870 }
871
872 return send_resp ? ptp_port_management_resp(port, req, tlv) : 0;
873 }
874
port_enable(struct ptp_port * port)875 static int port_enable(struct ptp_port *port)
876 {
877 while (!net_if_is_up(port->iface)) {
878 return -1;
879 }
880
881 port->link_status = PORT_LINK_UP;
882
883 if (ptp_transport_open(port)) {
884 LOG_ERR("Couldn't open socket on Port %d.", port->port_ds.id.port_number);
885 return -1;
886 }
887
888 port->port_ds.enable = true;
889
890 ptp_clock_pollfd_invalidate();
891 LOG_DBG("Port %d opened", port->port_ds.id.port_number);
892 return 0;
893 }
894
port_is_enabled(struct ptp_port * port)895 static bool port_is_enabled(struct ptp_port *port)
896 {
897 enum ptp_port_state state = ptp_port_state(port);
898
899 if (state == PTP_PS_FAULTY ||
900 state == PTP_PS_DISABLED ||
901 state == PTP_PS_INITIALIZING) {
902 return false;
903 }
904 return true;
905 }
906
port_disable(struct ptp_port * port)907 static void port_disable(struct ptp_port *port)
908 {
909 k_timer_stop(&port->timers.announce);
910 k_timer_stop(&port->timers.delay);
911 k_timer_stop(&port->timers.sync);
912 k_timer_stop(&port->timers.qualification);
913
914 atomic_clear(&port->timeouts);
915
916 ptp_transport_close(port);
917 ptp_port_free_foreign_tts(port);
918 port->best = NULL;
919
920 net_if_unregister_timestamp_cb(&port->sync_ts_cb);
921 net_if_unregister_timestamp_cb(&port->delay_req_ts_cb);
922
923 ptp_clock_pollfd_invalidate();
924 port->port_ds.enable = false;
925 LOG_DBG("Port %d disabled", port->port_ds.id.port_number);
926 }
927
port_state_update(struct ptp_port * port,enum ptp_port_event event,bool tt_diff)928 int port_state_update(struct ptp_port *port, enum ptp_port_event event, bool tt_diff)
929 {
930 enum ptp_port_state next_state = port->state_machine(ptp_port_state(port),
931 event,
932 tt_diff);
933
934 if (next_state == PTP_PS_FAULTY) {
935 /* clear fault if interface is UP */
936 if (net_if_oper_state(port->iface) == NET_IF_OPER_UP) {
937 next_state = port->state_machine(next_state, PTP_EVT_FAULT_CLEARED, false);
938 }
939 }
940
941 if (next_state == PTP_PS_INITIALIZING) {
942 if (port_is_enabled(port)) {
943 port_disable(port);
944 }
945 if (port_enable(port)) {
946 event = PTP_EVT_FAULT_DETECTED;
947 } else {
948 event = PTP_EVT_INIT_COMPLETE;
949 }
950 next_state = port->state_machine(next_state, event, false);
951 }
952
953 if (next_state != ptp_port_state(port)) {
954 LOG_DBG("Port %d changed state from %s to %s",
955 port->port_ds.id.port_number,
956 port_state_str(ptp_port_state(port)),
957 port_state_str(next_state));
958
959 port->port_ds.state = next_state;
960 return 1;
961 }
962
963 return 0;
964 }
965
port_link_monitor(struct net_mgmt_event_callback * cb,uint32_t mgmt_event,struct net_if * iface)966 static void port_link_monitor(struct net_mgmt_event_callback *cb,
967 uint32_t mgmt_event,
968 struct net_if *iface)
969 {
970 ARG_UNUSED(cb);
971
972 enum ptp_port_event event = PTP_EVT_NONE;
973 struct ptp_port *port = ptp_clock_port_from_iface(iface);
974 uint8_t iface_state = mgmt_event == NET_EVENT_IF_UP ? PORT_LINK_UP : PORT_LINK_DOWN;
975
976 if (!port) {
977 return;
978 }
979
980 if (iface_state & port->link_status) {
981 port->link_status = iface_state;
982 } else {
983 port->link_status = iface_state | PORT_LINK_CHANGED;
984 LOG_DBG("Port %d link %s",
985 port->port_ds.id.port_number,
986 port->link_status & PORT_LINK_UP ? "up" : "down");
987 }
988
989 if (port->link_status & PORT_LINK_CHANGED) {
990 event = iface_state == PORT_LINK_UP ?
991 PTP_EVT_FAULT_CLEARED : PTP_EVT_FAULT_DETECTED;
992 port->link_status ^= PORT_LINK_CHANGED;
993 }
994
995 if (port->link_status & PORT_LINK_DOWN) {
996 ptp_clock_state_decision_req();
997 }
998
999 ptp_port_event_handle(port, event, false);
1000 }
1001
ptp_port_init(struct net_if * iface,void * user_data)1002 void ptp_port_init(struct net_if *iface, void *user_data)
1003 {
1004 struct ptp_port *port;
1005 const struct ptp_default_ds *dds = ptp_clock_default_ds();
1006
1007 ARG_UNUSED(user_data);
1008
1009 if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
1010 return;
1011 }
1012
1013 if (dds->n_ports > CONFIG_PTP_NUM_PORTS) {
1014 LOG_WRN("Exceeded number of PTP Ports.");
1015 return;
1016 }
1017
1018 port = &ports[dds->n_ports];
1019
1020 port->iface = iface;
1021 port->best = NULL;
1022 port->socket[PTP_SOCKET_EVENT] = -1;
1023 port->socket[PTP_SOCKET_GENERAL] = -1;
1024
1025 port->state_machine = dds->time_receiver_only ? ptp_tr_state_machine : ptp_state_machine;
1026 port->last_sync_fup = NULL;
1027
1028 port_ds_init(port);
1029 sys_slist_init(&port->foreign_list);
1030 sys_slist_init(&port->delay_req_list);
1031
1032 port_timer_init(&port->timers.delay, port_timer_to_handler, port);
1033 port_timer_init(&port->timers.announce, port_timer_to_handler, port);
1034 port_timer_init(&port->timers.sync, port_timer_to_handler, port);
1035 port_timer_init(&port->timers.qualification, port_timer_to_handler, port);
1036
1037 ptp_clock_pollfd_invalidate();
1038 ptp_clock_port_add(port);
1039
1040 net_mgmt_init_event_callback(&port->link_cb, port_link_monitor, PORT_LINK_EVENT_MASK);
1041 net_mgmt_add_event_callback(&port->link_cb);
1042
1043 LOG_DBG("Port %d initialized", port->port_ds.id.port_number);
1044 }
1045
ptp_port_event_gen(struct ptp_port * port,int idx)1046 enum ptp_port_event ptp_port_event_gen(struct ptp_port *port, int idx)
1047 {
1048 enum ptp_port_event event = PTP_EVT_NONE;
1049 struct ptp_msg *msg;
1050 int ret, cnt;
1051
1052 if (idx < 0) {
1053 return event;
1054 }
1055
1056 msg = ptp_msg_alloc();
1057 if (!msg) {
1058 return PTP_EVT_FAULT_DETECTED;
1059 }
1060
1061 cnt = ptp_transport_recv(port, msg, idx);
1062 if (cnt <= 0) {
1063 LOG_ERR("Error during message reception");
1064 ptp_msg_unref(msg);
1065 return PTP_EVT_FAULT_DETECTED;
1066 }
1067
1068 ret = ptp_msg_post_recv(port, msg, cnt);
1069 if (ret) {
1070 ptp_msg_unref(msg);
1071 return PTP_EVT_FAULT_DETECTED;
1072 }
1073
1074 if (ptp_port_id_eq(&msg->header.src_port_id, &port->port_ds.id)) {
1075 ptp_msg_unref(msg);
1076 return PTP_EVT_NONE;
1077 }
1078
1079 switch (ptp_msg_type(msg)) {
1080 case PTP_MSG_SYNC:
1081 port_sync_msg_process(port, msg);
1082 break;
1083 case PTP_MSG_DELAY_REQ:
1084 if (port_delay_req_msg_process(port, msg)) {
1085 event = PTP_EVT_FAULT_DETECTED;
1086 }
1087 break;
1088 case PTP_MSG_PDELAY_REQ:
1089 __fallthrough;
1090 case PTP_MSG_PDELAY_RESP:
1091 __fallthrough;
1092 case PTP_MSG_PDELAY_RESP_FOLLOW_UP:
1093 /* P2P delay mechanism not supported */
1094 break;
1095 case PTP_MSG_FOLLOW_UP:
1096 port_follow_up_msg_process(port, msg);
1097 break;
1098 case PTP_MSG_DELAY_RESP:
1099 port_delay_resp_msg_process(port, msg);
1100 break;
1101 case PTP_MSG_ANNOUNCE:
1102 if (port_announce_msg_process(port, msg)) {
1103 event = PTP_EVT_STATE_DECISION;
1104 }
1105 break;
1106 case PTP_MSG_SIGNALING:
1107 /* Signalling messages not supported */
1108 break;
1109 case PTP_MSG_MANAGEMENT:
1110 if (ptp_clock_management_msg_process(port, msg)) {
1111 event = PTP_EVT_STATE_DECISION;
1112 }
1113 break;
1114 default:
1115 break;
1116 }
1117
1118 ptp_msg_unref(msg);
1119 return event;
1120 }
1121
ptp_port_event_handle(struct ptp_port * port,enum ptp_port_event event,bool tt_diff)1122 void ptp_port_event_handle(struct ptp_port *port, enum ptp_port_event event, bool tt_diff)
1123 {
1124 const struct ptp_current_ds *cds = ptp_clock_current_ds();
1125
1126 if (event == PTP_EVT_NONE) {
1127 return;
1128 }
1129
1130 if (!port_state_update(port, event, tt_diff)) {
1131 /* No PTP Port state change */
1132 return;
1133 }
1134
1135 k_timer_stop(&port->timers.announce);
1136 k_timer_stop(&port->timers.delay);
1137 k_timer_stop(&port->timers.sync);
1138 k_timer_stop(&port->timers.qualification);
1139
1140 switch (port->port_ds.state) {
1141 case PTP_PS_INITIALIZING:
1142 break;
1143 case PTP_PS_FAULTY:
1144 __fallthrough;
1145 case PTP_PS_DISABLED:
1146 port_disable(port);
1147 break;
1148 case PTP_PS_LISTENING:
1149 port_timer_set_timeout_random(&port->timers.announce,
1150 port->port_ds.announce_receipt_timeout,
1151 1,
1152 port->port_ds.log_announce_interval);
1153 break;
1154 case PTP_PS_PRE_TIME_TRANSMITTER:
1155 port_timer_set_timeout(&port->timers.qualification,
1156 1 + cds->steps_rm,
1157 port->port_ds.log_announce_interval);
1158 break;
1159 case PTP_PS_GRAND_MASTER:
1160 __fallthrough;
1161 case PTP_PS_TIME_TRANSMITTER:
1162 port_timer_set_timeout(&port->timers.announce,
1163 1,
1164 port->port_ds.log_announce_interval);
1165 port_timer_set_timeout(&port->timers.sync, 1, port->port_ds.log_sync_interval);
1166 break;
1167 case PTP_PS_PASSIVE:
1168 port_timer_set_timeout_random(&port->timers.announce,
1169 port->port_ds.announce_receipt_timeout,
1170 1,
1171 port->port_ds.log_announce_interval);
1172 break;
1173 case PTP_PS_UNCALIBRATED:
1174 if (port->last_sync_fup) {
1175 ptp_msg_unref(port->last_sync_fup);
1176 port->last_sync_fup = NULL;
1177 }
1178 port_clear_delay_req(port);
1179 __fallthrough;
1180 case PTP_PS_TIME_RECEIVER:
1181 port_timer_set_timeout_random(&port->timers.announce,
1182 port->port_ds.announce_receipt_timeout,
1183 1,
1184 port->port_ds.log_announce_interval);
1185 port_timer_set_timeout_random(&port->timers.delay,
1186 0,
1187 2,
1188 port->port_ds.log_min_delay_req_interval);
1189 break;
1190 };
1191 }
1192
ptp_port_state(struct ptp_port * port)1193 enum ptp_port_state ptp_port_state(struct ptp_port *port)
1194 {
1195 return (enum ptp_port_state)port->port_ds.state;
1196 }
1197
ptp_port_timer_event_gen(struct ptp_port * port,struct k_timer * timer)1198 enum ptp_port_event ptp_port_timer_event_gen(struct ptp_port *port, struct k_timer *timer)
1199 {
1200 enum ptp_port_event event = PTP_EVT_NONE;
1201 enum ptp_port_state state = ptp_port_state(port);
1202
1203 switch (state) {
1204 case PTP_PS_PRE_TIME_TRANSMITTER:
1205 if (timer == &port->timers.qualification &&
1206 atomic_test_bit(&port->timeouts, PTP_PORT_TIMER_QUALIFICATION_TO)) {
1207 LOG_DBG("Port %d Qualification timeout", port->port_ds.id.port_number);
1208 atomic_clear_bit(&port->timeouts, PTP_PORT_TIMER_QUALIFICATION_TO);
1209
1210 return PTP_EVT_QUALIFICATION_TIMEOUT_EXPIRES;
1211 }
1212 break;
1213 case PTP_PS_GRAND_MASTER:
1214 __fallthrough;
1215 case PTP_PS_TIME_TRANSMITTER:
1216 if (timer == &port->timers.sync &&
1217 atomic_test_bit(&port->timeouts, PTP_PORT_TIMER_SYNC_TO)) {
1218 LOG_DBG("Port %d TX Sync timeout", port->port_ds.id.port_number);
1219 port_timer_set_timeout(&port->timers.sync,
1220 1,
1221 port->port_ds.log_sync_interval);
1222 atomic_clear_bit(&port->timeouts, PTP_PORT_TIMER_SYNC_TO);
1223
1224 return port_sync_msg_transmit(port) == 0 ? PTP_EVT_NONE :
1225 PTP_EVT_FAULT_DETECTED;
1226 }
1227
1228 if (timer == &port->timers.announce &&
1229 atomic_test_bit(&port->timeouts, PTP_PORT_TIMER_ANNOUNCE_TO)) {
1230 LOG_DBG("Port %d TimeTransmitter Announce timeout",
1231 port->port_ds.id.port_number);
1232 port_timer_set_timeout(&port->timers.announce,
1233 1,
1234 port->port_ds.log_announce_interval);
1235 atomic_clear_bit(&port->timeouts, PTP_PORT_TIMER_ANNOUNCE_TO);
1236
1237 return port_announce_msg_transmit(port) == 0 ? PTP_EVT_NONE :
1238 PTP_EVT_FAULT_DETECTED;
1239 }
1240 break;
1241 case PTP_PS_TIME_RECEIVER:
1242 if (timer == &port->timers.delay &&
1243 atomic_test_bit(&port->timeouts, PTP_PORT_TIMER_DELAY_TO)) {
1244
1245 atomic_clear_bit(&port->timeouts, PTP_PORT_TIMER_DELAY_TO);
1246 port_delay_req_cleanup(port);
1247 port_timer_set_timeout(&port->timers.delay,
1248 1,
1249 port->port_ds.log_announce_interval);
1250
1251 if (port_delay_req_msg_transmit(port) < 0) {
1252 return PTP_EVT_FAULT_DETECTED;
1253 }
1254 }
1255 __fallthrough;
1256 case PTP_PS_PASSIVE:
1257 __fallthrough;
1258 case PTP_PS_UNCALIBRATED:
1259 __fallthrough;
1260 case PTP_PS_LISTENING:
1261 if ((timer == &port->timers.announce || timer == &port->timers.sync) &&
1262 (atomic_test_bit(&port->timeouts, PTP_PORT_TIMER_ANNOUNCE_TO) ||
1263 atomic_test_bit(&port->timeouts, PTP_PORT_TIMER_SYNC_TO))) {
1264
1265 LOG_DBG("Port %d %s timeout",
1266 port->port_ds.id.port_number,
1267 timer == &port->timers.announce ? "Announce" : "RX Sync");
1268
1269 atomic_clear_bit(&port->timeouts, PTP_PORT_TIMER_ANNOUNCE_TO);
1270 atomic_clear_bit(&port->timeouts, PTP_PORT_TIMER_SYNC_TO);
1271
1272 if (port->best) {
1273 port_clear_foreign_clock_records(port->best);
1274 }
1275
1276 port_delay_req_cleanup(port);
1277 port_timer_set_timeout_random(&port->timers.announce,
1278 port->port_ds.announce_receipt_timeout,
1279 1,
1280 port->port_ds.log_announce_interval);
1281
1282 return PTP_EVT_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES;
1283 }
1284 break;
1285 default:
1286 break;
1287 }
1288
1289 return event;
1290 }
1291
ptp_port_id_eq(const struct ptp_port_id * p1,const struct ptp_port_id * p2)1292 bool ptp_port_id_eq(const struct ptp_port_id *p1, const struct ptp_port_id *p2)
1293 {
1294 return memcmp(p1, p2, sizeof(struct ptp_port_id)) == 0;
1295 }
1296
ptp_port_best_foreign_ds(struct ptp_port * port)1297 struct ptp_dataset *ptp_port_best_foreign_ds(struct ptp_port *port)
1298 {
1299 return port->best ? &port->best->dataset : NULL;
1300 }
1301
ptp_port_best_foreign(struct ptp_port * port)1302 struct ptp_foreign_tt_clock *ptp_port_best_foreign(struct ptp_port *port)
1303 {
1304 struct ptp_foreign_tt_clock *foreign;
1305 struct ptp_announce_msg *last;
1306
1307 port->best = NULL;
1308
1309 if (port->port_ds.time_transmitter_only) {
1310 return NULL;
1311 }
1312
1313 SYS_SLIST_FOR_EACH_CONTAINER(&port->foreign_list, foreign, node) {
1314 if (!foreign->messages_count) {
1315 continue;
1316 }
1317
1318 foreign_clock_cleanup(foreign);
1319
1320 if (foreign->messages_count < FOREIGN_TIME_TRANSMITTER_THRESHOLD) {
1321 continue;
1322 }
1323
1324 last = (struct ptp_announce_msg *)k_fifo_peek_head(&foreign->messages);
1325
1326 foreign->dataset.priority1 = last->gm_priority1;
1327 foreign->dataset.priority2 = last->gm_priority2;
1328 foreign->dataset.steps_rm = last->steps_rm;
1329
1330 memcpy(&foreign->dataset.clk_quality,
1331 &last->gm_clk_quality,
1332 sizeof(last->gm_clk_quality));
1333 memcpy(&foreign->dataset.clk_id, &last->gm_id, sizeof(last->gm_id));
1334 memcpy(&foreign->dataset.receiver, &port->port_ds.id, sizeof(port->port_ds.id));
1335
1336 if (!port->best) {
1337 port->best = foreign;
1338 } else if (ptp_btca_ds_cmp(&foreign->dataset, &port->best->dataset)) {
1339 port->best = foreign;
1340 } else {
1341 port_clear_foreign_clock_records(foreign);
1342 }
1343 }
1344 return port->best;
1345 }
1346
ptp_port_add_foreign_tt(struct ptp_port * port,struct ptp_msg * msg)1347 int ptp_port_add_foreign_tt(struct ptp_port *port, struct ptp_msg *msg)
1348 {
1349 struct ptp_foreign_tt_clock *foreign;
1350 struct ptp_msg *last;
1351 int diff = 0;
1352
1353 SYS_SLIST_FOR_EACH_CONTAINER(&port->foreign_list, foreign, node) {
1354 if (ptp_port_id_eq(&msg->header.src_port_id, &foreign->dataset.sender)) {
1355 break;
1356 }
1357 }
1358
1359 if (!foreign) {
1360 LOG_DBG("Port %d has a new foreign timeTransmitter %s",
1361 port->port_ds.id.port_number,
1362 port_id_str(&msg->header.src_port_id));
1363
1364 int ret = k_mem_slab_alloc(&foreign_tts_slab, (void **)&foreign, K_NO_WAIT);
1365
1366 if (ret) {
1367 LOG_ERR("Couldn't allocate memory for new foreign timeTransmitter");
1368 return 0;
1369 }
1370
1371 memset(foreign, 0, sizeof(*foreign));
1372 memcpy(&foreign->dataset.sender,
1373 &msg->header.src_port_id,
1374 sizeof(foreign->dataset.sender));
1375 k_fifo_init(&foreign->messages);
1376 foreign->port = port;
1377
1378 sys_slist_append(&port->foreign_list, &foreign->node);
1379
1380 /* First message is not added to records. */
1381 return 0;
1382 }
1383
1384 foreign_clock_cleanup(foreign);
1385 ptp_msg_ref(msg);
1386
1387 foreign->messages_count++;
1388 k_fifo_put(&foreign->messages, (void *)msg);
1389
1390 if (foreign->messages_count > 1) {
1391 last = (struct ptp_msg *)k_fifo_peek_tail(&foreign->messages);
1392 diff = ptp_msg_announce_cmp(&msg->announce, &last->announce);
1393 }
1394
1395 return (foreign->messages_count == FOREIGN_TIME_TRANSMITTER_THRESHOLD ? 1 : 0) || diff;
1396 }
1397
ptp_port_free_foreign_tts(struct ptp_port * port)1398 void ptp_port_free_foreign_tts(struct ptp_port *port)
1399 {
1400 sys_snode_t *iter;
1401 struct ptp_foreign_tt_clock *foreign;
1402
1403 while (!sys_slist_is_empty(&port->foreign_list)) {
1404 iter = sys_slist_get(&port->foreign_list);
1405 foreign = CONTAINER_OF(iter, struct ptp_foreign_tt_clock, node);
1406
1407 while (foreign->messages_count > FOREIGN_TIME_TRANSMITTER_THRESHOLD) {
1408 struct ptp_msg *msg = (struct ptp_msg *)k_fifo_get(&foreign->messages,
1409 K_NO_WAIT);
1410 foreign->messages_count--;
1411 ptp_msg_unref(msg);
1412 }
1413
1414 k_mem_slab_free(&foreign_tts_slab, (void *)foreign);
1415 }
1416 }
1417
ptp_port_update_current_time_transmitter(struct ptp_port * port,struct ptp_msg * msg)1418 int ptp_port_update_current_time_transmitter(struct ptp_port *port, struct ptp_msg *msg)
1419 {
1420 struct ptp_foreign_tt_clock *foreign = port->best;
1421
1422 if (!foreign ||
1423 !ptp_port_id_eq(&msg->header.src_port_id, &foreign->dataset.sender)) {
1424 return ptp_port_add_foreign_tt(port, msg);
1425 }
1426
1427 foreign_clock_cleanup(foreign);
1428 ptp_msg_ref(msg);
1429
1430 k_fifo_put(&foreign->messages, (void *)msg);
1431 foreign->messages_count++;
1432
1433 port_timer_set_timeout_random(&port->timers.announce,
1434 port->port_ds.announce_receipt_timeout,
1435 1,
1436 port->port_ds.log_announce_interval);
1437
1438 if (foreign->messages_count > 1) {
1439 struct ptp_msg *last = (struct ptp_msg *)k_fifo_peek_tail(&foreign->messages);
1440
1441 return ptp_msg_announce_cmp(&msg->announce, &last->announce);
1442 }
1443
1444 return 0;
1445 }
1446
ptp_port_management_msg_process(struct ptp_port * port,struct ptp_port * ingress,struct ptp_msg * msg,struct ptp_tlv_mgmt * tlv)1447 int ptp_port_management_msg_process(struct ptp_port *port,
1448 struct ptp_port *ingress,
1449 struct ptp_msg *msg,
1450 struct ptp_tlv_mgmt *tlv)
1451 {
1452 int ret = 0;
1453 uint16_t target_port = msg->management.target_port_id.port_number;
1454
1455 if (target_port != port->port_ds.id.port_number && target_port != 0xFFFF) {
1456 return ret;
1457 }
1458
1459 if (ptp_mgmt_action(msg) == PTP_MGMT_SET) {
1460 ret = port_management_set(port, msg, tlv);
1461 } else {
1462 ret = ptp_port_management_resp(port, msg, tlv);
1463 }
1464
1465 return ret;
1466 }
1467
ptp_port_management_error(struct ptp_port * port,struct ptp_msg * msg,enum ptp_mgmt_err err)1468 int ptp_port_management_error(struct ptp_port *port, struct ptp_msg *msg, enum ptp_mgmt_err err)
1469 {
1470 int ret;
1471 struct ptp_tlv *tlv;
1472 struct ptp_tlv_mgmt_err *mgmt_err;
1473 struct ptp_tlv_mgmt *mgmt = (struct ptp_tlv_mgmt *)msg->management.suffix;
1474
1475 struct ptp_msg *resp = port_management_resp_prepare(port, msg);
1476
1477 if (!resp) {
1478 return -ENOMEM;
1479 }
1480
1481 tlv = ptp_msg_add_tlv(resp, sizeof(struct ptp_tlv_mgmt_err));
1482 if (!tlv) {
1483 ptp_msg_unref(resp);
1484 return -ENOMEM;
1485 }
1486
1487 mgmt_err = (struct ptp_tlv_mgmt_err *)tlv;
1488
1489 mgmt_err->type = PTP_TLV_TYPE_MANAGEMENT_ERROR_STATUS;
1490 mgmt_err->length = 8;
1491 mgmt_err->err_id = err;
1492 mgmt_err->id = mgmt->id;
1493
1494 ret = port_msg_send(port, resp, PTP_SOCKET_GENERAL);
1495 ptp_msg_unref(resp);
1496
1497 if (ret) {
1498 return -EFAULT;
1499 }
1500
1501 LOG_DBG("Port %d sends Menagement Error message", port->port_ds.id.port_number);
1502 return 0;
1503 }
1504
ptp_port_management_resp(struct ptp_port * port,struct ptp_msg * req,struct ptp_tlv_mgmt * tlv)1505 int ptp_port_management_resp(struct ptp_port *port, struct ptp_msg *req, struct ptp_tlv_mgmt *tlv)
1506 {
1507 int ret;
1508 struct ptp_msg *resp = port_management_resp_prepare(port, req);
1509
1510 if (!resp) {
1511 return -ENOMEM;
1512 }
1513
1514 ret = port_management_resp_tlv_fill(port, req, resp, tlv);
1515 if (ret) {
1516 return ret;
1517 }
1518
1519 ret = port_msg_send(port, resp, PTP_SOCKET_GENERAL);
1520 ptp_msg_unref(resp);
1521
1522 if (ret < 0) {
1523 return -EFAULT;
1524 }
1525
1526 LOG_DBG("Port %d sends Menagement message response", port->port_ds.id.port_number);
1527 return 0;
1528 }
1529