Hi, > I realize all of that is anecdotal, in that > a TC-based fork of Linuxptp might have performed well also. Nevertheless, I'm > concerned that a fully TC-based implementation would move the code away > from conformance with 802.1AS-2011, and interoperation would break as a > result.
I'd like to know why the move towards BC based .1AS implementation, when the section 7.5 in .1AS 2020 shows that the AVB profile is like a very controlled BC, more like a P2P TC (+BMC) with its usage of Sync/Follow-up and PDelay message set (instead of Delay_Req / Delay_Resp pairs). Also, whether the syntonization of the bridge serves the purpose to send forward the corrections (residence + link delay) and calculation of rate-ratios, or a phase-sync is also required in the bridges implementing PTP relay, in which case BC might make more sense? Regards, Jagmeet On Thu, Oct 24, 2019 at 9:28 AM Y.b. Lu <yangbo...@nxp.com> wrote: > Hi Richard, > May I have your comments? > > Hi Rodney, > Please see my comments inline. > > Thanks a lot. > > Best regards, > Yangbo Lu > > > -----Original Message----- > > From: Rodney Cummings <rodney.cummi...@ni.com> > > Sent: Tuesday, October 15, 2019 1:12 AM > > To: Y.b. Lu <yangbo...@nxp.com>; linuxptp-devel@lists.sourceforge.net; > > Richard Cochran <richardcoch...@gmail.com>; Erik Hons <erik.h...@ni.com> > > Subject: RE: [RFC V2] Add IEEE 802.1AS-2011 time-aware bridge support > > > > Thanks Yangbo, > > > > I'd like to interject some overall comments/questions before digging into > > comments on the code. > > > > In my opinion I prefer this v2 (BC) over the previous v1 (TC). > > > > To me, it isn't so much about the name. It is more about aligning the > code with > > the 802.1AS-2011 requirements ("shall"s). My employer (National > Instruments) > > has been shipping our own BC-based fork of Linuxptp for years now (e.g. > uses > > bc_dispatch() and bc_event() as is). That code has passed UNH-IOL > > conformance for 802.1AS-2011, performed well in 802.1AS-2011 plugfests > (i.e. > > ICC, Avnu, ISPCS), and interoperated in customer applications with many > other > > 802.1AS-2011 end-stations and bridges. I realize all of that is > anecdotal, in that > > a TC-based fork of Linuxptp might have performed well also. > Nevertheless, I'm > > concerned that a fully TC-based implementation would move the code away > > from conformance with 802.1AS-2011, and interoperation would break as a > > result. > > > > [Y.b. Lu] To me, I think BC is proper after you clarified that, although I > thought it's TC before. > > > Assuming the group is okay with BC, there is probably one other major > > question to answer before we go much further: > > Are we okay implementing the 802.1AS-2011 BC specifics in clock.c, > > or do we prefer to move most of that to a different file (bridge.c, > > gptp_relay.c, or whatever)? > > > > [Y.b. Lu] I'm ok with any method. We can have Richard's comment. > From my patch, there were not too much changes to reuse BC. > > > There's a short list of items that make 802.1AS-2011 BC different from > > 1588-2008 P2P Default BC: > > > > 1. Transfer Sync / FollowUp differences from Slave (receive) to Master > > (transmit) ports. > > 2. Support distinct sync intervals on Slave and Master ports (like a > typical BC). > > > > The v2 patch covers item 1 and 2, which are the core differences. > Nevertheless, > > it might be good to keep other differences in mind (i.e. future patches) > before > > we decide the preceding question: > > > > [Y.b. Lu] Yes. The patch had core changes, so that it could be reviewed to > decide which method is good to add it in linuxptp. > > > 3. Transfer Pdelay differences from Slave to Master ports (cumulative > rate > > ratio). > > [Y.b. Lu] I have already done that in patch. But it's different with > standard. I'm very confused on this, and doubt the standard. > See below changes. > + /* Update follow_up TLV */ > + gm_rr *= nrr; > + fui->cumulativeScaledRateOffset = gm_rr * POW2_41 - POW2_41; > > I can't understand why standard gets rateRatio with, > rateRatio += (neighborRateRatio - 1.0); > not, > rateRatio *= neighborRateRatio; > > As I understand, the rateRatio got from neighbor should be freq_gm / > freq_neighbor. > The neighborRateRato should be freq_neighbor / freq_cureent. > So rateRatio for current device (freq_gm / freq_cureent) should be > rateRatio * neighborRateRato. > > I will appreciate if you can help me to get it right. > > > 4. BMCA: Skip over UNCALIBRATED and PRE_MASTER states. > > 5. BMCA: Remove foreign master qualification (i.e. change threshold from > 2 to > > 1). > > 6. Check performance requirement in 802.1AS-2011 B.1.1 for neighbor rate > > ratio computation. > > 7. BMCA: FAULTY causes a State Decision Event. 802.1AS-2011's methodology > > for faults is to avoid waiting in that FAULTY state in hopes that > management > > will notice. Instead, 802.1AS moves on to search for a valid non-faulty > state > > (SDE). If supported, the fault is logged so that management can notice > later, > > but that logging isn't a requirement. > > [Y.b. Lu] Thanks. No problem for me to generate patches to support these. > I don't think these will introduce much changes either. I tend to not > create new files for TAB/PRI. > > > > > There's one other item in the upcoming revision (presumably 802.1AS-2020) > > that is not explicitly stated in 802.1AS-2011: > > > > 8. If-and-only-if the sync interval is the same for a Slave and Master > port pair, > > "this PTP Port, when operating as a Master port, shall transmit a Sync > as soon > > as possible after the Slave port received a Sync (ignoring > syncInterval)." To > > Richard's credit, this is TC-like behavior. In the code, it presumably > represents a > > call to tc_fwd_sync() as was done in Yangbo's v1 patch. When we dig into > the > > details, there might be some 802.1AS-specifics, so maybe it will warrant > a new > > gptp_relay_fwd_sync() function. > > > > Since 802.1AS-2020 isn't published yet, I'd be perfectly happy ignoring > item 8 > > for now. We can always revisit the issue later on. > > > > In the upcoming revision of 1588, all of items 1-8 are supported as > options > > that a PTP Profile (like 802.1AS) can list as required. For example, the > 1588 > > revision allows UNCALIBRATED and PRE_MASTER to be skipped (whereas > > 1588-2008 requires those states). Therefore, items 1-8 will be conformant > > 1588 behavior that any profile can use. I mention this because if we > want to > > avoid "gptp" or "802.1AS" in the naming of items 1-8, that sounds fine, > > because they are not necessarily exclusive to 802.1AS in the future. > > [Y.b. Lu] Thank you for sharing these information. That's much helpful :) > > > > > Rodney > > > -----Original Message----- > > > From: Yangbo Lu <yangbo...@nxp.com> > > > Sent: Monday, October 14, 2019 5:27 AM > > > To: linuxptp-devel@lists.sourceforge.net; Rodney Cummings > > > <rodney.cummi...@ni.com>; Richard Cochran > > <richardcoch...@gmail.com>; > > > Erik Hons <erik.h...@ni.com> > > > Cc: Yangbo Lu <yangbo...@nxp.com> > > > Subject: [EXTERNAL] [RFC V2] Add IEEE 802.1AS-2011 time-aware bridge > > > support > > > > > > This patch is to add IEEE 802.1AS-2011 time-aware bridge support based > > > on current BC clock type. It implements only time information relay, > > > and BMCA was not touched. To run it, the profile gPTP.cfg could be > > > used with multiple interfaces specified using -i option. > > > > > > The main code changes are, > > > - Create syfu_relay_info structure for time information relay. > > > - Implement port_syfu_relay_info_insert() to update follow_up (with > TLV) > > > message with time information for relay. > > > > > > Signed-off-by: Yangbo Lu <yangbo...@nxp.com> > > > --- > > > Changes for v2: > > > - Implemented based on BC instead of TC. > > > --- > > > clock.c | 43 ++++++++++++++++++++++++++++++++++++- > > > clock.h | 45 +++++++++++++++++++++++++++++++++++++++ > > > port.c | 75 > > > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- > > > 3 files changed, 158 insertions(+), 5 deletions(-) > > > > > > diff --git a/clock.c b/clock.c > > > index 146576a..1865ecb 100644 > > > --- a/clock.c > > > +++ b/clock.c > > > @@ -45,7 +45,6 @@ > > > #include "util.h" > > > > > > #define N_CLOCK_PFD (N_POLLFD + 1) /* one extra per port, for the > > > fault timer */ -#define POW2_41 ((double)(1ULL << 41)) > > > > > > struct port { > > > LIST_ENTRY(port) list; > > > @@ -123,6 +122,7 @@ struct clock { > > > int stats_interval; > > > struct clockcheck *sanity_check; > > > struct interface uds_interface; > > > + struct syfu_relay_info syfu_relay; > > > LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers; > }; > > > > > > @@ -1117,6 +1117,8 @@ struct clock *clock_create(enum clock_type type, > > > struct config *config, > > > } > > > } > > > > > > + memset(&c->syfu_relay, 0, sizeof(struct syfu_relay_info)); > > > + > > > /* Initialize the parentDS. */ > > > clock_update_grandmaster(c); > > > c->dad.pds.parentStats = 0; > > > @@ -1208,6 +1210,15 @@ void clock_follow_up_info(struct clock *c, > > > struct follow_up_info_tlv *f) > > > sizeof(c->status.lastGmPhaseChange)); > > > } > > > > > > +static void clock_get_follow_up_info(struct clock *c, struct > > > +follow_up_info_tlv *f) { > > > + f->cumulativeScaledRateOffset = c- > > > >status.cumulativeScaledRateOffset; > > > + f->scaledLastGmPhaseChange = c->status.scaledLastGmPhaseChange; > > > + f->gmTimeBaseIndicator = c->status.gmTimeBaseIndicator; > > > + memcpy(&f->lastGmPhaseChange, &c->status.lastGmPhaseChange, > > > + sizeof(f->lastGmPhaseChange)); } > > > + > > > int clock_free_running(struct clock *c) { > > > return c->free_running ? 1 : 0; > > > @@ -1583,6 +1594,16 @@ void clock_peer_delay(struct clock *c, tmv_t > > > ppd, tmv_t req, tmv_t rx, > > > stats_add_value(c->stats.delay, tmv_dbl(ppd)); } > > > > > > +tmv_t clock_get_path_delay(struct clock *c) { > > > + return c->path_delay; > > > +} > > > + > > > +double clock_get_nrr(struct clock *c) { > > > + return c->nrr; > > > +} > > > + > > > int clock_slave_only(struct clock *c) { > > > return c->dds.flags & DDS_SLAVE_ONLY; @@ -1776,6 +1797,7 @@ static > > > void handle_state_decision_event(struct clock > > > *c) > > > c->path_delay = c->initial_delay; > > > c->nrr = 1.0; > > > fresh_best = 1; > > > + clock_disable_syfu_relay(c); > > > } > > > > > > c->best = best; > > > @@ -1847,3 +1869,22 @@ enum servo_state clock_servo_state(struct clock > > > *c) { > > > return c->servo_state; > > > } > > > + > > > +void clock_prepare_syfu_relay(struct clock *c, struct ptp_message > *sync, > > > + struct ptp_message *fup) > > > +{ > > > + c->syfu_relay.precise_origin_ts = timestamp_to_tmv(fup->ts.pdu); > > > + c->syfu_relay.correction = fup->header.correction; > > > + clock_get_follow_up_info(c, &c->syfu_relay.fup_info_tlv); > > > + c->syfu_relay.avail = 1; > > > +} > > > + > > > +void clock_disable_syfu_relay(struct clock *c) { > > > + c->syfu_relay.avail = 0; > > > +} > > > + > > > +struct syfu_relay_info *clock_get_syfu_relay(struct clock *c) { > > > + return &c->syfu_relay; > > > +} > > > diff --git a/clock.h b/clock.h > > > index 9d3133a..8ff1181 100644 > > > --- a/clock.h > > > +++ b/clock.h > > > @@ -29,8 +29,18 @@ > > > #include "tmv.h" > > > #include "transport.h" > > > > > > +#define POW2_41 ((double)(1ULL << 41)) > > > + > > > struct ptp_message; /*forward declaration*/ > > > > > > +struct syfu_relay_info { > > > + tmv_t precise_origin_ts; > > > + Integer64 correction; > > > + struct follow_up_info_tlv fup_info_tlv; > > > + /* Auxiliary info */ > > > + int avail; > > > +}; > > > + > > > /** Opaque type. */ > > > struct clock; > > > > > > @@ -240,6 +250,20 @@ void clock_peer_delay(struct clock *c, tmv_t ppd, > > > tmv_t req, tmv_t rx, > > > double nrr); > > > > > > /** > > > + * Get the path delay as measured on a slave port. > > > + * @param c The clock instance. > > > + * @return The path delay as measured on a slave port. > > > + */ > > > +tmv_t clock_get_path_delay(struct clock *c); > > > + > > > +/** > > > + * Get the neighbor rate ratio as measured on a slave port. > > > + * @param c The clock instance. > > > + * @return The neighbor rate ratio as measured on a slave > > > port. > > > + */ > > > +double clock_get_nrr(struct clock *c); > > > + > > > +/** > > > * Set clock sde > > > * @param c A pointer to a clock instance obtained with > > > clock_create(). > > > * @param sde Pass one (1) if need a decision event and zero if not. > > > @@ -359,4 +383,25 @@ void clock_check_ts(struct clock *c, uint64_t ts); > > > */ > > > double clock_rate_ratio(struct clock *c); > > > > > > +/** > > > + * Prepare sync/follow_up relay. > > > + * @param c The clock instance. > > > + * @param sync The sync message. > > > + * @param fup The follow_up message. > > > + */ > > > +void clock_prepare_syfu_relay(struct clock *c, struct ptp_message > *sync, > > > + struct ptp_message *fup); > > > + > > > +/** > > > + * Disable sync/follow_up relay. > > > + * @param c The clock instance. > > > + */ > > > +void clock_disable_syfu_relay(struct clock *c); > > > + > > > +/** > > > + * Get sync/follow_up relay information. > > > + * @param c The clock instance. > > > + * @return The sync/follow_up relay information. > > > + */ > > > +struct syfu_relay_info *clock_get_syfu_relay(struct clock *c); > > > #endif > > > diff --git a/port.c b/port.c > > > index 07ad3f0..073e71a 100644 > > > --- a/port.c > > > +++ b/port.c > > > @@ -1241,6 +1241,10 @@ static void port_syfufsm(struct port *p, enum > > > syfu_event event, > > > break; > > > case FUP_MATCH: > > > syn = p->last_syncfup; > > > + if (p->follow_up_info) > > > + clock_prepare_syfu_relay(p->clock, syn, m); > > > + else > > > + clock_disable_syfu_relay(p->clock); > > > port_synchronize(p, syn->hwts.ts, m->ts.pdu, > > > syn->header.correction, > > > m->header.correction, > > > @@ -1261,6 +1265,10 @@ static void port_syfufsm(struct port *p, enum > > > syfu_event event, > > > break; > > > case SYNC_MATCH: > > > fup = p->last_syncfup; > > > + if (p->follow_up_info) > > > + clock_prepare_syfu_relay(p->clock, m, fup); > > > + else > > > + clock_disable_syfu_relay(p->clock); > > > port_synchronize(p, m->hwts.ts, fup->ts.pdu, > > > m->header.correction, > > > fup->header.correction, > > > @@ -1450,6 +1458,60 @@ int port_tx_announce(struct port *p, struct > > > address > > > *dst) > > > return err; > > > } > > > > > > +static void port_syfu_relay_info_insert(struct port *p, > > > + struct ptp_message *sync, > > > + struct ptp_message *fup) > > > +{ > > > + struct syfu_relay_info *syfu_relay = > clock_get_syfu_relay(p->clock); > > > + struct follow_up_info_tlv *fui_relay = &syfu_relay->fup_info_tlv; > > > + struct follow_up_info_tlv *fui = follow_up_info_extract(fup); > > > + tmv_t ingress, egress, residence, path_delay; > > > + double gm_rr, nrr, rr; > > > + struct timestamp ts; > > > + > > > + if (syfu_relay->avail == 0) > > > + return; > > > + > > > + fup->follow_up.preciseOriginTimestamp = > > > + tmv_to_Timestamp(syfu_relay->precise_origin_ts); > > > + fup->header.correction = syfu_relay->correction; > > > + > > > + /* Calculate residence time. */ > > > + ingress = clock_ingress_time(p->clock); > > > + egress = sync->hwts.ts; > > > + residence = tmv_sub(egress, ingress); > > > + rr = clock_rate_ratio(p->clock); > > > + if (rr != 1.0) { > > > + residence = dbl_tmv(tmv_dbl(residence) * rr); > > > + } > > > + > > > + gm_rr = 1.0 + (fui_relay->cumulativeScaledRateOffset + 0.0) / > > > POW2_41; > > > + nrr = clock_get_nrr(p->clock); > > > + > > > + /* Add corrected residence time into correction. */ > > > + fup->header.correction += tmv_to_TimeInterval(residence) * gm_rr * > > > +nrr; > > > + > > > + /* Add corrected path delay into correction. */ > > > + path_delay = clock_get_path_delay(p->clock); > > > + fup->header.correction += tmv_to_TimeInterval(path_delay) * gm_rr; > > > + > > > + /* Update follow_up TLV */ > > > + gm_rr *= nrr; > > > + fui->cumulativeScaledRateOffset = gm_rr * POW2_41 - POW2_41; > > > + fui->scaledLastGmPhaseChange = fui_relay->scaledLastGmPhaseChange; > > > + fui->gmTimeBaseIndicator = fui_relay->gmTimeBaseIndicator; > > > + memcpy(&fui->lastGmPhaseChange, &fui_relay->lastGmPhaseChange, > > > + sizeof(fui->lastGmPhaseChange)); > > > + > > > + ts.sec = fup->follow_up.preciseOriginTimestamp.seconds_msb; > > > + ts.sec = ts.sec << 32 | fup- > > > >follow_up.preciseOriginTimestamp.seconds_lsb; > > > + ts.nsec = fup->follow_up.preciseOriginTimestamp.nanoseconds; > > > + pr_debug("port %hu: syfu_relay info:", portnum(p)); > > > + pr_debug("port %hu: precise_origin_ts %" PRIu64 ".%u", > portnum(p), > > > ts.sec, ts.nsec); > > > + pr_debug("port %hu: correction %" PRId64, portnum(p), fup- > > > >header.correction >> 16); > > > + pr_debug("port %hu: fup_info %.9f", portnum(p), gm_rr); > > > +} > > > + > > > int port_tx_sync(struct port *p, struct address *dst) { > > > struct ptp_message *msg, *fup; > > > @@ -1543,10 +1605,15 @@ int port_tx_sync(struct port *p, struct > > > address > > > *dst) > > > fup->address = *dst; > > > fup->header.flagField[0] |= UNICAST; > > > } > > > - if (p->follow_up_info && follow_up_info_append(fup)) { > > > - pr_err("port %hu: append fup info failed", portnum(p)); > > > - err = -1; > > > - goto out; > > > + > > > + if (p->follow_up_info) { > > > + if (follow_up_info_append(fup)) { > > > + pr_err("port %hu: append fup info failed", > portnum(p)); > > > + err = -1; > > > + goto out; > > > + } > > > + > > > + port_syfu_relay_info_insert(p, msg, fup); > > > } > > > > > > err = port_prepare_and_send(p, fup, TRANS_GENERAL); > > > -- > > > 2.7.4 > > > > _______________________________________________ > Linuxptp-devel mailing list > Linuxptp-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/linuxptp-devel > -- Best Regards, ~ Jagmeet Singh Hanspal ~
_______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel