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

Reply via email to