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 *one_hdr = GPTP_HDR(pkt); \
30 \
31 if (one_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(one_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(one_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_IC);
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 gptp_follow_up *fup;
242 struct net_if *iface;
243 struct net_pkt *pkt;
244 struct net_ptp_time *sync_ts;
245
246 NET_ASSERT(sync);
247 NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
248 iface = GPTP_PORT_IFACE(port);
249 NET_ASSERT(iface);
250
251 pkt = setup_gptp_frame(iface, sizeof(struct gptp_follow_up));
252 if (!pkt) {
253 NET_DBG("Cannot get gPTP frame");
254 return NULL;
255 }
256
257 net_pkt_set_priority(pkt, NET_PRIORITY_CA);
258
259 hdr = GPTP_HDR(pkt);
260 fup = GPTP_FOLLOW_UP(pkt);
261 sync_hdr = GPTP_HDR(sync);
262 sync_ts = net_pkt_timestamp(sync);
263
264 /*
265 * Header configuration.
266 *
267 * Some fields are set by gptp_md_follow_up_prepare().
268 */
269 hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
270 hdr->message_type = GPTP_FOLLOWUP_MESSAGE;
271 hdr->ptp_version = GPTP_VERSION;
272 hdr->sequence_id = sync_hdr->sequence_id;
273 hdr->domain_number = 0U;
274 /*
275 * Grand master clock should keep correction_field at zero,
276 * according to IEEE802.1AS Table 11-6 and 10.6.2.2.9
277 */
278 hdr->correction_field = 0LL;
279 hdr->flags.octets[0] = 0U;
280 hdr->flags.octets[1] = GPTP_FLAG_PTP_TIMESCALE;
281 hdr->message_length = htons(sizeof(struct gptp_hdr) +
282 sizeof(struct gptp_follow_up));
283 hdr->control = GPTP_FUP_CONTROL_VALUE;
284
285 /* Clear reserved fields. */
286 hdr->reserved0 = 0U;
287 hdr->reserved1 = 0U;
288 hdr->reserved2 = 0U;
289
290 /*
291 * Get preciseOriginTimestamp from previous sync message
292 * according to IEEE802.1AS 11.4.4.2.1 syncEventEgressTimestamp
293 */
294 fup->prec_orig_ts_secs_high = htons(sync_ts->_sec.high);
295 fup->prec_orig_ts_secs_low = htonl(sync_ts->_sec.low);
296 fup->prec_orig_ts_nsecs = htonl(sync_ts->nanosecond);
297
298 /* PTP configuration will be set by the MDSyncSend state machine. */
299
300 return pkt;
301 }
302
gptp_prepare_pdelay_req(int port)303 struct net_pkt *gptp_prepare_pdelay_req(int port)
304 {
305 struct gptp_pdelay_req *req;
306 struct gptp_port_ds *port_ds;
307 struct net_if *iface;
308 struct net_pkt *pkt;
309 struct gptp_hdr *hdr;
310
311 NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
312 iface = GPTP_PORT_IFACE(port);
313 NET_ASSERT(iface);
314
315 pkt = setup_gptp_frame(iface, sizeof(struct gptp_pdelay_req));
316 if (!pkt) {
317 NET_DBG("Cannot get gPTP frame");
318 return NULL;
319 }
320
321 net_pkt_set_priority(pkt, NET_PRIORITY_IC);
322
323 port_ds = GPTP_PORT_DS(port);
324 req = GPTP_PDELAY_REQ(pkt);
325 hdr = GPTP_HDR(pkt);
326
327 /* Header configuration. */
328 hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
329 hdr->message_type = GPTP_PATH_DELAY_REQ_MESSAGE;
330 hdr->ptp_version = GPTP_VERSION;
331 hdr->sequence_id = htons(port_ds->pdelay_req_seq_id);
332 hdr->domain_number = 0U;
333 hdr->correction_field = 0;
334 hdr->flags.octets[0] = 0U;
335 hdr->flags.octets[1] = GPTP_FLAG_PTP_TIMESCALE;
336
337 hdr->message_length = htons(sizeof(struct gptp_hdr) +
338 sizeof(struct gptp_pdelay_req));
339 hdr->port_id.port_number = htons(port_ds->port_id.port_number);
340 hdr->control = GPTP_OTHER_CONTROL_VALUE;
341 hdr->log_msg_interval = port_ds->cur_log_pdelay_req_itv;
342
343 /* Clear reserved fields. */
344 hdr->reserved0 = 0U;
345 hdr->reserved1 = 0U;
346 hdr->reserved2 = 0U;
347
348 memcpy(hdr->port_id.clk_id,
349 port_ds->port_id.clk_id, GPTP_CLOCK_ID_LEN);
350
351 /* PTP configuration. */
352 (void)memset(&req->reserved1, 0, sizeof(req->reserved1));
353 (void)memset(&req->reserved2, 0, sizeof(req->reserved2));
354
355 /* Update sequence number. */
356 port_ds->pdelay_req_seq_id++;
357
358 return pkt;
359 }
360
gptp_prepare_pdelay_resp(int port,struct net_pkt * req)361 struct net_pkt *gptp_prepare_pdelay_resp(int port,
362 struct net_pkt *req)
363 {
364 struct net_if *iface = net_pkt_iface(req);
365 struct gptp_pdelay_resp *pdelay_resp;
366 struct gptp_hdr *hdr, *query;
367 struct gptp_port_ds *port_ds;
368 struct net_pkt *pkt;
369
370 pkt = setup_gptp_frame(iface, sizeof(struct gptp_pdelay_resp));
371 if (!pkt) {
372 NET_DBG("Cannot get gPTP frame");
373 return NULL;
374 }
375
376 net_pkt_set_priority(pkt, NET_PRIORITY_IC);
377
378 port_ds = GPTP_PORT_DS(port);
379
380 pdelay_resp = GPTP_PDELAY_RESP(pkt);
381 hdr = GPTP_HDR(pkt);
382
383 query = GPTP_HDR(req);
384
385 /* Header configuration. */
386 hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
387 hdr->message_type = GPTP_PATH_DELAY_RESP_MESSAGE;
388 hdr->ptp_version = GPTP_VERSION;
389 hdr->sequence_id = query->sequence_id;
390 hdr->domain_number = query->domain_number;
391 hdr->correction_field = query->correction_field;
392 hdr->flags.octets[0] = GPTP_FLAG_TWO_STEP;
393 hdr->flags.octets[1] = GPTP_FLAG_PTP_TIMESCALE;
394
395 hdr->message_length = htons(sizeof(struct gptp_hdr) +
396 sizeof(struct gptp_pdelay_resp));
397 hdr->port_id.port_number = htons(port_ds->port_id.port_number);
398 hdr->control = GPTP_OTHER_CONTROL_VALUE;
399 hdr->log_msg_interval = GPTP_RESP_LOG_MSG_ITV;
400
401 /* Clear reserved fields. */
402 hdr->reserved0 = 0U;
403 hdr->reserved1 = 0U;
404 hdr->reserved2 = 0U;
405
406 memcpy(hdr->port_id.clk_id, port_ds->port_id.clk_id,
407 GPTP_CLOCK_ID_LEN);
408
409 /* PTP configuration. */
410 pdelay_resp->req_receipt_ts_secs_high = 0U;
411 pdelay_resp->req_receipt_ts_secs_low = 0U;
412 pdelay_resp->req_receipt_ts_nsecs = 0U;
413
414 memcpy(&pdelay_resp->requesting_port_id,
415 &query->port_id, sizeof(struct gptp_port_identity));
416
417 return pkt;
418 }
419
gptp_prepare_pdelay_follow_up(int port,struct net_pkt * resp)420 struct net_pkt *gptp_prepare_pdelay_follow_up(int port,
421 struct net_pkt *resp)
422 {
423 struct net_if *iface = net_pkt_iface(resp);
424 struct gptp_pdelay_resp_follow_up *follow_up;
425 struct gptp_pdelay_resp *pdelay_resp;
426 struct gptp_hdr *hdr, *resp_hdr;
427 struct gptp_port_ds *port_ds;
428 struct net_pkt *pkt;
429
430 pkt = setup_gptp_frame(iface,
431 sizeof(struct gptp_pdelay_resp_follow_up));
432 if (!pkt) {
433 NET_DBG("Cannot get gPTP frame");
434 return NULL;
435 }
436
437 net_pkt_set_priority(pkt, NET_PRIORITY_CA);
438
439 port_ds = GPTP_PORT_DS(port);
440
441 follow_up = GPTP_PDELAY_RESP_FOLLOWUP(pkt);
442 hdr = GPTP_HDR(pkt);
443
444 pdelay_resp = GPTP_PDELAY_RESP(resp);
445 resp_hdr = GPTP_HDR(resp);
446
447 /* Header configuration. */
448 hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
449 hdr->ptp_version = GPTP_VERSION;
450 hdr->message_type = GPTP_PATH_DELAY_FOLLOWUP_MESSAGE;
451 hdr->sequence_id = resp_hdr->sequence_id;
452 hdr->domain_number = resp_hdr->domain_number;
453 hdr->correction_field = 0;
454 hdr->message_length = htons(sizeof(struct gptp_hdr) +
455 sizeof(struct gptp_pdelay_resp_follow_up));
456 hdr->port_id.port_number = htons(port_ds->port_id.port_number);
457 hdr->control = GPTP_OTHER_CONTROL_VALUE;
458 hdr->log_msg_interval = GPTP_RESP_LOG_MSG_ITV;
459
460 hdr->flags.octets[0] = 0U;
461 hdr->flags.octets[1] = GPTP_FLAG_PTP_TIMESCALE;
462
463 /* Clear reserved fields. */
464 hdr->reserved0 = 0U;
465 hdr->reserved1 = 0U;
466 hdr->reserved2 = 0U;
467
468 memcpy(hdr->port_id.clk_id, port_ds->port_id.clk_id,
469 GPTP_CLOCK_ID_LEN);
470
471 /* PTP configuration. */
472 follow_up->resp_orig_ts_secs_high = 0U;
473 follow_up->resp_orig_ts_secs_low = 0U;
474 follow_up->resp_orig_ts_nsecs = 0U;
475
476 memcpy(&follow_up->requesting_port_id,
477 &pdelay_resp->requesting_port_id,
478 sizeof(struct gptp_port_identity));
479
480 return pkt;
481 }
482
gptp_prepare_announce(int port)483 struct net_pkt *gptp_prepare_announce(int port)
484 {
485 struct gptp_global_ds *global_ds;
486 struct gptp_default_ds *default_ds;
487 struct gptp_port_ds *port_ds;
488 struct gptp_announce *ann;
489 struct net_if *iface;
490 struct net_pkt *pkt;
491 struct gptp_hdr *hdr;
492 struct gptp_priority_vector *gm_prio;
493
494 NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
495 global_ds = GPTP_GLOBAL_DS();
496 default_ds = GPTP_DEFAULT_DS();
497 iface = GPTP_PORT_IFACE(port);
498 NET_ASSERT(iface);
499
500 pkt = setup_gptp_frame(iface, sizeof(struct gptp_announce) - 8 +
501 ntohs(global_ds->path_trace.len));
502 if (!pkt) {
503 NET_DBG("Cannot get gPTP frame");
504 return NULL;
505 }
506
507 net_pkt_set_priority(pkt, NET_PRIORITY_CA);
508
509 hdr = GPTP_HDR(pkt);
510 ann = GPTP_ANNOUNCE(pkt);
511 port_ds = GPTP_PORT_DS(port);
512
513 hdr->message_type = GPTP_ANNOUNCE_MESSAGE;
514 hdr->transport_specific = GPTP_TRANSPORT_802_1_AS;
515 hdr->ptp_version = GPTP_VERSION;
516
517 hdr->domain_number = 0U;
518 hdr->correction_field = 0;
519 hdr->flags.octets[0] = 0U;
520
521 /* Copy leap61, leap59, current UTC offset valid, time traceable and
522 * frequency traceable flags.
523 */
524 hdr->flags.octets[1] =
525 global_ds->global_flags.octets[1] | GPTP_FLAG_PTP_TIMESCALE;
526
527 memcpy(hdr->port_id.clk_id, GPTP_DEFAULT_DS()->clk_id,
528 GPTP_CLOCK_ID_LEN);
529
530 hdr->port_id.port_number = htons(port);
531 hdr->control = GPTP_OTHER_CONTROL_VALUE;
532 hdr->log_msg_interval = port_ds->cur_log_announce_itv;
533
534 /* Clear reserved fields. */
535 hdr->reserved0 = 0U;
536 hdr->reserved1 = 0U;
537 hdr->reserved2 = 0U;
538
539 ann->cur_utc_offset = htons(global_ds->current_utc_offset);
540 ann->time_source = global_ds->time_source;
541
542 gm_prio = &global_ds->gm_priority;
543 switch (GPTP_PORT_BMCA_DATA(port)->info_is) {
544 case GPTP_INFO_IS_MINE:
545 case GPTP_INFO_IS_RECEIVED:
546 memcpy(&ann->root_system_id,
547 &gm_prio->root_system_id,
548 sizeof(struct gptp_root_system_identity));
549 break;
550 default:
551 goto fail;
552 }
553
554 ann->steps_removed = global_ds->master_steps_removed;
555 hdr->sequence_id = htons(port_ds->announce_seq_id);
556 port_ds->announce_seq_id++;
557
558 ann->tlv.type = GPTP_ANNOUNCE_MSG_PATH_SEQ_TYPE;
559
560 /* Clear reserved fields. */
561 (void)memset(ann->reserved1, 0, sizeof(ann->reserved1));
562 ann->reserved2 = 0U;
563
564 hdr->message_length = htons(sizeof(struct gptp_hdr) +
565 sizeof(struct gptp_announce) - 8 +
566 ntohs(global_ds->path_trace.len));
567
568 ann->tlv.len = global_ds->path_trace.len;
569
570 net_pkt_cursor_init(pkt);
571
572 /* setup_gptp_frame() already added all the length, so let's not
573 * add up more with net_pkt_skip/write_new(), let's just overwrite
574 */
575 net_pkt_set_overwrite(pkt, true);
576
577 if (net_pkt_skip(pkt, sizeof(struct gptp_hdr) +
578 sizeof(struct gptp_announce) - 8) ||
579 net_pkt_write(pkt, &global_ds->path_trace.path_sequence[0][0],
580 ntohs(global_ds->path_trace.len))) {
581 goto fail;
582 }
583
584 net_pkt_set_overwrite(pkt, false);
585
586 return pkt;
587
588 fail:
589 net_pkt_unref(pkt);
590
591 return NULL;
592 }
593
gptp_handle_sync(int port,struct net_pkt * pkt)594 void gptp_handle_sync(int port, struct net_pkt *pkt)
595 {
596 struct gptp_sync_rcv_state *state;
597 struct gptp_hdr *hdr;
598 uint64_t upstream_sync_itv;
599 k_timeout_t duration;
600
601 state = &GPTP_PORT_STATE(port)->sync_rcv;
602 hdr = GPTP_HDR(state->rcvd_sync_ptr);
603
604 upstream_sync_itv = NSEC_PER_SEC * GPTP_POW2(hdr->log_msg_interval);
605
606 /* Convert ns to ms. */
607 duration = K_MSEC((upstream_sync_itv / 1000000U));
608
609 /* Start timeout timer. */
610 k_timer_start(&state->follow_up_discard_timer, duration, K_NO_WAIT);
611 }
612
gptp_handle_follow_up(int port,struct net_pkt * pkt)613 int gptp_handle_follow_up(int port, struct net_pkt *pkt)
614 {
615 struct gptp_sync_rcv_state *state;
616 struct gptp_hdr *sync_hdr, *hdr;
617
618 state = &GPTP_PORT_STATE(port)->sync_rcv;
619
620 sync_hdr = GPTP_HDR(state->rcvd_sync_ptr);
621 hdr = GPTP_HDR(pkt);
622
623 if (sync_hdr->sequence_id != hdr->sequence_id) {
624 NET_WARN("%s sequence id %d %s %s %d",
625 "FOLLOWUP", ntohs(hdr->sequence_id),
626 "does not match",
627 "SYNC", ntohs(sync_hdr->sequence_id));
628 return -EINVAL;
629 }
630
631 GPTP_STATS_INC(port, rx_fup_count);
632
633 return 0;
634 }
635
gptp_handle_pdelay_req(int port,struct net_pkt * pkt)636 void gptp_handle_pdelay_req(int port, struct net_pkt *pkt)
637 {
638 struct net_pkt *reply;
639
640 GPTP_STATS_INC(port, rx_pdelay_req_count);
641
642 if (ts_cb_registered == true) {
643 NET_WARN("Multiple pdelay requests");
644
645 net_if_unregister_timestamp_cb(&pdelay_response_timestamp_cb);
646 net_pkt_unref(pdelay_response_timestamp_cb.pkt);
647
648 ts_cb_registered = false;
649 }
650
651 /* Prepare response and send */
652 reply = gptp_prepare_pdelay_resp(port, pkt);
653 if (!reply) {
654 return;
655 }
656
657 net_if_register_timestamp_cb(&pdelay_response_timestamp_cb,
658 reply,
659 net_pkt_iface(pkt),
660 gptp_pdelay_response_timestamp_callback);
661
662 /* TS thread will send this back to us so increment ref count so that
663 * the packet is not removed when sending it. This will be unref'ed by
664 * timestamp callback in gptp_pdelay_response_timestamp_callback()
665 */
666 net_pkt_ref(reply);
667
668 ts_cb_registered = true;
669
670 gptp_send_pdelay_resp(port, reply, net_pkt_timestamp(pkt));
671 }
672
gptp_handle_pdelay_resp(int port,struct net_pkt * pkt)673 int gptp_handle_pdelay_resp(int port, struct net_pkt *pkt)
674 {
675 struct gptp_pdelay_req_state *state;
676 struct gptp_default_ds *default_ds;
677 struct gptp_pdelay_resp *resp;
678 struct gptp_hdr *hdr, *req_hdr;
679
680 hdr = GPTP_HDR(pkt);
681 resp = GPTP_PDELAY_RESP(pkt);
682 state = &GPTP_PORT_STATE(port)->pdelay_req;
683 default_ds = GPTP_DEFAULT_DS();
684
685 if (!state->tx_pdelay_req_ptr) {
686 goto reset;
687 }
688
689 req_hdr = GPTP_HDR(state->tx_pdelay_req_ptr);
690
691 /* Check clock identity. */
692 if (memcmp(default_ds->clk_id, resp->requesting_port_id.clk_id,
693 GPTP_CLOCK_ID_LEN)) {
694 NET_WARN("Requesting Clock Identity %s", "does not match");
695 goto reset;
696 }
697 if (memcmp(default_ds->clk_id, hdr->port_id.clk_id,
698 GPTP_CLOCK_ID_LEN) == 0) {
699 NET_WARN("Source Clock Identity is local Clock Identity");
700 goto reset;
701 }
702
703 /* Check port number. */
704 if (resp->requesting_port_id.port_number != htons(port)) {
705 NET_WARN("Requesting Port Number %s", "does not match");
706 goto reset;
707 }
708
709 /* Check sequence id. */
710 if (hdr->sequence_id != req_hdr->sequence_id) {
711 NET_WARN("Sequence Id %d %s %d",
712 ntohs(hdr->sequence_id),
713 "does not match",
714 ntohs(req_hdr->sequence_id));
715 goto reset;
716 }
717
718 GPTP_STATS_INC(port, rx_pdelay_resp_count);
719
720 return 0;
721
722 reset:
723 return -EINVAL;
724 }
725
gptp_handle_pdelay_follow_up(int port,struct net_pkt * pkt)726 int gptp_handle_pdelay_follow_up(int port, struct net_pkt *pkt)
727 {
728 struct gptp_pdelay_resp_follow_up *follow_up;
729 struct gptp_hdr *hdr, *req_hdr, *resp_hdr;
730 struct gptp_pdelay_req_state *state;
731 struct gptp_default_ds *default_ds;
732
733 hdr = GPTP_HDR(pkt);
734 follow_up = GPTP_PDELAY_RESP_FOLLOWUP(pkt);
735 state = &GPTP_PORT_STATE(port)->pdelay_req;
736 default_ds = GPTP_DEFAULT_DS();
737
738 if (!state->tx_pdelay_req_ptr) {
739 goto reset;
740 }
741
742 req_hdr = GPTP_HDR(state->tx_pdelay_req_ptr);
743
744 if (!state->rcvd_pdelay_resp_ptr) {
745 goto reset;
746 }
747
748 resp_hdr = GPTP_HDR(state->rcvd_pdelay_resp_ptr);
749
750 /* Check clock identity. */
751 if (memcmp(default_ds->clk_id, follow_up->requesting_port_id.clk_id,
752 GPTP_CLOCK_ID_LEN)) {
753 NET_WARN("Requesting Clock Identity %s", "does not match");
754 goto reset;
755 }
756
757 if (memcmp(default_ds->clk_id, hdr->port_id.clk_id,
758 GPTP_CLOCK_ID_LEN) == 0) {
759 NET_WARN("Source Clock Identity is local Clock Identity");
760 goto reset;
761 }
762
763 /* Check port number. */
764 if (follow_up->requesting_port_id.port_number != htons(port)) {
765 NET_WARN("Requesting Port Number %s", "does not match");
766 goto reset;
767 }
768
769 /* Check sequence id. */
770 if (hdr->sequence_id != req_hdr->sequence_id) {
771 NET_WARN("Sequence Id %d %s %d",
772 ntohs(hdr->sequence_id),
773 "does not match",
774 ntohs(req_hdr->sequence_id));
775 goto reset;
776 }
777
778 /* Check source port. */
779 if (memcmp(&hdr->port_id, &resp_hdr->port_id,
780 sizeof(hdr->port_id)) != 0) {
781 NET_WARN("pDelay response and follow up port IDs %s",
782 "does not match");
783 goto reset;
784 }
785
786 GPTP_STATS_INC(port, rx_fup_count);
787
788 return 0;
789
790 reset:
791 return -EINVAL;
792 }
793
gptp_handle_signaling(int port,struct net_pkt * pkt)794 void gptp_handle_signaling(int port, struct net_pkt *pkt)
795 {
796 struct gptp_port_ds *port_ds;
797 struct gptp_signaling *sig;
798
799 sig = GPTP_SIGNALING(pkt);
800 port_ds = GPTP_PORT_DS(port);
801
802 /* If time-synchronization not enabled, drop packet. */
803 if (!port_ds->ptt_port_enabled) {
804 return;
805 }
806
807 /* pDelay interval. */
808 gptp_update_pdelay_req_interval(port, sig->tlv.link_delay_itv);
809
810 /* Sync interval. */
811 gptp_update_sync_interval(port, sig->tlv.time_sync_itv);
812
813 /* Announce interval. */
814 gptp_update_announce_interval(port, sig->tlv.announce_itv);
815
816 port_ds->compute_neighbor_rate_ratio =
817 sig->tlv.compute_neighbor_rate_ratio;
818 port_ds->compute_neighbor_prop_delay =
819 sig->tlv.compute_neighbor_prop_delay;
820 }
821
gptp_send_sync(int port,struct net_pkt * pkt)822 void gptp_send_sync(int port, struct net_pkt *pkt)
823 {
824 if (!sync_cb_registered) {
825 net_if_register_timestamp_cb(&sync_timestamp_cb,
826 pkt,
827 net_pkt_iface(pkt),
828 gptp_sync_timestamp_callback);
829 sync_cb_registered = true;
830 }
831
832 GPTP_STATS_INC(port, tx_sync_count);
833
834 /* TS thread will send this back to us so increment ref count
835 * so that the packet is not removed when sending it.
836 * This will be unref'ed by timestamp callback in
837 * gptp_sync_timestamp_callback()
838 */
839 net_pkt_ref(pkt);
840
841 NET_GPTP_INFO("SYNC", pkt);
842
843 net_if_queue_tx(net_pkt_iface(pkt), pkt);
844 }
845
gptp_send_follow_up(int port,struct net_pkt * pkt)846 void gptp_send_follow_up(int port, struct net_pkt *pkt)
847 {
848 GPTP_STATS_INC(port, tx_fup_count);
849
850 NET_GPTP_INFO("FOLLOWUP", pkt);
851
852 net_if_queue_tx(net_pkt_iface(pkt), pkt);
853 }
854
gptp_send_announce(int port,struct net_pkt * pkt)855 void gptp_send_announce(int port, struct net_pkt *pkt)
856 {
857 GPTP_STATS_INC(port, tx_announce_count);
858
859 NET_GPTP_INFO("ANNOUNCE", pkt);
860
861 net_if_queue_tx(net_pkt_iface(pkt), pkt);
862 }
863
gptp_send_pdelay_req(int port)864 void gptp_send_pdelay_req(int port)
865 {
866 struct gptp_pdelay_req_state *state;
867 struct net_pkt *pkt;
868
869 NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
870 state = &GPTP_PORT_STATE(port)->pdelay_req;
871
872 pkt = gptp_prepare_pdelay_req(port);
873 if (pkt) {
874 if (state->tx_pdelay_req_ptr) {
875 NET_DBG("Unref pending %s %p", "PDELAY_REQ",
876 state->tx_pdelay_req_ptr);
877
878 net_pkt_unref(state->tx_pdelay_req_ptr);
879 }
880
881 /* Keep the buffer alive until pdelay_rate_ratio is computed. */
882 state->tx_pdelay_req_ptr = net_pkt_ref(pkt);
883
884 GPTP_STATS_INC(port, tx_pdelay_req_count);
885
886 NET_GPTP_INFO("PDELAY_REQ", pkt);
887
888 net_if_queue_tx(net_pkt_iface(pkt), pkt);
889 } else {
890 NET_ERR("Failed to prepare %s", "PDELAY_REQ");
891 }
892 }
893
gptp_send_pdelay_resp(int port,struct net_pkt * pkt,struct net_ptp_time * treq)894 void gptp_send_pdelay_resp(int port, struct net_pkt *pkt,
895 struct net_ptp_time *treq)
896 {
897 struct gptp_pdelay_resp *resp;
898 struct gptp_hdr *hdr;
899
900 hdr = GPTP_HDR(pkt);
901
902 /* No Fractional nsec .*/
903 hdr->correction_field = 0;
904
905 resp = GPTP_PDELAY_RESP(pkt);
906 resp->req_receipt_ts_secs_high = htons(treq->_sec.high);
907 resp->req_receipt_ts_secs_low = htonl(treq->_sec.low);
908 resp->req_receipt_ts_nsecs = htonl(treq->nanosecond);
909
910 GPTP_STATS_INC(port, tx_pdelay_resp_count);
911
912 NET_GPTP_INFO("PDELAY_RESP", pkt);
913
914 net_if_queue_tx(net_pkt_iface(pkt), pkt);
915 }
916
gptp_send_pdelay_follow_up(int port,struct net_pkt * pkt,struct net_ptp_time * tresp)917 void gptp_send_pdelay_follow_up(int port, struct net_pkt *pkt,
918 struct net_ptp_time *tresp)
919 {
920 struct gptp_pdelay_resp_follow_up *follow_up;
921 struct gptp_hdr *hdr;
922
923 hdr = GPTP_HDR(pkt);
924
925 /* No Fractional nsec .*/
926 hdr->correction_field = 0;
927
928 follow_up = GPTP_PDELAY_RESP_FOLLOWUP(pkt);
929 follow_up->resp_orig_ts_secs_high = htons(tresp->_sec.high);
930 follow_up->resp_orig_ts_secs_low = htonl(tresp->_sec.low);
931 follow_up->resp_orig_ts_nsecs = htonl(tresp->nanosecond);
932
933 GPTP_STATS_INC(port, tx_pdelay_resp_fup_count);
934
935 NET_GPTP_INFO("PDELAY_FOLLOWUP", pkt);
936
937 net_if_queue_tx(net_pkt_iface(pkt), pkt);
938 }
939