From 6c54c31dca7c36eaa9ed6d737905955de1a7ec6e Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Wed, 12 Sep 2012 17:44:20 +0200 Subject: [PATCH] Introduce the time status management message. This non-portable, implementation specific message is designed to inform external programs about the relationship between the local clock and the remote master clock. Signed-off-by: Richard Cochran --- clock.c | 19 +++++++++++++++++++ pmc.c | 25 +++++++++++++++++++++++++ tlv.c | 22 ++++++++++++++++++++++ tlv.h | 4 ++++ 4 files changed, 70 insertions(+) diff --git a/clock.c b/clock.c index 92ff9e4..459b7b9 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; 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/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; /**