IEEE 1588 v2.1 and ITU G.8275.1/2 call for an optional "synchronization
uncertain" flag passed in Announce messages along with the other flags
from the time properties data set.  The value of the flag depends is a
logical OR function of the inputs from the remote master and the local
process.  This patch adds background support for handling the flag.

Signed-off-by: Richard Cochran <richardcoch...@gmail.com>
---
 clock.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++----
 clock.h |  4 ++--
 msg.h   |  1 +
 port.c  | 12 ++++++------
 tlv.h   |  6 ++++++
 5 files changed, 61 insertions(+), 12 deletions(-)

diff --git a/clock.c b/clock.c
index a6e31e6..11082fe 100644
--- a/clock.c
+++ b/clock.c
@@ -103,6 +103,7 @@ struct clock {
        int sde;
        int free_running;
        int freq_est_interval;
+       int local_sync_uncertain;
        int write_phase_mode;
        int grand_master_capable; /* for 802.1AS only */
        int utc_timescale;
@@ -137,6 +138,7 @@ struct clock the_clock;
 static void handle_state_decision_event(struct clock *c);
 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 void remove_subscriber(struct clock_subscriber *s)
 {
@@ -446,6 +448,11 @@ static int clock_management_fill_response(struct clock *c, 
struct port *p,
                clock_get_subscription(c, req, sen->bitmask, &sen->duration);
                datalen = sizeof(*sen);
                break;
+       case TLV_SYNCHRONIZATION_UNCERTAIN_NP:
+               mtd = (struct management_tlv_datum *) tlv->data;
+               mtd->val = c->local_sync_uncertain;
+               datalen = sizeof(*mtd);
+               break;
        default:
                /* The caller should *not* respond to this message. */
                tlv_extra_recycle(extra);
@@ -519,6 +526,21 @@ static int clock_management_set(struct clock *c, struct 
port *p,
                clock_update_subscription(c, req, sen->bitmask, sen->duration);
                respond = 1;
                break;
+       case TLV_SYNCHRONIZATION_UNCERTAIN_NP:
+               mtd = (struct management_tlv_datum *) tlv->data;
+               switch (mtd->val) {
+               case SYNC_UNCERTAIN_DONTCARE:
+               case SYNC_UNCERTAIN_FALSE:
+               case SYNC_UNCERTAIN_TRUE:
+                       /* Display stats on change of local_sync_uncertain */
+                       if (c->local_sync_uncertain != mtd->val
+                           && stats_get_num_values(c->stats.offset))
+                               clock_stats_display(&c->stats);
+                       c->local_sync_uncertain = mtd->val;
+                       respond = 1;
+                       break;
+               }
+               break;
        }
        if (respond && !clock_management_get_response(c, p, id, req))
                pr_err("failed to send management set response");
@@ -528,14 +550,19 @@ static int clock_management_set(struct clock *c, struct 
port *p,
 static void clock_stats_update(struct clock_stats *s,
                               double offset, double freq)
 {
-       struct stats_result offset_stats, freq_stats, delay_stats;
-
        stats_add_value(s->offset, offset);
        stats_add_value(s->freq, freq);
 
        if (stats_get_num_values(s->offset) < s->max_count)
                return;
 
+       clock_stats_display(s);
+}
+
+static void clock_stats_display(struct clock_stats *s)
+{
+       struct stats_result offset_stats, freq_stats, delay_stats;
+
        stats_get_result(s->offset, &offset_stats);
        stats_get_result(s->freq, &freq_stats);
 
@@ -1030,6 +1057,7 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
        c->config = config;
        c->free_running = config_get_int(config, NULL, "free_running");
        c->freq_est_interval = config_get_int(config, NULL, 
"freq_est_interval");
+       c->local_sync_uncertain = SYNC_UNCERTAIN_DONTCARE;
        c->write_phase_mode = config_get_int(config, NULL, "write_phase_mode");
        c->grand_master_capable = config_get_int(config, NULL, "gmCapable");
        c->kernel_leap = config_get_int(config, NULL, "kernel_leap");
@@ -1429,6 +1457,7 @@ int clock_manage(struct clock *c, struct port *p, struct 
ptp_message *msg)
        case TLV_TIME_STATUS_NP:
        case TLV_GRANDMASTER_SETTINGS_NP:
        case TLV_SUBSCRIBE_EVENTS_NP:
+       case TLV_SYNCHRONIZATION_UNCERTAIN_NP:
                clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
                break;
        default:
@@ -1751,9 +1780,22 @@ void clock_sync_interval(struct clock *c, int n)
        servo_sync_interval(c->servo, n < 0 ? 1.0 / (1 << -n) : 1 << n);
 }
 
-struct timePropertiesDS *clock_time_properties(struct clock *c)
+struct timePropertiesDS clock_time_properties(struct clock *c)
 {
-       return &c->tds;
+       struct timePropertiesDS tds = c->tds;
+
+       switch (c->local_sync_uncertain) {
+       case SYNC_UNCERTAIN_DONTCARE:
+               tds.flags &= ~SYNC_UNCERTAIN;
+               break;
+       case SYNC_UNCERTAIN_FALSE:
+               /* Pass the upstream value, if any. */
+               break;
+       case SYNC_UNCERTAIN_TRUE:
+               tds.flags |= SYNC_UNCERTAIN;
+               break;
+       }
+       return tds;
 }
 
 void clock_update_time_properties(struct clock *c, struct timePropertiesDS tds)
diff --git a/clock.h b/clock.h
index 9d3133a..1256856 100644
--- a/clock.h
+++ b/clock.h
@@ -320,9 +320,9 @@ void clock_sync_interval(struct clock *c, int n);
 /**
  * Obtain a clock's time properties data set.
  * @param c  The clock instance.
- * @return   A pointer to the time properties data set of the clock.
+ * @return   A copy of the clock's time properties data set.
  */
-struct timePropertiesDS *clock_time_properties(struct clock *c);
+struct timePropertiesDS clock_time_properties(struct clock *c);
 
 /**
  * Update a clock's time properties data set.
diff --git a/msg.h b/msg.h
index c1294c2..e71d3ce 100644
--- a/msg.h
+++ b/msg.h
@@ -56,6 +56,7 @@
 #define PTP_TIMESCALE  (1<<3)
 #define TIME_TRACEABLE (1<<4)
 #define FREQ_TRACEABLE (1<<5)
+#define SYNC_UNCERTAIN (1<<6)
 
 /*
  * Signaling interval special values. For more info look at 802.1AS table 10-11
diff --git a/port.c b/port.c
index 368c3b8..6104061 100644
--- a/port.c
+++ b/port.c
@@ -412,7 +412,7 @@ static int follow_up_info_append(struct ptp_message *m)
 
 static int net_sync_resp_append(struct port *p, struct ptp_message *m)
 {
-       struct timePropertiesDS *tp = clock_time_properties(p->clock);
+       struct timePropertiesDS tp = clock_time_properties(p->clock);
        struct ClockIdentity cid = clock_identity(p->clock), pid;
        struct currentDS *cds = clock_current_dataset(p->clock);
        struct parent_ds *dad = clock_parent_ds(p->clock);
@@ -468,7 +468,7 @@ static int net_sync_resp_append(struct port *p, struct 
ptp_message *m)
 
        memcpy(&extra->foot->parent, &dad->pds, sizeof(extra->foot->parent));
        memcpy(&extra->foot->current, cds, sizeof(extra->foot->current));
-       memcpy(&extra->foot->timeprop, tp, sizeof(extra->foot->timeprop));
+       memcpy(&extra->foot->timeprop, &tp, sizeof(extra->foot->timeprop));
        memcpy(&extra->foot->lastsync, &last_sync, 
sizeof(extra->foot->lastsync));
 
        return 0;
@@ -1407,7 +1407,7 @@ out:
 
 int port_tx_announce(struct port *p, struct address *dst)
 {
-       struct timePropertiesDS *tp = clock_time_properties(p->clock);
+       struct timePropertiesDS tp = clock_time_properties(p->clock);
        struct parent_ds *dad = clock_parent_ds(p->clock);
        struct ptp_message *msg;
        int err;
@@ -1434,19 +1434,19 @@ int port_tx_announce(struct port *p, struct address 
*dst)
        msg->header.control            = CTL_OTHER;
        msg->header.logMessageInterval = p->logAnnounceInterval;
 
-       msg->header.flagField[1] = tp->flags;
+       msg->header.flagField[1] = tp.flags;
 
        if (dst) {
                msg->address = *dst;
                msg->header.flagField[0] |= UNICAST;
        }
-       msg->announce.currentUtcOffset        = tp->currentUtcOffset;
+       msg->announce.currentUtcOffset        = tp.currentUtcOffset;
        msg->announce.grandmasterPriority1    = dad->pds.grandmasterPriority1;
        msg->announce.grandmasterClockQuality = 
dad->pds.grandmasterClockQuality;
        msg->announce.grandmasterPriority2    = dad->pds.grandmasterPriority2;
        msg->announce.grandmasterIdentity     = dad->pds.grandmasterIdentity;
        msg->announce.stepsRemoved            = clock_steps_removed(p->clock);
-       msg->announce.timeSource              = tp->timeSource;
+       msg->announce.timeSource              = tp.timeSource;
 
        if (p->path_trace_enabled && path_trace_append(p, msg, dad)) {
                pr_err("port %hu: append path trace failed", portnum(p));
diff --git a/tlv.h b/tlv.h
index faf5742..75aa1de 100644
--- a/tlv.h
+++ b/tlv.h
@@ -84,6 +84,7 @@ enum management_action {
 #define TLV_TIME_STATUS_NP                             0xC000
 #define TLV_GRANDMASTER_SETTINGS_NP                    0xC001
 #define TLV_SUBSCRIBE_EVENTS_NP                                0xC003
+#define TLV_SYNCHRONIZATION_UNCERTAIN_NP               0xC006
 
 /* Port management ID values */
 #define TLV_NULL_MANAGEMENT                            0x0000
@@ -116,6 +117,11 @@ enum management_action {
 #define TLV_NOT_SUPPORTED                              0x0006
 #define TLV_GENERAL_ERROR                              0xFFFE
 
+/* Values for the SYNCHRONIZATION_UNCERTAIN_NP management TLV */
+#define SYNC_UNCERTAIN_DONTCARE        0xff
+#define SYNC_UNCERTAIN_FALSE   0
+#define SYNC_UNCERTAIN_TRUE    1
+
 #define CANCEL_UNICAST_MAINTAIN_REQUEST        (1 << 0)
 #define CANCEL_UNICAST_MAINTAIN_GRANT  (1 << 1)
 #define GRANT_UNICAST_RENEWAL_INVITED  (1 << 0)
-- 
2.20.1



_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to