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/net/net_if.h>
11
12 #include "gptp_messages.h"
13 #include "gptp_data_set.h"
14 #include "gptp_md.h"
15 #include "gptp_private.h"
16
17 #define NET_BUF_TIMEOUT K_MSEC(100)
18
19 static struct net_if_timestamp_cb sync_timestamp_cb;
20 static struct net_if_timestamp_cb pdelay_response_timestamp_cb;
21 static bool sync_cb_registered;
22 static bool ts_cb_registered;
23
24 static const struct net_eth_addr gptp_multicast_eth_addr = {
25 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e } };
26
27 #define NET_GPTP_INFO(msg, pkt) \
28 if (CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG) { \
29 struct gptp_hdr *hdr = GPTP_HDR(pkt); \
30 \
31 if (hdr->message_type == GPTP_ANNOUNCE_MESSAGE) { \
32 struct gptp_announce *ann = GPTP_ANNOUNCE(pkt); \
33 char output[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")]; \
34 \
35 gptp_sprint_clock_id( \
36 ann->root_system_id.grand_master_id, \
37 output, \
38 sizeof(output)); \
39 \
40 NET_DBG("Sending %s seq %d pkt %p", \
41 msg, \
42 ntohs(hdr->sequence_id), pkt); \
43 \
44 NET_DBG(" GM %d/%d/0x%x/%d/%s",\
45 ann->root_system_id.grand_master_prio1, \
46 ann->root_system_id.clk_quality.clock_class, \
47 ann->root_system_id.clk_quality.clock_accuracy,\
48 ann->root_system_id.grand_master_prio2, \
49 output); \
50 } else { \
51 NET_DBG("Sending %s seq %d pkt %p", \
52 msg, \
53 ntohs(hdr->sequence_id), pkt); \
54 } \
55 }
56
gptp_get_hdr(struct net_pkt * pkt)57 struct gptp_hdr *gptp_get_hdr(struct net_pkt *pkt)
58 {
59 struct net_buf *buf = pkt->frags;
60
61 NET_ASSERT(buf);
62
63 if (sizeof(struct gptp_hdr) <= buf->len) {
64 return (struct gptp_hdr *)buf->data;
65 }
66
67 /* Check if there is a link layer buf in the front and skip it
68 * if needed.
69 */
70 buf = buf->frags;
71 if (!buf) {
72 /* Do not return null here but let the caller failure
73 * checks to fail the packet.
74 */
75 return (struct gptp_hdr *)pkt->frags->data;
76 }
77
78 return (struct gptp_hdr *)buf->data;
79 }
80
gptp_sync_timestamp_callback(struct net_pkt * pkt)81 static void gptp_sync_timestamp_callback(struct net_pkt *pkt)
82 {
83 int port = 0;
84 struct gptp_sync_send_state *state;
85 struct gptp_hdr *hdr;
86
87 port = gptp_get_port_number(net_pkt_iface(pkt));
88 if (port == -ENODEV) {
89 NET_DBG("No port found for ptp buffer");
90 return;
91 }
92
93 state = &GPTP_PORT_STATE(port)->sync_send;
94
95 hdr = GPTP_HDR(pkt);
96
97 /* If this buffer is a sync, flag it to the state machine. */
98 if (hdr->message_type == GPTP_SYNC_MESSAGE) {
99 state->md_sync_timestamp_avail = true;
100
101 net_if_unregister_timestamp_cb(&sync_timestamp_cb);
102 sync_cb_registered = false;
103
104 /* The pkt was ref'ed in gptp_send_sync() */
105 net_pkt_unref(pkt);
106 }
107 }
108
gptp_pdelay_response_timestamp_callback(struct net_pkt * pkt)109 static void gptp_pdelay_response_timestamp_callback(struct net_pkt *pkt)
110 {
111 int port = 0;
112 struct net_pkt *follow_up;
113 struct gptp_hdr *hdr;
114
115 port = gptp_get_port_number(net_pkt_iface(pkt));
116 if (port == -ENODEV) {
117 NET_DBG("No port found for ptp buffer");
118 goto out;
119 }
120
121 hdr = GPTP_HDR(pkt);
122
123 /* If this buffer is a path delay response, send the follow up. */
124 if (hdr->message_type == GPTP_PATH_DELAY_RESP_MESSAGE) {
125 follow_up = gptp_prepare_pdelay_follow_up(port, pkt);
126 if (!follow_up) {
127 /* Cannot handle the follow up, abort */
128 NET_ERR("Could not get buffer");
129 goto out;
130 }
131
132 net_if_unregister_timestamp_cb(&pdelay_response_timestamp_cb);
133 ts_cb_registered = false;
134
135 gptp_send_pdelay_follow_up(port, follow_up,
136 net_pkt_timestamp(pkt));
137
138 out:
139 /* The pkt was ref'ed in gptp_handle_pdelay_req() */
140 net_pkt_unref(pkt);
141 }
142 }
143
144 #if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
setup_gptp_frame_debug(struct net_if * iface,size_t extra_header,const char * caller,int line)145 static struct net_pkt *setup_gptp_frame_debug(struct net_if *iface,
146 size_t extra_header,
147 const char *caller,
148 int line)
149 #define setup_gptp_frame(iface, extra_header) \
150 setup_gptp_frame_debug(iface, extra_header, __func__, __LINE__)
151 #else
152 static struct net_pkt *setup_gptp_frame(struct net_if *iface,
153 size_t extra_header)
154 #endif
155 {
156 struct net_pkt *pkt;
157
158 #if defined(CONFIG_NET_DEBUG_NET_PKT_ALLOC)
159 pkt = net_pkt_alloc_with_buffer_debug(iface, sizeof(struct gptp_hdr) +
160 extra_header, AF_UNSPEC, 0,
161 NET_BUF_TIMEOUT, caller, line);
162 #else
163 pkt = net_pkt_alloc_with_buffer(iface, sizeof(struct gptp_hdr) +
164 extra_header, AF_UNSPEC, 0,
165 NET_BUF_TIMEOUT);
166 #endif
167 if (!pkt) {
168 return NULL;
169 }
170
171 net_buf_add(pkt->buffer, sizeof(struct gptp_hdr) + extra_header);
172 net_pkt_set_ptp(pkt, true);
173
174 net_pkt_lladdr_src(pkt)->addr = net_if_get_link_addr(iface)->addr;
175 net_pkt_lladdr_src(pkt)->len = net_if_get_link_addr(iface)->len;
176
177 net_pkt_lladdr_dst(pkt)->addr = (uint8_t *)&gptp_multicast_eth_addr;
178 net_pkt_lladdr_dst(pkt)->len = sizeof(struct net_eth_addr);
179
180 return pkt;
181 }
182
gptp_prepare_sync(int port)183 struct net_pkt *gptp_prepare_sync(int port)
184 {
185 struct gptp_port_ds *port_ds;
186 struct gptp_sync *sync;
187 struct net_if *iface;
188 struct net_pkt *pkt;
189 struct gptp_hdr *hdr;
190
191 NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
192 iface = GPTP_PORT_IFACE(port);
193 NET_ASSERT(iface);
194
195 pkt = setup_gptp_frame(iface, sizeof(struct gptp_sync));
196 if (!pkt) {
197 NET_DBG("Cannot get gPTP frame");
198 return NULL;
199 }
200
201 net_pkt_set_priority(pkt, NET_PRIORITY_CA);
202
203 port_ds = GPTP_PORT_DS(port);
204 sync = GPTP_SYNC(pkt);
205 hdr = GPTP_HDR(pkt);
206
207 /*
208 * Header configuration.
209 *
210 * Some fields are set by gptp_md_sync_send_prepare().
211 */
212 hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
213 hdr->message_type = GPTP_SYNC_MESSAGE;
214 hdr->ptp_version = GPTP_VERSION;
215 hdr->sequence_id = htons(port_ds->sync_seq_id);
216 hdr->domain_number = 0U;
217 hdr->correction_field = 0;
218 hdr->flags.octets[0] = GPTP_FLAG_TWO_STEP;
219 hdr->flags.octets[1] = GPTP_FLAG_PTP_TIMESCALE;
220 hdr->message_length = htons(sizeof(struct gptp_hdr) +
221 sizeof(struct gptp_sync));
222 hdr->control = GPTP_SYNC_CONTROL_VALUE;
223
224 /* Clear reserved fields. */
225 hdr->reserved0 = 0U;
226 hdr->reserved1 = 0U;
227 hdr->reserved2 = 0U;
228
229 /* PTP configuration. */
230 (void)memset(&sync->reserved, 0, sizeof(sync->reserved));
231
232 /* Update sequence number. */
233 port_ds->sync_seq_id++;
234
235 return pkt;
236 }
237
gptp_prepare_follow_up(int port,struct net_pkt * sync)238 struct net_pkt *gptp_prepare_follow_up(int port, struct net_pkt *sync)
239 {
240 struct gptp_hdr *hdr, *sync_hdr;
241 struct net_if *iface;
242 struct net_pkt *pkt;
243
244 NET_ASSERT(sync);
245 NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
246 iface = GPTP_PORT_IFACE(port);
247 NET_ASSERT(iface);
248
249 pkt = setup_gptp_frame(iface, sizeof(struct gptp_follow_up));
250 if (!pkt) {
251 NET_DBG("Cannot get gPTP frame");
252 return NULL;
253 }
254
255 net_pkt_set_priority(pkt, NET_PRIORITY_IC);
256
257 hdr = GPTP_HDR(pkt);
258 sync_hdr = GPTP_HDR(sync);
259
260 /*
261 * Header configuration.
262 *
263 * Some fields are set by gptp_md_follow_up_prepare().
264 */
265 hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
266 hdr->message_type = GPTP_FOLLOWUP_MESSAGE;
267 hdr->ptp_version = GPTP_VERSION;
268 hdr->sequence_id = sync_hdr->sequence_id;
269 hdr->domain_number = 0U;
270 /* Store timestamp value in correction field. */
271 hdr->correction_field = gptp_timestamp_to_nsec(&sync->timestamp);
272 hdr->flags.octets[0] = 0U;
273 hdr->flags.octets[1] = GPTP_FLAG_PTP_TIMESCALE;
274 hdr->message_length = htons(sizeof(struct gptp_hdr) +
275 sizeof(struct gptp_follow_up));
276 hdr->control = GPTP_FUP_CONTROL_VALUE;
277
278 /* Clear reserved fields. */
279 hdr->reserved0 = 0U;
280 hdr->reserved1 = 0U;
281 hdr->reserved2 = 0U;
282
283 /* PTP configuration will be set by the MDSyncSend state machine. */
284
285 return pkt;
286 }
287
gptp_prepare_pdelay_req(int port)288 struct net_pkt *gptp_prepare_pdelay_req(int port)
289 {
290 struct gptp_pdelay_req *req;
291 struct gptp_port_ds *port_ds;
292 struct net_if *iface;
293 struct net_pkt *pkt;
294 struct gptp_hdr *hdr;
295
296 NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
297 iface = GPTP_PORT_IFACE(port);
298 NET_ASSERT(iface);
299
300 pkt = setup_gptp_frame(iface, sizeof(struct gptp_pdelay_req));
301 if (!pkt) {
302 NET_DBG("Cannot get gPTP frame");
303 return NULL;
304 }
305
306 net_pkt_set_priority(pkt, NET_PRIORITY_CA);
307
308 port_ds = GPTP_PORT_DS(port);
309 req = GPTP_PDELAY_REQ(pkt);
310 hdr = GPTP_HDR(pkt);
311
312 /* Header configuration. */
313 hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
314 hdr->message_type = GPTP_PATH_DELAY_REQ_MESSAGE;
315 hdr->ptp_version = GPTP_VERSION;
316 hdr->sequence_id = htons(port_ds->pdelay_req_seq_id);
317 hdr->domain_number = 0U;
318 hdr->correction_field = 0;
319 hdr->flags.octets[0] = 0U;
320 hdr->flags.octets[1] = GPTP_FLAG_PTP_TIMESCALE;
321
322 hdr->message_length = htons(sizeof(struct gptp_hdr) +
323 sizeof(struct gptp_pdelay_req));
324 hdr->port_id.port_number = htons(port_ds->port_id.port_number);
325 hdr->control = GPTP_OTHER_CONTROL_VALUE;
326 hdr->log_msg_interval = port_ds->cur_log_pdelay_req_itv;
327
328 /* Clear reserved fields. */
329 hdr->reserved0 = 0U;
330 hdr->reserved1 = 0U;
331 hdr->reserved2 = 0U;
332
333 memcpy(hdr->port_id.clk_id,
334 port_ds->port_id.clk_id, GPTP_CLOCK_ID_LEN);
335
336 /* PTP configuration. */
337 (void)memset(&req->reserved1, 0, sizeof(req->reserved1));
338 (void)memset(&req->reserved2, 0, sizeof(req->reserved2));
339
340 /* Update sequence number. */
341 port_ds->pdelay_req_seq_id++;
342
343 return pkt;
344 }
345
gptp_prepare_pdelay_resp(int port,struct net_pkt * req)346 struct net_pkt *gptp_prepare_pdelay_resp(int port,
347 struct net_pkt *req)
348 {
349 struct net_if *iface = net_pkt_iface(req);
350 struct gptp_pdelay_resp *pdelay_resp;
351 struct gptp_hdr *hdr, *query;
352 struct gptp_port_ds *port_ds;
353 struct net_pkt *pkt;
354
355 pkt = setup_gptp_frame(iface, sizeof(struct gptp_pdelay_resp));
356 if (!pkt) {
357 NET_DBG("Cannot get gPTP frame");
358 return NULL;
359 }
360
361 net_pkt_set_priority(pkt, NET_PRIORITY_CA);
362
363 port_ds = GPTP_PORT_DS(port);
364
365 pdelay_resp = GPTP_PDELAY_RESP(pkt);
366 hdr = GPTP_HDR(pkt);
367
368 query = GPTP_HDR(req);
369
370 /* Header configuration. */
371 hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
372 hdr->message_type = GPTP_PATH_DELAY_RESP_MESSAGE;
373 hdr->ptp_version = GPTP_VERSION;
374 hdr->sequence_id = query->sequence_id;
375 hdr->domain_number = query->domain_number;
376 hdr->correction_field = query->correction_field;
377 hdr->flags.octets[0] = GPTP_FLAG_TWO_STEP;
378 hdr->flags.octets[1] = GPTP_FLAG_PTP_TIMESCALE;
379
380 hdr->message_length = htons(sizeof(struct gptp_hdr) +
381 sizeof(struct gptp_pdelay_resp));
382 hdr->port_id.port_number = htons(port_ds->port_id.port_number);
383 hdr->control = GPTP_OTHER_CONTROL_VALUE;
384 hdr->log_msg_interval = GPTP_RESP_LOG_MSG_ITV;
385
386 /* Clear reserved fields. */
387 hdr->reserved0 = 0U;
388 hdr->reserved1 = 0U;
389 hdr->reserved2 = 0U;
390
391 memcpy(hdr->port_id.clk_id, port_ds->port_id.clk_id,
392 GPTP_CLOCK_ID_LEN);
393
394 /* PTP configuration. */
395 pdelay_resp->req_receipt_ts_secs_high = 0U;
396 pdelay_resp->req_receipt_ts_secs_low = 0U;
397 pdelay_resp->req_receipt_ts_nsecs = 0U;
398
399 memcpy(&pdelay_resp->requesting_port_id,
400 &query->port_id, sizeof(struct gptp_port_identity));
401
402 return pkt;
403 }
404
gptp_prepare_pdelay_follow_up(int port,struct net_pkt * resp)405 struct net_pkt *gptp_prepare_pdelay_follow_up(int port,
406 struct net_pkt *resp)
407 {
408 struct net_if *iface = net_pkt_iface(resp);
409 struct gptp_pdelay_resp_follow_up *follow_up;
410 struct gptp_pdelay_resp *pdelay_resp;
411 struct gptp_hdr *hdr, *resp_hdr;
412 struct gptp_port_ds *port_ds;
413 struct net_pkt *pkt;
414
415 pkt = setup_gptp_frame(iface,
416 sizeof(struct gptp_pdelay_resp_follow_up));
417 if (!pkt) {
418 NET_DBG("Cannot get gPTP frame");
419 return NULL;
420 }
421
422 net_pkt_set_priority(pkt, NET_PRIORITY_IC);
423
424 port_ds = GPTP_PORT_DS(port);
425
426 follow_up = GPTP_PDELAY_RESP_FOLLOWUP(pkt);
427 hdr = GPTP_HDR(pkt);
428
429 pdelay_resp = GPTP_PDELAY_RESP(resp);
430 resp_hdr = GPTP_HDR(resp);
431
432 /* Header configuration. */
433 hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
434 hdr->ptp_version = GPTP_VERSION;
435 hdr->message_type = GPTP_PATH_DELAY_FOLLOWUP_MESSAGE;
436 hdr->sequence_id = resp_hdr->sequence_id;
437 hdr->domain_number = resp_hdr->domain_number;
438 hdr->correction_field = 0;
439 hdr->message_length = htons(sizeof(struct gptp_hdr) +
440 sizeof(struct gptp_pdelay_resp_follow_up));
441 hdr->port_id.port_number = htons(port_ds->port_id.port_number);
442 hdr->control = GPTP_OTHER_CONTROL_VALUE;
443 hdr->log_msg_interval = GPTP_RESP_LOG_MSG_ITV;
444
445 hdr->flags.octets[0] = 0U;
446 hdr->flags.octets[1] = GPTP_FLAG_PTP_TIMESCALE;
447
448 /* Clear reserved fields. */
449 hdr->reserved0 = 0U;
450 hdr->reserved1 = 0U;
451 hdr->reserved2 = 0U;
452
453 memcpy(hdr->port_id.clk_id, port_ds->port_id.clk_id,
454 GPTP_CLOCK_ID_LEN);
455
456 /* PTP configuration. */
457 follow_up->resp_orig_ts_secs_high = 0U;
458 follow_up->resp_orig_ts_secs_low = 0U;
459 follow_up->resp_orig_ts_nsecs = 0U;
460
461 memcpy(&follow_up->requesting_port_id,
462 &pdelay_resp->requesting_port_id,
463 sizeof(struct gptp_port_identity));
464
465 return pkt;
466 }
467
gptp_prepare_announce(int port)468 struct net_pkt *gptp_prepare_announce(int port)
469 {
470 struct gptp_global_ds *global_ds;
471 struct gptp_default_ds *default_ds;
472 struct gptp_port_ds *port_ds;
473 struct gptp_announce *ann;
474 struct net_if *iface;
475 struct net_pkt *pkt;
476 struct gptp_hdr *hdr;
477
478 NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
479 global_ds = GPTP_GLOBAL_DS();
480 default_ds = GPTP_DEFAULT_DS();
481 iface = GPTP_PORT_IFACE(port);
482 NET_ASSERT(iface);
483
484 pkt = setup_gptp_frame(iface, sizeof(struct gptp_announce) - 8 +
485 ntohs(global_ds->path_trace.len));
486 if (!pkt) {
487 NET_DBG("Cannot get gPTP frame");
488 return NULL;
489 }
490
491 net_pkt_set_priority(pkt, NET_PRIORITY_IC);
492
493 hdr = GPTP_HDR(pkt);
494 ann = GPTP_ANNOUNCE(pkt);
495 port_ds = GPTP_PORT_DS(port);
496
497 hdr->message_type = GPTP_ANNOUNCE_MESSAGE;
498 hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
499 hdr->ptp_version = GPTP_VERSION;
500
501 hdr->domain_number = 0U;
502 hdr->correction_field = 0;
503 hdr->flags.octets[0] = 0U;
504
505 /* Copy leap61, leap59, current UTC offset valid, time traceable and
506 * frequency traceable flags.
507 */
508 hdr->flags.octets[1] =
509 global_ds->global_flags.octets[1] | GPTP_FLAG_PTP_TIMESCALE;
510
511 memcpy(hdr->port_id.clk_id, GPTP_DEFAULT_DS()->clk_id,
512 GPTP_CLOCK_ID_LEN);
513
514 hdr->port_id.port_number = htons(port);
515 hdr->control = GPTP_OTHER_CONTROL_VALUE;
516 hdr->log_msg_interval = port_ds->cur_log_announce_itv;
517
518 /* Clear reserved fields. */
519 hdr->reserved0 = 0U;
520 hdr->reserved1 = 0U;
521 hdr->reserved2 = 0U;
522
523 ann->cur_utc_offset = global_ds->current_utc_offset;
524 ann->time_source = global_ds->time_source;
525
526 switch (GPTP_PORT_BMCA_DATA(port)->info_is) {
527 case GPTP_INFO_IS_MINE:
528 ann->root_system_id.grand_master_prio1 = default_ds->priority1;
529 ann->root_system_id.grand_master_prio2 = default_ds->priority2;
530
531 memcpy(&ann->root_system_id.clk_quality,
532 &default_ds->clk_quality,
533 sizeof(struct gptp_clock_quality));
534
535 memcpy(&ann->root_system_id.grand_master_id,
536 default_ds->clk_id,
537 GPTP_CLOCK_ID_LEN);
538 break;
539 case GPTP_INFO_IS_RECEIVED:
540 memcpy(&ann->root_system_id,
541 &GPTP_PORT_BMCA_DATA(port)->
542 master_priority.root_system_id,
543 sizeof(struct gptp_root_system_identity));
544 break;
545 default:
546 goto fail;
547 }
548
549 ann->steps_removed = global_ds->master_steps_removed;
550 hdr->sequence_id = htons(port_ds->announce_seq_id);
551 port_ds->announce_seq_id++;
552
553 ann->tlv.type = GPTP_ANNOUNCE_MSG_PATH_SEQ_TYPE;
554
555 /* Clear reserved fields. */
556 (void)memset(ann->reserved1, 0, sizeof(ann->reserved1));
557 ann->reserved2 = 0U;
558
559 hdr->message_length = htons(sizeof(struct gptp_hdr) +
560 sizeof(struct gptp_announce) - 8 +
561 ntohs(global_ds->path_trace.len));
562
563 ann->tlv.len = global_ds->path_trace.len;
564
565 net_pkt_cursor_init(pkt);
566
567 /* setup_gptp_frame() already added all the length, so let's not
568 * add up more with net_pkt_skip/write_new(), let's just overwrite
569 */
570 net_pkt_set_overwrite(pkt, true);
571
572 if (net_pkt_skip(pkt, sizeof(struct gptp_hdr) +
573 sizeof(struct gptp_announce) - 8) ||
574 net_pkt_write(pkt, &global_ds->path_trace.path_sequence[0][0],
575 ntohs(global_ds->path_trace.len))) {
576 goto fail;
577 }
578
579 net_pkt_set_overwrite(pkt, false);
580
581 return pkt;
582
583 fail:
584 net_pkt_unref(pkt);
585
586 return NULL;
587 }
588
gptp_handle_sync(int port,struct net_pkt * pkt)589 void gptp_handle_sync(int port, struct net_pkt *pkt)
590 {
591 struct gptp_sync_rcv_state *state;
592 struct gptp_hdr *hdr;
593 uint64_t upstream_sync_itv;
594 k_timeout_t duration;
595
596 state = &GPTP_PORT_STATE(port)->sync_rcv;
597 hdr = GPTP_HDR(state->rcvd_sync_ptr);
598
599 upstream_sync_itv = NSEC_PER_SEC * GPTP_POW2(hdr->log_msg_interval);
600
601 /* Convert ns to ms. */
602 duration = K_MSEC((upstream_sync_itv / 1000000U));
603
604 /* Start timeout timer. */
605 k_timer_start(&state->follow_up_discard_timer, duration, K_NO_WAIT);
606 }
607
gptp_handle_follow_up(int port,struct net_pkt * pkt)608 int gptp_handle_follow_up(int port, struct net_pkt *pkt)
609 {
610 struct gptp_sync_rcv_state *state;
611 struct gptp_hdr *sync_hdr, *hdr;
612
613 state = &GPTP_PORT_STATE(port)->sync_rcv;
614
615 sync_hdr = GPTP_HDR(state->rcvd_sync_ptr);
616 hdr = GPTP_HDR(pkt);
617
618 if (sync_hdr->sequence_id != hdr->sequence_id) {
619 NET_WARN("%s sequence id %d %s %s %d",
620 "FOLLOWUP", ntohs(hdr->sequence_id),
621 "does not match",
622 "SYNC", ntohs(sync_hdr->sequence_id));
623 return -EINVAL;
624 }
625
626 GPTP_STATS_INC(port, rx_fup_count);
627
628 return 0;
629 }
630
gptp_handle_pdelay_req(int port,struct net_pkt * pkt)631 void gptp_handle_pdelay_req(int port, struct net_pkt *pkt)
632 {
633 struct net_pkt *reply;
634
635 GPTP_STATS_INC(port, rx_pdelay_req_count);
636
637 if (ts_cb_registered == true) {
638 NET_WARN("Multiple pdelay requests");
639
640 net_if_unregister_timestamp_cb(&pdelay_response_timestamp_cb);
641 net_pkt_unref(pdelay_response_timestamp_cb.pkt);
642
643 ts_cb_registered = false;
644 }
645
646 /* Prepare response and send */
647 reply = gptp_prepare_pdelay_resp(port, pkt);
648 if (!reply) {
649 return;
650 }
651
652 net_if_register_timestamp_cb(&pdelay_response_timestamp_cb,
653 reply,
654 net_pkt_iface(pkt),
655 gptp_pdelay_response_timestamp_callback);
656
657 /* TS thread will send this back to us so increment ref count so that
658 * the packet is not removed when sending it. This will be unref'ed by
659 * timestamp callback in gptp_pdelay_response_timestamp_callback()
660 */
661 net_pkt_ref(reply);
662
663 ts_cb_registered = true;
664
665 gptp_send_pdelay_resp(port, reply, net_pkt_timestamp(pkt));
666 }
667
gptp_handle_pdelay_resp(int port,struct net_pkt * pkt)668 int gptp_handle_pdelay_resp(int port, struct net_pkt *pkt)
669 {
670 struct gptp_pdelay_req_state *state;
671 struct gptp_default_ds *default_ds;
672 struct gptp_pdelay_resp *resp;
673 struct gptp_hdr *hdr, *req_hdr;
674
675 hdr = GPTP_HDR(pkt);
676 resp = GPTP_PDELAY_RESP(pkt);
677 state = &GPTP_PORT_STATE(port)->pdelay_req;
678 default_ds = GPTP_DEFAULT_DS();
679
680 if (!state->tx_pdelay_req_ptr) {
681 goto reset;
682 }
683
684 req_hdr = GPTP_HDR(state->tx_pdelay_req_ptr);
685
686 /* Check clock identity. */
687 if (memcmp(default_ds->clk_id, resp->requesting_port_id.clk_id,
688 GPTP_CLOCK_ID_LEN)) {
689 NET_WARN("Requesting Clock Identity %s", "does not match");
690 goto reset;
691 }
692 if (memcmp(default_ds->clk_id, hdr->port_id.clk_id,
693 GPTP_CLOCK_ID_LEN) == 0) {
694 NET_WARN("Source Clock Identity is local Clock Identity");
695 goto reset;
696 }
697
698 /* Check port number. */
699 if (resp->requesting_port_id.port_number != htons(port)) {
700 NET_WARN("Requesting Port Number %s", "does not match");
701 goto reset;
702 }
703
704 /* Check sequence id. */
705 if (hdr->sequence_id != req_hdr->sequence_id) {
706 NET_WARN("Sequence Id %d %s %d",
707 ntohs(hdr->sequence_id),
708 "does not match",
709 ntohs(req_hdr->sequence_id));
710 goto reset;
711 }
712
713 GPTP_STATS_INC(port, rx_pdelay_resp_count);
714
715 return 0;
716
717 reset:
718 return -EINVAL;
719 }
720
gptp_handle_pdelay_follow_up(int port,struct net_pkt * pkt)721 int gptp_handle_pdelay_follow_up(int port, struct net_pkt *pkt)
722 {
723 struct gptp_pdelay_resp_follow_up *follow_up;
724 struct gptp_hdr *hdr, *req_hdr, *resp_hdr;
725 struct gptp_pdelay_req_state *state;
726 struct gptp_default_ds *default_ds;
727
728 hdr = GPTP_HDR(pkt);
729 follow_up = GPTP_PDELAY_RESP_FOLLOWUP(pkt);
730 state = &GPTP_PORT_STATE(port)->pdelay_req;
731 default_ds = GPTP_DEFAULT_DS();
732
733 if (!state->tx_pdelay_req_ptr) {
734 goto reset;
735 }
736
737 req_hdr = GPTP_HDR(state->tx_pdelay_req_ptr);
738
739 if (!state->rcvd_pdelay_resp_ptr) {
740 goto reset;
741 }
742
743 resp_hdr = GPTP_HDR(state->rcvd_pdelay_resp_ptr);
744
745 /* Check clock identity. */
746 if (memcmp(default_ds->clk_id, follow_up->requesting_port_id.clk_id,
747 GPTP_CLOCK_ID_LEN)) {
748 NET_WARN("Requesting Clock Identity %s", "does not match");
749 goto reset;
750 }
751
752 if (memcmp(default_ds->clk_id, hdr->port_id.clk_id,
753 GPTP_CLOCK_ID_LEN) == 0) {
754 NET_WARN("Source Clock Identity is local Clock Identity");
755 goto reset;
756 }
757
758 /* Check port number. */
759 if (follow_up->requesting_port_id.port_number != htons(port)) {
760 NET_WARN("Requesting Port Number %s", "does not match");
761 goto reset;
762 }
763
764 /* Check sequence id. */
765 if (hdr->sequence_id != req_hdr->sequence_id) {
766 NET_WARN("Sequence Id %d %s %d",
767 ntohs(hdr->sequence_id),
768 "does not match",
769 ntohs(req_hdr->sequence_id));
770 goto reset;
771 }
772
773 /* Check source port. */
774 if (memcmp(&hdr->port_id, &resp_hdr->port_id,
775 sizeof(hdr->port_id)) != 0) {
776 NET_WARN("pDelay response and follow up port IDs %s",
777 "does not match");
778 goto reset;
779 }
780
781 GPTP_STATS_INC(port, rx_fup_count);
782
783 return 0;
784
785 reset:
786 return -EINVAL;
787 }
788
gptp_handle_signaling(int port,struct net_pkt * pkt)789 void gptp_handle_signaling(int port, struct net_pkt *pkt)
790 {
791 struct gptp_port_ds *port_ds;
792 struct gptp_signaling *sig;
793
794 sig = GPTP_SIGNALING(pkt);
795 port_ds = GPTP_PORT_DS(port);
796
797 /* If time-synchronization not enabled, drop packet. */
798 if (!port_ds->ptt_port_enabled) {
799 return;
800 }
801
802 /* pDelay interval. */
803 gptp_update_pdelay_req_interval(port, sig->tlv.link_delay_itv);
804
805 /* Sync interval. */
806 gptp_update_sync_interval(port, sig->tlv.time_sync_itv);
807
808 /* Announce interval. */
809 gptp_update_announce_interval(port, sig->tlv.announce_itv);
810
811 port_ds->compute_neighbor_rate_ratio =
812 sig->tlv.compute_neighbor_rate_ratio;
813 port_ds->compute_neighbor_prop_delay =
814 sig->tlv.compute_neighbor_prop_delay;
815 }
816
gptp_send_sync(int port,struct net_pkt * pkt)817 void gptp_send_sync(int port, struct net_pkt *pkt)
818 {
819 if (!sync_cb_registered) {
820 net_if_register_timestamp_cb(&sync_timestamp_cb,
821 pkt,
822 net_pkt_iface(pkt),
823 gptp_sync_timestamp_callback);
824 sync_cb_registered = true;
825 }
826
827 GPTP_STATS_INC(port, tx_sync_count);
828
829 /* TS thread will send this back to us so increment ref count
830 * so that the packet is not removed when sending it.
831 * This will be unref'ed by timestamp callback in
832 * gptp_sync_timestamp_callback()
833 */
834 net_pkt_ref(pkt);
835
836 NET_GPTP_INFO("SYNC", pkt);
837
838 net_if_queue_tx(net_pkt_iface(pkt), pkt);
839 }
840
gptp_send_follow_up(int port,struct net_pkt * pkt)841 void gptp_send_follow_up(int port, struct net_pkt *pkt)
842 {
843 GPTP_STATS_INC(port, tx_fup_count);
844
845 NET_GPTP_INFO("FOLLOWUP", pkt);
846
847 net_if_queue_tx(net_pkt_iface(pkt), pkt);
848 }
849
gptp_send_announce(int port,struct net_pkt * pkt)850 void gptp_send_announce(int port, struct net_pkt *pkt)
851 {
852 GPTP_STATS_INC(port, tx_announce_count);
853
854 NET_GPTP_INFO("ANNOUNCE", pkt);
855
856 net_if_queue_tx(net_pkt_iface(pkt), pkt);
857 }
858
gptp_send_pdelay_req(int port)859 void gptp_send_pdelay_req(int port)
860 {
861 struct gptp_pdelay_req_state *state;
862 struct net_pkt *pkt;
863
864 NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
865 state = &GPTP_PORT_STATE(port)->pdelay_req;
866
867 pkt = gptp_prepare_pdelay_req(port);
868 if (pkt) {
869 if (state->tx_pdelay_req_ptr) {
870 NET_DBG("Unref pending %s %p", "PDELAY_REQ",
871 state->tx_pdelay_req_ptr);
872
873 net_pkt_unref(state->tx_pdelay_req_ptr);
874 }
875
876 /* Keep the buffer alive until pdelay_rate_ratio is computed. */
877 state->tx_pdelay_req_ptr = net_pkt_ref(pkt);
878
879 GPTP_STATS_INC(port, tx_pdelay_req_count);
880
881 NET_GPTP_INFO("PDELAY_REQ", pkt);
882
883 net_if_queue_tx(net_pkt_iface(pkt), pkt);
884 } else {
885 NET_ERR("Failed to prepare %s", "PDELAY_REQ");
886 }
887 }
888
gptp_send_pdelay_resp(int port,struct net_pkt * pkt,struct net_ptp_time * treq)889 void gptp_send_pdelay_resp(int port, struct net_pkt *pkt,
890 struct net_ptp_time *treq)
891 {
892 struct gptp_pdelay_resp *resp;
893 struct gptp_hdr *hdr;
894
895 hdr = GPTP_HDR(pkt);
896
897 /* No Fractional nsec .*/
898 hdr->correction_field = 0;
899
900 resp = GPTP_PDELAY_RESP(pkt);
901 resp->req_receipt_ts_secs_high = htons(treq->_sec.high);
902 resp->req_receipt_ts_secs_low = htonl(treq->_sec.low);
903 resp->req_receipt_ts_nsecs = htonl(treq->nanosecond);
904
905 GPTP_STATS_INC(port, tx_pdelay_resp_count);
906
907 NET_GPTP_INFO("PDELAY_RESP", pkt);
908
909 net_if_queue_tx(net_pkt_iface(pkt), pkt);
910 }
911
gptp_send_pdelay_follow_up(int port,struct net_pkt * pkt,struct net_ptp_time * tresp)912 void gptp_send_pdelay_follow_up(int port, struct net_pkt *pkt,
913 struct net_ptp_time *tresp)
914 {
915 struct gptp_pdelay_resp_follow_up *follow_up;
916 struct gptp_hdr *hdr;
917
918 hdr = GPTP_HDR(pkt);
919
920 /* No Fractional nsec .*/
921 hdr->correction_field = 0;
922
923 follow_up = GPTP_PDELAY_RESP_FOLLOWUP(pkt);
924 follow_up->resp_orig_ts_secs_high = htons(tresp->_sec.high);
925 follow_up->resp_orig_ts_secs_low = htonl(tresp->_sec.low);
926 follow_up->resp_orig_ts_nsecs = htonl(tresp->nanosecond);
927
928 GPTP_STATS_INC(port, tx_pdelay_resp_fup_count);
929
930 NET_GPTP_INFO("PDELAY_FOLLOWUP", pkt);
931
932 net_if_queue_tx(net_pkt_iface(pkt), pkt);
933 }
934