Add the computation for scaledLastGmFreqChange, as specified in
IEEE 802.1AS-2020, clause 11.4.4.3.9. This incorporates the
necessary logic to calculate scaledLastGmFreqChange and
appends the result to the follow-up TLV.

In addition, a naming error has been rectified from
scaledLastGmPhaseChange to scaledLastGmFreqChange.

Signed-off-by: Tan Tee Min <tee.min....@linux.intel.com>
Signed-off-by: Chwee-Lin Choong <chwee.lin.cho...@intel.com>
---
 clock.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 clock.h |  7 +++++++
 pmc.c   |  4 ++--
 port.c  |  5 +++--
 tlv.c   |  8 ++++----
 tlv.h   |  4 ++--
 6 files changed, 73 insertions(+), 14 deletions(-)

diff --git a/clock.c b/clock.c
index b66dda5..c24d496 100644
--- a/clock.c
+++ b/clock.c
@@ -148,6 +148,7 @@ struct clock {
        int step_window_counter;
        int step_window;
        struct time_zone tz[MAX_TIME_ZONES];
+       struct follow_up_info_tlv clksrc_fup_info;
 };
 
 struct clock the_clock;
@@ -544,13 +545,15 @@ static int clock_management_fill_response(struct clock 
*c, struct port *p,
                tsn->cumulativeScaledRateOffset =
                        (Integer32) (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.pds.grandmasterIdentity, 
&c->dds.clockIdentity))
+               if (cid_eq(&c->dad.pds.grandmasterIdentity, 
&c->dds.clockIdentity)) {
                        tsn->gmPresent = 0;
-               else
+                       tsn->scaledLastGmFreqChange = 
c->clksrc_fup_info.scaledLastGmFreqChange;
+               } else {
                        tsn->gmPresent = 1;
+                       tsn->scaledLastGmFreqChange = 
c->status.scaledLastGmFreqChange;
+               }
                tsn->gmIdentity = c->dad.pds.grandmasterIdentity;
                datalen = sizeof(*tsn);
                break;
@@ -1289,6 +1292,7 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
        c->utc_offset = config_get_int(config, NULL, "utc_offset");
        c->time_source = config_get_int(config, NULL, "timeSource");
        c->step_window = config_get_int(config, NULL, "step_window");
