- adding organizational TLV support for interface rate
- delay asymmetry calculation for master and slave

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>
---
 clock.c           | 12 ++++++++++++
 clock.h           | 14 ++++++++++++++
 config.c          |  1 +
 interface.c       | 15 +++++++++++++++
 interface.h       |  7 +++++++
 pdt.h             |  1 +
 port_private.h    |  1 +
 port_signaling.c  | 33 ++++++++++++++++++++++++++++++++-
 ptp4l.8           |  6 ++++++
 tlv.c             |  1 +
 tlv.h             | 14 ++++++++++++++
 unicast_service.c | 35 +++++++++++++++++++++++++++++++++++
 12 files changed, 139 insertions(+), 1 deletion(-)

diff --git a/clock.c b/clock.c
index 8f328e5..e271f5a 100644
--- a/clock.c
+++ b/clock.c
@@ -137,6 +137,7 @@ struct clock {
        struct monitor *slave_event_monitor;
        int step_window_counter;
        int step_window;
+       bool iface_rate_tlv;
 };
 
 struct clock the_clock;
@@ -1107,6 +1108,7 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
        c->utc_offset = config_get_int(config, NULL, "utc_offset");
        c->time_source = config_get_int(config, NULL, "timeSource");
        c->step_window = config_get_int(config, NULL, "step_window");
+       c->iface_rate_tlv = config_get_int(config, NULL, "interface_rate_tlv");
 
        if (c->free_running) {
                c->clkid = CLOCK_INVALID;
@@ -1718,6 +1720,11 @@ int clock_slave_only(struct clock *c)
        return c->dds.flags & DDS_SLAVE_ONLY;
 }
 
