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 <[email protected]>
> Signed-off-by: Leon Goldin <[email protected]>
> Signed-off-by: Devasish Dey <[email protected]>
> Signed-off-by: Vipin Sharma <[email protected]>
> ---
> 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel