On Wed, 2022-12-07 at 17:34 +0530, SyncMonk Technologies wrote: > Delay asymmetry calculation based on the PTP port interface speed of > master obtained from TLV and the slave interface rate obtained by > ethtool. > > v3: updating network/host byte order handling. > v1: initial commit > > Signed-off-by: Greg Armstrong <greg.armstrong...@renesas.com> > Signed-off-by: Leon Goldin <leon.goldin...@renesas.com> > Signed-off-by: Devasish Dey <devasish....@syncmonk.net> > Signed-off-by: Vipin Sharma <vipin.sha...@syncmonk.net> > --- > interface.c | 10 ++++++++++ > interface.h | 7 +++++++ > port_private.h | 1 + > port_signaling.c | 39 ++++++++++++++++++++++++++++++++++++--- > ptp4l.8 | 7 +++++++ > tlv.c | 29 +++++++++++++++++++++++++++++ > unicast_service.c | 32 ++++++++++++++++++++++++++++++++ > 7 files changed, 122 insertions(+), 3 deletions(-) > > diff --git a/interface.c b/interface.c > index 3157e8c..02d530e 100644 > --- a/interface.c > +++ b/interface.c > @@ -94,3 +94,13 @@ int interface_get_vclock(struct interface *iface) > { > return iface->vclock; > } > + > +uint64_t interface_bitperiod(struct interface *iface) > +{ > + if (!iface->if_info.valid) > + return 0; > + > + /* Megabits per secon converted to attoseconds per bit. */ > + return 1000000000000ULL/ iface->if_info.speed; Performing division in running is not a very good idea. It is better to perform the division when updating the speed and store it in if_info.
Are you sure we need attoseconds (10^-18), we usually uses nanoseconds (10^-9). I would except a better resolution, but that much? Please explain your choosing. > +} > + > diff --git a/interface.h b/interface.h > index f4b9545..7c9a6bd 100644 > --- a/interface.h > +++ b/interface.h > @@ -113,4 +113,11 @@ void interface_set_vclock(struct interface > *iface, int vclock); > */ > int interface_get_vclock(struct interface *iface); > > +/** > + * Obtains the interface bit period based on the speed. Perhaps: "Obtains bit period based on interface speed." > + * @param iface The interface of interest. We must be interesting "Pointer to the interface" can be suffiecnt :-) > + * @return if valid speed return interface bitperiod in atto > seconds. No need to make the return complicated, make it simple "return interface bit period in attoseconds". We know functions handle errors. > + */ > +uint64_t interface_bitperiod(struct interface *iface); > + > #endif > diff --git a/port_private.h b/port_private.h > index d6487eb..6ad4af8 100644 > --- a/port_private.h > +++ b/port_private.h > @@ -146,6 +146,7 @@ struct port { > UInteger8 delay_response_counter; > UInteger8 delay_response_timeout; > bool iface_rate_tlv; > + Integer64 portAsymmetry; > struct PortStats stats; > struct PortServiceStats service_stats; > /* foreignMasterDS */ > diff --git a/port_signaling.c b/port_signaling.c > index ed217c0..75a0689 100644 > --- a/port_signaling.c > +++ b/port_signaling.c > @@ -103,10 +103,37 @@ static int process_interval_request(struct port > *p, > return 0; > } > > +static int process_interface_rate(struct port *p, > + struct msg_interface_rate_tlv *r) > +{ > + Integer64 delayAsymmetry; > + double nsDelay; > + Integer64 slaveBitPeriod; > + Integer64 masterBitPeriod; > + > + if (p->iface_rate_tlv && interface_ifinfo_valid(p->iface)) { > + slaveBitPeriod = interface_bitperiod(p->iface); > + masterBitPeriod = r->interfaceBitPeriod; > + > + /* Delay Asymmetry Calculation */ > + nsDelay = (masterBitPeriod - slaveBitPeriod) / (2 * > 1.0e9); > + delayAsymmetry = > + (r->numberOfBitsAfterTimestamp - r- > >numberOfBitsBeforeTimestamp) * nsDelay; > + > + if (delayAsymmetry != p->portAsymmetry) { > + p->asymmetry += ((delayAsymmetry - p- > >portAsymmetry) << 16); > + p->portAsymmetry = delayAsymmetry; > + } > + } > + return 0; > +} > + > int process_signaling(struct port *p, struct ptp_message *m) > { > struct tlv_extra *extra; > + struct organization_tlv *org; > struct msg_interval_req_tlv *r; > + struct msg_interface_rate_tlv *rate; > int err = 0, result; > > switch (p->state) { > @@ -160,11 +187,17 @@ int process_signaling(struct port *p, struct > ptp_message *m) > break; > > case TLV_ORGANIZATION_EXTENSION: > - r = (struct msg_interval_req_tlv *) extra- > >tlv; > + org = (struct organization_tlv *)extra->tlv; > > - if (0 == memcmp(r->id, ieee8021_id, > sizeof(ieee8021_id)) && > - r->subtype[0] == 0 && r->subtype[1] == 0 > && r->subtype[2] == 2) > + if (0 == memcmp(org->id, ieee8021_id, > sizeof(ieee8021_id)) && > + org->subtype[0] == 0 && org->subtype[1] > == 0 && org->subtype[2] == 2) { > + r = (struct msg_interval_req_tlv *) > extra->tlv; > err = process_interval_request(p, r); > + } else if (0 == memcmp(org->id, itu_t_id, > sizeof(itu_t_id)) && > + org->subtype[0] == 0 && org- > >subtype[1] == 0 && org->subtype[2] == 2) { > + rate = (struct msg_interface_rate_tlv > *) extra->tlv; > + err = process_interface_rate(p, > rate); > + } > break; > } > } > diff --git a/ptp4l.8 b/ptp4l.8 > index cd6299f..e96d090 100644 > --- a/ptp4l.8 > +++ b/ptp4l.8 > @@ -697,6 +697,13 @@ The default is 0 (disabled). > Print messages to the system log if enabled. > The default is 1 (enabled). > .TP > +.B interface_rate_tlv > +When the client and server are operating are operating at different > interface rate, > +delay asymmetry caused due to different interface rate needs to be > compensated. > +The server sends its interface rate using interface rate TLV > +as per G.8275.2 Annex D. > +The default is 0 (does not support interface rate tlv). > +.TP > .B summary_interval > The time interval in which are printed summary statistics of the > clock. It is > specified as a power of two in seconds. The statistics include > offset root mean > diff --git a/tlv.c b/tlv.c > index 35bee4f..7a2a4fa 100644 > --- a/tlv.c > +++ b/tlv.c > @@ -681,6 +681,7 @@ static void nsm_resp_pre_send(struct tlv_extra > *extra) > static int org_post_recv(struct organization_tlv *org) > { > struct follow_up_info_tlv *f; > + struct msg_interface_rate_tlv *m; > > if (0 == memcmp(org->id, ieee8021_id, sizeof(ieee8021_id))) { > if (org->subtype[0] || org->subtype[1]) { > @@ -701,6 +702,21 @@ static int org_post_recv(struct organization_tlv > *org) > if (org->length + sizeof(struct TLV) != > sizeof(struct msg_interval_req_tlv)) > goto bad_length; > } > + } else if (0 == memcmp(org->id, itu_t_id, sizeof(itu_t_id))) > { > + if (org->subtype[0] || org->subtype[1]) { > + return 0; > + } > + switch (org->subtype[2]) { > + case 2: > + if (org->length + sizeof(struct TLV) != > sizeof(struct msg_interface_rate_tlv)) > + goto bad_length; > + m = (struct msg_interface_rate_tlv *)org; > + m->interfaceBitPeriod = net2host64(m- > >interfaceBitPeriod); > + m->numberOfBitsBeforeTimestamp = ntohs(m- > >numberOfBitsBeforeTimestamp); > + m->numberOfBitsAfterTimestamp = ntohs(m- > >numberOfBitsAfterTimestamp); > + break; > + } > + > } > return 0; > bad_length: > @@ -710,6 +726,7 @@ bad_length: > static void org_pre_send(struct organization_tlv *org) > { > struct follow_up_info_tlv *f; > + struct msg_interface_rate_tlv *m; > > if (0 == memcmp(org->id, ieee8021_id, sizeof(ieee8021_id))) { > if (org->subtype[0] || org->subtype[1]) { > @@ -724,6 +741,18 @@ static void org_pre_send(struct organization_tlv > *org) > f->scaledLastGmPhaseChange = htonl(f- > >scaledLastGmPhaseChange); > break; > } > + } else if (0 == memcmp(org->id, itu_t_id, sizeof(itu_t_id))) > { > + if (org->subtype[0] || org->subtype[1]) { > + return; > + } > + switch (org->subtype[2]) { > + case 2: > + m = (struct msg_interface_rate_tlv *)org; > + m->interfaceBitPeriod = host2net64(m- > >interfaceBitPeriod); > + m->numberOfBitsBeforeTimestamp = htons(m- > >numberOfBitsBeforeTimestamp); > + m->numberOfBitsAfterTimestamp = htons(m- > >numberOfBitsAfterTimestamp); > + break; > + } > } > } > > diff --git a/unicast_service.c b/unicast_service.c > index 3154894..1078041 100644 > --- a/unicast_service.c > +++ b/unicast_service.c > @@ -84,6 +84,30 @@ static int attach_grant(struct ptp_message *msg, > return 0; > } > > +static int attach_interface_rate(struct ptp_message *msg, > + uint64_t iface_bit_period, > + uint16_t no_of_bits_before_ts, > + uint16_t no_of_bits_after_ts) > +{ > + struct msg_interface_rate_tlv *mir; > + struct tlv_extra *extra; > + > + extra = msg_tlv_append(msg, sizeof(*mir)); > + if (!extra) { > + return -1; > + } > + mir = (struct msg_interface_rate_tlv *) extra->tlv; > + mir->type = TLV_ORGANIZATION_EXTENSION; > + mir->length = sizeof(*mir) - sizeof(mir->type) - sizeof(mir- > >length); > + memcpy(mir->id, itu_t_id, sizeof(itu_t_id)); > + mir->subtype[2] = 2; > + mir->interfaceBitPeriod = iface_bit_period; > + mir->numberOfBitsBeforeTimestamp = no_of_bits_before_ts; > + mir->numberOfBitsAfterTimestamp = no_of_bits_after_ts; > + > + return 0; > +} > + > static int compare_timeout(void *ain, void *bin) > { > struct unicast_service_interval *a, *b; > @@ -256,6 +280,14 @@ static int unicast_service_reply(struct port *p, > struct ptp_message *dst, > if (err) { > goto out; > } > + if (p->iface_rate_tlv && duration > 0 && > interface_ifinfo_valid(p->iface)) { > + err = attach_interface_rate(msg, > + interface_bitperiod(p->iface), 64, > 720); > + if (err) { > + goto out; > + } > + } > + > err = port_prepare_and_send(p, msg, TRANS_GENERAL); > if (err) { > pr_err("%s: signaling message failed", p->log_name); Erez _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel