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 67c0044..75d7c40 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;
@@ -896,6 +957,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;
@@ -1613,7 +1690,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 20f7b22..f5f6ec4 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 },
@@ -182,6 +182,7 @@ static void do_set_action(struct pmc *pmc, int action, int 
index, char *str)
        char display_name[11] = {0};
        uint64_t jump;
        uint8_t key;
+       int enable;
 
        mtd.reserved = 0;
 
@@ -210,6 +211,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 "
@@ -613,6 +625,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 f2aabfb..3453716 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

Reply via email to