Hello dears,

I was checking the patches provided by Yangbo and also got confused with
the same point regarding the rateRatio calculation.
The implemented way (gm_rr *= nrr) seems to be the correct one in my
opinion. Any clarification regarding the method explained in the
standard (rateRatio += neighborRateRatio - 1.0)?


Additionally, I would like to raise the same discussion started earlier
by Michael. Some hardware already supports two PTP clocks, one can be
free running and used to transport 802.1AS synchronization while the
other is a synchronized clock that can be used by TSN as an example. Do
you think it is worth it to add this feature to linuxptp? 
Of course, this will require extra efforts outside the linuxptp circle
since we will need to define two PHCs per interface and pass
cross-timestamps up through the kernel. Would you please give us your
expert opinion on this?


Thank you.
Kind Regards
------------------------------------------
M.Sc. Kamil Alkhouri
Tel. +49 781 205-4871
Fax. +49 781 205-454871
Email: kamil.alkho...@hs-offenburg.de

Hochschule Offenburg
Institut für verlässliche Embedded Systems und Kommunikationselektronik
(ivESK)
Badstraße 24
77652 Offenburg
http://www.hs-offenburg.de
 
 
This E-mail and any files transmitted with it are official and intended
solely for the use of the individual or entity to whom they are
addressed. If you are not the intended recipient, the E-mail and any
files have been transmitted to you in error and any copying,
distribution or other use of the information contained in them is
prohibited.
 
Diese E-Mail und jede mit ihr übermittelte Datei sind dienstlich und
ausschließlich fuer die Nutzung durch die Person oder Stelle bestimmt,
die als Empfänger benannt ist. Sind Sie nicht der genannte Empfänger,
ist diese E-Mail und jede enthaltene Datei fälschlicherweise an Sie
übermittelt worden. Das Kopieren, Verteilen und jede sonstige Nutzung
der enthaltenen Informationen ist verboten.



---------- Original Message ---------
From: Y.b. Lu <yangbo...@nxp.com>
Date: Thu, Oct 24, 2019 at 5:58 AM
Subject: Re: [Linuxptp-devel] [RFC V2] Add IEEE 802.1AS-2011 time-aware
bridge support
To: Rodney Cummings <rodney.cummi...@ni.com>,
linuxptp-devel@lists.sourceforge.net
<linuxptp-devel@lists.sourceforge.net>, Richard Cochran
<richardcoch...@gmail.com>, Erik Hons <erik.h...@ni.com>



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 > 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 informa > > 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.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,
 > >                               > > *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
 

 


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

Reply via email to