1 // SPDX-License-Identifier: LGPL-2.1
2 /*
3 * Copyright (C) 2019, VMware, Tzvetomir Stoyanov tz.stoyanov@gmail.com>
4 *
5 */
6
7 #include <fcntl.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <arpa/inet.h>
11 #include <sys/types.h>
12 #include <linux/types.h>
13 #include <time.h>
14 #include <sched.h>
15 #include <limits.h>
16
17 #include "trace-cmd.h"
18 #include "trace-cmd-private.h"
19 #include "tracefs.h"
20 #include "trace-tsync-local.h"
21 #include "trace-msg.h"
22 #include "trace-cmd-local.h"
23
24 typedef __be32 be32;
25 typedef __u64 u64;
26 typedef __s64 s64;
27
28 #define PTP_SYNC_LOOP 339
29
30 #define PTP_SYNC_PKT_START 1
31 #define PTP_SYNC_PKT_PROBE 2
32 #define PTP_SYNC_PKT_PROBES 3
33 #define PTP_SYNC_PKT_OFFSET 4
34 #define PTP_SYNC_PKT_END 5
35
36 /* print time sync debug messages */
37 /* #define TSYNC_DEBUG */
38
39 struct ptp_clock_sync {
40 struct tep_handle *tep;
41 struct tep_format_field *id;
42 int raw_id;
43 int marker_fd;
44 int series_id;
45 int flags;
46 int debug_fd;
47 };
48
49 enum {
50 /*
51 * Consider only the probe with fastest response time,
52 * otherwise make a histogram from all probes.
53 */
54 PTP_FLAG_FASTEST_RESPONSE = (1 << 0),
55 /*
56 * Use trace marker to get the clock,
57 * otherwise use the system clock directly.
58 */
59 PTP_FLAG_USE_MARKER = (1 << 1),
60 };
61 static int ptp_flags = PTP_FLAG_FASTEST_RESPONSE | PTP_FLAG_USE_MARKER;
62
63 /*
64 * Calculated using formula [CPU rate]*[calculated offset deviation]
65 * tested on 3GHz CPU, with x86-tsc trace clock and compare the calculated
66 * offset with /sys/kernel/debug/kvm/<VM ID>/vcpu0/tsc-offset
67 * measured 2000ns deviation
68 * using PTP flags PTP_FLAG_FASTEST_RESPONSE | PTP_FLAG_USE_MARKER
69 */
70 #define PTP_ACCURACY 6000
71 #define PTP_NAME "ptp"
72
73 struct ptp_clock_start_msg {
74 be32 series_id;
75 be32 flags;
76 } __packed;
77
78 struct ptp_clock_sample {
79 s64 ts;
80 be32 id;
81 } __packed;
82
83 struct ptp_clock_result_msg {
84 be32 series_id;
85 be32 count;
86 struct ptp_clock_sample samples[2*PTP_SYNC_LOOP];
87 } __packed;
88
89 struct ptp_clock_offset_msg {
90 s64 ts;
91 s64 offset;
92 };
93
94 struct ptp_markers_context {
95 struct clock_sync_context *clock;
96 struct ptp_clock_sync *ptp;
97 struct ptp_clock_result_msg msg;
98 int size;
99 };
100
101 struct ptp_marker_buf {
102 int local_id;
103 int remote_id;
104 int count;
105 int packet_id;
106 } __packed;
107
108 struct ptp_marker {
109 int series_id;
110 struct ptp_marker_buf data;
111 } __packed;
112
ptp_clock_sync_init(struct tracecmd_time_sync * tsync)113 static int ptp_clock_sync_init(struct tracecmd_time_sync *tsync)
114 {
115 const char *systems[] = {"ftrace", NULL};
116 struct clock_sync_context *clock_context;
117 struct ptp_clock_sync *ptp;
118 struct tep_event *raw;
119 char *path;
120
121 if (!tsync || !tsync->context)
122 return -1;
123 clock_context = (struct clock_sync_context *)tsync->context;
124 if (clock_context->proto_data)
125 return 0;
126
127 ptp = calloc(1, sizeof(struct ptp_clock_sync));
128 if (!ptp)
129 return -1;
130
131 ptp->marker_fd = -1;
132 ptp->debug_fd = -1;
133
134 path = tracefs_instance_get_dir(clock_context->instance);
135 if (!path)
136 goto error;
137 ptp->tep = tracefs_local_events_system(path, systems);
138 tracefs_put_tracing_file(path);
139 if (!ptp->tep)
140 goto error;
141 raw = tep_find_event_by_name(ptp->tep, "ftrace", "raw_data");
142 if (!raw)
143 goto error;
144 ptp->id = tep_find_field(raw, "id");
145 if (!ptp->id)
146 goto error;
147 ptp->raw_id = raw->id;
148
149 tep_set_file_bigendian(ptp->tep, tracecmd_host_bigendian());
150 tep_set_local_bigendian(ptp->tep, tracecmd_host_bigendian());
151
152 path = tracefs_instance_get_file(clock_context->instance, "trace_marker_raw");
153 if (!path)
154 goto error;
155 ptp->marker_fd = open(path, O_WRONLY);
156 tracefs_put_tracing_file(path);
157
158 clock_context->proto_data = ptp;
159
160 #ifdef TSYNC_DEBUG
161 if (clock_context->is_server) {
162 char buff[256];
163 int res_fd;
164
165 sprintf(buff, "res-id%d.txt", clock_context->remote_id);
166
167 res_fd = open(buff, O_CREAT|O_WRONLY|O_TRUNC, 0644);
168 if (res_fd > 0)
169 close(res_fd);
170 }
171 #endif
172
173 return 0;
174
175 error:
176 if (ptp) {
177 tep_free(ptp->tep);
178 if (ptp->marker_fd >= 0)
179 close(ptp->marker_fd);
180 }
181 free(ptp);
182 return -1;
183 }
184
ptp_clock_sync_free(struct tracecmd_time_sync * tsync)185 static int ptp_clock_sync_free(struct tracecmd_time_sync *tsync)
186 {
187 struct clock_sync_context *clock_context;
188 struct ptp_clock_sync *ptp;
189
190 if (!tsync || !tsync->context)
191 return -1;
192 clock_context = (struct clock_sync_context *)tsync->context;
193
194 if (clock_context && clock_context->proto_data) {
195 ptp = (struct ptp_clock_sync *)clock_context->proto_data;
196 tep_free(ptp->tep);
197 if (ptp->marker_fd >= 0)
198 close(ptp->marker_fd);
199 if (ptp->debug_fd >= 0)
200 close(ptp->debug_fd);
201 free(clock_context->proto_data);
202 clock_context->proto_data = NULL;
203 }
204 return 0;
205 }
206
207 /* Save the timestamps of sent ('s') and returned ('r') probes in the
208 * ctx->msg.samples[] array. Depending of the context (server or client), there
209 * may be only returned probes, or both sent and returned probes. The returned
210 * probes are saved first in the array, after them are the sent probes.
211 * Depending of the context, the array can be with size:
212 * [0 .. max data.count] - holds only returned probes
213 * [0 .. 2 * max data.count] - holds both returned and sent probes
214 */
ptp_probe_store(struct ptp_markers_context * ctx,struct ptp_marker * marker,unsigned long long ts)215 static void ptp_probe_store(struct ptp_markers_context *ctx,
216 struct ptp_marker *marker,
217 unsigned long long ts)
218 {
219 int index = -1;
220
221 if (marker->data.packet_id == 'r' &&
222 marker->data.count <= ctx->size) {
223 index = marker->data.count - 1;
224 } else if (marker->data.packet_id == 's' &&
225 marker->data.count * 2 <= ctx->size){
226 index = ctx->size / 2 + marker->data.count - 1;
227 }
228
229 if (index >= 0) {
230 ctx->msg.samples[index].id = marker->data.count;
231 ctx->msg.samples[index].ts = ts;
232 ctx->msg.count++;
233 }
234 }
235
ptp_marker_find(struct tep_event * event,struct tep_record * record,int cpu,void * context)236 static int ptp_marker_find(struct tep_event *event, struct tep_record *record,
237 int cpu, void *context)
238 {
239 struct ptp_markers_context *ctx;
240 struct ptp_marker *marker;
241
242 ctx = (struct ptp_markers_context *)context;
243
244 /* Make sure this is our event */
245 if (event->id != ctx->ptp->raw_id || !ctx->ptp->id)
246 return 0;
247 if (record->size >= (ctx->ptp->id->offset + sizeof(struct ptp_marker))) {
248 marker = (struct ptp_marker *)(record->data + ctx->ptp->id->offset);
249 if (marker->data.local_id == ctx->clock->local_id &&
250 marker->data.remote_id == ctx->clock->remote_id &&
251 marker->series_id == ctx->ptp->series_id &&
252 marker->data.count)
253 ptp_probe_store(ctx, marker, record->ts);
254 }
255
256 return 0;
257 }
258
good_probe(struct ptp_clock_sample * server_sample,struct ptp_clock_sample * send_sample,struct ptp_clock_sample * client_sample,int * bad_probes)259 static inline bool good_probe(struct ptp_clock_sample *server_sample,
260 struct ptp_clock_sample *send_sample,
261 struct ptp_clock_sample *client_sample,
262 int *bad_probes)
263 {
264 if (server_sample->ts && send_sample->ts && client_sample->ts &&
265 server_sample->id == send_sample->id &&
266 server_sample->id == client_sample->id)
267 return true;
268 (*bad_probes)++;
269 return false;
270 }
271
ptp_calc_offset_fastest(struct clock_sync_context * clock,struct ptp_clock_result_msg * server,struct ptp_clock_result_msg * client,long long * offset_ret,long long * ts_ret,int * bad_probes)272 static int ptp_calc_offset_fastest(struct clock_sync_context *clock,
273 struct ptp_clock_result_msg *server,
274 struct ptp_clock_result_msg *client,
275 long long *offset_ret, long long *ts_ret,
276 int *bad_probes)
277 {
278 struct ptp_clock_sample *sample_send;
279 long long delta_min = LLONG_MAX;
280 long long offset = 0;
281 long long delta = 0;
282 long long ts = 0;
283 int max_i;
284 int i;
285
286 *bad_probes = 0;
287 sample_send = server->samples + (server->count / 2);
288 max_i = server->count / 2 < client->count ?
289 server->count / 2 : client->count;
290 for (i = 0; i < max_i; i++) {
291 if (!good_probe(&server->samples[i], &sample_send[i],
292 &client->samples[i], bad_probes))
293 continue;
294 ts = (sample_send[i].ts + server->samples[i].ts) / 2;
295 offset = client->samples[i].ts - ts;
296
297 delta = server->samples[i].ts - sample_send[i].ts;
298 if (delta_min > delta) {
299 delta_min = delta;
300 *offset_ret = offset;
301 *ts_ret = ts;
302 }
303 #ifdef TSYNC_DEBUG
304 {
305 struct ptp_clock_sync *ptp;
306
307 ptp = (struct ptp_clock_sync *)clock->proto_data;
308 if (ptp && ptp->debug_fd > 0) {
309 char buff[256];
310
311 sprintf(buff, "%lld %lld %lld\n",
312 ts, client->samples[i].ts, offset);
313 write(ptp->debug_fd, buff, strlen(buff));
314 }
315 }
316 #endif
317 }
318
319 return 0;
320 }
321
ptp_calc_offset_hist(struct clock_sync_context * clock,struct ptp_clock_result_msg * server,struct ptp_clock_result_msg * client,long long * offset_ret,long long * ts_ret,int * bad_probes)322 static int ptp_calc_offset_hist(struct clock_sync_context *clock,
323 struct ptp_clock_result_msg *server,
324 struct ptp_clock_result_msg *client,
325 long long *offset_ret, long long *ts_ret,
326 int *bad_probes)
327 {
328 struct ptp_clock_sample *sample_send;
329 long long timestamps[PTP_SYNC_LOOP];
330 long long offsets[PTP_SYNC_LOOP];
331 long long offset_min = LLONG_MAX;
332 long long offset_max = 0;
333 int hist[PTP_SYNC_LOOP];
334 int ind, max = 0;
335 long long bin;
336 int i, k = 0;
337
338 *bad_probes = 0;
339 memset(hist, 0, sizeof(int) * PTP_SYNC_LOOP);
340 sample_send = server->samples + (server->count / 2);
341 for (i = 0; i * 2 < server->count && i < client->count; i++) {
342 if (!good_probe(&server->samples[i], &sample_send[i],
343 &client->samples[i], bad_probes))
344 continue;
345 timestamps[k] = (sample_send[i].ts + server->samples[i].ts) / 2;
346 offsets[k] = client->samples[i].ts - timestamps[k];
347 if (offset_max < llabs(offsets[k]))
348 offset_max = llabs(offsets[k]);
349 if (offset_min > llabs(offsets[k]))
350 offset_min = llabs(offsets[k]);
351 #ifdef TSYNC_DEBUG
352 {
353 struct ptp_clock_sync *ptp;
354
355 ptp = (struct ptp_clock_sync *)clock->proto_data;
356
357 if (ptp && ptp->debug_fd > 0) {
358 char buff[256];
359
360 sprintf(buff, "%lld %lld %lld\n",
361 timestamps[k],
362 client->samples[i].ts, offsets[k]);
363 write(ptp->debug_fd, buff, strlen(buff));
364 }
365 }
366 #endif
367 k++;
368 }
369
370 bin = (offset_max - offset_min) / PTP_SYNC_LOOP;
371 for (i = 0; i < k; i++) {
372 ind = (llabs(offsets[i]) - offset_min) / bin;
373 if (ind < PTP_SYNC_LOOP) {
374 hist[ind]++;
375 if (max < hist[ind]) {
376 max = hist[ind];
377 *offset_ret = offsets[i];
378 *ts_ret = timestamps[i];
379 }
380 }
381 }
382
383 return 0;
384 }
385
ntoh_ptp_results(struct ptp_clock_result_msg * msg)386 static void ntoh_ptp_results(struct ptp_clock_result_msg *msg)
387 {
388 int i;
389
390 msg->count = ntohl(msg->count);
391 for (i = 0; i < msg->count; i++) {
392 msg->samples[i].id = ntohl(msg->samples[i].id);
393 msg->samples[i].ts = ntohll(msg->samples[i].ts);
394 }
395 msg->series_id = ntohl(msg->series_id);
396 }
397
398
hton_ptp_results(struct ptp_clock_result_msg * msg)399 static void hton_ptp_results(struct ptp_clock_result_msg *msg)
400 {
401 int i;
402
403 for (i = 0; i < msg->count; i++) {
404 msg->samples[i].id = htonl(msg->samples[i].id);
405 msg->samples[i].ts = htonll(msg->samples[i].ts);
406 }
407 msg->series_id = htonl(msg->series_id);
408 msg->count = htonl(msg->count);
409 }
410
ptp_track_clock(struct ptp_markers_context * ctx,struct ptp_marker * marker)411 static inline void ptp_track_clock(struct ptp_markers_context *ctx,
412 struct ptp_marker *marker)
413 {
414 if (ctx->ptp->flags & PTP_FLAG_USE_MARKER) {
415 write(ctx->ptp->marker_fd, marker, sizeof(struct ptp_marker));
416 } else {
417 struct timespec clock;
418 unsigned long long ts;
419
420 clock_gettime(CLOCK_MONOTONIC_RAW, &clock);
421 ts = clock.tv_sec * 1000000000LL;
422 ts += clock.tv_nsec;
423 ptp_probe_store(ctx, marker, ts);
424 }
425 }
426
ptp_clock_client(struct tracecmd_time_sync * tsync,long long * offset,long long * timestamp)427 static int ptp_clock_client(struct tracecmd_time_sync *tsync,
428 long long *offset, long long *timestamp)
429 {
430 char sync_proto[TRACECMD_TSYNC_PNAME_LENGTH];
431 struct clock_sync_context *clock_context;
432 struct ptp_clock_offset_msg res_offset;
433 struct ptp_clock_start_msg start;
434 struct ptp_markers_context ctx;
435 struct ptp_clock_sync *ptp;
436 struct ptp_marker marker;
437 unsigned int sync_msg;
438 unsigned int size;
439 char *msg;
440 int count;
441 int ret;
442
443 if (!tsync || !tsync->context || !tsync->msg_handle)
444 return -1;
445
446 clock_context = (struct clock_sync_context *)tsync->context;
447 if (clock_context->proto_data == NULL)
448 return -1;
449
450 ptp = (struct ptp_clock_sync *)clock_context->proto_data;
451 size = sizeof(start);
452 msg = (char *)&start;
453 ret = tracecmd_msg_recv_time_sync(tsync->msg_handle,
454 sync_proto, &sync_msg,
455 &size, &msg);
456 if (ret || strncmp(sync_proto, PTP_NAME, TRACECMD_TSYNC_PNAME_LENGTH) ||
457 sync_msg != PTP_SYNC_PKT_START)
458 return -1;
459 ret = tracecmd_msg_send_time_sync(tsync->msg_handle, PTP_NAME,
460 PTP_SYNC_PKT_START, sizeof(start),
461 (char *)&start);
462 marker.data.local_id = clock_context->local_id;
463 marker.data.remote_id = clock_context->remote_id;
464 marker.series_id = ntohl(start.series_id);
465 marker.data.packet_id = 'r';
466 ptp->series_id = marker.series_id;
467 ptp->flags = ntohl(start.flags);
468 msg = (char *)&count;
469 size = sizeof(count);
470 ctx.msg.count = 0;
471 ctx.size = PTP_SYNC_LOOP;
472 ctx.ptp = ptp;
473 ctx.clock = clock_context;
474 ctx.msg.series_id = ptp->series_id;
475 while (true) {
476 count = 0;
477 ret = tracecmd_msg_recv_time_sync(tsync->msg_handle,
478 sync_proto, &sync_msg,
479 &size, &msg);
480 if (ret || strncmp(sync_proto, PTP_NAME, TRACECMD_TSYNC_PNAME_LENGTH) ||
481 sync_msg != PTP_SYNC_PKT_PROBE || !ntohl(count))
482 break;
483 marker.data.count = ntohl(count);
484 ptp_track_clock(&ctx, &marker);
485 ret = tracecmd_msg_send_time_sync(tsync->msg_handle, PTP_NAME,
486 PTP_SYNC_PKT_PROBE,
487 sizeof(count), (char *)&count);
488 if (ret)
489 break;
490 }
491
492 if (strncmp(sync_proto, PTP_NAME, TRACECMD_TSYNC_PNAME_LENGTH) ||
493 sync_msg != PTP_SYNC_PKT_END)
494 return -1;
495
496 if (ptp->flags & PTP_FLAG_USE_MARKER)
497 tracefs_iterate_raw_events(ptp->tep, clock_context->instance,
498 NULL, 0, ptp_marker_find, &ctx);
499
500 hton_ptp_results(&ctx.msg);
501 ret = tracecmd_msg_send_time_sync(tsync->msg_handle, PTP_NAME,
502 PTP_SYNC_PKT_PROBES,
503 sizeof(ctx.msg), (char *)&ctx.msg);
504
505 msg = (char *)&res_offset;
506 size = sizeof(res_offset);
507 ret = tracecmd_msg_recv_time_sync(tsync->msg_handle,
508 sync_proto, &sync_msg,
509 &size, (char **)&msg);
510 if (ret || strncmp(sync_proto, PTP_NAME, TRACECMD_TSYNC_PNAME_LENGTH) ||
511 sync_msg != PTP_SYNC_PKT_OFFSET)
512 return -1;
513
514 *offset = ntohll(res_offset.offset);
515 *timestamp = ntohll(res_offset.ts);
516
517 return 0;
518 }
519
520
ptp_clock_server(struct tracecmd_time_sync * tsync,long long * offset,long long * timestamp)521 static int ptp_clock_server(struct tracecmd_time_sync *tsync,
522 long long *offset, long long *timestamp)
523 {
524 char sync_proto[TRACECMD_TSYNC_PNAME_LENGTH];
525 struct ptp_clock_result_msg *results = NULL;
526 struct clock_sync_context *clock_context;
527 struct ptp_clock_offset_msg res_offset;
528 struct ptp_clock_start_msg start;
529 struct ptp_markers_context ctx;
530 int sync_loop = PTP_SYNC_LOOP;
531 struct ptp_clock_sync *ptp;
532 struct ptp_marker marker;
533 unsigned int sync_msg;
534 unsigned int size;
535 int bad_probes;
536 int count = 1;
537 int msg_count;
538 int msg_ret;
539 char *msg;
540 int ret;
541
542 if (!tsync || !tsync->context || !tsync->msg_handle)
543 return -1;
544
545 clock_context = (struct clock_sync_context *)tsync->context;
546 if (clock_context->proto_data == NULL)
547 return -1;
548
549 ptp = (struct ptp_clock_sync *)clock_context->proto_data;
550 ptp->flags = ptp_flags;
551 memset(&start, 0, sizeof(start));
552 start.series_id = htonl(ptp->series_id + 1);
553 start.flags = htonl(ptp->flags);
554 ret = tracecmd_msg_send_time_sync(tsync->msg_handle, PTP_NAME,
555 PTP_SYNC_PKT_START, sizeof(start),
556 (char *)&start);
557 if (!ret)
558 ret = tracecmd_msg_recv_time_sync(tsync->msg_handle,
559 sync_proto, &sync_msg,
560 NULL, NULL);
561 if (ret || strncmp(sync_proto, PTP_NAME, TRACECMD_TSYNC_PNAME_LENGTH) ||
562 sync_msg != PTP_SYNC_PKT_START)
563 return -1;
564
565 tracefs_instance_file_write(clock_context->instance, "trace", "\0");
566
567 ptp->series_id++;
568 marker.data.local_id = clock_context->local_id;
569 marker.data.remote_id = clock_context->remote_id;
570 marker.series_id = ptp->series_id;
571 msg = (char *)&msg_ret;
572 size = sizeof(msg_ret);
573 ctx.size = 2*PTP_SYNC_LOOP;
574 ctx.ptp = ptp;
575 ctx.clock = clock_context;
576 ctx.msg.count = 0;
577 ctx.msg.series_id = ptp->series_id;
578 do {
579 marker.data.count = count++;
580 marker.data.packet_id = 's';
581 msg_count = htonl(marker.data.count);
582 ptp_track_clock(&ctx, &marker);
583 ret = tracecmd_msg_send_time_sync(tsync->msg_handle, PTP_NAME,
584 PTP_SYNC_PKT_PROBE,
585 sizeof(msg_count),
586 (char *)&msg_count);
587 if (!ret)
588 ret = tracecmd_msg_recv_time_sync(tsync->msg_handle,
589 sync_proto, &sync_msg,
590 &size, &msg);
591
592 marker.data.packet_id = 'r';
593 ptp_track_clock(&ctx, &marker);
594 if (ret || strncmp(sync_proto, PTP_NAME, TRACECMD_TSYNC_PNAME_LENGTH) ||
595 sync_msg != PTP_SYNC_PKT_PROBE ||
596 ntohl(msg_ret) != marker.data.count)
597 break;
598 } while (--sync_loop);
599
600 if (sync_loop)
601 return -1;
602
603 ret = tracecmd_msg_send_time_sync(tsync->msg_handle, PTP_NAME,
604 PTP_SYNC_PKT_END, 0, NULL);
605
606 size = 0;
607 ret = tracecmd_msg_recv_time_sync(tsync->msg_handle,
608 sync_proto, &sync_msg,
609 &size, (char **)&results);
610 if (ret || strncmp(sync_proto, PTP_NAME, TRACECMD_TSYNC_PNAME_LENGTH) ||
611 sync_msg != PTP_SYNC_PKT_PROBES || size == 0 || results == NULL)
612 return -1;
613
614 ntoh_ptp_results(results);
615 if (ptp->flags & PTP_FLAG_USE_MARKER)
616 tracefs_iterate_raw_events(ptp->tep, clock_context->instance,
617 NULL, 0, ptp_marker_find, &ctx);
618 if (ptp->flags & PTP_FLAG_FASTEST_RESPONSE)
619 ptp_calc_offset_fastest(clock_context, &ctx.msg, results, offset,
620 timestamp, &bad_probes);
621 else
622 ptp_calc_offset_hist(clock_context, &ctx.msg, results, offset,
623 timestamp, &bad_probes);
624 #ifdef TSYNC_DEBUG
625 {
626 char buff[256];
627 int res_fd;
628
629 sprintf(buff, "res-id%d.txt", clock_context->remote_id);
630
631 res_fd = open(buff, O_WRONLY|O_APPEND, 0644);
632 if (res_fd > 0) {
633 if (*offset && *timestamp) {
634 sprintf(buff, "%d %lld %lld\n",
635 ptp->series_id, *offset, *timestamp);
636 write(res_fd, buff, strlen(buff));
637 }
638 close(res_fd);
639 }
640
641 printf("\n calculated offset %d: %lld, %d probes, filtered out %d, PTP flags 0x%X\n\r",
642 ptp->series_id, *offset, results->count, bad_probes, ptp->flags);
643 if (ptp && ptp->debug_fd > 0) {
644 sprintf(buff, "%lld %lld 0\n", *offset, *timestamp);
645 write(ptp->debug_fd, buff, strlen(buff));
646 close(ptp->debug_fd);
647 ptp->debug_fd = -1;
648 }
649
650 }
651 #endif
652
653 res_offset.offset = htonll(*offset);
654 res_offset.ts = htonll(*timestamp);
655 ret = tracecmd_msg_send_time_sync(tsync->msg_handle, PTP_NAME,
656 PTP_SYNC_PKT_OFFSET,
657 sizeof(res_offset),
658 (char *)&res_offset);
659
660 free(results);
661 return 0;
662 }
663
ptp_clock_sync_calc(struct tracecmd_time_sync * tsync,long long * offset,long long * scaling,long long * frac,long long * timestamp,unsigned int cpu)664 static int ptp_clock_sync_calc(struct tracecmd_time_sync *tsync,
665 long long *offset, long long *scaling, long long *frac,
666 long long *timestamp, unsigned int cpu)
667 {
668 struct clock_sync_context *clock_context;
669 int ret;
670
671 if (!tsync || !tsync->context)
672 return -1;
673 clock_context = (struct clock_sync_context *)tsync->context;
674
675 #ifdef TSYNC_DEBUG
676 if (clock_context->is_server) {
677 struct ptp_clock_sync *ptp;
678 char buff[256];
679
680 ptp = (struct ptp_clock_sync *)clock_context->proto_data;
681 if (ptp->debug_fd > 0)
682 close(ptp->debug_fd);
683 sprintf(buff, "s-id%d_%d.txt",
684 clock_context->remote_id, ptp->series_id+1);
685 ptp->debug_fd = open(buff, O_CREAT|O_WRONLY|O_TRUNC, 0644);
686 }
687 #endif
688
689 if (scaling)
690 *scaling = 1;
691 if (frac)
692 *frac = 0;
693 if (clock_context->is_server)
694 ret = ptp_clock_server(tsync, offset, timestamp);
695 else
696 ret = ptp_clock_client(tsync, offset, timestamp);
697
698 return ret;
699 }
700
ptp_clock_sync_register(void)701 int ptp_clock_sync_register(void)
702 {
703 return tracecmd_tsync_proto_register(PTP_NAME, PTP_ACCURACY,
704 TRACECMD_TIME_SYNC_ROLE_GUEST |
705 TRACECMD_TIME_SYNC_ROLE_HOST |
706 TRACECMD_TIME_SYNC_ROLE_CLIENT |
707 TRACECMD_TIME_SYNC_ROLE_SERVER,
708 0, TRACECMD_TSYNC_FLAG_INTERPOLATE,
709 ptp_clock_sync_init,
710 ptp_clock_sync_free,
711 ptp_clock_sync_calc);
712
713 }
714
ptp_clock_sync_unregister(void)715 int ptp_clock_sync_unregister(void)
716 {
717 return tracecmd_tsync_proto_unregister(PTP_NAME);
718 }
719