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 <richardcochran@gmail.com>
master
Richard Cochran 2012-09-12 17:44:20 +02:00
parent 4e09ff8585
commit 6c54c31dca
4 changed files with 70 additions and 0 deletions

19
clock.c
View File

@ -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;

25
pmc.c
View File

@ -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");

22
tlv.c
View File

@ -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;
}
}

4
tlv.h
View File

@ -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;
/**