Add support for testing the new PTP_SYS_OFFSET_EXTENDED_ATTRS and PTP_SYS_OFFSET_PRECISE_ATTRS ioctls in the testptp utility.
Add a "-a" modifier that requests clock quality attributes (error_bound, status, timescale) alongside the existing extended (-x) and precise (-X) offset requests: -x N -a: extended offset with attributes (N samples) -X -a: precise cross-timestamp with attributes When the device does not report a given attribute, print an explicit "not reported" line so all attributes are always accounted for. Also print the system counter value and its identifier (sys_counter, sys_counter_id) returned in struct ptp_sys_time, so the counter source is visible; a sys_counter_id of 0 (UNKNOWN) with sys_counter 0 indicates an unavailable or unidentified counter source. These options allow testing and validation of PHC devices that provide clock quality information alongside timestamps. Also display the new extended_attrs/precise_attrs capabilities in the -c output, and update print_system_timestamp to print unrecognized clock types instead of silently dropping them. Co-developed-by: Amit Bernstein <[email protected]> Signed-off-by: Amit Bernstein <[email protected]> Signed-off-by: Arthur Kiyanovski <[email protected]> --- tools/testing/selftests/ptp/testptp.c | 124 +++++++++++++++++++++++++- 1 file changed, 120 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/ptp/testptp.c b/tools/testing/selftests/ptp/testptp.c index d603d9f82237..62b1d0340d71 100644 --- a/tools/testing/selftests/ptp/testptp.c +++ b/tools/testing/selftests/ptp/testptp.c @@ -148,6 +148,8 @@ static void usage(char *progname) " -T val set the ptp clock time to 'val' seconds\n" " -x val get an extended ptp clock time with the desired number of samples (up to %d)\n" " -X get a ptp clock cross timestamp\n" + " -a also report clock quality attributes (error_bound,\n" + " status, timescale); use together with -x or -X\n" " -y val pre/post tstamp timebase to use {realtime|monotonic|monotonic-raw}\n" " -z test combinations of rising/falling external time stamp flags\n", progname, PTP_MAX_SAMPLES); @@ -174,8 +176,10 @@ static void print_system_timestamp(int sample_num, __kernel_clockid_t clockid, break; } - if (!name) + if (!name) { + printf("sample #%2d: unknown clock %d\n", sample_num, clockid); return; + } printf("sample #%2d: %s time %s: %lld.%09u\n", sample_num, name, when, sec, nsec); @@ -194,6 +198,7 @@ int main(int argc, char *argv[]) struct ptp_sys_offset *sysoff; struct ptp_sys_offset_extended *soe; struct ptp_sys_offset_precise *xts; + struct ptp_sys_offset_attrs *attrs_data; char *progname; unsigned int i; @@ -215,6 +220,7 @@ int main(int argc, char *argv[]) int pct_offset = 0; int getextended = 0; int getcross = 0; + int use_attrs = 0; int n_samples = 0; int pin_index = -1, pin_func; int pps = -1; @@ -232,7 +238,8 @@ int main(int argc, char *argv[]) progname = strrchr(argv[0], '/'); progname = progname ? 1+progname : argv[0]; - while (EOF != (c = getopt(argc, argv, "cd:e:E:f:F:ghH:i:k:lL:n:o:p:P:rsSt:T:w:x:Xy:z"))) { + while (EOF != (c = getopt(argc, argv, + "acd:e:E:f:F:ghH:i:k:lL:n:o:p:P:rsSt:T:w:x:Xy:z"))) { switch (c) { case 'c': capabilities = 1; @@ -317,6 +324,9 @@ int main(int argc, char *argv[]) return -1; } break; + case 'a': + use_attrs = 1; + break; case 'X': getcross = 1; break; @@ -373,6 +383,8 @@ int main(int argc, char *argv[]) " %d programmable pins\n" " %d cross timestamping\n" " %d adjust_phase\n" + " %d extended_attrs\n" + " %d precise_attrs\n" " %d maximum phase adjustment (ns)\n", caps.max_adj, caps.n_alarm, @@ -382,6 +394,8 @@ int main(int argc, char *argv[]) caps.n_pins, caps.cross_timestamping, caps.adjust_phase, + caps.extended_attrs, + caps.precise_attrs, caps.max_phase_adj); } } @@ -619,7 +633,7 @@ int main(int argc, char *argv[]) free(sysoff); } - if (getextended) { + if (getextended && !use_attrs) { soe = calloc(1, sizeof(*soe)); if (!soe) { perror("calloc"); @@ -654,7 +668,60 @@ int main(int argc, char *argv[]) free(soe); } - if (getcross) { + if (getextended && use_attrs) { + attrs_data = calloc(1, sizeof(*attrs_data) + + getextended * sizeof(struct ptp_timestamp)); + if (!attrs_data) { + perror("calloc"); + return -1; + } + + attrs_data->request.num_samples = getextended; + attrs_data->request.clock_id = ext_clockid; + + if (ioctl(fd, PTP_SYS_OFFSET_EXTENDED_ATTRS, attrs_data)) { + perror("PTP_SYS_OFFSET_EXTENDED_ATTRS"); + } else { + printf("extended attrs timestamp request returned %d samples\n", + getextended); + + for (i = 0; i < getextended; i++) { + struct ptp_timestamp *ts = &attrs_data->timestamps[i]; + + printf(" sample #%u:\n", i); + printf(" sys before: %lld ns\n", + (long long)ts->pre_systime.sys_time); + printf(" sys_counter_id: %u\n", + ts->pre_systime.sys_counter_id); + printf(" sys_counter: %llu\n", + (unsigned long long)ts->pre_systime.sys_counter); + printf(" phc time: %lld.%09u\n", + ts->devtime.device_time.sec, + ts->devtime.device_time.nsec); + if (ts->devtime.attrs.valid & PTP_ATTRS_VALID_ERROR_BOUND) + printf(" error_bound: %u ns\n", + ts->devtime.attrs.error_bound); + else + printf(" error_bound: not reported\n"); + if (ts->devtime.attrs.valid & PTP_ATTRS_VALID_STATUS) + printf(" status: %u\n", + ts->devtime.attrs.status); + else + printf(" status: not reported\n"); + if (ts->devtime.attrs.valid & PTP_ATTRS_VALID_TIMESCALE) + printf(" timescale: %u\n", + ts->devtime.attrs.timescale); + else + printf(" timescale: not reported\n"); + printf(" sys after: %lld ns\n", + (long long)ts->post_systime.sys_time); + } + } + + free(attrs_data); + } + + if (getcross && !use_attrs) { xts = calloc(1, sizeof(*xts)); if (!xts) { perror("calloc"); @@ -677,6 +744,55 @@ int main(int argc, char *argv[]) free(xts); } + if (getcross && use_attrs) { + attrs_data = calloc(1, sizeof(*attrs_data) + + sizeof(struct ptp_timestamp)); + if (!attrs_data) { + perror("calloc"); + return -1; + } + + attrs_data->request.num_samples = 1; + /* precise crosstimestamp supports only CLOCK_REALTIME/AUX */ + attrs_data->request.clock_id = CLOCK_REALTIME; + + if (ioctl(fd, PTP_SYS_OFFSET_PRECISE_ATTRS, attrs_data)) { + perror("PTP_SYS_OFFSET_PRECISE_ATTRS"); + } else { + struct ptp_timestamp *ts = &attrs_data->timestamps[0]; + + puts("precise attrs crosstimestamp request okay"); + printf("device time: %lld.%09u\n", + ts->devtime.device_time.sec, + ts->devtime.device_time.nsec); + printf("system time: %lld ns\n", + (long long)ts->systime.sys_time); + printf("raw time: %lld ns\n", + (long long)ts->systime.sys_rawtime); + printf("sys_counter_id: %u\n", + ts->systime.sys_counter_id); + printf("sys_counter: %llu\n", + (unsigned long long)ts->systime.sys_counter); + if (ts->devtime.attrs.valid & PTP_ATTRS_VALID_ERROR_BOUND) + printf("error_bound: %u ns\n", + ts->devtime.attrs.error_bound); + else + printf("error_bound: not reported\n"); + if (ts->devtime.attrs.valid & PTP_ATTRS_VALID_STATUS) + printf("status: %u\n", + ts->devtime.attrs.status); + else + printf("status: not reported\n"); + if (ts->devtime.attrs.valid & PTP_ATTRS_VALID_TIMESCALE) + printf("timescale: %u\n", + ts->devtime.attrs.timescale); + else + printf("timescale: not reported\n"); + } + + free(attrs_data); + } + if (channel >= 0) { if (ioctl(fd, PTP_MASK_CLEAR_ALL)) { perror("PTP_MASK_CLEAR_ALL"); -- 2.47.3