+       memset(&c->clksrc_fup_info, 0 , sizeof(c->clksrc_fup_info));
 
        if (c->free_running) {
                c->clkid = CLOCK_INVALID;
@@ -1482,12 +1486,21 @@ struct port *clock_first_port(struct clock *c)
 void clock_follow_up_info(struct clock *c, struct follow_up_info_tlv *f)
 {
        c->status.cumulativeScaledRateOffset = f->cumulativeScaledRateOffset;
-       c->status.scaledLastGmPhaseChange = f->scaledLastGmPhaseChange;
+       c->status.scaledLastGmFreqChange = f->scaledLastGmFreqChange;
        c->status.gmTimeBaseIndicator = f->gmTimeBaseIndicator;
        memcpy(&c->status.lastGmPhaseChange, &f->lastGmPhaseChange,
               sizeof(c->status.lastGmPhaseChange));
 }
 
+void clock_set_follow_up_info(struct clock *c, struct follow_up_info_tlv *f)
+{
+       if (cid_eq(&c->dad.pds.grandmasterIdentity, &c->dds.clockIdentity)) {
+               f->scaledLastGmFreqChange = 
c->clksrc_fup_info.scaledLastGmFreqChange;
+       } else {
+               f->scaledLastGmFreqChange = c->status.scaledLastGmFreqChange;
+       }
+}
+
 int clock_free_running(struct clock *c)
 {
        return c->free_running ? 1 : 0;
@@ -1991,6 +2004,42 @@ static int clock_synchronize_locked(struct clock *c, 
double adj)
        return 0;
 }
 
+void calculate_freq_change(struct clock *c, tmv_t ingress, tmv_t origin)
+{
+       struct freq_estimator *f = &c->fest;
+       double ratio;
+
+       /*
+        * The ratio of the local clock freqency to the master clock
+        * is estimated by:
+        *
+        *    (origin_2 - origin_1) / (ingress_2 - ingress_1)
+        *
+        * Both of the origin time estimates include the path delay,
+        * but we assume that the path delay is in fact constant.
+        * By leaving out the path delay altogther, we can avoid the
+        * error caused by our imperfect path delay measurement.
+        */
+       if (tmv_is_zero(f->ingress1)) {
+               f->ingress1 = ingress;
+               f->origin1 = origin;
+               return;
+       }
+
+       if (tmv_cmp(ingress, f->ingress1) == 0) {
+               pr_warning("bad timestamps in rate ratio calculation");
+               return;
+       }
+
+       ratio = tmv_dbl(tmv_sub(origin, f->origin1)) /
+               tmv_dbl(tmv_sub(ingress, f->ingress1));
+
+       c->clksrc_fup_info.scaledLastGmFreqChange = (Integer32)((ratio - 1.0) * 
POW2_41);
+
+       f->ingress1 = ingress;
+       f->origin1 = origin;
+}
+
 enum servo_state clock_synchronize(struct clock *c, tmv_t ingress, tmv_t 
origin)
 {
        enum servo_state state = SERVO_UNLOCKED;
@@ -2023,6 +2072,8 @@ enum servo_state clock_synchronize(struct clock *c, tmv_t 
ingress, tmv_t origin)
 
        c->cur.offsetFromMaster = tmv_to_TimeInterval(c->master_offset);
 
+       calculate_freq_change(c, ingress, origin);
+
        if (c->free_running) {
                state = clock_no_adjust(c, ingress, origin);
                clock_notify_event(c, NOTIFY_TIME_SYNC);
diff --git a/clock.h b/clock.h
index ce9ae91..f17bea9 100644
--- a/clock.h
+++ b/clock.h
@@ -150,6 +150,13 @@ struct port *clock_first_port(struct clock *c);
  */
 void clock_follow_up_info(struct clock *c, struct follow_up_info_tlv *f);
 
+/**
+ * Set the follow_up info TLV for a slave port.
+ * @param c  The clock instance.
+ * @param f  Pointer to the TLV.
+ */
+void clock_set_follow_up_info(struct clock *c, struct follow_up_info_tlv *f);
+
 /**
  * Determine if a clock is free running or not.
  * @param c  The clock instance.
diff --git a/pmc.c b/pmc.c
index 9faf790..97ea3d2 100644
--- a/pmc.c
+++ b/pmc.c
@@ -404,7 +404,7 @@ static void pmc_show(struct ptp_message *msg, FILE *fp)
                        IFMT "master_offset              %" PRId64
                        IFMT "ingress_time               %" PRId64
                        IFMT "cumulativeScaledRateOffset %+.9f"
-                       IFMT "scaledLastGmPhaseChange    %d"
+                       IFMT "scaledLastGmFreqChange     %d"
                        IFMT "gmTimeBaseIndicator        %hu"
                        IFMT "lastGmPhaseChange          0x%04hx'%016" PRIx64 
".%04hx"
                        IFMT "gmPresent                  %s"
@@ -412,7 +412,7 @@ static void pmc_show(struct ptp_message *msg, FILE *fp)
                        tsn->master_offset,
                        tsn->ingress_time,
                        (tsn->cumulativeScaledRateOffset + 0.0) / P41,
-                       tsn->scaledLastGmPhaseChange,
+                       tsn->scaledLastGmFreqChange,
                        tsn->gmTimeBaseIndicator,
                        tsn->lastGmPhaseChange.nanoseconds_msb,
                        tsn->lastGmPhaseChange.nanoseconds_lsb,
diff --git a/port.c b/port.c
index 61d03d4..f99ef4c 100644
--- a/port.c
+++ b/port.c
@@ -432,7 +432,7 @@ static int add_foreign_master(struct port *p, struct 
ptp_message *m)
        return broke_threshold || diff;
 }
 
-static int follow_up_info_append(struct ptp_message *m)
+static int follow_up_info_append(struct port *p, struct ptp_message *m)
 {
        struct follow_up_info_tlv *fui;
        struct tlv_extra *extra;
@@ -446,6 +446,7 @@ static int follow_up_info_append(struct ptp_message *m)
        fui->length = sizeof(*fui) - sizeof(fui->type) - sizeof(fui->length);
        memcpy(fui->id, ieee8021_id, sizeof(ieee8021_id));
        fui->subtype[2] = 1;
+       clock_set_follow_up_info(p->clock, fui);
 
        return 0;
 }
@@ -1782,7 +1783,7 @@ int port_tx_sync(struct port *p, struct address *dst, 
uint16_t sequence_id)
                fup->address = *dst;
                fup->header.flagField[0] |= UNICAST;
        }
-       if (p->follow_up_info && follow_up_info_append(fup)) {
+       if (p->follow_up_info && follow_up_info_append(p, fup)) {
                pr_err("%s: append fup info failed", p->log_name);
                err = -1;
                goto out;
diff --git a/tlv.c b/tlv.c
index 9b82bd9..71619f0 100644
--- a/tlv.c
+++ b/tlv.c
@@ -362,7 +362,7 @@ static int mgt_post_recv(struct management_tlv *m, uint16_t 
data_len,
                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->scaledLastGmFreqChange = 
ntohl(tsn->scaledLastGmFreqChange);
                tsn->gmTimeBaseIndicator = ntohs(tsn->gmTimeBaseIndicator);
                scaled_ns_n2h(&tsn->lastGmPhaseChange);
                tsn->gmPresent = ntohl(tsn->gmPresent);
@@ -582,7 +582,7 @@ static void mgt_pre_send(struct management_tlv *m, struct 
tlv_extra *extra)
                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->scaledLastGmFreqChange = 
htonl(tsn->scaledLastGmFreqChange);
                tsn->gmTimeBaseIndicator = htons(tsn->gmTimeBaseIndicator);
                scaled_ns_h2n(&tsn->lastGmPhaseChange);
                tsn->gmPresent = htonl(tsn->gmPresent);
@@ -798,7 +798,7 @@ static int org_post_recv(struct organization_tlv *org)
                        f->cumulativeScaledRateOffset = 
ntohl(f->cumulativeScaledRateOffset);
                        f->gmTimeBaseIndicator = ntohs(f->gmTimeBaseIndicator);
                        scaled_ns_n2h(&f->lastGmPhaseChange);
-                       f->scaledLastGmPhaseChange = 
ntohl(f->scaledLastGmPhaseChange);
+                       f->scaledLastGmFreqChange = 
ntohl(f->scaledLastGmFreqChange);
                        break;
 
                case 2:
@@ -860,7 +860,7 @@ static void org_pre_send(struct organization_tlv *org)
                        f->cumulativeScaledRateOffset = 
htonl(f->cumulativeScaledRateOffset);
                        f->gmTimeBaseIndicator = htons(f->gmTimeBaseIndicator);
                        scaled_ns_h2n(&f->lastGmPhaseChange);
-                       f->scaledLastGmPhaseChange = 
htonl(f->scaledLastGmPhaseChange);
+                       f->scaledLastGmFreqChange = 
htonl(f->scaledLastGmFreqChange);
                        break;
                }
        } else if (0 == memcmp(org->id, itu_t_id, sizeof(itu_t_id))) {
diff --git a/tlv.h b/tlv.h
index 8b51ffd..ce87c72 100644
--- a/tlv.h
+++ b/tlv.h
@@ -331,7 +331,7 @@ struct follow_up_info_tlv {
        Integer32     cumulativeScaledRateOffset;
        UInteger16    gmTimeBaseIndicator;
        ScaledNs      lastGmPhaseChange;
-       Integer32     scaledLastGmPhaseChange;
+       Integer32     scaledLastGmFreqChange;
 } PACKED;
 
 struct ieee_c37_238_2011_tlv {
@@ -380,7 +380,7 @@ struct time_status_np {
        int64_t       master_offset; /*nanoseconds*/
        int64_t       ingress_time;  /*nanoseconds*/
        Integer32     cumulativeScaledRateOffset;
-       Integer32     scaledLastGmPhaseChange;
+       Integer32     scaledLastGmFreqChange;
        UInteger16    gmTimeBaseIndicator;
        ScaledNs      lastGmPhaseChange;
        Integer32     gmPresent;
-- 
2.42.0



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

Reply via email to