+bool clock_telecom_profile(struct clock *c)
+{
+       return (c->dscmp == telecom_dscmp);
+}
+
 UInteger8 clock_max_steps_removed(struct clock *c)
 {
        return c->max_steps_removed;
@@ -2083,3 +2090,8 @@ enum servo_state clock_servo_state(struct clock *c)
 {
        return c->servo_state;
 }
+
+bool clock_interface_rate_tlv (struct clock *c)
+{
+       return c->iface_rate_tlv;
+}
diff --git a/clock.h b/clock.h
index 0534f21..d38ef6a 100644
--- a/clock.h
+++ b/clock.h
@@ -388,4 +388,18 @@ void clock_check_ts(struct clock *c, uint64_t ts);
  */
 double clock_rate_ratio(struct clock *c);
 
+/**
+ * Obtain interface rate tlv support configuration.
+ * @param c  The clock instance.
+ * @return   The interface_rate_supoort config true if supported, else false.
+ */
+bool clock_interface_rate_tlv(struct clock *c);
+
+/**
+ * Obtain the clock is set for telecom profile .
+ * @param c  The clock instance.
+ * @return   True if the profile is telecom, false otherwise.
+ */
+bool clock_telecom_profile(struct clock *c);
+
 #endif
diff --git a/config.c b/config.c
index 6ba9996..90040de 100644
--- a/config.c
+++ b/config.c
@@ -240,6 +240,7 @@ struct config_item config_tab[] = {
        GLOB_ITEM_ENU("clock_type", CLOCK_TYPE_ORDINARY, clock_type_enu),
        GLOB_ITEM_ENU("dataset_comparison", DS_CMP_IEEE1588, dataset_comp_enu),
        PORT_ITEM_INT("delayAsymmetry", 0, INT_MIN, INT_MAX),
+       GLOB_ITEM_INT("interface_rate_tlv", 0, 0, 1),
        PORT_ITEM_ENU("delay_filter", FILTER_MOVING_MEDIAN, delay_filter_enu),
        PORT_ITEM_INT("delay_filter_length", 10, 1, INT_MAX),
        PORT_ITEM_ENU("delay_mechanism", DM_E2E, delay_mech_enu),
diff --git a/interface.c b/interface.c
index 44d6588..d186455 100644
--- a/interface.c
+++ b/interface.c
@@ -99,3 +99,18 @@ int interface_get_vclock(struct interface *iface)
 {
        return iface->vclock;
 }
+
+uint64_t interface_bitperiod(struct interface *iface)
+{
+       /* 10^18 atto-sec per bit*/
+       uint64_t if_atto_sec_bit_period = 0x0DE0B6B3A7640000;
+
+       if (!iface->if_info.valid) {
+               return 0;
+       }
+
+       if_atto_sec_bit_period /= iface->if_info.speed;
+       if_atto_sec_bit_period /= 1000000; /* 1 Mb = 10^6 */
+       return if_atto_sec_bit_period;
+
+}
diff --git a/interface.h b/interface.h
index fbbe919..4303568 100644
--- a/interface.h
+++ b/interface.h
@@ -119,4 +119,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.
+ * @param iface  The interface of interest.
+ * @return       if valid speed return interface bitperiod in atto seconds.
+ */
+uint64_t interface_bitperiod(struct interface *iface);
+
 #endif
diff --git a/pdt.h b/pdt.h
index e46b218..1ad23d4 100644
--- a/pdt.h
+++ b/pdt.h
@@ -39,6 +39,7 @@ typedef uint16_t  UInteger16;
 typedef int32_t   Integer32;
 typedef uint32_t  UInteger32;
 typedef int64_t   Integer64;
+typedef uint64_t  UInteger64;
 typedef uint8_t   Octet;
 
 #endif
diff --git a/port_private.h b/port_private.h
index d27dceb..d1a1e76 100644
--- a/port_private.h
+++ b/port_private.h
@@ -145,6 +145,7 @@ struct port {
        UInteger8           versionNumber; /* UInteger4 */
        UInteger8           delay_response_counter;
        UInteger8           delay_response_timeout;
+       Integer64           portAsymmetry;
        struct PortStats    stats;
        struct PortServiceStats    service_stats;
        /* foreignMasterDS */
diff --git a/port_signaling.c b/port_signaling.c
index ed217c0..78db221 100644
--- a/port_signaling.c
+++ b/port_signaling.c
@@ -103,10 +103,38 @@ 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;
+
+       if (clock_interface_rate_tlv (p->clock) &&
+                       interface_ifinfo_valid(p->iface)) {
+               /* Delay Asymmetry Calculation */
+               delayAsymmetry  = r->interfaceBitPeriod -
+                       interface_bitperiod(p->iface);
+               delayAsymmetry  = delayAsymmetry/2;
+               nsDelay = (double)delayAsymmetry / 1000000000;
+               delayAsymmetry =
+                       (r->numberOfBitsAfterTimestamp -
+                        r->numberOfBitsBeforeTimestamp)  * nsDelay;
+               if (delayAsymmetry != p->portAsymmetry) {
+                       /* Updating the nanosecond part */
+                       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 msg_interval_req_tlv *r;
+       struct msg_interface_rate_tlv *rate;
        int err = 0, result;
 
        switch (p->state) {
@@ -161,10 +189,13 @@ int process_signaling(struct port *p, struct ptp_message 
*m)
 
                case TLV_ORGANIZATION_EXTENSION:
                        r = (struct msg_interval_req_tlv *) extra->tlv;
-
+                       rate = (struct msg_interface_rate_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)
                                err = process_interval_request(p, r);
+                       else if (0 == memcmp(r->id, itu_t_id, sizeof(itu_t_id)) 
&&
+                               r->subtype[0] == 0 && r->subtype[1] == 0 && 
r->subtype[2] == 2)
+                               err = process_interface_rate(p, rate);
                        break;
                }
        }
diff --git a/ptp4l.8 b/ptp4l.8
index e33454a..01b0d0f 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -705,6 +705,12 @@ the interval, the sample will be printed instead of the 
statistics. The
 messages are printed at the LOG_INFO level.
 The default is 0 (1 second).
 .TP
+.B interface_rate_tlv
+When master and slave instances are operating at different interface rate,
+delay asymmetry caused due to different interface rate needs to be compensated.
+The master and slave exhanges their interface rate based on interface rate TLV
+as per G.8275.2 Annex D.
+The default is 0 (does not support interface rate tlv).
 .B time_stamping
 The time stamping method to be used.  The allowed values are hardware,
 software, legacy, onestep, and p2p1step.
diff --git a/tlv.c b/tlv.c
index 1c13460..35bee4f 100644
--- a/tlv.c
+++ b/tlv.c
@@ -35,6 +35,7 @@
        (tlv->length < sizeof(struct type) - sizeof(struct TLV))
 
 uint8_t ieee8021_id[3] = { IEEE_802_1_COMMITTEE };
+uint8_t itu_t_id[3] = { ITU_T_COMMITTEE };
 
 static TAILQ_HEAD(tlv_pool, tlv_extra) tlv_pool =
        TAILQ_HEAD_INITIALIZER(tlv_pool);
diff --git a/tlv.h b/tlv.h
index 8966696..ec22e2f 100644
--- a/tlv.h
+++ b/tlv.h
@@ -395,6 +395,20 @@ struct tlv_extra {
        };
 };
 
+/* Organizationally Unique Identifiers */
+#define ITU_T_COMMITTEE 0x00, 0x19, 0xA7
+extern uint8_t itu_t_id[3];
+
+struct msg_interface_rate_tlv {
+       Enumeration16 type;
+       UInteger16    length;
+       Octet         id[3];
+       Octet         subtype[3];
+       UInteger64    interfaceBitPeriod;
+       UInteger16    numberOfBitsBeforeTimestamp;
+       UInteger16    numberOfBitsAfterTimestamp;
+} PACKED;
+
 /**
  * Allocates a new tlv_extra structure.
  * @return  Pointer to a new structure on success or NULL otherwise.
diff --git a/unicast_service.c b/unicast_service.c
index 3154894..d7bcc42 100644
--- a/unicast_service.c
+++ b/unicast_service.c
@@ -84,6 +84,31 @@ 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 +281,16 @@ static int unicast_service_reply(struct port *p, struct 
ptp_message *dst,
        if (err) {
                goto out;
        }
+
+       if (clock_interface_rate_tlv (p->clock) && duration > 0 &&
+               clock_telecom_profile(p->clock) &&
+              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);
-- 
2.17.1



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

Reply via email to