If the local PTP management client enables a time zone, append the matching TLV to outgoing Announce messages.
Signed-off-by: Richard Cochran <richardcoch...@gmail.com> --- clock.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++-- clock.h | 8 ++++++ pmc.c | 8 ++++++ pmc_common.c | 17 ++++++++++- port.c | 3 ++ 5 files changed, 113 insertions(+), 3 deletions(-) diff --git a/clock.c b/clock.c index ab3b892..96f391f 100644 --- a/clock.c +++ b/clock.c @@ -157,6 +157,43 @@ static int clock_resize_pollfd(struct clock *c, int new_nports); static void clock_remove_port(struct clock *c, struct port *p); static void clock_stats_display(struct clock_stats *s); +static int clock_alttime_offset_append(struct clock *c, int key, struct ptp_message *m) +{ + struct alternate_time_offset_indicator_tlv *atoi; + struct tlv_extra *extra; + int tlv_len; + + tlv_len = sizeof(*atoi) + c->tz[key].display_name.length; + if (tlv_len % 2) { + tlv_len++; + } + extra = msg_tlv_append(m, tlv_len); + if (!extra) { + return -1; + } + atoi = (struct alternate_time_offset_indicator_tlv *) extra->tlv; + atoi->type = TLV_ALTERNATE_TIME_OFFSET_INDICATOR; + atoi->length = tlv_len - sizeof(atoi->type) - sizeof(atoi->length); + atoi->keyField = key; + + /* Message alignment broken by design. */ + memcpy(&atoi->currentOffset, &c->tz[key].current_offset, + sizeof(atoi->currentOffset)); + + memcpy(&atoi->jumpSeconds, &c->tz[key].jump_seconds, + sizeof(atoi->jumpSeconds)); + + memcpy(&atoi->timeOfNextJump.seconds_lsb, &c->tz[key].next_jump_lsb, + sizeof(atoi->timeOfNextJump.seconds_lsb)); + + memcpy(&atoi->timeOfNextJump.seconds_msb, &c->tz[key].next_jump_msb, + sizeof(atoi->timeOfNextJump.seconds_msb)); + + ptp_text_copy(&atoi->displayName, &c->tz[key].display_name); + + return 0; +} + uint8_t clock_alttime_offset_get_key(struct ptp_message *req) { struct management_tlv_datum *mtd; @@ -462,6 +499,16 @@ static int clock_management_fill_response(struct clock *c, struct port *p, mtd->val = c->tds.flags & PTP_TIMESCALE; datalen = sizeof(*mtd); break; + case MID_ALTERNATE_TIME_OFFSET_ENABLE: + key = clock_alttime_offset_get_key(req); + if (key >= MAX_TIME_ZONES) { + break; + } + mtd = (struct management_tlv_datum *) tlv->data; + mtd->val = key; + mtd->reserved = c->tz[key].enabled ? 1 : 0; + datalen = sizeof(*mtd); + break; case MID_ALTERNATE_TIME_OFFSET_NAME: key = clock_alttime_offset_get_key(req); if (key >= MAX_TIME_ZONES) { @@ -574,7 +621,7 @@ static int clock_management_set(struct clock *c, struct port *p, struct management_tlv_datum *mtd; struct subscribe_events_np *sen; struct management_tlv *tlv; - int key, respond = 0; + int k, key, respond = 0; tlv = (struct management_tlv *) req->management.suffix; @@ -591,6 +638,20 @@ static int clock_management_set(struct clock *c, struct port *p, *changed = 1; respond = 1; break; + case MID_ALTERNATE_TIME_OFFSET_ENABLE: + mtd = (struct management_tlv_datum *) tlv->data; + key = mtd->val; + if (key == 0xff) { + for (k = 0; k < MAX_TIME_ZONES; k++) { + c->tz[k].enabled = mtd->reserved & 1 ? true : false; + } + respond = 1; + } + if (key < MAX_TIME_ZONES) { + c->tz[key].enabled = mtd->reserved & 1 ? true : false; + respond = 1; + } + break; case MID_ALTERNATE_TIME_OFFSET_NAME: aton = (struct alternate_time_offset_name *) tlv->data; key = aton->keyField; @@ -894,6 +955,22 @@ static int forwarding(struct clock *c, struct port *p) /* public methods */ +int clock_append_timezones(struct clock *c, struct ptp_message *m) +{ + int err = 0, i; + + for (i = 0; i < MAX_TIME_ZONES; i++) { + if (!c->tz[i].enabled) { + continue; + } + err = clock_alttime_offset_append(c, i, m); + if (err) { + break; + } + } + return err; +} + UInteger8 clock_class(struct clock *c) { return c->dds.clockQuality.clockClass; @@ -1609,7 +1686,6 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg) case MID_GRANDMASTER_CLUSTER_TABLE: case MID_ACCEPTABLE_MASTER_TABLE: case MID_ACCEPTABLE_MASTER_MAX_TABLE_SIZE: - case MID_ALTERNATE_TIME_OFFSET_ENABLE: case MID_ALTERNATE_TIME_OFFSET_MAX_KEY: case MID_TRANSPARENT_CLOCK_DEFAULT_DATA_SET: case MID_PRIMARY_DOMAIN: diff --git a/clock.h b/clock.h index 0534f21..ce9ae91 100644 --- a/clock.h +++ b/clock.h @@ -43,6 +43,14 @@ enum clock_type { CLOCK_TYPE_MANAGEMENT = 0x0800, }; +/** + * Appends the active time zone TLVs to a given message. + * @param c The clock instance. + * @param m The message that will receive the TLVs. + * @return Zero on success, non-zero otherwise. + */ +int clock_append_timezones(struct clock *c, struct ptp_message *m); + /** * Obtains a reference to the best foreign master of a clock. * @param c The clock instance. diff --git a/pmc.c b/pmc.c index 35dddba..00e691f 100644 --- a/pmc.c +++ b/pmc.c @@ -362,6 +362,14 @@ static void pmc_show(struct ptp_message *msg, FILE *fp) fprintf(fp, "TIMESCALE_PROPERTIES " IFMT "ptpTimescale %d", mtd->val & PTP_TIMESCALE ? 1 : 0); break; + case MID_ALTERNATE_TIME_OFFSET_ENABLE: + mtd = (struct management_tlv_datum *) mgt->data; + fprintf(fp, "ALTERNATE_TIME_OFFSET_ENABLE " + IFMT "keyField %hhu" + IFMT "enable %d", + mtd->val, + mtd->reserved & 1 ? 1 : 0); + break; case MID_ALTERNATE_TIME_OFFSET_NAME: aton = (struct alternate_time_offset_name *) mgt->data; fprintf(fp, "ALTERNATE_TIME_OFFSET_NAME " diff --git a/pmc_common.c b/pmc_common.c index 1062c59..6cab5e0 100644 --- a/pmc_common.c +++ b/pmc_common.c @@ -121,7 +121,7 @@ struct management_id idtab[] = { { "GRANDMASTER_CLUSTER_TABLE", MID_GRANDMASTER_CLUSTER_TABLE, not_supported }, { "ACCEPTABLE_MASTER_TABLE", MID_ACCEPTABLE_MASTER_TABLE, not_supported }, { "ACCEPTABLE_MASTER_MAX_TABLE_SIZE", MID_ACCEPTABLE_MASTER_MAX_TABLE_SIZE, not_supported }, - { "ALTERNATE_TIME_OFFSET_ENABLE", MID_ALTERNATE_TIME_OFFSET_ENABLE, not_supported }, + { "ALTERNATE_TIME_OFFSET_ENABLE", MID_ALTERNATE_TIME_OFFSET_ENABLE, do_set_action }, { "ALTERNATE_TIME_OFFSET_NAME", MID_ALTERNATE_TIME_OFFSET_NAME, do_set_action }, { "ALTERNATE_TIME_OFFSET_MAX_KEY", MID_ALTERNATE_TIME_OFFSET_MAX_KEY, not_supported }, { "ALTERNATE_TIME_OFFSET_PROPERTIES", MID_ALTERNATE_TIME_OFFSET_PROPERTIES, do_set_action }, @@ -181,6 +181,7 @@ static void do_set_action(struct pmc *pmc, int action, int index, char *str) char onoff_time_status[4] = "off"; char display_name[11] = {0}; uint8_t key; + int enable; mtd.reserved = 0; @@ -209,6 +210,17 @@ static void do_set_action(struct pmc *pmc, int action, int index, char *str) } pmc_send_set_action(pmc, code, &mtd, sizeof(mtd)); break; + case MID_ALTERNATE_TIME_OFFSET_ENABLE: + cnt = sscanf(str, " %*s %*s keyField %hhu enable %d", + &mtd.val, &enable); + if (cnt != 2) { + fprintf(stderr, "%s SET needs 2 values\n", + idtab[index].name); + break; + } + mtd.reserved = enable ? 1 : 0; + pmc_send_set_action(pmc, code, &mtd, sizeof(mtd)); + break; case MID_ALTERNATE_TIME_OFFSET_NAME: cnt = sscanf(str, " %*s %*s " "keyField %hhu " @@ -610,6 +622,9 @@ static int pmc_tlv_datalen(struct pmc *pmc, int id) case MID_TIME_STATUS_NP: len += sizeof(struct time_status_np); break; + case MID_ALTERNATE_TIME_OFFSET_ENABLE: + len += sizeof(struct management_tlv_datum); + break; case MID_ALTERNATE_TIME_OFFSET_NAME: len += sizeof(struct alternate_time_offset_name); break; diff --git a/port.c b/port.c index 7200a87..208ee73 100644 --- a/port.c +++ b/port.c @@ -1683,6 +1683,9 @@ int port_tx_announce(struct port *p, struct address *dst, uint16_t sequence_id) if (ieee_c37_238_append(p, msg)) { pr_err("%s: append power profile failed", p->log_name); } + if (clock_append_timezones(p->clock, msg)) { + pr_err("%s: append time zones failed", p->log_name); + } err = port_prepare_and_send(p, msg, TRANS_GENERAL); if (err) { -- 2.30.2 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel