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_REGISTER(net_gptp, CONFIG_NET_GPTP_LOG_LEVEL);
9 
10 #include <zephyr/net/net_pkt.h>
11 #include <zephyr/drivers/ptp_clock.h>
12 #include <zephyr/net/ethernet_mgmt.h>
13 #include <zephyr/random/random.h>
14 
15 #include <zephyr/net/gptp.h>
16 
17 #include "gptp_messages.h"
18 #include "gptp_mi.h"
19 #include "gptp_data_set.h"
20 
21 #include "gptp_private.h"
22 
23 #if CONFIG_NET_GPTP_NUM_PORTS > 32
24 /*
25  * Boolean arrays sizes have been hardcoded.
26  * It has been arbitrary chosen that a system can not
27  * have more than 32 ports.
28  */
29 #error Maximum number of ports exceeded. (Max is 32).
30 #endif
31 
32 K_KERNEL_STACK_DEFINE(gptp_stack, CONFIG_NET_GPTP_STACK_SIZE);
33 K_FIFO_DEFINE(gptp_rx_queue);
34 
35 static k_tid_t tid;
36 static struct k_thread gptp_thread_data;
37 struct gptp_domain gptp_domain;
38 
gptp_get_port_number(struct net_if * iface)39 int gptp_get_port_number(struct net_if *iface)
40 {
41 	int port = net_eth_get_ptp_port(iface) + 1;
42 
43 	if (port >= GPTP_PORT_START && port < GPTP_PORT_END) {
44 		return port;
45 	}
46 
47 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
48 		if (GPTP_PORT_IFACE(port) == iface) {
49 			return port;
50 		}
51 	}
52 
53 	return -ENODEV;
54 }
55 
gptp_is_slave_port(int port)56 bool gptp_is_slave_port(int port)
57 {
58 	return (GPTP_GLOBAL_DS()->selected_role[port] == GPTP_PORT_SLAVE);
59 }
60 
61 /*
62  * Use the given port to generate the clock identity
63  * for the device.
64  * The clock identity is unique for one time-aware system.
65  */
gptp_compute_clock_identity(int port)66 static void gptp_compute_clock_identity(int port)
67 {
68 	struct net_if *iface = GPTP_PORT_IFACE(port);
69 	struct gptp_default_ds *default_ds;
70 
71 	default_ds = GPTP_DEFAULT_DS();
72 
73 	if (iface) {
74 		default_ds->clk_id[0] = net_if_get_link_addr(iface)->addr[0];
75 		default_ds->clk_id[1] = net_if_get_link_addr(iface)->addr[1];
76 		default_ds->clk_id[2] = net_if_get_link_addr(iface)->addr[2];
77 		default_ds->clk_id[3] = 0xFF;
78 		default_ds->clk_id[4] = 0xFE;
79 		default_ds->clk_id[5] = net_if_get_link_addr(iface)->addr[3];
80 		default_ds->clk_id[6] = net_if_get_link_addr(iface)->addr[4];
81 		default_ds->clk_id[7] = net_if_get_link_addr(iface)->addr[5];
82 	}
83 }
84 
85 #define PRINT_INFO(msg, hdr, pkt)				\
86 	NET_DBG("Received %s seq %d pkt %p", (const char *)msg,	\
87 		ntohs(hdr->sequence_id), pkt)			\
88 
89 
gptp_handle_critical_msg(struct net_if * iface,struct net_pkt * pkt)90 static bool gptp_handle_critical_msg(struct net_if *iface, struct net_pkt *pkt)
91 {
92 	struct gptp_hdr *hdr = GPTP_HDR(pkt);
93 	bool handled = false;
94 	int port;
95 
96 	switch (hdr->message_type) {
97 	case GPTP_PATH_DELAY_REQ_MESSAGE:
98 		if (GPTP_CHECK_LEN(pkt, GPTP_PDELAY_REQ_LEN)) {
99 			NET_WARN("Invalid length for %s packet "
100 				 "should have %zd bytes but has %zd bytes",
101 				 "PDELAY_REQ",
102 				 GPTP_PDELAY_REQ_LEN,
103 				 GPTP_PACKET_LEN(pkt));
104 			break;
105 		}
106 
107 		PRINT_INFO("PDELAY_REQ", hdr, pkt);
108 
109 		port = gptp_get_port_number(iface);
110 		if (port == -ENODEV) {
111 			NET_DBG("No port found for gPTP buffer");
112 			return handled;
113 		}
114 
115 		if (GPTP_PORT_STATE(port)->pdelay_resp.state !=
116 						GPTP_PDELAY_RESP_NOT_ENABLED) {
117 			gptp_handle_pdelay_req(port, pkt);
118 		}
119 
120 		handled = true;
121 		break;
122 	default:
123 		/* Not a critical message, this will be handled later. */
124 		break;
125 	}
126 
127 	return handled;
128 }
129 
gptp_handle_msg(struct net_pkt * pkt)130 static void gptp_handle_msg(struct net_pkt *pkt)
131 {
132 	struct gptp_hdr *hdr = GPTP_HDR(pkt);
133 	struct gptp_pdelay_req_state *pdelay_req_state;
134 	struct gptp_sync_rcv_state *sync_rcv_state;
135 	struct gptp_port_announce_receive_state *pa_rcv_state;
136 	struct gptp_port_bmca_data *bmca_data;
137 	int port;
138 
139 	port = gptp_get_port_number(net_pkt_iface(pkt));
140 	if (port == -ENODEV) {
141 		NET_DBG("No port found for ptp buffer");
142 		return;
143 	}
144 
145 	pdelay_req_state = &GPTP_PORT_STATE(port)->pdelay_req;
146 	sync_rcv_state = &GPTP_PORT_STATE(port)->sync_rcv;
147 
148 	switch (hdr->message_type) {
149 	case GPTP_SYNC_MESSAGE:
150 		if (GPTP_CHECK_LEN(pkt, GPTP_SYNC_LEN)) {
151 			NET_WARN("Invalid length for %s packet "
152 				 "should have %zd bytes but has %zd bytes",
153 				 "SYNC",
154 				 GPTP_SYNC_LEN,
155 				 GPTP_PACKET_LEN(pkt));
156 			GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
157 			break;
158 		}
159 
160 		PRINT_INFO("SYNC", hdr, pkt);
161 
162 		sync_rcv_state->rcvd_sync = true;
163 
164 		/* If we already have one, drop the previous one. */
165 		if (sync_rcv_state->rcvd_sync_ptr) {
166 			net_pkt_unref(sync_rcv_state->rcvd_sync_ptr);
167 		}
168 
169 		/* Keep the buffer alive until follow_up is received. */
170 		net_pkt_ref(pkt);
171 		sync_rcv_state->rcvd_sync_ptr = pkt;
172 
173 		GPTP_STATS_INC(port, rx_sync_count);
174 		break;
175 
176 	case GPTP_DELAY_REQ_MESSAGE:
177 		NET_DBG("Delay Request not handled.");
178 		break;
179 
180 	case GPTP_PATH_DELAY_REQ_MESSAGE:
181 		/*
182 		 * Path Delay Responses to Path Delay Requests need
183 		 * very low latency. These need to handled in priority
184 		 * when received as they cannot afford to be delayed
185 		 * by context switches.
186 		 */
187 		NET_WARN("Path Delay Request received as normal messages!");
188 		GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
189 		break;
190 
191 	case GPTP_PATH_DELAY_RESP_MESSAGE:
192 		if (GPTP_CHECK_LEN(pkt, GPTP_PDELAY_RESP_LEN)) {
193 			NET_WARN("Invalid length for %s packet "
194 				 "should have %zd bytes but has %zd bytes",
195 				 "PDELAY_RESP",
196 				 GPTP_PDELAY_RESP_LEN,
197 				 GPTP_PACKET_LEN(pkt));
198 			GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
199 			break;
200 		}
201 
202 		PRINT_INFO("PDELAY_RESP", hdr, pkt);
203 
204 		pdelay_req_state->rcvd_pdelay_resp++;
205 
206 		/* If we already have one, drop the received one. */
207 		if (pdelay_req_state->rcvd_pdelay_resp_ptr) {
208 			break;
209 		}
210 
211 		/* Keep the buffer alive until pdelay_rate_ratio is computed. */
212 		net_pkt_ref(pkt);
213 		pdelay_req_state->rcvd_pdelay_resp_ptr = pkt;
214 		break;
215 
216 	case GPTP_FOLLOWUP_MESSAGE:
217 		if (GPTP_CHECK_LEN(pkt, GPTP_FOLLOW_UP_LEN)) {
218 			NET_WARN("Invalid length for %s packet "
219 				 "should have %zd bytes but has %zd bytes",
220 				 "FOLLOWUP",
221 				 GPTP_FOLLOW_UP_LEN,
222 				 GPTP_PACKET_LEN(pkt));
223 			GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
224 			break;
225 		}
226 
227 		PRINT_INFO("FOLLOWUP", hdr, pkt);
228 
229 		sync_rcv_state->rcvd_follow_up = true;
230 
231 		/* If we already have one, drop the previous one. */
232 		if (sync_rcv_state->rcvd_follow_up_ptr) {
233 			net_pkt_unref(sync_rcv_state->rcvd_follow_up_ptr);
234 		}
235 
236 		/* Keep the pkt alive until info is extracted. */
237 		sync_rcv_state->rcvd_follow_up_ptr = net_pkt_ref(pkt);
238 		NET_DBG("Keeping %s seq %d pkt %p", "FOLLOWUP",
239 			ntohs(hdr->sequence_id), pkt);
240 		break;
241 
242 	case GPTP_PATH_DELAY_FOLLOWUP_MESSAGE:
243 		if (GPTP_CHECK_LEN(pkt, GPTP_PDELAY_RESP_FUP_LEN)) {
244 			NET_WARN("Invalid length for %s packet "
245 				 "should have %zd bytes but has %zd bytes",
246 				 "PDELAY_FOLLOWUP",
247 				 GPTP_PDELAY_RESP_FUP_LEN,
248 				 GPTP_PACKET_LEN(pkt));
249 			GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
250 			break;
251 		}
252 
253 		PRINT_INFO("PDELAY_FOLLOWUP", hdr, pkt);
254 
255 		pdelay_req_state->rcvd_pdelay_follow_up++;
256 
257 		/* If we already have one, drop the received one. */
258 		if (pdelay_req_state->rcvd_pdelay_follow_up_ptr) {
259 			break;
260 		}
261 
262 		/* Keep the buffer alive until pdelay_rate_ratio is computed. */
263 		net_pkt_ref(pkt);
264 		pdelay_req_state->rcvd_pdelay_follow_up_ptr = pkt;
265 
266 		GPTP_STATS_INC(port, rx_pdelay_resp_fup_count);
267 		break;
268 
269 	case GPTP_ANNOUNCE_MESSAGE:
270 		if (GPTP_ANNOUNCE_CHECK_LEN(pkt)) {
271 			NET_WARN("Invalid length for %s packet "
272 				 "should have %zd bytes but has %zd bytes",
273 				 "ANNOUNCE",
274 				 GPTP_ANNOUNCE_LEN(pkt),
275 				 GPTP_PACKET_LEN(pkt));
276 			GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
277 			break;
278 		}
279 
280 		PRINT_INFO("ANNOUNCE", hdr, pkt);
281 
282 		pa_rcv_state = &GPTP_PORT_STATE(port)->pa_rcv;
283 		bmca_data = GPTP_PORT_BMCA_DATA(port);
284 
285 		if (pa_rcv_state->rcvd_announce == false &&
286 				bmca_data->rcvd_announce_ptr == NULL) {
287 			pa_rcv_state->rcvd_announce = true;
288 			bmca_data->rcvd_announce_ptr = pkt;
289 			net_pkt_ref(pkt);
290 		}
291 
292 		GPTP_STATS_INC(port, rx_announce_count);
293 		break;
294 
295 	case GPTP_SIGNALING_MESSAGE:
296 		if (GPTP_CHECK_LEN(pkt, GPTP_SIGNALING_LEN)) {
297 			NET_WARN("Invalid length for %s packet "
298 				 "should have %zd bytes but has %zd bytes",
299 				 "SIGNALING",
300 				 GPTP_SIGNALING_LEN,
301 				 GPTP_PACKET_LEN(pkt));
302 			GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
303 			break;
304 		}
305 
306 		PRINT_INFO("SIGNALING", hdr, pkt);
307 
308 		gptp_handle_signaling(port, pkt);
309 		break;
310 
311 	case GPTP_MANAGEMENT_MESSAGE:
312 		PRINT_INFO("MANAGEMENT", hdr, pkt);
313 		GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
314 		break;
315 
316 	default:
317 		NET_DBG("Received unknown message %x", hdr->message_type);
318 		GPTP_STATS_INC(port, rx_ptp_packet_discard_count);
319 		break;
320 	}
321 }
322 
net_gptp_recv(struct net_if * iface,uint16_t ptype,struct net_pkt * pkt)323 static enum net_verdict net_gptp_recv(struct net_if *iface, uint16_t ptype,
324 				      struct net_pkt *pkt)
325 {
326 	struct gptp_hdr *hdr = GPTP_HDR(pkt);
327 
328 	ARG_UNUSED(ptype);
329 
330 	if (!(net_eth_is_addr_ptp_multicast(
331 		      (struct net_eth_addr *)net_pkt_lladdr_dst(pkt)->addr) ||
332 	      net_eth_is_addr_lldp_multicast(
333 		      (struct net_eth_addr *)net_pkt_lladdr_dst(pkt)->addr))) {
334 		return NET_DROP;
335 	}
336 
337 	if ((hdr->ptp_version != GPTP_VERSION) ||
338 			(hdr->transport_specific != GPTP_TRANSPORT_802_1_AS)) {
339 		/* The stack only supports PTP V2 and transportSpecific set
340 		 * to 1 with IEEE802.1AS-2011.
341 		 */
342 		return NET_DROP;
343 	}
344 
345 	/* Handle critical messages. */
346 	if (!gptp_handle_critical_msg(iface, pkt)) {
347 		k_fifo_put(&gptp_rx_queue, pkt);
348 
349 		/* Returning OK here makes sure the network statistics are
350 		 * properly updated.
351 		 */
352 		return NET_OK;
353 	}
354 
355 	/* Message not propagated up in the stack. */
356 	return NET_DROP;
357 }
358 
359 ETH_NET_L3_REGISTER(gPTP, NET_ETH_PTYPE_PTP, net_gptp_recv);
360 
gptp_init_clock_ds(void)361 static void gptp_init_clock_ds(void)
362 {
363 	struct gptp_global_ds *global_ds;
364 	struct gptp_default_ds *default_ds;
365 	struct gptp_current_ds *current_ds;
366 	struct gptp_parent_ds *parent_ds;
367 	struct gptp_time_prop_ds *prop_ds;
368 
369 	global_ds = GPTP_GLOBAL_DS();
370 	default_ds = GPTP_DEFAULT_DS();
371 	current_ds = GPTP_CURRENT_DS();
372 	parent_ds = GPTP_PARENT_DS();
373 	prop_ds = GPTP_PROPERTIES_DS();
374 
375 	/* Initialize global data set. */
376 	(void)memset(global_ds, 0, sizeof(struct gptp_global_ds));
377 
378 	/* Initialize default data set. */
379 
380 	/* Compute the clock identity from the first port MAC address. */
381 	gptp_compute_clock_identity(GPTP_PORT_START);
382 
383 	default_ds->gm_capable = IS_ENABLED(CONFIG_NET_GPTP_GM_CAPABLE);
384 	default_ds->clk_quality.clock_class = GPTP_CLASS_OTHER;
385 	default_ds->clk_quality.clock_accuracy =
386 		CONFIG_NET_GPTP_CLOCK_ACCURACY;
387 	default_ds->clk_quality.offset_scaled_log_var =
388 		GPTP_OFFSET_SCALED_LOG_VAR_UNKNOWN;
389 
390 	if (default_ds->gm_capable) {
391 		/* The priority1 value cannot be 255 for GM capable
392 		 * system.
393 		 */
394 		if (CONFIG_NET_GPTP_BMCA_PRIORITY1 ==
395 		    GPTP_PRIORITY1_NON_GM_CAPABLE) {
396 			default_ds->priority1 = GPTP_PRIORITY1_GM_CAPABLE;
397 		} else {
398 			default_ds->priority1 = CONFIG_NET_GPTP_BMCA_PRIORITY1;
399 		}
400 	} else {
401 		default_ds->priority1 = GPTP_PRIORITY1_NON_GM_CAPABLE;
402 	}
403 
404 	default_ds->priority2 = GPTP_PRIORITY2_DEFAULT;
405 
406 	default_ds->cur_utc_offset = 37U; /* Current leap seconds TAI - UTC */
407 	default_ds->flags.all = 0U;
408 	default_ds->flags.octets[1] = GPTP_FLAG_TIME_TRACEABLE;
409 	default_ds->time_source = GPTP_TS_INTERNAL_OSCILLATOR;
410 
411 	/* Initialize current data set. */
412 	(void)memset(current_ds, 0, sizeof(struct gptp_current_ds));
413 
414 	/* Initialize parent data set. */
415 
416 	/* parent clock id is initialized to default_ds clock id. */
417 	memcpy(parent_ds->port_id.clk_id, default_ds->clk_id,
418 	       GPTP_CLOCK_ID_LEN);
419 	memcpy(parent_ds->gm_id, default_ds->clk_id, GPTP_CLOCK_ID_LEN);
420 	parent_ds->port_id.port_number = 0U;
421 
422 	/* TODO: Check correct value for below field. */
423 	parent_ds->cumulative_rate_ratio = 0;
424 
425 	parent_ds->gm_clk_quality.clock_class =
426 		default_ds->clk_quality.clock_class;
427 	parent_ds->gm_clk_quality.clock_accuracy =
428 		default_ds->clk_quality.clock_accuracy;
429 	parent_ds->gm_clk_quality.offset_scaled_log_var =
430 		default_ds->clk_quality.offset_scaled_log_var;
431 	parent_ds->gm_priority1 = default_ds->priority1;
432 	parent_ds->gm_priority2 = default_ds->priority2;
433 
434 	/* Initialize properties data set. */
435 
436 	/* TODO: Get accurate values for below. From the GM. */
437 	prop_ds->cur_utc_offset = 37U; /* Current leap seconds TAI - UTC */
438 	prop_ds->cur_utc_offset_valid = false;
439 	prop_ds->leap59 = false;
440 	prop_ds->leap61 = false;
441 	prop_ds->time_traceable = false;
442 	prop_ds->freq_traceable = false;
443 	prop_ds->time_source = GPTP_TS_INTERNAL_OSCILLATOR;
444 
445 	/* Set system values. */
446 	global_ds->sys_flags.all = default_ds->flags.all;
447 	global_ds->sys_current_utc_offset = default_ds->cur_utc_offset;
448 	global_ds->sys_time_source = default_ds->time_source;
449 	global_ds->clk_master_sync_itv =
450 		NSEC_PER_SEC * GPTP_POW2(CONFIG_NET_GPTP_INIT_LOG_SYNC_ITV);
451 }
452 
gptp_init_port_ds(int port)453 static void gptp_init_port_ds(int port)
454 {
455 	struct gptp_default_ds *default_ds;
456 	struct gptp_port_ds *port_ds;
457 
458 #if defined(CONFIG_NET_GPTP_STATISTICS)
459 	struct gptp_port_param_ds *port_param_ds;
460 
461 	port_param_ds = GPTP_PORT_PARAM_DS(port);
462 #endif
463 
464 	default_ds = GPTP_DEFAULT_DS();
465 	port_ds = GPTP_PORT_DS(port);
466 
467 	/* Initialize port data set. */
468 	memcpy(port_ds->port_id.clk_id, default_ds->clk_id, GPTP_CLOCK_ID_LEN);
469 	port_ds->port_id.port_number = port;
470 
471 	port_ds->ptt_port_enabled = true;
472 	port_ds->prev_ptt_port_enabled = true;
473 
474 	port_ds->neighbor_prop_delay = 0;
475 	port_ds->neighbor_prop_delay_thresh = GPTP_NEIGHBOR_PROP_DELAY_THR;
476 	port_ds->delay_asymmetry = 0;
477 
478 	port_ds->ini_log_announce_itv = CONFIG_NET_GPTP_INIT_LOG_ANNOUNCE_ITV;
479 	port_ds->cur_log_announce_itv = port_ds->ini_log_announce_itv;
480 	port_ds->announce_receipt_timeout =
481 		CONFIG_NET_GPTP_ANNOUNCE_RECEIPT_TIMEOUT;
482 
483 	/* Subtract 1 to divide by 2 the sync interval. */
484 	port_ds->ini_log_half_sync_itv = CONFIG_NET_GPTP_INIT_LOG_SYNC_ITV - 1;
485 	port_ds->cur_log_half_sync_itv = port_ds->ini_log_half_sync_itv;
486 	port_ds->sync_receipt_timeout = CONFIG_NET_GPTP_SYNC_RECEIPT_TIMEOUT;
487 	port_ds->sync_receipt_timeout_time_itv = 10000000U; /* 10ms */
488 
489 	port_ds->ini_log_pdelay_req_itv =
490 		CONFIG_NET_GPTP_INIT_LOG_PDELAY_REQ_ITV;
491 	port_ds->cur_log_pdelay_req_itv = port_ds->ini_log_pdelay_req_itv;
492 	port_ds->allowed_lost_responses = GPTP_ALLOWED_LOST_RESP;
493 	port_ds->version = GPTP_VERSION;
494 
495 	gptp_set_time_itv(&port_ds->pdelay_req_itv, 1,
496 			  port_ds->cur_log_pdelay_req_itv);
497 
498 	gptp_set_time_itv(&port_ds->half_sync_itv, 1,
499 			  port_ds->cur_log_half_sync_itv);
500 
501 	port_ds->compute_neighbor_rate_ratio = true;
502 	port_ds->compute_neighbor_prop_delay = true;
503 
504 	/* Random Sequence Numbers. */
505 	port_ds->sync_seq_id = sys_rand16_get();
506 	port_ds->pdelay_req_seq_id = sys_rand16_get();
507 	port_ds->announce_seq_id = sys_rand16_get();
508 	port_ds->signaling_seq_id = sys_rand16_get();
509 
510 #if defined(CONFIG_NET_GPTP_STATISTICS)
511 	/* Initialize stats data set. */
512 	(void)memset(port_param_ds, 0, sizeof(struct gptp_port_param_ds));
513 #endif
514 }
515 
gptp_init_state_machine(void)516 static void gptp_init_state_machine(void)
517 {
518 	gptp_md_init_state_machine();
519 	gptp_mi_init_state_machine();
520 }
521 
gptp_state_machine(void)522 static void gptp_state_machine(void)
523 {
524 	int port;
525 
526 	/* Manage port states. */
527 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
528 		struct gptp_port_ds *port_ds = GPTP_PORT_DS(port);
529 
530 		/* If interface is down, don't move forward */
531 		if (net_if_flag_is_set(GPTP_PORT_IFACE(port), NET_IF_UP)) {
532 			switch (GPTP_GLOBAL_DS()->selected_role[port]) {
533 			case GPTP_PORT_DISABLED:
534 			case GPTP_PORT_MASTER:
535 			case GPTP_PORT_PASSIVE:
536 			case GPTP_PORT_SLAVE:
537 				gptp_md_state_machines(port);
538 				gptp_mi_port_sync_state_machines(port);
539 				gptp_mi_port_bmca_state_machines(port);
540 				break;
541 			default:
542 				NET_DBG("%s: Unknown port state", __func__);
543 				break;
544 			}
545 		} else {
546 			GPTP_GLOBAL_DS()->selected_role[port] = GPTP_PORT_DISABLED;
547 		}
548 
549 		port_ds->prev_ptt_port_enabled = port_ds->ptt_port_enabled;
550 	}
551 
552 	gptp_mi_state_machines();
553 }
554 
gptp_thread(void * p1,void * p2,void * p3)555 static void gptp_thread(void *p1, void *p2, void *p3)
556 {
557 	ARG_UNUSED(p1);
558 	ARG_UNUSED(p2);
559 	ARG_UNUSED(p3);
560 
561 	int port;
562 
563 	NET_DBG("Starting PTP thread");
564 
565 	gptp_init_clock_ds();
566 
567 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
568 		gptp_init_port_ds(port);
569 		gptp_change_port_state(port, GPTP_PORT_DISABLED);
570 	}
571 
572 	while (1) {
573 		struct net_pkt *pkt;
574 
575 		pkt = k_fifo_get(&gptp_rx_queue,
576 				 K_MSEC(GPTP_THREAD_WAIT_TIMEOUT_MS));
577 		if (pkt) {
578 			gptp_handle_msg(pkt);
579 			net_pkt_unref(pkt);
580 		}
581 
582 		gptp_state_machine();
583 	}
584 }
585 
586 
gptp_add_port(struct net_if * iface,void * user_data)587 static void gptp_add_port(struct net_if *iface, void *user_data)
588 {
589 	int *num_ports = user_data;
590 	const struct device *clk;
591 
592 	if (*num_ports >= CONFIG_NET_GPTP_NUM_PORTS) {
593 		return;
594 	}
595 
596 	/* Check if interface has a PTP clock. */
597 	clk = net_eth_get_ptp_clock(iface);
598 	if (clk) {
599 		gptp_domain.iface[*num_ports] = iface;
600 		net_eth_set_ptp_port(iface, *num_ports);
601 		(*num_ports)++;
602 	}
603 }
604 
gptp_set_time_itv(struct gptp_uscaled_ns * interval,uint16_t seconds,int8_t log_msg_interval)605 void gptp_set_time_itv(struct gptp_uscaled_ns *interval,
606 		       uint16_t seconds,
607 		       int8_t log_msg_interval)
608 {
609 	int i;
610 
611 	if (seconds == 0U) {
612 		interval->low = 0U;
613 		interval->high = 0U;
614 		return;
615 	} else if (log_msg_interval >= 96) {
616 		/* Overflow, set maximum. */
617 		interval->low = UINT64_MAX;
618 		interval->high = UINT32_MAX;
619 
620 		return;
621 	} else if (log_msg_interval <= -64) {
622 		/* Underflow, set to 0. */
623 		interval->low = 0U;
624 		interval->high = 0U;
625 		return;
626 	}
627 
628 
629 	/* NSEC_PER_SEC is between 2^30 and 2^31, seconds is less than 2^16,
630 	 * thus the computation will be less than 2^63.
631 	 */
632 	interval->low =	(seconds * (uint64_t)NSEC_PER_SEC) << 16;
633 
634 	if (log_msg_interval <= 0) {
635 		interval->low >>= -log_msg_interval;
636 		interval->high = 0U;
637 	} else {
638 		/* Find highest bit set. */
639 		for (i = 63; i >= 0; i--) {
640 			if (interval->low >> i) {
641 				break;
642 			}
643 		}
644 
645 		if ((i + log_msg_interval) >= 96 || log_msg_interval > 64) {
646 			/* Overflow, set maximum. */
647 			interval->low = UINT64_MAX;
648 			interval->high = UINT32_MAX;
649 		} else {
650 			interval->high =
651 				interval->low >> (64 - log_msg_interval);
652 
653 			/* << operator is undefined if the shift value is equal
654 			 * to the number of bits in the left expression’s type
655 			 */
656 			if (log_msg_interval == 64) {
657 				interval->low = 0U;
658 			} else {
659 				interval->low <<= log_msg_interval;
660 			}
661 		}
662 	}
663 }
664 
gptp_uscaled_ns_to_timer_ms(struct gptp_uscaled_ns * usns)665 int32_t gptp_uscaled_ns_to_timer_ms(struct gptp_uscaled_ns *usns)
666 {
667 	uint64_t tmp;
668 
669 	if (usns->high) {
670 		/* Do not calculate, it reaches max value. */
671 		return INT32_MAX;
672 	}
673 
674 	tmp = (usns->low >> 16) / USEC_PER_SEC;
675 	if (tmp == 0U) {
676 		/* Timer must be started with a minimum value of 1. */
677 		return 1;
678 	}
679 
680 	if (tmp > INT32_MAX) {
681 		return INT32_MAX;
682 	}
683 
684 	return (tmp & INT32_MAX);
685 
686 }
687 
timer_get_remaining_and_stop(struct k_timer * timer)688 static int32_t timer_get_remaining_and_stop(struct k_timer *timer)
689 {
690 	unsigned int key;
691 	int32_t timer_value;
692 
693 	key = irq_lock();
694 	timer_value = k_timer_remaining_get(timer);
695 
696 	/* Stop timer as the period is about to be modified. */
697 	k_timer_stop(timer);
698 	irq_unlock(key);
699 
700 	return timer_value;
701 }
702 
update_itv(struct gptp_uscaled_ns * itv,int8_t * cur_log_itv,int8_t * ini_log_itv,int8_t new_log_itv,int8_t correction_log_itv)703 static int32_t update_itv(struct gptp_uscaled_ns *itv,
704 			 int8_t *cur_log_itv,
705 			 int8_t *ini_log_itv,
706 			 int8_t new_log_itv,
707 			 int8_t correction_log_itv)
708 {
709 	switch (new_log_itv) {
710 	case GPTP_ITV_KEEP:
711 		break;
712 	case GPTP_ITV_SET_TO_INIT:
713 		*cur_log_itv = *ini_log_itv;
714 		gptp_set_time_itv(itv, 1, *ini_log_itv);
715 		break;
716 	case GPTP_ITV_STOP:
717 	default:
718 		*cur_log_itv = new_log_itv + correction_log_itv;
719 		gptp_set_time_itv(itv, 1, *cur_log_itv);
720 		break;
721 	}
722 
723 	return gptp_uscaled_ns_to_timer_ms(itv);
724 }
725 
gptp_update_pdelay_req_interval(int port,int8_t log_val)726 void gptp_update_pdelay_req_interval(int port, int8_t log_val)
727 {
728 	int32_t remaining;
729 	int32_t new_itv, old_itv;
730 	struct gptp_pdelay_req_state *state_pdelay;
731 	struct gptp_port_ds *port_ds;
732 
733 	port_ds = GPTP_PORT_DS(port);
734 	state_pdelay = &GPTP_PORT_STATE(port)->pdelay_req;
735 	remaining = timer_get_remaining_and_stop(&state_pdelay->pdelay_timer);
736 
737 	old_itv = gptp_uscaled_ns_to_timer_ms(&port_ds->pdelay_req_itv);
738 	new_itv = update_itv(&port_ds->pdelay_req_itv,
739 			     &port_ds->cur_log_pdelay_req_itv,
740 			     &port_ds->ini_log_pdelay_req_itv,
741 			     log_val,
742 			     0);
743 
744 	new_itv -= (old_itv-remaining);
745 	if (new_itv <= 0) {
746 		new_itv = 1;
747 	}
748 
749 	k_timer_start(&state_pdelay->pdelay_timer, K_MSEC(new_itv), K_NO_WAIT);
750 }
751 
gptp_update_sync_interval(int port,int8_t log_val)752 void gptp_update_sync_interval(int port, int8_t log_val)
753 {
754 	struct gptp_pss_send_state *state_pss_send;
755 	struct gptp_port_ds *port_ds;
756 	int32_t new_itv, old_itv, period;
757 	int32_t remaining;
758 	uint32_t time_spent;
759 
760 	port_ds = GPTP_PORT_DS(port);
761 	state_pss_send = &GPTP_PORT_STATE(port)->pss_send;
762 	remaining =
763 		timer_get_remaining_and_stop(
764 				&state_pss_send->half_sync_itv_timer);
765 	old_itv = gptp_uscaled_ns_to_timer_ms(&port_ds->half_sync_itv);
766 	new_itv = update_itv(&port_ds->half_sync_itv,
767 			     &port_ds->cur_log_half_sync_itv,
768 			     &port_ds->ini_log_half_sync_itv,
769 			     log_val,
770 			     -1);
771 	period = new_itv;
772 
773 	/* Get the time spent from the start of the timer. */
774 	time_spent = old_itv;
775 	if (state_pss_send->half_sync_itv_timer_expired) {
776 		time_spent *= 2U;
777 	}
778 	time_spent -= remaining;
779 
780 	/* Calculate remaining time and if half timer has expired. */
781 	if ((time_spent / 2U) > new_itv) {
782 		state_pss_send->sync_itv_timer_expired = true;
783 		state_pss_send->half_sync_itv_timer_expired = true;
784 		new_itv = 1;
785 	} else if (time_spent > new_itv) {
786 		state_pss_send->sync_itv_timer_expired = false;
787 		state_pss_send->half_sync_itv_timer_expired = true;
788 		new_itv -= (time_spent - new_itv);
789 	} else {
790 		state_pss_send->sync_itv_timer_expired = false;
791 		state_pss_send->half_sync_itv_timer_expired = false;
792 		new_itv -= time_spent;
793 	}
794 
795 	if (new_itv <= 0) {
796 		new_itv = 1;
797 	}
798 
799 	k_timer_start(&state_pss_send->half_sync_itv_timer, K_MSEC(new_itv),
800 		      K_MSEC(period));
801 }
802 
gptp_update_announce_interval(int port,int8_t log_val)803 void gptp_update_announce_interval(int port, int8_t log_val)
804 {
805 	int32_t remaining;
806 	int32_t new_itv, old_itv;
807 	struct gptp_port_announce_transmit_state *state_ann;
808 	struct gptp_port_bmca_data *bmca_data;
809 	struct gptp_port_ds *port_ds;
810 
811 	port_ds = GPTP_PORT_DS(port);
812 	state_ann = &GPTP_PORT_STATE(port)->pa_transmit;
813 	bmca_data = GPTP_PORT_BMCA_DATA(port);
814 	remaining = timer_get_remaining_and_stop(
815 			&state_ann->ann_send_periodic_timer);
816 
817 	old_itv = gptp_uscaled_ns_to_timer_ms(&bmca_data->announce_interval);
818 	new_itv = update_itv(&bmca_data->announce_interval,
819 			     &port_ds->cur_log_announce_itv,
820 			     &port_ds->ini_log_announce_itv,
821 			     log_val,
822 			     0);
823 
824 	new_itv -= (old_itv-remaining);
825 	if (new_itv <= 0) {
826 		new_itv = 1;
827 	}
828 
829 	k_timer_start(&state_ann->ann_send_periodic_timer, K_MSEC(new_itv),
830 		      K_NO_WAIT);
831 }
832 
833 struct port_user_data {
834 	gptp_port_cb_t cb;
835 	void *user_data;
836 };
837 
gptp_get_port(struct net_if * iface,void * user_data)838 static void gptp_get_port(struct net_if *iface, void *user_data)
839 {
840 	struct port_user_data *ud = user_data;
841 	const struct device *clk;
842 
843 	/* Check if interface has a PTP clock. */
844 	clk = net_eth_get_ptp_clock(iface);
845 	if (clk) {
846 		int port = gptp_get_port_number(iface);
847 
848 		if (port < 0) {
849 			return;
850 		}
851 
852 		ud->cb(port, iface, ud->user_data);
853 	}
854 }
855 
gptp_foreach_port(gptp_port_cb_t cb,void * user_data)856 void gptp_foreach_port(gptp_port_cb_t cb, void *user_data)
857 {
858 	struct port_user_data ud = {
859 		.cb = cb,
860 		.user_data = user_data
861 	};
862 
863 	net_if_foreach(gptp_get_port, &ud);
864 }
865 
gptp_get_domain(void)866 struct gptp_domain *gptp_get_domain(void)
867 {
868 	return &gptp_domain;
869 }
870 
gptp_get_port_data(struct gptp_domain * domain,int port,struct gptp_port_ds ** port_ds,struct gptp_port_param_ds ** port_param_ds,struct gptp_port_states ** port_state,struct gptp_port_bmca_data ** port_bmca_data,struct net_if ** iface)871 int gptp_get_port_data(struct gptp_domain *domain,
872 		       int port,
873 		       struct gptp_port_ds **port_ds,
874 		       struct gptp_port_param_ds **port_param_ds,
875 		       struct gptp_port_states **port_state,
876 		       struct gptp_port_bmca_data **port_bmca_data,
877 		       struct net_if **iface)
878 {
879 	if (domain != &gptp_domain) {
880 		return -ENOENT;
881 	}
882 
883 	if (port < GPTP_PORT_START || port >= GPTP_PORT_END) {
884 		return -EINVAL;
885 	}
886 
887 	if (port_ds) {
888 		*port_ds = GPTP_PORT_DS(port);
889 	}
890 
891 	if (port_param_ds) {
892 #if defined(CONFIG_NET_GPTP_STATISTICS)
893 		*port_param_ds = GPTP_PORT_PARAM_DS(port);
894 #else
895 		*port_param_ds = NULL;
896 #endif
897 	}
898 
899 	if (port_state) {
900 		*port_state = GPTP_PORT_STATE(port);
901 	}
902 
903 	if (port_bmca_data) {
904 		*port_bmca_data = GPTP_PORT_BMCA_DATA(port);
905 	}
906 
907 	if (iface) {
908 		*iface = GPTP_PORT_IFACE(port);
909 	}
910 
911 	return 0;
912 }
913 
init_ports(void)914 static void init_ports(void)
915 {
916 	net_if_foreach(gptp_add_port, &gptp_domain.default_ds.nb_ports);
917 
918 	/* Only initialize the state machine once the ports are known. */
919 	gptp_init_state_machine();
920 
921 	tid = k_thread_create(&gptp_thread_data, gptp_stack,
922 			      K_KERNEL_STACK_SIZEOF(gptp_stack),
923 			      gptp_thread,
924 			      NULL, NULL, NULL, K_PRIO_COOP(5), 0, K_NO_WAIT);
925 	k_thread_name_set(&gptp_thread_data, "gptp");
926 }
927 
net_gptp_init(void)928 void net_gptp_init(void)
929 {
930 	gptp_domain.default_ds.nb_ports = 0U;
931 
932 	init_ports();
933 }
934