diff --git a/clock.c b/clock.c index 92ff9e4..eeefd39 100644 --- a/clock.c +++ b/clock.c @@ -134,6 +134,7 @@ static int clock_management_response(struct clock *c, struct port *p, int id, int datalen = 0, err, pdulen, respond = 0; struct management_tlv *tlv; struct ptp_message *rsp; + struct time_status_np *tsn; struct PortIdentity pid = port_identity(p); rsp = port_management_reply(pid, p, req); @@ -150,6 +151,24 @@ static int clock_management_response(struct clock *c, struct port *p, int id, datalen = sizeof(c->cur); respond = 1; break; + case TIME_STATUS_NP: + tsn = (struct time_status_np *) tlv->data; + tsn->master_offset = c->master_offset; + tsn->ingress_time = tmv_to_nanoseconds(c->t2); + tsn->cumulativeScaledRateOffset = + (UInteger32) (c->status.cumulativeScaledRateOffset + + c->nrr * POW2_41 - POW2_41); + tsn->scaledLastGmPhaseChange = c->status.scaledLastGmPhaseChange; + tsn->gmTimeBaseIndicator = c->status.gmTimeBaseIndicator; + tsn->lastGmPhaseChange = c->status.lastGmPhaseChange; + if (cid_eq(&c->dad.grandmasterIdentity, &c->dds.clockIdentity)) + tsn->gmPresent = 0; + else + tsn->gmPresent = 1; + tsn->gmIdentity = c->dad.grandmasterIdentity; + datalen = sizeof(*tsn); + respond = 1; + break; } if (respond) { tlv->length = sizeof(tlv->id) + datalen; @@ -383,7 +402,9 @@ struct clock *clock_create(int phc_index, struct interface *iface, int count, if (c->nports) clock_destroy(c); - if (phc_index >= 0) { + if (c->dds.free_running) { + c->clkid = CLOCK_INVALID; + } else if (phc_index >= 0) { snprintf(phc, 31, "/dev/ptp%d", phc_index); c->clkid = phc_open(phc); if (c->clkid == CLOCK_INVALID) { diff --git a/pmc.c b/pmc.c index f9b1df6..8f3140b 100644 --- a/pmc.c +++ b/pmc.c @@ -35,6 +35,7 @@ #define BAD_ID -1 #define AMBIGUOUS_ID -2 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define P41 ((double)(1ULL << 41)) static UInteger16 sequence_id; static UInteger8 boundary_hops = 1; @@ -87,6 +88,7 @@ struct management_id idtab[] = { { "ALTERNATE_TIME_OFFSET_PROPERTIES", ALTERNATE_TIME_OFFSET_PROPERTIES, not_supported }, { "TRANSPARENT_CLOCK_DEFAULT_DATA_SET", TRANSPARENT_CLOCK_DEFAULT_DATA_SET, not_supported }, { "PRIMARY_DOMAIN", PRIMARY_DOMAIN, not_supported }, + { "TIME_STATUS_NP", TIME_STATUS_NP, do_get_action }, /* Port management ID values */ { "NULL_MANAGEMENT", NULL_MANAGEMENT, null_management }, { "CLOCK_DESCRIPTION", CLOCK_DESCRIPTION, not_supported }, @@ -169,6 +171,7 @@ static void pmc_show(struct ptp_message *msg, FILE *fp) struct TLV *tlv; struct management_tlv *mgt; struct currentDS *cds; + struct time_status_np *tsn; if (msg_type(msg) != MANAGEMENT) { return; } @@ -202,6 +205,28 @@ static void pmc_show(struct ptp_message *msg, FILE *fp) cds->stepsRemoved, cds->offsetFromMaster / 65536.0, cds->meanPathDelay / 65536.0); break; + case TIME_STATUS_NP: + tsn = (struct time_status_np *) mgt->data; + fprintf(fp, "TIME_STATUS_NP " + IFMT "master_offset %lld " + IFMT "ingress_time %lld " + IFMT "cumulativeScaledRateOffset %+.9f " + IFMT "scaledLastGmPhaseChange %d " + IFMT "gmTimeBaseIndicator %hu " + IFMT "lastGmPhaseChange 0x%04hx'%016llx.%04hx " + IFMT "gmPresent %s " + IFMT "gmIdentity %s ", + tsn->master_offset, + tsn->ingress_time, + 1.0 + (tsn->cumulativeScaledRateOffset + 0.0) / P41, + tsn->scaledLastGmPhaseChange, + tsn->gmTimeBaseIndicator, + tsn->lastGmPhaseChange.nanoseconds_msb, + tsn->lastGmPhaseChange.nanoseconds_lsb, + tsn->lastGmPhaseChange.fractional_nanoseconds, + tsn->gmPresent ? "true" : "false", + cid2str(&tsn->gmIdentity)); + break; } out: fprintf(fp, "\n"); diff --git a/ptp4l.c b/ptp4l.c index 12bb3f3..6fc210a 100644 --- a/ptp4l.c +++ b/ptp4l.c @@ -247,7 +247,9 @@ int main(int argc, char *argv[]) } /* determine PHC Clock index */ - if (*timestamping == TS_SOFTWARE || *timestamping == TS_LEGACY_HW) { + if (ds->free_running) { + phc_index = -1; + } else if (*timestamping == TS_SOFTWARE || *timestamping == TS_LEGACY_HW) { phc_index = -1; } else if (req_phc) { if (1 != sscanf(req_phc, "/dev/ptp%d", &phc_index)) { diff --git a/tlv.c b/tlv.c index 9552dd1..f93947e 100644 --- a/tlv.c +++ b/tlv.c @@ -41,6 +41,7 @@ static void scaled_ns_h2n(ScaledNs *sns) static void mgt_post_recv(struct management_tlv *m) { struct currentDS *cds; + struct time_status_np *tsn; switch (m->id) { case CURRENT_DATA_SET: cds = (struct currentDS *) m->data; @@ -48,12 +49,23 @@ static void mgt_post_recv(struct management_tlv *m) cds->offsetFromMaster = net2host64(cds->offsetFromMaster); cds->meanPathDelay = net2host64(cds->meanPathDelay); break; + case TIME_STATUS_NP: + tsn = (struct time_status_np *) m->data; + tsn->master_offset = net2host64(tsn->master_offset); + tsn->ingress_time = net2host64(tsn->ingress_time); + tsn->cumulativeScaledRateOffset = ntohl(tsn->cumulativeScaledRateOffset); + tsn->scaledLastGmPhaseChange = ntohl(tsn->scaledLastGmPhaseChange); + tsn->gmTimeBaseIndicator = ntohs(tsn->gmTimeBaseIndicator); + scaled_ns_n2h(&tsn->lastGmPhaseChange); + tsn->gmPresent = ntohl(tsn->gmPresent); + break; } } static void mgt_pre_send(struct management_tlv *m) { struct currentDS *cds; + struct time_status_np *tsn; switch (m->id) { case CURRENT_DATA_SET: cds = (struct currentDS *) m->data; @@ -61,6 +73,16 @@ static void mgt_pre_send(struct management_tlv *m) cds->offsetFromMaster = host2net64(cds->offsetFromMaster); cds->meanPathDelay = host2net64(cds->meanPathDelay); break; + case TIME_STATUS_NP: + tsn = (struct time_status_np *) m->data; + tsn->master_offset = host2net64(tsn->master_offset); + tsn->ingress_time = host2net64(tsn->ingress_time); + tsn->cumulativeScaledRateOffset = htonl(tsn->cumulativeScaledRateOffset); + tsn->scaledLastGmPhaseChange = htonl(tsn->scaledLastGmPhaseChange); + tsn->gmTimeBaseIndicator = htons(tsn->gmTimeBaseIndicator); + scaled_ns_h2n(&tsn->lastGmPhaseChange); + tsn->gmPresent = htonl(tsn->gmPresent); + break; } } diff --git a/tlv.h b/tlv.h index 0590656..7c95e2d 100644 --- a/tlv.h +++ b/tlv.h @@ -167,10 +167,14 @@ struct follow_up_info_tlv { } PACKED; struct time_status_np { + int64_t master_offset; /*nanoseconds*/ + int64_t ingress_time; /*nanoseconds*/ Integer32 cumulativeScaledRateOffset; Integer32 scaledLastGmPhaseChange; UInteger16 gmTimeBaseIndicator; ScaledNs lastGmPhaseChange; + Integer32 gmPresent; + struct ClockIdentity gmIdentity; } PACKED; /** diff --git a/tmv.h b/tmv.h index e850a63..16a0772 100644 --- a/tmv.h +++ b/tmv.h @@ -81,6 +81,11 @@ static inline double tmv_dbl(tmv_t x) return (double) x; } +static inline int64_t tmv_to_nanoseconds(tmv_t x) +{ + return x; +} + static inline TimeInterval tmv_to_TimeInterval(tmv_t x) { return x << 16;