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