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. v2: Maintain existing printed name 'scaledLastGmPhaseChange' in pmc.c to avoid potential disruptions to users' setups. 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 | 2 +- port.c | 5 +++-- tlv.c | 8 ++++---- tlv.h | 4 ++-- 6 files changed, 72 insertions(+), 13 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..b4b146f 100644 --- a/pmc.c +++ b/pmc.c @@ -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 136d036..f94789b 100644 --- a/port.c +++ b/port.c @@ -431,7 +431,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; @@ -445,6 +445,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; } @@ -1781,7 +1782,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