1 /*
2 * Copyright (c) 2017 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_DECLARE(net_gptp, CONFIG_NET_GPTP_LOG_LEVEL);
9
10 #include <zephyr/drivers/ptp_clock.h>
11
12 #include "gptp_messages.h"
13 #include "gptp_data_set.h"
14 #include "gptp_state.h"
15 #include "gptp_private.h"
16
17 #if CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG
state2str(enum gptp_port_state state)18 static const char * const state2str(enum gptp_port_state state)
19 {
20 switch (state) {
21 case GPTP_PORT_INITIALIZING:
22 return "INITIALIZING";
23 case GPTP_PORT_FAULTY:
24 return "FAULTY";
25 case GPTP_PORT_DISABLED:
26 return "DISABLED";
27 case GPTP_PORT_LISTENING:
28 return "LISTENING";
29 case GPTP_PORT_PRE_MASTER:
30 return "PRE_MASTER";
31 case GPTP_PORT_MASTER:
32 return "MASTER";
33 case GPTP_PORT_PASSIVE:
34 return "PASSIVE";
35 case GPTP_PORT_UNCALIBRATED:
36 return "UNCALIBRATED";
37 case GPTP_PORT_SLAVE:
38 return "SLAVE";
39 }
40
41 return "<unknown>";
42 }
43
pa_info_state2str(enum gptp_pa_info_states state)44 static const char * const pa_info_state2str(enum gptp_pa_info_states state)
45 {
46 switch (state) {
47 case GPTP_PA_INFO_DISABLED:
48 return "DISABLED";
49 case GPTP_PA_INFO_POST_DISABLED:
50 return "POST_DISABLED";
51 case GPTP_PA_INFO_AGED:
52 return "AGED";
53 case GPTP_PA_INFO_UPDATE:
54 return "UPDATE";
55 case GPTP_PA_INFO_CURRENT:
56 return "CURRENT";
57 case GPTP_PA_INFO_RECEIVE:
58 return "RECEIVE";
59 case GPTP_PA_INFO_SUPERIOR_MASTER_PORT:
60 return "SUPERIOR_MASTER_PORT";
61 case GPTP_PA_INFO_REPEATED_MASTER_PORT:
62 return "REPEATED_MASTER_PORT";
63 case GPTP_PA_INFO_INFERIOR_MASTER_OR_OTHER_PORT:
64 return "INFERIOR_MASTER_OR_OTHER_PORT";
65 }
66
67 return "<unknown>";
68 }
69 #endif
70
71 #if CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG
gptp_change_port_state_debug(int port,enum gptp_port_state state,const char * caller,int line)72 void gptp_change_port_state_debug(int port, enum gptp_port_state state,
73 const char *caller,
74 int line)
75 #else
76 void gptp_change_port_state(int port, enum gptp_port_state state)
77 #endif
78 {
79 struct gptp_global_ds *global_ds = GPTP_GLOBAL_DS();
80
81 if (global_ds->selected_role[port] == state) {
82 return;
83 }
84
85 #if CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG
86 NET_DBG("[%d] state %s -> %s (%s():%d)", port,
87 state2str(global_ds->selected_role[port]),
88 state2str(state), caller, line);
89 #endif
90
91 global_ds->selected_role[port] = state;
92 };
93
94 #if CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG
gptp_change_pa_info_state_debug(int port,struct gptp_port_announce_information_state * pa_info_state,enum gptp_pa_info_states state,const char * caller,int line)95 void gptp_change_pa_info_state_debug(
96 int port,
97 struct gptp_port_announce_information_state *pa_info_state,
98 enum gptp_pa_info_states state,
99 const char *caller,
100 int line)
101 #else
102 void gptp_change_pa_info_state(
103 int port,
104 struct gptp_port_announce_information_state *pa_info_state,
105 enum gptp_pa_info_states state)
106 #endif
107 {
108 if (pa_info_state->state == state) {
109 return;
110 }
111
112 #if CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG
113 NET_DBG("[%d] PA info state %s -> %s (%s():%d)", port,
114 pa_info_state2str(pa_info_state->state),
115 pa_info_state2str(state), caller, line);
116 #endif
117
118 pa_info_state->state = state;
119 }
120
gptp_mi_half_sync_itv_timeout(struct k_timer * timer)121 static void gptp_mi_half_sync_itv_timeout(struct k_timer *timer)
122 {
123 struct gptp_pss_send_state *state;
124 int port;
125
126 for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
127 state = &GPTP_PORT_STATE(port)->pss_send;
128 if (&state->half_sync_itv_timer == timer) {
129 if (!state->half_sync_itv_timer_expired) {
130 state->half_sync_itv_timer_expired = true;
131 } else {
132 /* We do not need the timer anymore. */
133 k_timer_stop(timer);
134
135 state->sync_itv_timer_expired = true;
136 }
137 }
138 }
139 }
140
gptp_mi_rcv_sync_receipt_timeout(struct k_timer * timer)141 static void gptp_mi_rcv_sync_receipt_timeout(struct k_timer *timer)
142 {
143 struct gptp_pss_rcv_state *state;
144 int port;
145
146 for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
147 state = &GPTP_PORT_STATE(port)->pss_rcv;
148 if (&state->rcv_sync_receipt_timeout_timer == timer) {
149 state->rcv_sync_receipt_timeout_timer_expired = true;
150 }
151
152 GPTP_STATS_INC(port, sync_receipt_timeout_count);
153 }
154 }
155
gptp_mi_send_sync_receipt_timeout(struct k_timer * timer)156 static void gptp_mi_send_sync_receipt_timeout(struct k_timer *timer)
157 {
158 struct gptp_pss_send_state *state;
159 int port;
160
161 for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
162 state = &GPTP_PORT_STATE(port)->pss_send;
163 if (&state->send_sync_receipt_timeout_timer == timer) {
164 state->send_sync_receipt_timeout_timer_expired = true;
165 }
166
167 GPTP_STATS_INC(port, sync_receipt_timeout_count);
168 }
169 }
170
gptp_mi_init_port_sync_sync_rcv_sm(int port)171 static void gptp_mi_init_port_sync_sync_rcv_sm(int port)
172 {
173 struct gptp_pss_rcv_state *pss_rcv;
174
175 pss_rcv = &GPTP_PORT_STATE(port)->pss_rcv;
176 (void)memset(pss_rcv, 0, sizeof(struct gptp_pss_rcv_state));
177
178 k_timer_init(&pss_rcv->rcv_sync_receipt_timeout_timer,
179 gptp_mi_rcv_sync_receipt_timeout, NULL);
180
181 pss_rcv->state = GPTP_PSS_RCV_DISCARD;
182 }
183
gptp_mi_init_port_sync_sync_send_sm(int port)184 static void gptp_mi_init_port_sync_sync_send_sm(int port)
185 {
186 struct gptp_pss_send_state *pss_send;
187
188 pss_send = &GPTP_PORT_STATE(port)->pss_send;
189 (void)memset(pss_send, 0, sizeof(struct gptp_pss_send_state));
190
191 k_timer_init(&pss_send->half_sync_itv_timer,
192 gptp_mi_half_sync_itv_timeout, NULL);
193 k_timer_init(&pss_send->send_sync_receipt_timeout_timer,
194 gptp_mi_send_sync_receipt_timeout, NULL);
195
196 pss_send->state = GPTP_PSS_SEND_TRANSMIT_INIT;
197 }
198
gptp_mi_init_site_sync_sync_sm(void)199 static void gptp_mi_init_site_sync_sync_sm(void)
200 {
201 struct gptp_site_sync_sync_state *site_ss;
202
203 site_ss = &GPTP_STATE()->site_ss;
204 (void)memset(site_ss, 0, sizeof(struct gptp_site_sync_sync_state));
205 site_ss->state = GPTP_SSS_INITIALIZING;
206 }
207
gptp_mi_init_clock_slave_sync_sm(void)208 static void gptp_mi_init_clock_slave_sync_sm(void)
209 {
210 struct gptp_clk_slave_sync_state *clk_ss;
211
212 clk_ss = &GPTP_STATE()->clk_slave_sync;
213 (void)memset(clk_ss, 0, sizeof(struct gptp_clk_slave_sync_state));
214 clk_ss->state = GPTP_CLK_SLAVE_SYNC_INITIALIZING;
215 }
216
gptp_mi_init_port_announce_rcv_sm(int port)217 static void gptp_mi_init_port_announce_rcv_sm(int port)
218 {
219 struct gptp_port_announce_receive_state *pa_rcv;
220
221 pa_rcv = &GPTP_PORT_STATE(port)->pa_rcv;
222 (void)memset(pa_rcv, 0,
223 sizeof(struct gptp_port_announce_receive_state));
224 pa_rcv->state = GPTP_PA_RCV_DISCARD;
225 }
226
gptp_mi_init_clock_master_sync_rcv_sm(void)227 static void gptp_mi_init_clock_master_sync_rcv_sm(void)
228 {
229 struct gptp_clk_master_sync_rcv_state *cms_rcv;
230
231 cms_rcv = &GPTP_STATE()->clk_master_sync_receive;
232 (void)memset(cms_rcv, 0, sizeof(struct gptp_clk_master_sync_rcv_state));
233 cms_rcv->state = GPTP_CMS_RCV_INITIALIZING;
234 }
235
announce_timer_handler(struct k_timer * timer)236 static void announce_timer_handler(struct k_timer *timer)
237 {
238 int port;
239 struct gptp_port_announce_information_state *state;
240
241 for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
242 state = &GPTP_PORT_STATE(port)->pa_info;
243 if (&state->ann_rcpt_expiry_timer == timer) {
244 state->ann_expired = true;
245 GPTP_STATS_INC(port, announce_receipt_timeout_count);
246 break;
247 }
248 }
249 }
250
gptp_mi_init_port_announce_info_sm(int port)251 static void gptp_mi_init_port_announce_info_sm(int port)
252 {
253 struct gptp_port_announce_information_state *state;
254
255 state = &GPTP_PORT_STATE(port)->pa_info;
256
257 k_timer_init(&state->ann_rcpt_expiry_timer,
258 announce_timer_handler, NULL);
259
260 state->ann_expired = false;
261 gptp_change_pa_info_state(port, state, GPTP_PA_INFO_DISABLED);
262 }
263
gptp_mi_init_bmca_data(int port)264 static void gptp_mi_init_bmca_data(int port)
265 {
266 struct gptp_port_bmca_data *bmca_data;
267
268 bmca_data = GPTP_PORT_BMCA_DATA(port);
269
270 (void)memset(bmca_data, 0, sizeof(struct gptp_port_bmca_data));
271
272 gptp_set_time_itv(&bmca_data->announce_interval, 1,
273 CONFIG_NET_GPTP_INIT_LOG_ANNOUNCE_ITV);
274
275 (void)memset(&bmca_data->port_priority, 0xFF,
276 sizeof(struct gptp_priority_vector));
277 (void)memset(&bmca_data->master_priority, 0xFF,
278 sizeof(struct gptp_priority_vector));
279 }
280
announce_periodic_timer_handler(struct k_timer * timer)281 static void announce_periodic_timer_handler(struct k_timer *timer)
282 {
283 int port;
284 struct gptp_port_announce_transmit_state *state;
285
286 for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
287 state = &GPTP_PORT_STATE(port)->pa_transmit;
288 if (&state->ann_send_periodic_timer == timer) {
289 state->ann_trigger = true;
290 break;
291 }
292 }
293 }
294
gptp_mi_init_port_announce_transmit_sm(int port)295 static void gptp_mi_init_port_announce_transmit_sm(int port)
296 {
297 struct gptp_port_announce_transmit_state *state;
298
299 state = &GPTP_PORT_STATE(port)->pa_transmit;
300
301 k_timer_init(&state->ann_send_periodic_timer,
302 announce_periodic_timer_handler, NULL);
303
304 state->ann_trigger = false;
305 state->state = GPTP_PA_TRANSMIT_INIT;
306 }
307
gptp_mi_init_port_role_selection_sm(void)308 static void gptp_mi_init_port_role_selection_sm(void)
309 {
310 GPTP_STATE()->pr_sel.state = GPTP_PR_SELECTION_INIT_BRIDGE;
311 }
312
gptp_mi_init_state_machine(void)313 void gptp_mi_init_state_machine(void)
314 {
315 int port;
316
317 for (port = GPTP_PORT_START;
318 port < (GPTP_PORT_START + CONFIG_NET_GPTP_NUM_PORTS); port++) {
319 gptp_mi_init_port_sync_sync_rcv_sm(port);
320 gptp_mi_init_port_sync_sync_send_sm(port);
321 gptp_mi_init_port_announce_rcv_sm(port);
322 gptp_mi_init_port_announce_info_sm(port);
323 gptp_mi_init_port_announce_transmit_sm(port);
324 gptp_mi_init_bmca_data(port);
325 }
326
327 gptp_mi_init_site_sync_sync_sm();
328 gptp_mi_init_clock_slave_sync_sm();
329 gptp_mi_init_port_role_selection_sm();
330 gptp_mi_init_clock_master_sync_rcv_sm();
331 }
332
gptp_get_current_time_nanosecond(int port)333 uint64_t gptp_get_current_time_nanosecond(int port)
334 {
335 const struct device *clk;
336
337 clk = net_eth_get_ptp_clock(GPTP_PORT_IFACE(port));
338 if (clk) {
339 struct net_ptp_time tm = {};
340
341 ptp_clock_get(clk, &tm);
342
343 if (tm.second == 0U && tm.nanosecond == 0U) {
344 goto use_uptime;
345 }
346
347 return gptp_timestamp_to_nsec(&tm);
348 }
349
350 use_uptime:
351 /* A workaround if clock cannot be found. Note that accuracy is
352 * only in milliseconds.
353 */
354 return k_uptime_get() * 1000000;
355 }
356
gptp_get_current_master_time_nanosecond(void)357 uint64_t gptp_get_current_master_time_nanosecond(void)
358 {
359 int port;
360 enum gptp_port_state *port_role;
361
362 port_role = GPTP_GLOBAL_DS()->selected_role;
363
364 for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
365 if (port_role[port] == GPTP_PORT_MASTER) {
366 return gptp_get_current_time_nanosecond(port);
367 }
368 }
369
370 /* No master */
371 return 0;
372 }
373
gptp_mi_pss_rcv_compute(int port)374 static void gptp_mi_pss_rcv_compute(int port)
375 {
376 struct gptp_pss_rcv_state *state;
377 struct gptp_mi_port_sync_sync *pss;
378 struct gptp_md_sync_info *sync_rcv;
379 struct gptp_port_ds *port_ds;
380
381 state = &GPTP_PORT_STATE(port)->pss_rcv;
382 pss = &state->pss;
383 sync_rcv = &state->sync_rcv;
384 port_ds = GPTP_PORT_DS(port);
385
386 state->rate_ratio = sync_rcv->rate_ratio;
387 state->rate_ratio += (port_ds->neighbor_rate_ratio - 1.0);
388
389 port_ds->sync_receipt_timeout_time_itv = port_ds->sync_receipt_timeout;
390 port_ds->sync_receipt_timeout_time_itv *= NSEC_PER_SEC;
391 port_ds->sync_receipt_timeout_time_itv *=
392 GPTP_POW2(sync_rcv->log_msg_interval);
393
394 pss->local_port_number = port;
395
396 memcpy(&pss->sync_info, sync_rcv, sizeof(struct gptp_md_sync_info));
397
398 pss->sync_receipt_timeout_time = gptp_get_current_time_nanosecond(port);
399 pss->sync_receipt_timeout_time +=
400 port_ds->sync_receipt_timeout_time_itv;
401
402 pss->sync_info.rate_ratio = state->rate_ratio;
403 }
404
start_rcv_sync_timer(struct gptp_port_ds * port_ds,struct gptp_pss_rcv_state * state)405 static void start_rcv_sync_timer(struct gptp_port_ds *port_ds,
406 struct gptp_pss_rcv_state *state)
407 {
408 k_timeout_t duration;
409
410 duration = K_MSEC(port_ds->sync_receipt_timeout_time_itv /
411 (NSEC_PER_USEC * USEC_PER_MSEC));
412
413 k_timer_start(&state->rcv_sync_receipt_timeout_timer, duration,
414 K_NO_WAIT);
415 }
416
gptp_mi_pss_rcv_state_machine(int port)417 static void gptp_mi_pss_rcv_state_machine(int port)
418 {
419 struct gptp_pss_rcv_state *state;
420 struct gptp_site_sync_sync_state *site_ss_state;
421 struct gptp_port_ds *port_ds;
422
423 state = &GPTP_PORT_STATE(port)->pss_rcv;
424 site_ss_state = &GPTP_STATE()->site_ss;
425 port_ds = GPTP_PORT_DS(port);
426
427 if ((!port_ds->ptt_port_enabled) || !port_ds->as_capable) {
428 state->rcvd_md_sync = false;
429 state->state = GPTP_PSS_RCV_DISCARD;
430 return;
431 }
432
433 switch (state->state) {
434 case GPTP_PSS_RCV_DISCARD:
435 k_timer_stop(&state->rcv_sync_receipt_timeout_timer);
436 state->rcv_sync_receipt_timeout_timer_expired = false;
437
438 __fallthrough;
439 case GPTP_PSS_RCV_RECEIVED_SYNC:
440 if (state->rcvd_md_sync) {
441 state->rcvd_md_sync = false;
442 gptp_mi_pss_rcv_compute(port);
443
444 state->state = GPTP_PSS_RCV_RECEIVED_SYNC;
445
446 site_ss_state->pss_rcv_ptr = &state->pss;
447 site_ss_state->rcvd_pss = true;
448
449 k_timer_stop(&state->rcv_sync_receipt_timeout_timer);
450 state->rcv_sync_receipt_timeout_timer_expired = false;
451
452 if (GPTP_GLOBAL_DS()->gm_present) {
453 start_rcv_sync_timer(port_ds, state);
454 }
455 }
456
457 break;
458 }
459 }
460
gptp_mi_pss_store_last_pss(int port)461 static void gptp_mi_pss_store_last_pss(int port)
462 {
463 struct gptp_pss_send_state *state;
464 struct gptp_mi_port_sync_sync *pss_ptr;
465 struct gptp_md_sync_info *sync_info;
466
467 state = &GPTP_PORT_STATE(port)->pss_send;
468 pss_ptr = state->pss_sync_ptr;
469 sync_info = &pss_ptr->sync_info;
470
471 state->last_rcvd_port_num = pss_ptr->local_port_number;
472
473 memcpy(&state->last_precise_orig_ts, &sync_info->precise_orig_ts,
474 sizeof(struct net_ptp_time));
475 memcpy(&state->last_gm_phase_change, &sync_info->last_gm_phase_change,
476 sizeof(struct gptp_scaled_ns));
477
478 state->last_follow_up_correction_field =
479 sync_info->follow_up_correction_field;
480 state->last_rate_ratio = sync_info->rate_ratio;
481 state->last_upstream_tx_time = sync_info->upstream_tx_time;
482 state->last_gm_time_base_indicator = sync_info->gm_time_base_indicator;
483 state->last_gm_freq_change = sync_info->last_gm_freq_change;
484 }
485
gptp_mi_pss_send_md_sync_send(int port)486 static void gptp_mi_pss_send_md_sync_send(int port)
487 {
488 struct gptp_pss_send_state *state;
489 struct gptp_mi_port_sync_sync *pss_ptr;
490 struct gptp_sync_send_state *sync_send;
491
492 state = &GPTP_PORT_STATE(port)->pss_send;
493 pss_ptr = state->pss_sync_ptr;
494 sync_send = &GPTP_PORT_STATE(port)->sync_send;
495
496 memcpy(&state->sync_send, &pss_ptr->sync_info,
497 sizeof(struct gptp_md_sync_info));
498
499 sync_send->sync_send_ptr = &state->sync_send;
500 sync_send->rcvd_md_sync = true;
501 }
502
gptp_mi_pss_send_state_machine(int port)503 static void gptp_mi_pss_send_state_machine(int port)
504 {
505 struct gptp_pss_send_state *state;
506 struct gptp_port_ds *port_ds;
507 struct gptp_global_ds *global_ds;
508 k_timeout_t duration;
509
510 global_ds = GPTP_GLOBAL_DS();
511 state = &GPTP_PORT_STATE(port)->pss_send;
512 port_ds = GPTP_PORT_DS(port);
513
514 /* Reset interval as defined in LinkDelaySyncIntervalSetting state
515 * machine.
516 */
517 if (port_ds->ptt_port_enabled && !port_ds->prev_ptt_port_enabled) {
518 gptp_update_sync_interval(port, GPTP_ITV_SET_TO_INIT);
519 }
520
521 if (state->rcvd_pss_sync && ((!port_ds->ptt_port_enabled) ||
522 !port_ds->as_capable)) {
523 state->rcvd_pss_sync = false;
524 state->state = GPTP_PSS_SEND_TRANSMIT_INIT;
525
526 return;
527 }
528
529 switch (state->state) {
530 case GPTP_PSS_SEND_TRANSMIT_INIT:
531 case GPTP_PSS_SEND_SYNC_RECEIPT_TIMEOUT:
532 if (state->rcvd_pss_sync &&
533 (state->pss_sync_ptr->local_port_number != port) &&
534 (global_ds->selected_role[port] == GPTP_PORT_MASTER)) {
535 state->state = GPTP_PSS_SEND_SEND_MD_SYNC;
536 } else {
537 break;
538 }
539
540 __fallthrough;
541 case GPTP_PSS_SEND_SEND_MD_SYNC:
542 if (state->rcvd_pss_sync) {
543 gptp_mi_pss_store_last_pss(port);
544 state->rcvd_pss_sync = false;
545 }
546
547 /* Make sure no previous timer is still running. */
548 k_timer_stop(&state->half_sync_itv_timer);
549 k_timer_stop(&state->send_sync_receipt_timeout_timer);
550
551 state->half_sync_itv_timer_expired = false;
552 state->sync_itv_timer_expired = false;
553 state->send_sync_receipt_timeout_timer_expired = false;
554
555 /* Convert ns to ms. */
556 duration = K_MSEC(gptp_uscaled_ns_to_timer_ms(
557 &port_ds->half_sync_itv));
558
559 /* Start 0.5 * syncInterval timeout timer. */
560 k_timer_start(&state->half_sync_itv_timer, duration,
561 K_NO_WAIT);
562
563 /* sourcePortIdentity is set to the portIdentity of this
564 * PTP Port (see ch. 10.2.12.2.1 and ch 8.5.2).
565 */
566 memcpy(&state->pss_sync_ptr->sync_info.src_port_id.clk_id,
567 GPTP_DEFAULT_DS()->clk_id,
568 GPTP_CLOCK_ID_LEN);
569 state->pss_sync_ptr->sync_info.src_port_id.port_number = port;
570
571
572 gptp_mi_pss_send_md_sync_send(port);
573
574 __fallthrough;
575 case GPTP_PSS_SEND_SET_SYNC_RECEIPT_TIMEOUT:
576 /* Test conditions have been slightly rearranged compared to
577 * their definitions in the standard in order not to test
578 * AsCapable and pttPortEnabled when not needed (they are
579 * already tested with rcvdPSSync for the reset of this state
580 * machine).
581 */
582 if ((global_ds->selected_role[port] == GPTP_PORT_MASTER) &&
583 ((state->rcvd_pss_sync &&
584 state->half_sync_itv_timer_expired &&
585 state->pss_sync_ptr->local_port_number != port) ||
586 (state->sync_itv_timer_expired &&
587 (state->last_rcvd_port_num != port) &&
588 port_ds->as_capable && port_ds->ptt_port_enabled))) {
589
590 state->state = GPTP_PSS_SEND_SEND_MD_SYNC;
591
592 } else if ((state->state == GPTP_PSS_SEND_SEND_MD_SYNC) ||
593 (state->rcvd_pss_sync &&
594 !state->sync_itv_timer_expired &&
595 (global_ds->selected_role[port] ==
596 GPTP_PORT_MASTER) &&
597 state->pss_sync_ptr->local_port_number != port)) {
598
599 /* Change state as it may have transitioned from
600 * SEND_MD_SYNC.
601 */
602 state->state = GPTP_PSS_SEND_SET_SYNC_RECEIPT_TIMEOUT;
603
604 /* Stop and (re)start receipt timeout timer. */
605 k_timer_stop(&state->send_sync_receipt_timeout_timer);
606 state->send_sync_receipt_timeout_timer_expired = false;
607
608 duration =
609 K_MSEC(port_ds->sync_receipt_timeout_time_itv /
610 (NSEC_PER_USEC * USEC_PER_MSEC));
611
612 k_timer_start(&state->send_sync_receipt_timeout_timer,
613 duration, K_NO_WAIT);
614
615 } else if (state->send_sync_receipt_timeout_timer_expired) {
616 state->state = GPTP_PSS_SEND_SYNC_RECEIPT_TIMEOUT;
617 }
618
619 break;
620 }
621 }
622
gptp_mi_site_ss_prepare_pss_send(void)623 static void gptp_mi_site_ss_prepare_pss_send(void)
624 {
625 struct gptp_site_sync_sync_state *state;
626
627 state = &GPTP_STATE()->site_ss;
628
629 memcpy(&state->pss_send, state->pss_rcv_ptr,
630 sizeof(struct gptp_mi_port_sync_sync));
631 }
632
gptp_mi_site_ss_send_to_pss(void)633 static void gptp_mi_site_ss_send_to_pss(void)
634 {
635 struct gptp_site_sync_sync_state *state;
636 struct gptp_pss_send_state *pss_send;
637 int port;
638
639 state = &GPTP_STATE()->site_ss;
640
641 for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
642 pss_send = &GPTP_PORT_STATE(port)->pss_send;
643 pss_send->pss_sync_ptr = &state->pss_send;
644 pss_send->rcvd_pss_sync = true;
645 }
646 }
647
gptp_mi_site_sync_sync_state_machine(void)648 static void gptp_mi_site_sync_sync_state_machine(void)
649 {
650 bool gm_present;
651 uint16_t local_port_number;
652 struct gptp_site_sync_sync_state *state;
653 struct gptp_clk_slave_sync_state *clk_ss;
654
655 state = &GPTP_STATE()->site_ss;
656 clk_ss = &GPTP_STATE()->clk_slave_sync;
657 gm_present = GPTP_GLOBAL_DS()->gm_present;
658
659 if (!state->pss_rcv_ptr) {
660 /* We do not have connection to GM yet */
661 return;
662 }
663
664 local_port_number = state->pss_rcv_ptr->local_port_number;
665
666 switch (state->state) {
667 case GPTP_SSS_INITIALIZING:
668 state->rcvd_pss = false;
669 state->state = GPTP_SSS_RECEIVING_SYNC;
670 break;
671
672 case GPTP_SSS_RECEIVING_SYNC:
673 if (state->rcvd_pss) {
674 state->rcvd_pss = false;
675 if (gptp_is_slave_port(local_port_number) &&
676 gm_present) {
677 gptp_mi_site_ss_prepare_pss_send();
678
679 /*
680 * Send Port Sync Sync to all
681 * PortSyncSyncSend State Machines.
682 */
683 gptp_mi_site_ss_send_to_pss();
684
685 /*
686 * Send PortSyncSync to
687 * ClockSlaveSync State Machine.
688 */
689 clk_ss->pss_rcv_ptr = &state->pss_send;
690 clk_ss->rcvd_pss = true;
691 }
692 }
693
694 break;
695 }
696 }
697
gptp_mi_clk_slave_sync_compute(void)698 static void gptp_mi_clk_slave_sync_compute(void)
699 {
700 struct gptp_clk_slave_sync_state *state;
701 struct gptp_clk_master_sync_offset_state *offset_state;
702 struct gptp_global_ds *global_ds;
703 struct gptp_md_sync_info *pss;
704 struct gptp_port_ds *port_ds;
705 uint64_t sync_receipt_time;
706
707 state = &GPTP_STATE()->clk_slave_sync;
708 offset_state = &GPTP_STATE()->clk_master_sync_offset;
709 global_ds = GPTP_GLOBAL_DS();
710 port_ds = GPTP_PORT_DS(state->pss_rcv_ptr->local_port_number);
711
712 pss = &state->pss_rcv_ptr->sync_info;
713
714 sync_receipt_time = port_ds->neighbor_prop_delay;
715 sync_receipt_time *= pss->rate_ratio;
716 sync_receipt_time /= port_ds->neighbor_rate_ratio;
717 sync_receipt_time += pss->follow_up_correction_field;
718 sync_receipt_time += port_ds->delay_asymmetry;
719
720 global_ds->sync_receipt_time.second = sync_receipt_time / NSEC_PER_SEC;
721 global_ds->sync_receipt_time.fract_nsecond =
722 (sync_receipt_time % NSEC_PER_SEC) * GPTP_POW2_16;
723 global_ds->sync_receipt_time.second += pss->precise_orig_ts.second;
724 global_ds->sync_receipt_time.fract_nsecond +=
725 pss->precise_orig_ts.nanosecond * GPTP_POW2_16;
726
727 global_ds->sync_receipt_local_time = port_ds->delay_asymmetry;
728 global_ds->sync_receipt_local_time /= pss->rate_ratio;
729 global_ds->sync_receipt_local_time +=
730 (port_ds->neighbor_prop_delay / port_ds->neighbor_rate_ratio);
731 global_ds->sync_receipt_local_time += pss->upstream_tx_time;
732
733 global_ds->gm_time_base_indicator = pss->gm_time_base_indicator;
734 global_ds->last_gm_phase_change.high = pss->last_gm_phase_change.high;
735 global_ds->last_gm_phase_change.low = pss->last_gm_phase_change.low;
736 global_ds->last_gm_freq_change = pss->last_gm_freq_change;
737
738 offset_state->rcvd_sync_receipt_time = true;
739 }
740
741 #if defined(CONFIG_NET_GPTP_USE_DEFAULT_CLOCK_UPDATE)
gptp_update_local_port_clock(void)742 static void gptp_update_local_port_clock(void)
743 {
744 struct gptp_clk_slave_sync_state *state;
745 struct gptp_global_ds *global_ds;
746 struct gptp_port_ds *port_ds;
747 int port;
748 int64_t nanosecond_diff;
749 int64_t second_diff;
750 const struct device *clk;
751 struct net_ptp_time tm;
752 unsigned int key;
753
754 state = &GPTP_STATE()->clk_slave_sync;
755 global_ds = GPTP_GLOBAL_DS();
756 port = state->pss_rcv_ptr->local_port_number;
757 NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
758
759 port_ds = GPTP_PORT_DS(port);
760
761 /* Check if the last neighbor rate ratio can still be used */
762 if (!port_ds->neighbor_rate_ratio_valid) {
763 return;
764 }
765
766 port_ds->neighbor_rate_ratio_valid = false;
767
768 second_diff = global_ds->sync_receipt_time.second -
769 (global_ds->sync_receipt_local_time / NSEC_PER_SEC);
770 nanosecond_diff =
771 (global_ds->sync_receipt_time.fract_nsecond / GPTP_POW2_16) -
772 (global_ds->sync_receipt_local_time % NSEC_PER_SEC);
773
774 clk = net_eth_get_ptp_clock(GPTP_PORT_IFACE(port));
775 if (!clk) {
776 return;
777 }
778
779 if (second_diff > 0 && nanosecond_diff < 0) {
780 second_diff--;
781 nanosecond_diff = NSEC_PER_SEC + nanosecond_diff;
782 }
783
784 if (second_diff < 0 && nanosecond_diff > 0) {
785 second_diff++;
786 nanosecond_diff = -(int64_t)NSEC_PER_SEC + nanosecond_diff;
787 }
788
789 ptp_clock_rate_adjust(clk, port_ds->neighbor_rate_ratio);
790
791 /* If time difference is too high, set the clock value.
792 * Otherwise, adjust it.
793 */
794 if (second_diff || (second_diff == 0 &&
795 (nanosecond_diff < -5000 ||
796 nanosecond_diff > 5000))) {
797 bool underflow = false;
798
799 key = irq_lock();
800 ptp_clock_get(clk, &tm);
801
802 if (second_diff < 0 && tm.second < -second_diff) {
803 NET_DBG("Do not set local clock because %lu < %ld",
804 (unsigned long int)tm.second,
805 (long int)-second_diff);
806 goto skip_clock_set;
807 }
808
809 tm.second += second_diff;
810
811 if (nanosecond_diff < 0 &&
812 tm.nanosecond < -nanosecond_diff) {
813 underflow = true;
814 }
815
816 tm.nanosecond += nanosecond_diff;
817
818 if (underflow) {
819 tm.second--;
820 tm.nanosecond += NSEC_PER_SEC;
821 } else if (tm.nanosecond >= NSEC_PER_SEC) {
822 tm.second++;
823 tm.nanosecond -= NSEC_PER_SEC;
824 }
825
826 /* This prints too much data normally but can be enabled to see
827 * what time we are setting to the local clock.
828 */
829 if (0) {
830 NET_INFO("Set local clock %lu.%lu",
831 (unsigned long int)tm.second,
832 (unsigned long int)tm.nanosecond);
833 }
834
835 ptp_clock_set(clk, &tm);
836
837 skip_clock_set:
838 irq_unlock(key);
839 } else {
840 if (nanosecond_diff < -200) {
841 nanosecond_diff = -200;
842 } else if (nanosecond_diff > 200) {
843 nanosecond_diff = 200;
844 }
845
846 ptp_clock_adjust(clk, nanosecond_diff);
847 }
848 }
849 #endif /* CONFIG_NET_GPTP_USE_DEFAULT_CLOCK_UPDATE */
850
gptp_mi_clk_slave_sync_state_machine(void)851 static void gptp_mi_clk_slave_sync_state_machine(void)
852 {
853 struct gptp_clk_slave_sync_state *state;
854
855 state = &GPTP_STATE()->clk_slave_sync;
856
857 switch (state->state) {
858 case GPTP_CLK_SLAVE_SYNC_INITIALIZING:
859 state->rcvd_pss = false;
860 state->state = GPTP_CLK_SLAVE_SYNC_SEND_SYNC_IND;
861 break;
862
863 case GPTP_CLK_SLAVE_SYNC_SEND_SYNC_IND:
864 if (state->rcvd_pss) {
865 state->rcvd_pss = false;
866 gptp_mi_clk_slave_sync_compute();
867
868 #if defined(CONFIG_NET_GPTP_USE_DEFAULT_CLOCK_UPDATE)
869 /* Instead of updating SlaveClock, update LocalClock */
870 gptp_update_local_port_clock();
871 #endif
872 gptp_call_phase_dis_cb();
873 }
874
875 break;
876 }
877 }
878
gptp_mi_clk_master_sync_offset_state_machine(void)879 static void gptp_mi_clk_master_sync_offset_state_machine(void)
880 {
881 struct gptp_clk_master_sync_offset_state *state;
882 struct gptp_global_ds *global_ds;
883
884 state = &GPTP_STATE()->clk_master_sync_offset;
885 global_ds = GPTP_GLOBAL_DS();
886
887 switch (state->state) {
888 case GPTP_CMS_OFFSET_INITIALIZING:
889 state->rcvd_sync_receipt_time = false;
890 state->state = GPTP_CMS_OFFSET_INDICATION;
891 break;
892 case GPTP_CMS_OFFSET_INDICATION:
893 if (!state->rcvd_sync_receipt_time) {
894 break;
895 }
896
897 state->rcvd_sync_receipt_time = false;
898
899 if (global_ds->selected_role[0] == GPTP_PORT_PASSIVE) {
900 /* TODO Calculate real values for proper BC support */
901 memset(&global_ds->clk_src_phase_offset, 0x0,
902 sizeof(struct gptp_scaled_ns));
903 global_ds->clk_src_freq_offset = 0;
904 } else if (global_ds->clk_src_time_base_indicator_prev
905 != global_ds->clk_src_time_base_indicator) {
906 memcpy(&global_ds->clk_src_phase_offset,
907 &global_ds->last_gm_phase_change,
908 sizeof(struct gptp_scaled_ns));
909
910 global_ds->clk_src_freq_offset =
911 global_ds->last_gm_freq_change;
912 }
913
914 break;
915 default:
916 NET_ERR("Unrecognised state %d", state->state);
917 break;
918 }
919 }
920
921 #if defined(CONFIG_NET_GPTP_GM_CAPABLE)
gptp_mi_setup_sync_send_time(void)922 static inline void gptp_mi_setup_sync_send_time(void)
923 {
924 struct gptp_clk_master_sync_snd_state *state;
925 struct gptp_global_ds *global_ds;
926 uint64_t time_helper;
927
928 state = &GPTP_STATE()->clk_master_sync_send;
929 global_ds = GPTP_GLOBAL_DS();
930
931 time_helper = state->sync_send_time.low;
932
933 state->sync_send_time.low +=
934 global_ds->clk_master_sync_itv;
935
936 /* Check for overflow */
937 if (state->sync_send_time.low < time_helper) {
938 state->sync_send_time.high += 1U;
939 state->sync_send_time.low =
940 UINT64_MAX - state->sync_send_time.low;
941 }
942 }
943
gptp_mi_set_ps_sync_cmss(void)944 static void gptp_mi_set_ps_sync_cmss(void)
945 {
946 struct gptp_clk_master_sync_snd_state *state;
947 struct gptp_global_ds *global_ds;
948 struct gptp_md_sync_info *sync_info;
949 uint64_t current_time;
950
951 global_ds = GPTP_GLOBAL_DS();
952 state = &GPTP_STATE()->clk_master_sync_send;
953
954 sync_info = &state->pss_snd.sync_info;
955
956 state->pss_snd.local_port_number = 0U;
957
958 current_time = gptp_get_current_master_time_nanosecond();
959
960 sync_info->precise_orig_ts.second = current_time / NSEC_PER_SEC;
961 sync_info->precise_orig_ts.nanosecond = current_time % NSEC_PER_SEC;
962
963 /* TODO calculate rate ratio and correction field properly.
964 * Whenever time aware system is the grand master clock, we currently
965 * make the following shortcuts:
966 * - assuming that clock source is the local clock,
967 * rate_ratio is set to 1.0 instead of being copied from global_ds.
968 * - considering that precise origin timestamp is directly inherited
969 * from sync egress timestamp in gptp_md_follow_up_prepare(),
970 * follow_up_correction_field is set to 0.
971 */
972 sync_info->follow_up_correction_field = 0;
973 sync_info->rate_ratio = 1.0;
974
975 memcpy(&sync_info->src_port_id.clk_id,
976 GPTP_DEFAULT_DS()->clk_id,
977 GPTP_CLOCK_ID_LEN);
978
979 sync_info->src_port_id.port_number = 0U;
980 sync_info->log_msg_interval = CONFIG_NET_GPTP_INIT_LOG_SYNC_ITV;
981 sync_info->upstream_tx_time = global_ds->local_time.low;
982
983 state->pss_snd.sync_receipt_timeout_time = UINT64_MAX;
984
985 sync_info->gm_time_base_indicator =
986 global_ds->clk_src_time_base_indicator;
987
988 memcpy(&sync_info->last_gm_phase_change,
989 &global_ds->clk_src_phase_offset,
990 sizeof(struct gptp_scaled_ns));
991
992 sync_info->last_gm_freq_change = global_ds->clk_src_freq_offset;
993 }
994
gptp_mi_tx_ps_sync_cmss(void)995 static inline void gptp_mi_tx_ps_sync_cmss(void)
996 {
997 struct gptp_clk_master_sync_snd_state *state;
998 struct gptp_pss_send_state *pss_send;
999 int port;
1000
1001 state = &GPTP_STATE()->clk_master_sync_send;
1002
1003 for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
1004 pss_send = &GPTP_PORT_STATE(port)->pss_send;
1005 pss_send->pss_sync_ptr = &state->pss_snd;
1006
1007 pss_send->rcvd_pss_sync = true;
1008 }
1009 }
1010
gptp_mi_clk_master_sync_snd_state_machine(void)1011 static void gptp_mi_clk_master_sync_snd_state_machine(void)
1012 {
1013 struct gptp_clk_master_sync_snd_state *state;
1014 uint64_t current_time;
1015
1016 state = &GPTP_STATE()->clk_master_sync_send;
1017
1018 switch (state->state) {
1019 case GPTP_CMS_SND_INITIALIZING:
1020 gptp_mi_setup_sync_send_time();
1021
1022 state->state = GPTP_CMS_SND_INDICATION;
1023 break;
1024
1025 case GPTP_CMS_SND_INDICATION:
1026 current_time = gptp_get_current_master_time_nanosecond();
1027
1028 if (current_time >= state->sync_send_time.low) {
1029 gptp_mi_set_ps_sync_cmss();
1030 gptp_mi_tx_ps_sync_cmss();
1031
1032 gptp_mi_setup_sync_send_time();
1033 }
1034
1035 break;
1036
1037 default:
1038 NET_ERR("Unrecognised state %d", state->state);
1039 break;
1040 }
1041 }
1042 #endif
1043
gptp_compute_gm_rate_ratio(void)1044 static void gptp_compute_gm_rate_ratio(void)
1045 {
1046 static struct net_ptp_extended_time src_time_0;
1047 static struct gptp_uscaled_ns local_time_0;
1048 struct net_ptp_extended_time src_time_n;
1049 struct gptp_uscaled_ns local_time_n;
1050 struct net_ptp_extended_time src_time_t;
1051 struct gptp_uscaled_ns local_time_t;
1052 struct gptp_clk_master_sync_rcv_state *state;
1053 struct gptp_global_ds *global_ds;
1054 double new_gm_rate;
1055
1056 state = &GPTP_STATE()->clk_master_sync_receive;
1057 global_ds = GPTP_GLOBAL_DS();
1058
1059 /* Get current local and source time */
1060 memcpy(&src_time_n, &state->rcvd_clk_src_req.src_time,
1061 sizeof(struct net_ptp_extended_time));
1062
1063 memcpy(&local_time_n, &global_ds->local_time,
1064 sizeof(struct gptp_uscaled_ns));
1065
1066 if ((src_time_0.second == 0U && src_time_0.fract_nsecond == 0U)
1067 || (local_time_0.high == 0U && local_time_0.low == 0U)) {
1068 memcpy(&src_time_0, &src_time_n,
1069 sizeof(struct net_ptp_extended_time));
1070
1071 memcpy(&local_time_0, &local_time_n,
1072 sizeof(struct gptp_uscaled_ns));
1073
1074 global_ds->gm_rate_ratio = 1.0;
1075
1076 return;
1077 }
1078
1079 /* Take care of the sign of the result */
1080 new_gm_rate = 1.0;
1081
1082 if ((src_time_n.second < src_time_0.second)
1083 || (src_time_n.second == src_time_0.second
1084 && src_time_n.fract_nsecond < src_time_0.fract_nsecond)) {
1085 /* Change result sign and swap src_time_n and src_time_0 */
1086 memcpy(&src_time_t, &src_time_n,
1087 sizeof(struct net_ptp_extended_time));
1088 memcpy(&src_time_n, &src_time_0,
1089 sizeof(struct net_ptp_extended_time));
1090 memcpy(&src_time_0, &src_time_t,
1091 sizeof(struct net_ptp_extended_time));
1092
1093 new_gm_rate *= -1;
1094 }
1095
1096 if ((local_time_n.high < local_time_0.high)
1097 || (local_time_n.high == local_time_0.high
1098 && local_time_n.low < local_time_0.low)) {
1099 /* Change result sign and swap local_time_n and local_time_0 */
1100 memcpy(&local_time_t, &local_time_n,
1101 sizeof(struct gptp_uscaled_ns));
1102 memcpy(&local_time_n, &local_time_0,
1103 sizeof(struct gptp_uscaled_ns));
1104 memcpy(&local_time_0, &local_time_t,
1105 sizeof(struct gptp_uscaled_ns));
1106
1107 new_gm_rate *= -1;
1108 }
1109
1110 /* At this point src_time_n >= src_time_0 */
1111 src_time_n.second -= src_time_0.second;
1112
1113 if (src_time_n.fract_nsecond >= src_time_0.fract_nsecond) {
1114 src_time_n.fract_nsecond -= src_time_0.fract_nsecond;
1115 } else {
1116 src_time_n.second -= 1U;
1117 src_time_n.fract_nsecond = (NSEC_PER_SEC * GPTP_POW2_16)
1118 - src_time_0.fract_nsecond;
1119 }
1120
1121 /* At this point local_time_n >= local_time_0 */
1122 local_time_n.high -= local_time_0.high;
1123
1124 if (local_time_n.low >= local_time_0.low) {
1125 local_time_n.low -= local_time_0.low;
1126 } else {
1127 local_time_n.high -= 1U;
1128 local_time_n.low = UINT64_MAX - local_time_0.low;
1129 }
1130
1131 /* Calculate it in nanoseconds, new_gm_rate is either 1 or -1 here */
1132 new_gm_rate *= ((src_time_n.second * NSEC_PER_SEC)
1133 + (src_time_n.fract_nsecond / GPTP_POW2_16));
1134
1135 new_gm_rate /= local_time_n.low;
1136
1137 global_ds->gm_rate_ratio = new_gm_rate;
1138 }
1139
gptp_mi_clk_master_sync_rcv_state_machine(void)1140 static void gptp_mi_clk_master_sync_rcv_state_machine(void)
1141 {
1142 struct gptp_clk_master_sync_rcv_state *s;
1143 struct gptp_global_ds *global_ds;
1144
1145 #ifdef CONFIG_NET_GPTP_PROBE_CLOCK_SOURCE_ON_DEMAND
1146 struct gptp_clk_src_time_invoke_params invoke_args = {};
1147 uint64_t cur = gptp_get_current_master_time_nanosecond();
1148
1149 invoke_args.src_time.second = cur / NSEC_PER_SEC;
1150 cur -= (invoke_args.src_time.second * NSEC_PER_SEC);
1151
1152 invoke_args.src_time.fract_nsecond = cur * GPTP_POW2_16;
1153
1154 memset(&invoke_args.last_gm_phase_change, 0x0,
1155 sizeof(struct gptp_scaled_ns));
1156 invoke_args.last_gm_freq_change = 0;
1157
1158 gptp_clk_src_time_invoke(&invoke_args);
1159 #endif
1160
1161 global_ds = GPTP_GLOBAL_DS();
1162
1163 s = &GPTP_STATE()->clk_master_sync_receive;
1164 switch (s->state) {
1165 case GPTP_CMS_RCV_INITIALIZING:
1166 s->state = GPTP_CMS_RCV_WAITING;
1167 break;
1168
1169 case GPTP_CMS_RCV_WAITING:
1170 if (s->rcvd_clock_source_req || s->rcvd_local_clock_tick) {
1171 s->state = GPTP_CMS_RCV_SOURCE_TIME;
1172 }
1173
1174 break;
1175
1176 case GPTP_CMS_RCV_SOURCE_TIME:
1177 global_ds->local_time.high = 0U;
1178 global_ds->local_time.low =
1179 gptp_get_current_master_time_nanosecond();
1180
1181 if (s->rcvd_clock_source_req) {
1182 gptp_compute_gm_rate_ratio();
1183
1184 global_ds->clk_src_time_base_indicator_prev =
1185 global_ds->clk_src_time_base_indicator;
1186
1187 global_ds->clk_src_time_base_indicator =
1188 s->rcvd_clk_src_req.time_base_indicator;
1189
1190 memcpy(&global_ds->clk_src_last_gm_phase_change,
1191 &s->rcvd_clk_src_req.last_gm_phase_change,
1192 sizeof(struct gptp_scaled_ns));
1193
1194 global_ds->clk_src_last_gm_freq_change =
1195 s->rcvd_clk_src_req.last_gm_freq_change;
1196 }
1197
1198 s->rcvd_clock_source_req = false;
1199 s->rcvd_local_clock_tick = false;
1200 s->state = GPTP_CMS_RCV_WAITING;
1201 break;
1202
1203 default:
1204 NET_ERR("Unrecognised state %d", s->state);
1205 break;
1206 }
1207 }
1208
copy_path_trace(struct gptp_announce * announce)1209 static void copy_path_trace(struct gptp_announce *announce)
1210 {
1211 int len = ntohs(announce->tlv.len);
1212 struct gptp_path_trace *sys_path_trace;
1213
1214 if (len > GPTP_MAX_PATHTRACE_SIZE) {
1215 NET_ERR("Too long path trace (%d vs %d)",
1216 GPTP_MAX_PATHTRACE_SIZE, len);
1217 return;
1218 }
1219
1220 sys_path_trace = &GPTP_GLOBAL_DS()->path_trace;
1221
1222 sys_path_trace->len = htons(len + GPTP_CLOCK_ID_LEN);
1223
1224 memcpy(sys_path_trace->path_sequence, announce->tlv.path_sequence,
1225 len);
1226
1227 /* Append local clockIdentity. */
1228 memcpy((uint8_t *)sys_path_trace->path_sequence + len,
1229 GPTP_DEFAULT_DS()->clk_id, GPTP_CLOCK_ID_LEN);
1230 }
1231
gptp_mi_qualify_announce(int port,struct net_pkt * announce_msg)1232 static bool gptp_mi_qualify_announce(int port, struct net_pkt *announce_msg)
1233 {
1234 struct gptp_announce *announce;
1235 struct gptp_hdr *hdr;
1236 int i;
1237 uint16_t len;
1238
1239 hdr = GPTP_HDR(announce_msg);
1240 announce = GPTP_ANNOUNCE(announce_msg);
1241
1242 if (memcmp(hdr->port_id.clk_id, GPTP_DEFAULT_DS()->clk_id,
1243 GPTP_CLOCK_ID_LEN) == 0) {
1244 return false;
1245 }
1246
1247 len = ntohs(announce->steps_removed);
1248 if (len >= 255U) {
1249 return false;
1250 }
1251
1252 for (i = 0; i < len + 1; i++) {
1253 if (memcmp(announce->tlv.path_sequence[i],
1254 GPTP_DEFAULT_DS()->clk_id,
1255 GPTP_CLOCK_ID_LEN) == 0) {
1256 return false;
1257 }
1258 }
1259
1260 if (GPTP_GLOBAL_DS()->selected_role[port] == GPTP_PORT_SLAVE) {
1261 copy_path_trace(announce);
1262 }
1263
1264 return true;
1265 }
1266
gptp_mi_port_announce_receive_state_machine(int port)1267 static void gptp_mi_port_announce_receive_state_machine(int port)
1268 {
1269 struct gptp_port_ds *port_ds;
1270 struct gptp_port_announce_receive_state *state;
1271 struct gptp_port_bmca_data *bmca_data;
1272
1273 state = &GPTP_PORT_STATE(port)->pa_rcv;
1274 port_ds = GPTP_PORT_DS(port);
1275 bmca_data = GPTP_PORT_BMCA_DATA(port);
1276
1277 if ((!port_ds->ptt_port_enabled) || (!port_ds->as_capable)) {
1278 state->state = GPTP_PA_RCV_DISCARD;
1279 }
1280
1281 switch (state->state) {
1282 case GPTP_PA_RCV_DISCARD:
1283 state->rcvd_announce = false;
1284 bmca_data->rcvd_msg = false;
1285 if (bmca_data->rcvd_announce_ptr != NULL) {
1286 net_pkt_unref(bmca_data->rcvd_announce_ptr);
1287 bmca_data->rcvd_announce_ptr = NULL;
1288 }
1289
1290 state->state = GPTP_PA_RCV_RECEIVE;
1291 break;
1292
1293 case GPTP_PA_RCV_RECEIVE:
1294 /* "portEnabled" is not checked: the interface is always up. */
1295 if (state->rcvd_announce &&
1296 port_ds->ptt_port_enabled &&
1297 port_ds->as_capable &&
1298 !bmca_data->rcvd_msg) {
1299 state->rcvd_announce = false;
1300
1301 bmca_data->rcvd_msg = gptp_mi_qualify_announce(
1302 port, bmca_data->rcvd_announce_ptr);
1303 if (!bmca_data->rcvd_msg) {
1304 net_pkt_unref(bmca_data->rcvd_announce_ptr);
1305 bmca_data->rcvd_announce_ptr = NULL;
1306 }
1307 }
1308
1309 break;
1310 }
1311 }
1312
1313 /*
1314 * Compare a vector to an announce message vector.
1315 * All must be in big endian (network) order.
1316 */
compare_priority_vectors(struct gptp_priority_vector * vector,struct net_pkt * pkt,int port)1317 static enum gptp_received_info compare_priority_vectors(
1318 struct gptp_priority_vector *vector,
1319 struct net_pkt *pkt, int port)
1320 {
1321 struct gptp_hdr *hdr;
1322 struct gptp_announce *announce;
1323 int rsi_cmp, spi_cmp, port_cmp;
1324
1325 hdr = GPTP_HDR(pkt);
1326 announce = GPTP_ANNOUNCE(pkt);
1327
1328 /* Compare rootSystemIdentity and stepsRemoved. */
1329 rsi_cmp = memcmp(&announce->root_system_id,
1330 &vector->root_system_id,
1331 sizeof(struct gptp_root_system_identity) +
1332 sizeof(uint16_t));
1333 if (rsi_cmp < 0) {
1334 /* Better rootSystemIdentity. */
1335 return GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO;
1336 }
1337
1338 /* Compare sourcePortIdentity. */
1339 spi_cmp = memcmp(&hdr->port_id, &vector->src_port_id,
1340 sizeof(struct gptp_port_identity));
1341
1342 port_cmp = (int)port - ntohs(vector->port_number);
1343
1344 if (spi_cmp == 0) {
1345 if (rsi_cmp == 0) {
1346 if (port_cmp == 0) {
1347 /* Same priority vector. */
1348 return GPTP_RCVD_INFO_REPEATED_MASTER_INFO;
1349 } else if (port_cmp < 0) {
1350 /* Priority vector with better reception port
1351 * number.
1352 */
1353 return GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO;
1354 }
1355 } else {
1356 /* Same master port but different Grand Master. */
1357 return GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO;
1358 }
1359 } else if ((spi_cmp < 0) && (rsi_cmp == 0)) {
1360 /* Same Grand Master but better masterPort. */
1361 return GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO;
1362 }
1363
1364 return GPTP_RCVD_INFO_INFERIOR_MASTER_INFO;
1365 }
1366
rcv_info(int port)1367 static enum gptp_received_info rcv_info(int port)
1368 {
1369 /* TODO
1370 * How can we define that a message does not convey the port
1371 * role Master port ?
1372 * It is needed to define that to be able to send
1373 * GPTP_RCVD_INFO_OTHER_INFO.
1374 */
1375 struct gptp_port_bmca_data *bmca_data;
1376 struct gptp_announce *announce;
1377
1378 bmca_data = GPTP_PORT_BMCA_DATA(port);
1379 announce = GPTP_ANNOUNCE(bmca_data->rcvd_announce_ptr);
1380
1381 bmca_data->message_steps_removed = announce->steps_removed;
1382
1383 return compare_priority_vectors(&bmca_data->port_priority,
1384 bmca_data->rcvd_announce_ptr,
1385 port);
1386 }
1387
record_other_announce_info(int port)1388 static void record_other_announce_info(int port)
1389 {
1390 struct gptp_hdr *hdr;
1391 struct gptp_announce *announce;
1392 struct gptp_port_bmca_data *bmca_data;
1393
1394 bmca_data = GPTP_PORT_BMCA_DATA(port);
1395 hdr = GPTP_HDR(bmca_data->rcvd_announce_ptr);
1396 announce = GPTP_ANNOUNCE(bmca_data->rcvd_announce_ptr);
1397
1398 /* Copy leap61, leap59, current UTC offset valid, time traceable and
1399 * frequency traceable flags.
1400 */
1401 bmca_data->ann_flags.octets[1] = hdr->flags.octets[1];
1402
1403 bmca_data->ann_current_utc_offset = ntohs(announce->cur_utc_offset);
1404 bmca_data->ann_time_source = announce->time_source;
1405 }
1406
copy_priority_vector(struct gptp_priority_vector * vector,struct net_pkt * pkt,int port)1407 static void copy_priority_vector(struct gptp_priority_vector *vector,
1408 struct net_pkt *pkt, int port)
1409 {
1410 struct gptp_hdr *hdr;
1411 struct gptp_announce *announce;
1412
1413 hdr = GPTP_HDR(pkt);
1414 announce = GPTP_ANNOUNCE(pkt);
1415
1416 memcpy(&vector->root_system_id, &announce->root_system_id,
1417 sizeof(struct gptp_root_system_identity) + sizeof(uint16_t));
1418
1419 memcpy(&vector->src_port_id, &hdr->port_id,
1420 sizeof(struct gptp_port_identity));
1421
1422 vector->port_number = htons(port);
1423 }
1424
gptp_mi_port_announce_information_state_machine(int port)1425 static void gptp_mi_port_announce_information_state_machine(int port)
1426 {
1427 struct gptp_port_ds *port_ds;
1428 struct gptp_global_ds *global_ds;
1429 struct gptp_port_announce_information_state *state;
1430 struct gptp_announce *announce;
1431 struct gptp_hdr *hdr;
1432 struct gptp_port_bmca_data *bmca_data;
1433 struct gptp_pss_rcv_state *pss_rcv;
1434
1435 bmca_data = GPTP_PORT_BMCA_DATA(port);
1436 state = &GPTP_PORT_STATE(port)->pa_info;
1437 port_ds = GPTP_PORT_DS(port);
1438 global_ds = GPTP_GLOBAL_DS();
1439
1440 if ((!port_ds->ptt_port_enabled || !port_ds->as_capable) &&
1441 (bmca_data->info_is != GPTP_INFO_IS_DISABLED)) {
1442 gptp_change_pa_info_state(port, state, GPTP_PA_INFO_DISABLED);
1443 }
1444
1445 switch (state->state) {
1446 case GPTP_PA_INFO_DISABLED:
1447 bmca_data->rcvd_msg = false;
1448 bmca_data->info_is = GPTP_INFO_IS_DISABLED;
1449 SET_RESELECT(global_ds, port);
1450 CLEAR_SELECTED(global_ds, port);
1451 gptp_change_pa_info_state(port, state,
1452 GPTP_PA_INFO_POST_DISABLED);
1453 k_timer_stop(&state->ann_rcpt_expiry_timer);
1454 state->ann_expired = true;
1455 __fallthrough;
1456
1457 case GPTP_PA_INFO_POST_DISABLED:
1458 if (port_ds->ptt_port_enabled && port_ds->as_capable) {
1459 gptp_change_pa_info_state(port, state,
1460 GPTP_PA_INFO_AGED);
1461 } else if (bmca_data->rcvd_msg) {
1462 gptp_change_pa_info_state(port, state,
1463 GPTP_PA_INFO_DISABLED);
1464 }
1465
1466 break;
1467
1468 case GPTP_PA_INFO_AGED:
1469 bmca_data->info_is = GPTP_INFO_IS_AGED;
1470 CLEAR_SELECTED(global_ds, port);
1471 SET_RESELECT(global_ds, port);
1472 /* Transition will be actually tested in UPDATE state. */
1473 gptp_change_pa_info_state(port, state, GPTP_PA_INFO_UPDATE);
1474 break;
1475
1476 case GPTP_PA_INFO_UPDATE:
1477 if (IS_SELECTED(global_ds, port) && bmca_data->updt_info) {
1478 memcpy(&bmca_data->port_priority,
1479 &bmca_data->master_priority,
1480 sizeof(struct gptp_priority_vector));
1481
1482 bmca_data->port_steps_removed =
1483 global_ds->master_steps_removed;
1484 bmca_data->updt_info = false;
1485 bmca_data->info_is = GPTP_INFO_IS_MINE;
1486 bmca_data->new_info = true;
1487 gptp_change_pa_info_state(port, state,
1488 GPTP_PA_INFO_CURRENT);
1489 }
1490
1491 break;
1492
1493 case GPTP_PA_INFO_CURRENT:
1494 pss_rcv = &GPTP_PORT_STATE(port)->pss_rcv;
1495 if (IS_SELECTED(global_ds, port) && bmca_data->updt_info) {
1496 gptp_change_pa_info_state(port, state,
1497 GPTP_PA_INFO_UPDATE);
1498 } else if (bmca_data->rcvd_msg && !bmca_data->updt_info) {
1499 gptp_change_pa_info_state(port, state,
1500 GPTP_PA_INFO_RECEIVE);
1501 } else if ((bmca_data->info_is == GPTP_INFO_IS_RECEIVED) &&
1502 !bmca_data->updt_info &&
1503 !bmca_data->rcvd_msg &&
1504 (state->ann_expired ||
1505 (global_ds->gm_present &&
1506 pss_rcv->rcv_sync_receipt_timeout_timer_expired))) {
1507 gptp_change_pa_info_state(port, state,
1508 GPTP_PA_INFO_AGED);
1509 }
1510
1511 break;
1512
1513 case GPTP_PA_INFO_RECEIVE:
1514 switch (rcv_info(port)) {
1515 case GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO:
1516 gptp_change_pa_info_state(port, state,
1517 GPTP_PA_INFO_SUPERIOR_MASTER_PORT);
1518 break;
1519 case GPTP_RCVD_INFO_REPEATED_MASTER_INFO:
1520 gptp_change_pa_info_state(port, state,
1521 GPTP_PA_INFO_REPEATED_MASTER_PORT);
1522 break;
1523 case GPTP_RCVD_INFO_INFERIOR_MASTER_INFO:
1524 __fallthrough;
1525 case GPTP_RCVD_INFO_OTHER_INFO:
1526 gptp_change_pa_info_state(port, state,
1527 GPTP_PA_INFO_INFERIOR_MASTER_OR_OTHER_PORT);
1528 break;
1529 }
1530
1531 break;
1532
1533 case GPTP_PA_INFO_SUPERIOR_MASTER_PORT:
1534 /* We copy directly the content of the message to the port
1535 * priority vector without using an intermediate
1536 * messagePriority structure.
1537 */
1538
1539 if (!bmca_data->rcvd_announce_ptr) {
1540 /* Shouldn't be reached. Checked for safety reason. */
1541 bmca_data->rcvd_msg = false;
1542 gptp_change_pa_info_state(port, state,
1543 GPTP_PA_INFO_CURRENT);
1544 break;
1545 }
1546
1547 copy_priority_vector(&bmca_data->port_priority,
1548 bmca_data->rcvd_announce_ptr, port);
1549
1550 announce = GPTP_ANNOUNCE(bmca_data->rcvd_announce_ptr);
1551 bmca_data->port_steps_removed = ntohs(announce->steps_removed);
1552 record_other_announce_info(port);
1553 hdr = GPTP_HDR(bmca_data->rcvd_announce_ptr);
1554 gptp_set_time_itv(&bmca_data->ann_rcpt_timeout_time_interval,
1555 port_ds->announce_receipt_timeout,
1556 hdr->log_msg_interval);
1557 bmca_data->info_is = GPTP_INFO_IS_RECEIVED;
1558 CLEAR_SELECTED(global_ds, port);
1559 SET_RESELECT(global_ds, port);
1560 __fallthrough;
1561
1562 case GPTP_PA_INFO_REPEATED_MASTER_PORT:
1563 k_timer_stop(&state->ann_rcpt_expiry_timer);
1564 state->ann_expired = false;
1565 k_timer_start(&state->ann_rcpt_expiry_timer,
1566 K_MSEC(gptp_uscaled_ns_to_timer_ms(
1567 &bmca_data->ann_rcpt_timeout_time_interval)),
1568 K_NO_WAIT);
1569 __fallthrough;
1570
1571 case GPTP_PA_INFO_INFERIOR_MASTER_OR_OTHER_PORT:
1572 if (bmca_data->rcvd_announce_ptr != NULL) {
1573 net_pkt_unref(bmca_data->rcvd_announce_ptr);
1574 bmca_data->rcvd_announce_ptr = NULL;
1575 }
1576
1577 bmca_data->rcvd_msg = false;
1578 gptp_change_pa_info_state(port, state, GPTP_PA_INFO_CURRENT);
1579 break;
1580 }
1581 }
1582
gptp_updt_role_disabled_tree(void)1583 static void gptp_updt_role_disabled_tree(void)
1584 {
1585 struct gptp_global_ds *global_ds;
1586 int port;
1587
1588 global_ds = GPTP_GLOBAL_DS();
1589
1590 /* Set all elements of the selectedRole array to DisabledPort. */
1591 for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
1592 gptp_change_port_state(port, GPTP_PORT_DISABLED);
1593 }
1594
1595 /* Set lastGmPriority to all ones. */
1596 (void)memset(&global_ds->last_gm_priority, 0xFF,
1597 sizeof(struct gptp_priority_vector));
1598
1599 /* Set pathTrace array to contain the single element thisClock. */
1600 global_ds->path_trace.len = htons(GPTP_CLOCK_ID_LEN);
1601 memcpy(global_ds->path_trace.path_sequence, GPTP_DEFAULT_DS()->clk_id,
1602 GPTP_CLOCK_ID_LEN);
1603 }
1604
gptp_clear_reselect_tree(void)1605 static void gptp_clear_reselect_tree(void)
1606 {
1607 /* Set all the elements of the reselect array to FALSE. */
1608 GPTP_GLOBAL_DS()->reselect_array = 0;
1609 }
1610
compute_best_vector(void)1611 static int compute_best_vector(void)
1612 {
1613 struct gptp_priority_vector *gm_prio;
1614 struct gptp_default_ds *default_ds;
1615 struct gptp_global_ds *global_ds;
1616 struct gptp_priority_vector *best_vector, *challenger;
1617 int best_port, port, tmp;
1618 struct gptp_pss_rcv_state *pss_rcv;
1619 struct gptp_port_announce_information_state *pa_info_state;
1620
1621 default_ds = GPTP_DEFAULT_DS();
1622 global_ds = GPTP_GLOBAL_DS();
1623 best_port = 0;
1624 gm_prio = &global_ds->gm_priority;
1625
1626 /* Write systemPriority into grandmaster. */
1627 (void)memset(gm_prio, 0, sizeof(struct gptp_priority_vector));
1628 gm_prio->root_system_id.grand_master_prio1 = default_ds->priority1;
1629 gm_prio->root_system_id.grand_master_prio2 = default_ds->priority2;
1630 gm_prio->root_system_id.clk_quality.clock_class =
1631 default_ds->clk_quality.clock_class;
1632 gm_prio->root_system_id.clk_quality.clock_accuracy =
1633 default_ds->clk_quality.clock_accuracy;
1634 gm_prio->root_system_id.clk_quality.offset_scaled_log_var =
1635 htons(default_ds->clk_quality.offset_scaled_log_var);
1636
1637 memcpy(gm_prio->src_port_id.clk_id, default_ds->clk_id,
1638 GPTP_CLOCK_ID_LEN);
1639 memcpy(gm_prio->root_system_id.grand_master_id, default_ds->clk_id,
1640 GPTP_CLOCK_ID_LEN);
1641
1642 best_vector = gm_prio;
1643
1644 for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
1645 challenger = &GPTP_PORT_BMCA_DATA(port)->port_priority;
1646 pa_info_state = &GPTP_PORT_STATE(port)->pa_info;
1647 pss_rcv = &GPTP_PORT_STATE(port)->pss_rcv;
1648
1649 if (pa_info_state->ann_expired ||
1650 (global_ds->gm_present &&
1651 pss_rcv->rcv_sync_receipt_timeout_timer_expired)) {
1652 continue;
1653 }
1654
1655 if (memcmp(challenger->src_port_id.clk_id, default_ds->clk_id,
1656 GPTP_CLOCK_ID_LEN) == 0) {
1657 /* Discard this challenger. */
1658 continue;
1659 }
1660
1661 if (best_port == 0) {
1662 tmp = memcmp(&challenger->root_system_id,
1663 &best_vector->root_system_id,
1664 sizeof(struct gptp_root_system_identity));
1665 if (tmp < 0) {
1666 best_vector = challenger;
1667 best_port = port;
1668 } else if (tmp > 0) {
1669 continue;
1670 }
1671
1672 tmp = (int)challenger->steps_removed -
1673 ((int)ntohs(best_vector->steps_removed) + 1);
1674 if (tmp < 0) {
1675 best_vector = challenger;
1676 best_port = port;
1677 } else if (tmp > 0) {
1678 continue;
1679 }
1680
1681 tmp = memcmp(&challenger->src_port_id,
1682 &best_vector->src_port_id,
1683 sizeof(struct gptp_port_identity));
1684 if (tmp < 0) {
1685 best_vector = challenger;
1686 best_port = port;
1687 } else if (tmp > 0) {
1688 continue;
1689 }
1690
1691 if (ntohs(challenger->port_number) <
1692 ntohs(best_vector->port_number)) {
1693 best_vector = challenger;
1694 best_port = port;
1695 }
1696
1697 } else {
1698 /* We can compare portPriority vectors without
1699 * calculating pathPriority vectors.
1700 */
1701 if (memcmp(challenger, best_vector,
1702 sizeof(struct gptp_priority_vector)) < 0) {
1703 best_vector = challenger;
1704 best_port = port;
1705 }
1706 }
1707 }
1708
1709 if (best_port != 0) {
1710 if (&global_ds->gm_priority.root_system_id !=
1711 &best_vector->root_system_id) {
1712 memcpy(&global_ds->gm_priority.root_system_id,
1713 &best_vector->root_system_id,
1714 sizeof(struct gptp_root_system_identity));
1715 }
1716
1717 global_ds->gm_priority.steps_removed =
1718 ntohs(best_vector->steps_removed) + 1;
1719
1720 if (&global_ds->gm_priority.src_port_id !=
1721 &best_vector->src_port_id) {
1722 memcpy(&global_ds->gm_priority.src_port_id,
1723 &best_vector->src_port_id,
1724 sizeof(struct gptp_port_identity));
1725 }
1726
1727 global_ds->gm_priority.port_number = best_vector->port_number;
1728 }
1729
1730 return best_port;
1731 }
1732
update_bmca(int port,int best_port,struct gptp_global_ds * global_ds,struct gptp_default_ds * default_ds,struct gptp_priority_vector * gm_prio)1733 static void update_bmca(int port,
1734 int best_port,
1735 struct gptp_global_ds *global_ds,
1736 struct gptp_default_ds *default_ds,
1737 struct gptp_priority_vector *gm_prio)
1738 {
1739 struct gptp_port_bmca_data *bmca_data = GPTP_PORT_BMCA_DATA(port);
1740
1741 /* Update masterPriorityVector for the port. */
1742 if (best_port == 0) {
1743 memcpy(&bmca_data->master_priority, gm_prio,
1744 sizeof(struct gptp_priority_vector));
1745
1746 bmca_data->master_priority.port_number = htons(port);
1747 bmca_data->master_priority.src_port_id.port_number =
1748 htons(port);
1749 } else {
1750 memcpy(&bmca_data->master_priority.root_system_id,
1751 &gm_prio->root_system_id,
1752 sizeof(struct gptp_root_system_identity));
1753 memcpy(bmca_data->master_priority.src_port_id.clk_id,
1754 default_ds->clk_id, GPTP_CLOCK_ID_LEN);
1755 bmca_data->master_priority.port_number = htons(port);
1756 bmca_data->master_priority.src_port_id.port_number =
1757 htons(port);
1758 }
1759
1760 switch (bmca_data->info_is) {
1761 case GPTP_INFO_IS_DISABLED:
1762 gptp_change_port_state(port, GPTP_PORT_DISABLED);
1763 break;
1764
1765 case GPTP_INFO_IS_AGED:
1766 bmca_data->updt_info = true;
1767 gptp_change_port_state(port, GPTP_PORT_MASTER);
1768 break;
1769
1770 case GPTP_INFO_IS_MINE:
1771 gptp_change_port_state(port, GPTP_PORT_MASTER);
1772
1773 if ((memcmp(&bmca_data->port_priority,
1774 &bmca_data->master_priority,
1775 sizeof(struct gptp_priority_vector)) != 0) ||
1776 (bmca_data->port_steps_removed !=
1777 global_ds->master_steps_removed)) {
1778 bmca_data->updt_info = true;
1779 }
1780
1781 break;
1782
1783 case GPTP_INFO_IS_RECEIVED:
1784 if (best_port == port) {
1785 /* gmPriorityVector is now derived from
1786 * portPriorityVector.
1787 */
1788 gptp_change_port_state(port, GPTP_PORT_SLAVE);
1789 bmca_data->updt_info = false;
1790 } else if (memcmp(&bmca_data->port_priority,
1791 &bmca_data->master_priority,
1792 sizeof(struct gptp_priority_vector)) <= 0) {
1793 /* The masterPriorityVector is not better than
1794 * the portPriorityVector.
1795 */
1796 gptp_change_port_state(port, GPTP_PORT_PASSIVE);
1797
1798 if (memcmp(bmca_data->port_priority.src_port_id.clk_id,
1799 default_ds->clk_id,
1800 GPTP_CLOCK_ID_LEN)) {
1801 /* The sourcePortIdentity component of
1802 * the portPriorityVector does not
1803 * reflect another port on the
1804 * time-aware system.
1805 */
1806 bmca_data->updt_info = true;
1807 } else {
1808 bmca_data->updt_info = false;
1809 }
1810 } else {
1811 gptp_change_port_state(port, GPTP_PORT_MASTER);
1812 bmca_data->updt_info = true;
1813 }
1814
1815 break;
1816 }
1817 }
1818
gptp_updt_roles_tree(void)1819 static void gptp_updt_roles_tree(void)
1820 {
1821 struct gptp_global_ds *global_ds;
1822 struct gptp_default_ds *default_ds;
1823 struct gptp_priority_vector *gm_prio, *last_gm_prio;
1824 struct gptp_port_bmca_data *bmca_data;
1825 int port, best_port;
1826
1827 global_ds = GPTP_GLOBAL_DS();
1828 default_ds = GPTP_DEFAULT_DS();
1829
1830 gm_prio = &global_ds->gm_priority;
1831 last_gm_prio = &global_ds->last_gm_priority;
1832
1833 /* Save gmPriority. */
1834 memcpy(last_gm_prio, gm_prio, sizeof(struct gptp_priority_vector));
1835
1836 best_port = compute_best_vector();
1837
1838 /* If the best vector was the systemPriorityVector. */
1839 if (best_port == 0) {
1840 /* Copy leap61, leap59, current UTC offset valid,
1841 * time traceable and frequency traceable flags.
1842 */
1843 global_ds->global_flags.octets[1] =
1844 global_ds->sys_flags.octets[1];
1845 global_ds->current_utc_offset =
1846 global_ds->sys_current_utc_offset;
1847 global_ds->time_source = global_ds->sys_time_source;
1848 global_ds->master_steps_removed = 0U;
1849 } else {
1850 bmca_data = GPTP_PORT_BMCA_DATA(best_port);
1851
1852 /* Copy leap61, leap59, current UTC offset valid,
1853 * time traceable and frequency traceable flags.
1854 */
1855 global_ds->global_flags.octets[1] =
1856 bmca_data->ann_flags.octets[1];
1857 global_ds->current_utc_offset =
1858 global_ds->sys_current_utc_offset;
1859 global_ds->time_source = bmca_data->ann_time_source;
1860 global_ds->master_steps_removed =
1861 htons(ntohs(bmca_data->message_steps_removed) + 1);
1862 }
1863
1864 for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
1865 update_bmca(port, best_port, global_ds, default_ds, gm_prio);
1866 }
1867
1868 /* Update gmPresent. */
1869 global_ds->gm_present =
1870 (gm_prio->root_system_id.grand_master_prio1 == 255U) ?
1871 false : true;
1872
1873 /* Assign the port role for port 0. */
1874 for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
1875 if (global_ds->selected_role[port] == GPTP_PORT_SLAVE) {
1876 gptp_change_port_state(0, GPTP_PORT_PASSIVE);
1877 break;
1878 }
1879 }
1880
1881 if (port == GPTP_PORT_END) {
1882 gptp_change_port_state(0, GPTP_PORT_SLAVE);
1883 }
1884
1885 /* If current system is the Grand Master, set pathTrace array. */
1886 if (memcmp(default_ds->clk_id, gm_prio->root_system_id.grand_master_id,
1887 GPTP_CLOCK_ID_LEN) == 0) {
1888 global_ds->path_trace.len = htons(GPTP_CLOCK_ID_LEN);
1889 memcpy(global_ds->path_trace.path_sequence,
1890 default_ds->clk_id, GPTP_CLOCK_ID_LEN);
1891 }
1892 }
1893
gptp_set_selected_tree(void)1894 static void gptp_set_selected_tree(void)
1895 {
1896 /* Set all the elements of the selected array to TRUE. */
1897 GPTP_GLOBAL_DS()->selected_array = ~0;
1898 }
1899
gptp_mi_port_role_selection_state_machine(void)1900 static void gptp_mi_port_role_selection_state_machine(void)
1901 {
1902 struct gptp_port_role_selection_state *state;
1903
1904 state = &GPTP_STATE()->pr_sel;
1905
1906 switch (state->state) {
1907 case GPTP_PR_SELECTION_INIT_BRIDGE:
1908 gptp_updt_role_disabled_tree();
1909 state->state = GPTP_PR_SELECTION_ROLE_SELECTION;
1910
1911 /* Be sure to enter the "if" statement immediately after. */
1912 GPTP_GLOBAL_DS()->reselect_array = ~0;
1913 __fallthrough;
1914
1915 case GPTP_PR_SELECTION_ROLE_SELECTION:
1916 if (GPTP_GLOBAL_DS()->reselect_array != 0) {
1917 gptp_clear_reselect_tree();
1918 gptp_updt_roles_tree();
1919 gptp_set_selected_tree();
1920 }
1921
1922 break;
1923 }
1924 }
1925
tx_announce(int port)1926 static void tx_announce(int port)
1927 {
1928 struct net_pkt *pkt;
1929
1930 pkt = gptp_prepare_announce(port);
1931 if (pkt) {
1932 gptp_send_announce(port, pkt);
1933 }
1934 }
1935
gptp_mi_port_announce_transmit_state_machine(int port)1936 static void gptp_mi_port_announce_transmit_state_machine(int port)
1937 {
1938 struct gptp_port_ds *port_ds;
1939 struct gptp_global_ds *global_ds;
1940 struct gptp_port_announce_transmit_state *state;
1941 struct gptp_port_bmca_data *bmca_data;
1942
1943 port_ds = GPTP_PORT_DS(port);
1944 global_ds = GPTP_GLOBAL_DS();
1945 bmca_data = GPTP_PORT_BMCA_DATA(port);
1946 state = &GPTP_PORT_STATE(port)->pa_transmit;
1947
1948 /* Reset interval as defined in AnnounceIntervalSetting
1949 * state machine.
1950 */
1951 if (port_ds->ptt_port_enabled && !port_ds->prev_ptt_port_enabled) {
1952 gptp_update_announce_interval(port, GPTP_ITV_SET_TO_INIT);
1953 }
1954
1955 switch (state->state) {
1956 case GPTP_PA_TRANSMIT_INIT:
1957 bmca_data->new_info = true;
1958 __fallthrough;
1959
1960 case GPTP_PA_TRANSMIT_IDLE:
1961 k_timer_stop(&state->ann_send_periodic_timer);
1962 state->ann_trigger = false;
1963 k_timer_start(&state->ann_send_periodic_timer,
1964 K_MSEC(gptp_uscaled_ns_to_timer_ms(
1965 &bmca_data->announce_interval)),
1966 K_NO_WAIT);
1967
1968 state->state = GPTP_PA_TRANSMIT_POST_IDLE;
1969 __fallthrough;
1970
1971 case GPTP_PA_TRANSMIT_POST_IDLE:
1972 if (IS_SELECTED(global_ds, port) &&
1973 !bmca_data->updt_info &&
1974 state->ann_trigger) {
1975
1976 state->state = GPTP_PA_TRANSMIT_PERIODIC;
1977
1978 } else if (IS_SELECTED(global_ds, port) &&
1979 !bmca_data->updt_info &&
1980 !state->ann_trigger &&
1981 (global_ds->selected_role[port] ==
1982 GPTP_PORT_MASTER) &&
1983 bmca_data->new_info) {
1984
1985 bmca_data->new_info = false;
1986 tx_announce(port);
1987 state->state = GPTP_PA_TRANSMIT_IDLE;
1988 }
1989
1990 break;
1991
1992 case GPTP_PA_TRANSMIT_PERIODIC:
1993 if (global_ds->selected_role[port] == GPTP_PORT_MASTER) {
1994 bmca_data->new_info = true;
1995 }
1996 state->state = GPTP_PA_TRANSMIT_IDLE;
1997 break;
1998 }
1999 }
2000
2001
gptp_mi_port_sync_state_machines(int port)2002 void gptp_mi_port_sync_state_machines(int port)
2003 {
2004 gptp_mi_pss_rcv_state_machine(port);
2005 gptp_mi_pss_send_state_machine(port);
2006 }
2007
gptp_mi_port_bmca_state_machines(int port)2008 void gptp_mi_port_bmca_state_machines(int port)
2009 {
2010 gptp_mi_port_announce_receive_state_machine(port);
2011 gptp_mi_port_announce_information_state_machine(port);
2012 gptp_mi_port_announce_transmit_state_machine(port);
2013 }
2014
gptp_mi_state_machines(void)2015 void gptp_mi_state_machines(void)
2016 {
2017 gptp_mi_site_sync_sync_state_machine();
2018 gptp_mi_clk_slave_sync_state_machine();
2019 gptp_mi_port_role_selection_state_machine();
2020 gptp_mi_clk_master_sync_offset_state_machine();
2021 #if defined(CONFIG_NET_GPTP_GM_CAPABLE)
2022 /*
2023 * Only call ClockMasterSyncSend state machine in case a Grand Master clock
2024 * is present and is this time aware system.
2025 * This check is not described by IEEE802.1AS. Instead, according to
2026 * 10.2.9.3, the SiteSyncSync state machine shall not take into account
2027 * information from ClockMasterSyncSend in case this time aware system is
2028 * not grand-master capable. Current implementation of ClockMasterSyncSend
2029 * state machine send sync indication to the PortSync entities, instead of
2030 * sending it to the SiteSyncSync entity. And the SiteSyncSync state machine
2031 * does not make sanity check.
2032 */
2033 if (memcmp(GPTP_GLOBAL_DS()->gm_priority.root_system_id.grand_master_id,
2034 GPTP_DEFAULT_DS()->clk_id, GPTP_CLOCK_ID_LEN) == 0 &&
2035 GPTP_GLOBAL_DS()->gm_present) {
2036 gptp_mi_clk_master_sync_snd_state_machine();
2037 }
2038 #endif
2039 gptp_mi_clk_master_sync_rcv_state_machine();
2040 }
2041