[Linuxptp-devel] [PATCH v4 1/4] [Interface Rate TLV] function to support get interface speed via ethtool
When master and slave instance interacting with each other operating at different interface speed, delay assymetry needs to be compensated as described in G.8271 appendix V. In this patch we are adding changes to get the interface speed using ethtool. v1: initial commit. v2: updating comments and data types. v3: updating Boolean data type to bool from v4: updating iface_if_info.speed data type to uint32_t from int. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- sk.c | 71 sk.h | 19 2 files changed, 90 insertions(+) diff --git a/sk.c b/sk.c index d27abff..1c14ca3 100644 --- a/sk.c +++ b/sk.c @@ -205,6 +205,77 @@ failed: return -1; } +int sk_get_if_info(const char *name, struct sk_if_info *if_info) +{ +#ifdef ETHTOOL_GLINKSETTINGS + struct ifreq ifr; + int fd, err; + + struct { + struct ethtool_link_settings req; + /* +* link_mode_data consists of supported[], advertising[], +* lp_advertising[] with size up to 127 each. +* The actual size is provided by the kernel. +*/ + __u32 link_mode_data[3 * 127]; + } ecmd; + + memset(, 0, sizeof(ifr)); + memset(, 0, sizeof(ecmd)); + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + goto failed; + } + + ecmd.req.cmd = ETHTOOL_GLINKSETTINGS; + + strncpy(ifr.ifr_name, name, IFNAMSIZ - 1); + ifr.ifr_data = (char *) + + /* Handshake with kernel to determine number of words for link +* mode bitmaps. When requested number of bitmap words is not +* the one expected by kernel, the latter returns the integer +* opposite of what it is expecting. We request length 0 below +* (aka. invalid bitmap length) to get this info. +*/ + err = ioctl(fd, SIOCETHTOOL, ); + if (err < 0) { + pr_err("ioctl SIOCETHTOOL failed: %m"); + close(fd); + goto failed; + } + + if (ecmd.req.link_mode_masks_nwords >= 0 || + ecmd.req.cmd != ETHTOOL_GLINKSETTINGS) { + return 1; + } + ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords; + + err = ioctl(fd, SIOCETHTOOL, ); + if (err < 0) { + pr_err("ioctl SIOCETHTOOL failed: %m"); + close(fd); + goto failed; + } + + close(fd); + + /* copy the necessary data to sk_info */ + memset(if_info, 0, sizeof(struct sk_if_info)); + if_info->valid = 1; + if_info->speed = ecmd.req.speed; + + return 0; +failed: +#endif + /* clear data and ensure it is not marked valid */ + memset(if_info, 0, sizeof(struct sk_if_info)); + return -1; +} + + static int sk_interface_guidaddr(const char *name, unsigned char *guid) { char file_name[64], buf[64], addr[8]; diff --git a/sk.h b/sk.h index 486dbc4..7a9058a 100644 --- a/sk.h +++ b/sk.h @@ -20,6 +20,7 @@ #ifndef HAVE_SK_H #define HAVE_SK_H +#include #include "address.h" #include "transport.h" @@ -49,6 +50,16 @@ struct sk_ts_info { unsigned int rx_filters; }; +/** + * Contains interface information returned by the GLINKSETTINGS ioctl. + * @valid:set to non-zero when the info struct contains valid data. + * @speed:interface speed. + */ +struct sk_if_info { + bool valid; + uint32_t speed; +}; + /** * Obtains a socket suitable for use with sk_interface_index(). * @return An open socket on success, -1 otherwise. @@ -78,6 +89,14 @@ int sk_general_init(int fd); */ int sk_get_ts_info(const char *name, struct sk_ts_info *sk_info); +/** + * Obtain supporte interface information + * @param name The name of the interface + * @param info Struct containing obtained interface information. + * @return zero on success, negative on failure. + */ +int sk_get_if_info(const char *name, struct sk_if_info *sk_info); + /** * Obtain the MAC address of a network interface. * @param name The name of the interface -- 2.34.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH v4 4/4] [Interface Rate TLV] adding delay asymmetry calculation
Delay asymmetry calculation based on the PTP port interface speed of master obtained from TLV and the slave interface rate obtained by ethtool. The calculation is done in attoseconds to accomodate interface bit period less than 1ns. (ITU-T G.8275.2(06/2021) annex D). v4: removing bit period calculation on every signalling message and updating the bit-period when link update happens v3: updating network/host byte order handling. v1: initial commit Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- interface.c | 5 + interface.h | 7 +++ port_private.h| 1 + port_signaling.c | 39 --- ptp4l.8 | 7 +++ tlv.c | 29 + unicast_service.c | 32 7 files changed, 117 insertions(+), 3 deletions(-) diff --git a/interface.c b/interface.c index 8524719..29229ad 100644 --- a/interface.c +++ b/interface.c @@ -94,3 +94,8 @@ int interface_get_vclock(struct interface *iface) { return iface->vclock; } + +uint64_t interface_bitperiod(struct interface *iface) +{ + return iface->if_info.iface_bit_period; +} diff --git a/interface.h b/interface.h index 5289a7f..0873bba 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. + * @param iface The interface of interest. + * @return return interface bitperiod in atto seconds. + */ +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; booliface_rate_tlv; + Integer64 portAsymmetry; struct PortStatsstats; struct PortServiceStatsservice_stats; /* foreignMasterDS */ diff --git a/port_signaling.c b/port_signaling.c index ed217c0..5a764d6 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; + doublensDelay; + 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 = (double)(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 ---
[Linuxptp-devel] [PATCH v4 3/4] [Interface Rate TLV] organization TLV support for interface rate
adding interface rate TLV as defined by ITU-T G.8275.2 Annex D to enable master to communicate PTP port interface rate to slave. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma v4: Updating comments for UInteger64 introduced in pdt.h as per ITU-T G.8275.2 --- config.c | 1 + pdt.h | 1 + port.c | 1 + port_private.h | 1 + tlv.c | 1 + tlv.h | 14 ++ 6 files changed, 19 insertions(+) diff --git a/config.c b/config.c index 08e3346..2fa95fc 100644 --- a/config.c +++ b/config.c @@ -267,6 +267,7 @@ struct config_item config_tab[] = { PORT_ITEM_INT("inhibit_delay_req", 0, 0, 1), PORT_ITEM_INT("inhibit_multicast_service", 0, 0, 1), GLOB_ITEM_INT("initial_delay", 0, 0, INT_MAX), + PORT_ITEM_INT("interface_rate_tlv", 0, 0, 1), GLOB_ITEM_INT("kernel_leap", 1, 0, 1), GLOB_ITEM_STR("leapfile", NULL), PORT_ITEM_INT("logAnnounceInterval", 1, INT8_MIN, INT8_MAX), diff --git a/pdt.h b/pdt.h index e46b218..eaad58b 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; /* ITU-T G.8275.2 */ typedef uint8_t Octet; #endif diff --git a/port.c b/port.c index 2a96c40..8a1c42a 100644 --- a/port.c +++ b/port.c @@ -1854,6 +1854,7 @@ int port_initialize(struct port *p) p->neighborPropDelayThresh = config_get_int(cfg, p->name, "neighborPropDelayThresh"); p->min_neighbor_prop_delay = config_get_int(cfg, p->name, "min_neighbor_prop_delay"); p->delay_response_timeout = config_get_int(cfg, p->name, "delay_response_timeout"); + p->iface_rate_tlv = config_get_int(cfg, p->name, "interface_rate_tlv"); if (config_get_int(cfg, p->name, "asCapable") == AS_CAPABLE_TRUE) { p->asCapable = ALWAYS_CAPABLE; diff --git a/port_private.h b/port_private.h index d27dceb..d6487eb 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; + booliface_rate_tlv; struct PortStatsstats; struct PortServiceStatsservice_stats; /* foreignMasterDS */ 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; + UInteger16length; + Octet id[3]; + Octet subtype[3]; + UInteger64interfaceBitPeriod; + UInteger16numberOfBitsBeforeTimestamp; + UInteger16numberOfBitsAfterTimestamp; +} PACKED; + /** * Allocates a new tlv_extra structure. * @return Pointer to a new structure on success or NULL otherwise. -- 2.34.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH v4 2/4] [Interface Rate TLV] adding speed field information for interface
Get the interface speed related information using ethtool and convert interface speed to bit rate in attoseconds per bit. v4: adding interface bit period in iface_if_info. This bit period is updated during init time and whenever there are port events like link up and down and speed updates. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- clock.c | 6 -- interface.c | 12 interface.h | 14 ++ port.c | 5 + sk.c| 2 ++ sk.h| 2 ++ 6 files changed, 39 insertions(+), 2 deletions(-) diff --git a/clock.c b/clock.c index 134c7c3..94da41b 100644 --- a/clock.c +++ b/clock.c @@ -1005,11 +1005,13 @@ struct clock *clock_create(enum clock_type type, struct config *config, memset(ts_label, 0, sizeof(ts_label)); if (!rtnl_get_ts_device(interface_name(iface), ts_label)) interface_set_label(iface, ts_label); + /* Interface speed information */ + interface_get_ifinfo(iface); interface_get_tsinfo(iface); if (interface_tsinfo_valid(iface) && - !interface_tsmodes_supported(iface, required_modes)) { + !interface_tsmodes_supported(iface, required_modes)) { pr_err("interface '%s' does not support requested timestamping mode", - interface_name(iface)); + interface_name(iface)); return NULL; } } diff --git a/interface.c b/interface.c index 6c2630c..8524719 100644 --- a/interface.c +++ b/interface.c @@ -12,6 +12,7 @@ struct interface { char name[MAX_IFNAME_SIZE + 1]; char ts_label[MAX_IFNAME_SIZE + 1]; struct sk_ts_info ts_info; + struct sk_if_info if_info; int vclock; }; @@ -40,11 +41,22 @@ int interface_get_tsinfo(struct interface *iface) return sk_get_ts_info(iface->ts_label, >ts_info); } +int interface_get_ifinfo(struct interface *iface) +{ + return sk_get_if_info(iface->ts_label, >if_info); +} + const char *interface_label(struct interface *iface) { return iface->ts_label; } +bool interface_ifinfo_valid(struct interface *iface) +{ + return iface->if_info.valid ? true : false; +} + + const char *interface_name(struct interface *iface) { return iface->name; diff --git a/interface.h b/interface.h index 5fc7836..5289a7f 100644 --- a/interface.h +++ b/interface.h @@ -40,6 +40,13 @@ void interface_destroy(struct interface *iface); */ int interface_get_tsinfo(struct interface *iface); +/** + * Populate the time stamping information of a given interface. + * @param iface The interface of interest. + * @return zero on success, negative on failure. + */ +int interface_get_ifinfo(struct interface *iface); + /** * Obtain the time stamping label of a network interface. This can be * different from the name of the interface when bonding is in effect. @@ -77,6 +84,13 @@ void interface_set_label(struct interface *iface, const char *label); */ bool interface_tsinfo_valid(struct interface *iface); +/** + * Tests whether an interface's interface information is valid or not. + * @param iface The interface of interest. + * @return True if the interface information is valid, false otherwise. + */ +bool interface_ifinfo_valid(struct interface *iface); + /** * Tests whether an interface supports a set of given time stamping modes. * @param iface The interface of interest. diff --git a/port.c b/port.c index 6baf5c8..2a96c40 100644 --- a/port.c +++ b/port.c @@ -2741,6 +2741,11 @@ void port_link_status(void *ctx, int linkup, int ts_index) p->link_status = link_state; } else { p->link_status = link_state | LINK_STATE_CHANGED; + /* Update Interface speed information on Link up*/ + if (linkup) { + interface_get_ifinfo(p->iface); + } + pr_notice("%s: link %s", p->log_name, linkup ? "up" : "down"); } diff --git a/sk.c b/sk.c index 1c14ca3..2e4ef2c 100644 --- a/sk.c +++ b/sk.c @@ -267,6 +267,8 @@ int sk_get_if_info(const char *name, struct sk_if_info *if_info) if_info->valid = 1; if_info->speed = ecmd.req.speed; + /* Megabits per second converted to attoseconds per bit */ + if_info->iface_bit_period = (1ULL/if_info->speed); return 0; failed: #endif diff --git a/sk.h b/sk.h index 7a9058a..df105d6 100644 --- a/sk.h +++ b/sk.h @@ -54,10 +54,12 @@ struct sk_ts_info { * Contains interface information returned by the GLINKSETTINGS ioctl. * @valid:set to non-zero when the info struct contains valid data. * @speed:interface speed. + * @iface_bit_period interface bit period in attoseconds
[Linuxptp-devel] [PATCH v3 2/4] [Interface Rate TLV] adding speed field information for interface
Get the interface speed related information using ethtool Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- clock.c | 2 ++ interface.c | 12 interface.h | 14 ++ port.c | 5 + 4 files changed, 33 insertions(+) diff --git a/clock.c b/clock.c index 5186010..7323636 100644 --- a/clock.c +++ b/clock.c @@ -1005,6 +1005,8 @@ struct clock *clock_create(enum clock_type type, struct config *config, memset(ts_label, 0, sizeof(ts_label)); if (!rtnl_get_ts_device(interface_name(iface), ts_label)) interface_set_label(iface, ts_label); +/* Interface speed information */ +interface_get_ifinfo(iface); interface_get_tsinfo(iface); if (interface_tsinfo_valid(iface) && !interface_tsmodes_supported(iface, required_modes)) { diff --git a/interface.c b/interface.c index 6c2630c..3157e8c 100644 --- a/interface.c +++ b/interface.c @@ -12,6 +12,7 @@ struct interface { char name[MAX_IFNAME_SIZE + 1]; char ts_label[MAX_IFNAME_SIZE + 1]; struct sk_ts_info ts_info; +struct sk_if_info if_info; int vclock; }; @@ -40,11 +41,22 @@ int interface_get_tsinfo(struct interface *iface) return sk_get_ts_info(iface->ts_label, >ts_info); } +int interface_get_ifinfo(struct interface *iface) +{ + return sk_get_if_info(iface->ts_label, >if_info); +} + const char *interface_label(struct interface *iface) { return iface->ts_label; } +bool interface_ifinfo_valid(struct interface *iface) +{ + return iface->if_info.valid ? true : false; +} + + const char *interface_name(struct interface *iface) { return iface->name; diff --git a/interface.h b/interface.h index 5fc7836..f4b9545 100644 --- a/interface.h +++ b/interface.h @@ -40,6 +40,13 @@ void interface_destroy(struct interface *iface); */ int interface_get_tsinfo(struct interface *iface); +/** + * Populate the time stamping information of a given interface. + * @param iface The interface of interest. + * @return zero on success, negative on failure. + */ +int interface_get_ifinfo(struct interface *iface); + /** * Obtain the time stamping label of a network interface. This can be * different from the name of the interface when bonding is in effect. @@ -77,6 +84,13 @@ void interface_set_label(struct interface *iface, const char *label); */ bool interface_tsinfo_valid(struct interface *iface); +/** + * Tests whether an interface's interface information is valid or not. + * @param iface The interface of interest. + * @return True if the interface information is valid, false otherwise. + */ +bool interface_ifinfo_valid(struct interface *iface); + /** * Tests whether an interface supports a set of given time stamping modes. * @param iface The interface of interest. diff --git a/port.c b/port.c index 1866a20..7fd50dd 100644 --- a/port.c +++ b/port.c @@ -2738,6 +2738,11 @@ void port_link_status(void *ctx, int linkup, int ts_index) p->link_status = link_state; } else { p->link_status = link_state | LINK_STATE_CHANGED; +/* Update Interface speed information on Link up*/ +if (linkup) { +interface_get_ifinfo(p->iface); +} + pr_notice("%s: link %s", p->log_name, linkup ? "up" : "down"); } -- 2.34.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH v3 3/4] [Interface Rate TLV] organization TLV support for interface rate
adding interface rate TLV as defined by ITU-T G.8275.2 Annex D to enable master to communicate PTP port interface rate to slave. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- config.c | 1 + pdt.h | 1 + port.c | 1 + port_private.h | 1 + tlv.c | 1 + tlv.h | 14 ++ 6 files changed, 19 insertions(+) diff --git a/config.c b/config.c index 08e3346..2fa95fc 100644 --- a/config.c +++ b/config.c @@ -267,6 +267,7 @@ struct config_item config_tab[] = { PORT_ITEM_INT("inhibit_delay_req", 0, 0, 1), PORT_ITEM_INT("inhibit_multicast_service", 0, 0, 1), GLOB_ITEM_INT("initial_delay", 0, 0, INT_MAX), + PORT_ITEM_INT("interface_rate_tlv", 0, 0, 1), GLOB_ITEM_INT("kernel_leap", 1, 0, 1), GLOB_ITEM_STR("leapfile", NULL), PORT_ITEM_INT("logAnnounceInterval", 1, INT8_MIN, INT8_MAX), 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.c b/port.c index 7fd50dd..85cfa4a 100644 --- a/port.c +++ b/port.c @@ -1854,6 +1854,7 @@ int port_initialize(struct port *p) p->neighborPropDelayThresh = config_get_int(cfg, p->name, "neighborPropDelayThresh"); p->min_neighbor_prop_delay = config_get_int(cfg, p->name, "min_neighbor_prop_delay"); p->delay_response_timeout = config_get_int(cfg, p->name, "delay_response_timeout"); + p->iface_rate_tlv = config_get_int(cfg, p->name, "interface_rate_tlv"); if (config_get_int(cfg, p->name, "asCapable") == AS_CAPABLE_TRUE) { p->asCapable = ALWAYS_CAPABLE; diff --git a/port_private.h b/port_private.h index d27dceb..d6487eb 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; + booliface_rate_tlv; struct PortStatsstats; struct PortServiceStatsservice_stats; /* foreignMasterDS */ 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; + UInteger16length; + Octet id[3]; + Octet subtype[3]; + UInteger64interfaceBitPeriod; + UInteger16numberOfBitsBeforeTimestamp; + UInteger16numberOfBitsAfterTimestamp; +} PACKED; + /** * Allocates a new tlv_extra structure. * @return Pointer to a new structure on success or NULL otherwise. -- 2.34.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH v3 4/4] [Interface Rate TLV] adding delay asymmetry calculation
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 Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- 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 1ULL/ iface->if_info.speed; +} + 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. + * @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/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; booliface_rate_tlv; + Integer64 portAsymmetry; struct PortStatsstats; struct PortServiceStatsservice_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; + doublensDelay; + 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
[Linuxptp-devel] [PATCH v3 1/4] [Interface Rate TLV] function to support get interface speed via ethtool
When master and slave instance interacting with each other operating at different interface speed, delay assymetry needs to be compensated as described in G.8271 appendix V. In this patch we are adding changes to get the interface speed using ethtool. v1: initial commit. v2: updating comments and data types. v3: updating Boolean data type to bool from --- sk.c | 71 sk.h | 19 2 files changed, 90 insertions(+) diff --git a/sk.c b/sk.c index d27abff..1d1a656 100644 --- a/sk.c +++ b/sk.c @@ -205,6 +205,77 @@ failed: return -1; } +int sk_get_if_info(const char *name, struct sk_if_info *if_info) +{ +#ifdef ETHTOOL_GLINKSETTINGS + struct ifreq ifr; + int fd, err; + + struct { + struct ethtool_link_settings req; + /* +* link_mode_data consists of supported[], advertising[], +* lp_advertising[] with size up to 127 each. +* The actual size is provided by the kernel. +*/ + __u32 link_mode_data[3 * 127]; + } ecmd; + + memset(, 0, sizeof(ifr)); + memset(, 0, sizeof(ecmd)); + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + goto failed; + } + + ecmd.req.cmd = ETHTOOL_GLINKSETTINGS; + + strncpy(ifr.ifr_name, name, IFNAMSIZ - 1); + ifr.ifr_data = (char *) + + /* Handshake with kernel to determine number of words for link +* mode bitmaps. When requested number of bitmap words is not +* the one expected by kernel, the latter returns the integer +* opposite of what it is expecting. We request length 0 below +* (aka. invalid bitmap length) to get this info. +*/ + err = ioctl(fd, SIOCETHTOOL, ); + if (err < 0) { + pr_err("ioctl SIOCETHTOOL failed: %m"); + close(fd); + goto failed; + } + + if (ecmd.req.link_mode_masks_nwords >= 0 || + ecmd.req.cmd != ETHTOOL_GLINKSETTINGS) { + return 1; + } + ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords; + + err = ioctl(fd, SIOCETHTOOL, ); + if (err < 0) { + pr_err("ioctl SIOCETHTOOL failed: %m"); + close(fd); + goto failed; + } + + close(fd); + + /* copy the necessary data to sk_info */ + memset(if_info, 0, sizeof(struct sk_if_info)); + if_info->valid = 1; + if_info->speed = ecmd.req.speed; + + return 0; +failed: +#endif + /* clear data and ensure it is not marked valid */ + memset(if_info, 0, sizeof(struct sk_if_info)); + return -1; +} + + static int sk_interface_guidaddr(const char *name, unsigned char *guid) { char file_name[64], buf[64], addr[8]; diff --git a/sk.h b/sk.h index 486dbc4..4cee3d7 100644 --- a/sk.h +++ b/sk.h @@ -20,6 +20,7 @@ #ifndef HAVE_SK_H #define HAVE_SK_H +#include #include "address.h" #include "transport.h" @@ -49,6 +50,16 @@ struct sk_ts_info { unsigned int rx_filters; }; +/** + * Contains interface information returned by theGLINKSETTINGS ioctl. + * @valid:set to non-zero when the info struct contains valid data. + * @speed:interface speed. + */ +struct sk_if_info { + bool valid; + int speed; +}; + /** * Obtains a socket suitable for use with sk_interface_index(). * @return An open socket on success, -1 otherwise. @@ -78,6 +89,14 @@ int sk_general_init(int fd); */ int sk_get_ts_info(const char *name, struct sk_ts_info *sk_info); +/** + * Obtain supporte interface information + * @param name The name of the interface + * @param info Struct containing obtained interface information. + * @return zero on success, negative on failure. + */ +int sk_get_if_info(const char *name, struct sk_if_info *sk_info); + /** * Obtain the MAC address of a network interface. * @param name The name of the interface -- 2.34.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH 4/4] [Interface Rate TLV] adding delay asymmetry calculation
From: devasishsyncmonk Delay asymmetry calculation based on the PTP port interface speed of master obtained from TLV and the slave interface rate obtained by ethtool. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- interface.c | 9 + interface.h | 7 +++ port_private.h| 1 + port_signaling.c | 32 ptp4l.8 | 7 +++ unicast_service.c | 35 +++ 6 files changed, 91 insertions(+) diff --git a/interface.c b/interface.c index 9c30499..6237e88 100644 --- a/interface.c +++ b/interface.c @@ -93,3 +93,12 @@ 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 1ULL/ iface->if_info.speed; +} diff --git a/interface.h b/interface.h index 5289a7f..e1dc0e8 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. + * @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/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 PortStatsstats; struct PortServiceStatsservice_stats; /* foreignMasterDS */ diff --git a/port_signaling.c b/port_signaling.c index ed217c0..d78acb6 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; + doublensDelay; + Integer64 slaveBitPeriod; + Integer64 masterBitPeriod; + + if (clock_interface_rate_tlv (p->clock) && + 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 msg_interval_req_tlv *r; + struct msg_interface_rate_tlv *rate; int err = 0, result; switch (p->state) { @@ -161,10 +189,14 @@ 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 1268802..eab4b47 100644 --- a/ptp4l.8 +++ b/ptp4l.8 @@ -695,6 +695,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). + .B summary_interval The time interval in which are printed summary statistics of the clock. It is specified as a power
[Linuxptp-devel] [PATCH 2/4] [Interface Rate TLV] adding speed field information for interface
From: devasishsyncmonk Get the interface speed related information using ethtool Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- clock.c | 2 ++ interface.c | 11 +++ interface.h | 14 ++ port.c | 4 4 files changed, 31 insertions(+) diff --git a/clock.c b/clock.c index d37bb87..086b1a8 100644 --- a/clock.c +++ b/clock.c @@ -1004,6 +1004,8 @@ struct clock *clock_create(enum clock_type type, struct config *config, memset(ts_label, 0, sizeof(ts_label)); if (!rtnl_get_ts_device(interface_name(iface), ts_label)) interface_set_label(iface, ts_label); +/* Interface speed information */ +interface_get_ifinfo(iface); interface_get_tsinfo(iface); if (interface_tsinfo_valid(iface) && !interface_tsmodes_supported(iface, required_modes)) { diff --git a/interface.c b/interface.c index 6c2630c..9c30499 100644 --- a/interface.c +++ b/interface.c @@ -12,6 +12,7 @@ struct interface { char name[MAX_IFNAME_SIZE + 1]; char ts_label[MAX_IFNAME_SIZE + 1]; struct sk_ts_info ts_info; +struct sk_if_info if_info; int vclock; }; @@ -40,11 +41,21 @@ int interface_get_tsinfo(struct interface *iface) return sk_get_ts_info(iface->ts_label, >ts_info); } +int interface_get_ifinfo(struct interface *iface) +{ + return sk_get_if_info(iface->ts_label, >if_info); +} + const char *interface_label(struct interface *iface) { return iface->ts_label; } +bool interface_ifinfo_valid(struct interface *iface) +{ + return iface->if_info.valid ? true : false; +} + const char *interface_name(struct interface *iface) { return iface->name; diff --git a/interface.h b/interface.h index 5fc7836..5289a7f 100644 --- a/interface.h +++ b/interface.h @@ -40,6 +40,13 @@ void interface_destroy(struct interface *iface); */ int interface_get_tsinfo(struct interface *iface); +/** + * Populate the time stamping information of a given interface. + * @param iface The interface of interest. + * @return zero on success, negative on failure. + */ +int interface_get_ifinfo(struct interface *iface); + /** * Obtain the time stamping label of a network interface. This can be * different from the name of the interface when bonding is in effect. @@ -77,6 +84,13 @@ void interface_set_label(struct interface *iface, const char *label); */ bool interface_tsinfo_valid(struct interface *iface); +/** + * Tests whether an interface's interface information is valid or not. + * @param iface The interface of interest. + * @return True if the interface information is valid, false otherwise. + */ +bool interface_ifinfo_valid(struct interface *iface); + /** * Tests whether an interface supports a set of given time stamping modes. * @param iface The interface of interest. diff --git a/port.c b/port.c index 871ad68..ca508a6 100644 --- a/port.c +++ b/port.c @@ -2726,6 +2726,10 @@ void port_link_status(void *ctx, int linkup, int ts_index) p->link_status = link_state; } else { p->link_status = link_state | LINK_STATE_CHANGED; + /* Update Interface speed information on Link up*/ +if (linkup) { +interface_get_ifinfo(p->iface); +} pr_notice("%s: link %s", p->log_name, linkup ? "up" : "down"); } -- 2.34.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH 1/4] [Interface Rate TLV] function to support get interface speed via ethtool
From: devasishsyncmonk When master and slave instance interacting with each other operating at different interface speed, delay assymetry needs to be compensated as described in G.8271 appendix V. In this patch we are adding changes to get the interface speed using ethtool. v1: initial commit. v2: updating comments and data types. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- sk.c | 71 sk.h | 20 + 2 files changed, 91 insertions(+) diff --git a/sk.c b/sk.c index 80075be..8525603 100644 --- a/sk.c +++ b/sk.c @@ -205,6 +205,77 @@ failed: return -1; } +int sk_get_if_info(const char *name, struct sk_if_info *if_info) +{ +#ifdef ETHTOOL_GLINKSETTINGS + struct ifreq ifr; + int fd, err; + + struct { + struct ethtool_link_settings req; + /* +* link_mode_data consists of supported[], advertising[], +* lp_advertising[] with size up to 127 each. +* The actual size is provided by the kernel. +*/ + __u32 link_mode_data[3 * 127]; + } ecmd; + + memset(, 0, sizeof(ifr)); + memset(, 0, sizeof(ecmd)); + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + goto failed; + } + + ecmd.req.cmd = ETHTOOL_GLINKSETTINGS; + + strncpy(ifr.ifr_name, name, IFNAMSIZ - 1); + ifr.ifr_data = (char *) + + /* Handshake with kernel to determine number of words for link +* mode bitmaps. When requested number of bitmap words is not +* the one expected by kernel, the latter returns the integer +* opposite of what it is expecting. We request length 0 below +* (aka. invalid bitmap length) to get this info. +*/ + err = ioctl(fd, SIOCETHTOOL, ); + if (err < 0) { + pr_err("ioctl SIOCETHTOOL failed: %m"); + close(fd); + goto failed; + } + + if (ecmd.req.link_mode_masks_nwords >= 0 || + ecmd.req.cmd != ETHTOOL_GLINKSETTINGS) { + return 1; + } + ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords; + + err = ioctl(fd, SIOCETHTOOL, ); + if (err < 0) { + pr_err("ioctl SIOCETHTOOL failed: %m"); + close(fd); + goto failed; + } + + close(fd); + + /* copy the necessary data to sk_info */ + memset(if_info, 0, sizeof(struct sk_if_info)); + if_info->valid = 1; + if_info->speed = ecmd.req.speed; + + return 0; +failed: +#endif + /* clear data and ensure it is not marked valid */ + memset(if_info, 0, sizeof(struct sk_if_info)); + return -1; +} + + static int sk_interface_guidaddr(const char *name, unsigned char *guid) { char file_name[64], buf[64], addr[8]; diff --git a/sk.h b/sk.h index 486dbc4..ea19a8e 100644 --- a/sk.h +++ b/sk.h @@ -49,6 +49,17 @@ struct sk_ts_info { unsigned int rx_filters; }; +/** + * Contains interface information returned by theGLINKSETTINGS ioctl. + * @valid:set to non-zero when the info struct contains valid data. + * @speed:interface speed. + */ +struct sk_if_info { + Boolean valid; + int speed; +}; + + /** * Obtains a socket suitable for use with sk_interface_index(). * @return An open socket on success, -1 otherwise. @@ -78,6 +89,15 @@ int sk_general_init(int fd); */ int sk_get_ts_info(const char *name, struct sk_ts_info *sk_info); +/** + * Obtain supporte interface information + * @param name The name of the interface + * @param info Struct containing obtained interface information. + * @return zero on success, negative on failure. + */ +int sk_get_if_info(const char *name, struct sk_if_info *sk_info); + + /** * Obtain the MAC address of a network interface. * @param name The name of the interface -- 2.34.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH 3/4] [Interface Rate TLV] organization TLV support for interface rate
From: devasishsyncmonk adding interface rate TLV as defined by ITU-T G.8275.2 Annex D to enable master to communicate PTP port interface rate to slave. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma -v1: initial commit -v2: maintaining alphabetical sequence for the config. --- clock.c | 7 +++ clock.h | 7 +++ config.c | 1 + pdt.h| 1 + tlv.c| 1 + tlv.h| 15 +++ 6 files changed, 32 insertions(+) diff --git a/clock.c b/clock.c index 086b1a8..c6708e0 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; @@ -1106,6 +1107,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; @@ -2083,6 +2085,11 @@ struct servo *clock_servo(struct clock *c) return c->servo; } +bool clock_interface_rate_tlv (struct clock *c) +{ + return c->iface_rate_tlv; +} + enum servo_state clock_servo_state(struct clock *c) { return c->servo_state; diff --git a/clock.h b/clock.h index 0534f21..b393c3e 100644 --- a/clock.h +++ b/clock.h @@ -388,4 +388,11 @@ 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); + #endif diff --git a/config.c b/config.c index e454c91..be19143 100644 --- a/config.c +++ b/config.c @@ -267,6 +267,7 @@ struct config_item config_tab[] = { PORT_ITEM_INT("inhibit_delay_req", 0, 0, 1), PORT_ITEM_INT("inhibit_multicast_service", 0, 0, 1), GLOB_ITEM_INT("initial_delay", 0, 0, INT_MAX), + PORT_ITEM_INT("interface_rate_tlv", 0, 0, 1), GLOB_ITEM_INT("kernel_leap", 1, 0, 1), GLOB_ITEM_STR("leapfile", NULL), PORT_ITEM_INT("logAnnounceInterval", 1, INT8_MIN, INT8_MAX), 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/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..1dfaac8 100644 --- a/tlv.h +++ b/tlv.h @@ -395,6 +395,21 @@ 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; + UInteger16length; + Octet id[3]; + Octet subtype[3]; + UInteger64interfaceBitPeriod; + UInteger16numberOfBitsBeforeTimestamp; + UInteger16numberOfBitsAfterTimestamp; +} PACKED; + + /** * Allocates a new tlv_extra structure. * @return Pointer to a new structure on success or NULL otherwise. -- 2.34.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH v3 3/3] Adding support for passing announce message from external source
The announce message from the External source is passed by virtual port for BMCA participation so that it becomes a selection source along with other ports for linuxPTP. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Vipin Sharma Signed-off-by: Devasish Dey v2->v3: - no change. v1->v2: - amended commit message --- ts2phc_phc_pps_source.c | 23 +++ ts2phc_phc_pps_source.h | 2 ++ ts2phc_pps_sink.c | 6 +- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/ts2phc_phc_pps_source.c b/ts2phc_phc_pps_source.c index 5f15e8e..0546913 100644 --- a/ts2phc_phc_pps_source.c +++ b/ts2phc_phc_pps_source.c @@ -14,10 +14,12 @@ #include "print.h" #include "ts2phc_phc_pps_source.h" #include "ts2phc_pps_source_private.h" +#include "ts2phc_vport.h" #include "util.h" struct ts2phc_phc_pps_source { struct ts2phc_pps_source pps_source; + struct ts2phc_vport *vport; clockid_t clkid; int channel; int fd; @@ -71,6 +73,9 @@ static void ts2phc_phc_pps_source_destroy(struct ts2phc_pps_source *src) pr_err(PTP_PEROUT_REQUEST_FAILED); } posix_clock_close(m->clkid); + if (m->vport) { + free(m->vport); + } free(m); } @@ -82,11 +87,21 @@ static int ts2phc_phc_pps_source_getppstime(struct ts2phc_pps_source *src, return clock_gettime(s->clkid, ts); } +int ts2phc_phc_pps_source_vport_transmit(struct ts2phc_pps_source *src, + struct timespec *ts) +{ + struct ts2phc_phc_pps_source *s = + container_of(src, struct ts2phc_phc_pps_source, pps_source); + return ts2phc_vport_tx_announce(s->vport); +} + + struct ts2phc_pps_source *ts2phc_phc_pps_source_create(struct config *cfg, const char *dev) { struct ts2phc_phc_pps_source *s; int junk; + const char *iface_name; s = calloc(1, sizeof(*s)); if (!s) { @@ -95,6 +110,14 @@ struct ts2phc_pps_source *ts2phc_phc_pps_source_create(struct config *cfg, s->pps_source.destroy = ts2phc_phc_pps_source_destroy; s->pps_source.getppstime = ts2phc_phc_pps_source_getppstime; + iface_name = config_get_string(cfg, NULL, "vport_address"); + if (iface_name && iface_name[0]) { + s->vport = ts2phc_vport_create(cfg); + if (!s->vport) { + pr_warning("Error in vport creation: %s\n", iface_name); + } + } + s->clkid = posix_clock_open(dev, ); if (s->clkid == CLOCK_INVALID) { free(s); diff --git a/ts2phc_phc_pps_source.h b/ts2phc_phc_pps_source.h index c9ab54e..01c1d8d 100644 --- a/ts2phc_phc_pps_source.h +++ b/ts2phc_phc_pps_source.h @@ -11,4 +11,6 @@ struct ts2phc_pps_source *ts2phc_phc_pps_source_create(struct config *cfg, const char *dev); +int ts2phc_phc_pps_source_vport_transmit(struct ts2phc_pps_source *src, +struct timespec *ts); #endif diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c index 91bd7c9..6e6acc0 100644 --- a/ts2phc_pps_sink.c +++ b/ts2phc_pps_sink.c @@ -23,6 +23,7 @@ #include "servo.h" #include "ts2phc_pps_sink.h" #include "ts2phc_pps_source.h" +#include "ts2phc_phc_pps_source.h" #include "util.h" #define NS_PER_SEC 10LL @@ -426,7 +427,10 @@ int ts2phc_pps_sink_poll(struct ts2phc_pps_source *src) err = ts2phc_pps_source_getppstime(src, _ts.ts); source_ts.valid = err ? false : true; - + if (source_ts.valid) { + /* Send Announce and Sync Message on Virtual Port */ + ts2phc_phc_pps_source_vport_transmit(src, _ts.ts); + } for (i = 0; i < ts2phc_n_sinks; i++) { if (polling_array.pfd[i].revents & (POLLIN|POLLPRI)) { ts2phc_pps_sink_event(polling_array.sink[i], source_ts); -- 2.25.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH v3 2/3] adding virtual port support for ts2phc
Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Vipin Sharma Signed-off-by: Devasish Dey v2->v3: - Using UDS interface for virtual PTP port support. v1->v2: - amended commit message - updated ts2phc.8 --- makefile | 7 +- ts2phc.8 | 70 ts2phc_vport.c | 281 + ts2phc_vport.h | 28 + 4 files changed, 383 insertions(+), 3 deletions(-) create mode 100644 ts2phc_vport.c create mode 100644 ts2phc_vport.h diff --git a/makefile b/makefile index 5295b60..cd15559 100644 --- a/makefile +++ b/makefile @@ -27,7 +27,8 @@ FILTERS = filter.o mave.o mmedian.o SERVOS = linreg.o ntpshm.o nullf.o pi.o servo.o TRANSP = raw.o transport.o udp.o udp6.o uds.o TS2PHC = ts2phc.o lstab.o nmea.o serial.o sock.o ts2phc_generic_pps_source.o \ - ts2phc_nmea_pps_source.o ts2phc_phc_pps_source.o ts2phc_pps_sink.o ts2phc_pps_source.o + ts2phc_nmea_pps_source.o ts2phc_phc_pps_source.o ts2phc_pps_sink.o \ + ts2phc_pps_source.o ts2phc_vport.o OBJ= bmc.o clock.o clockadj.o clockcheck.o config.o designated_fsm.o \ e2e_tc.o fault.o $(FILTERS) fsm.o hash.o interface.o monitor.o msg.o phc.o \ port.o port_signaling.o pqueue.o print.o ptp4l.o p2p_tc.o rtnl.o $(SERVOS) \ @@ -68,8 +69,8 @@ phc_ctl: phc_ctl.o phc.o sk.o util.o clockadj.o sysoff.o print.o version.o timemaster: phc.o print.o rtnl.o sk.o timemaster.o util.o version.o -ts2phc: config.o clockadj.o hash.o interface.o phc.o print.o $(SERVOS) sk.o \ - $(TS2PHC) util.o version.o +ts2phc: config.o clockadj.o hash.o msg.o tlv.o interface.o phc.o print.o $(SERVOS) sk.o \ + $(TS2PHC) $(TRANSP) util.o version.o version.o: .version version.sh $(filter-out version.d,$(DEPEND)) diff --git a/ts2phc.8 b/ts2phc.8 index 690c462..4166766 100644 --- a/ts2phc.8 +++ b/ts2phc.8 @@ -145,6 +145,76 @@ by changing the clock frequency instead of stepping the clock. When set to 0.0, the servo will never step the clock except on start. The default is 0.0. .TP +.B vport_address +Specifies the address of the UNIX domain socket for communicating with the +virtual PTP port to a PTP clock as defined in the G.8275 Annex B. The default +is NULL +.TP +.B utc_offset +The current offset between TAI and UTC. +The default is 37. +.TP +.B transportSpecific +The transport specific field. Must be in the range 0 to 255. +The default is 0. +.TP +.B domainNumber +The domain attribute of the local clock. +The default is 0. +.TP +.B logSyncInterval +The mean time interval between Sync messages. A shorter interval may improve +accuracy of the local clock. It's specified as a power of two in seconds. +The default is 0 (1 second). +.TP +.B logAnnounceInterval +The mean time interval between Announce messages. A shorter interval makes +ptp4l react faster to the changes in the client/server hierarchy. The interval +should be the same in the whole domain. It's specified as a power of two in +seconds. +.TP +.B priorty1 +The priority1 attribute of the local clock. It is used in the PTP server +selection algorithm, lower values take precedence. Must be in the range 0 to +255. +The default is 128. +.TP +.B priorty2 +The priority2 attribute of the local clock. It is used in the PTP server +selection algorithm, lower values take precedence. Must be in the range 0 to +255. +The default is 128. +.TP +.B timeSource +The time source is a single byte code that gives an idea of the kind +of local clock in use. The value is purely informational, having no +effect on the outcome of the Best Master Clock algorithm, and is +advertised when the clock becomes grand master. +.TP +.B clockClass +The clockClass attribute of the local clock. It denotes the traceability of the +time distributed by the grandmaster clock. +The default is 248. +.TP +.B clockAccuracy +The clockAccuracy attribute of the local clock. It is used in the PTP server +selection algorithm. +The default is 0xFE. +.TP +.B clockIdenitity +The clockIdentity attribute of the local clock. +The clockIdentity is an 8-octet array and should in this configuration be +written in textual form, see default. It should be unique since it is used to +identify the specific clock. +If default is used or if not set at all, the clockIdentity will be automtically +generated. +The default is "00..00" +.TP +.B offsetScaledLogVariance +The offsetScaledLogVariance attribute of the local clock. It characterizes the +stability of the clock. +The default is 0x. +.TP .B ts2phc.nmea_remote_host, ts2phc.nmea_remote_port Specifies the remote host providing ToD information when using the "nmea" PPS signal source. Note that if these two options are both diff --git a/ts2phc_vport.c b/ts2phc_vport.c new file mode 100644 index 000..539c48f --- /dev/null +++ b/ts2phc_vport.c @@ -0,0 +1,281 @@ +/** + * @file ts2phc_vport.c + * @note Copyright (C) 2022 SyncMonk Technologies + * @note SPDX-License-Identifier: GPL-2.0+ + *
[Linuxptp-devel] [PATCH v3 1/3] Adding virtual PTP port support
Virtual PTP port is for unidirectional tranfer of phase/time interface on a PTP clock. When associated with an external input signal, a virtual PTP port allows this external interface to participate in the PTP protocol. As an input, this external port can participate in the source selection with an associated virtual Erbest using the associated virtual PTP port. As per G.8275 (Annex-B) including virtual PTP ports on a PTP clock. This virtual port will be used to support Assisted Partial Timing Support (APTS), Inter Working Function (IWF) between different clock_domains. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Vipin Sharma Signed-off-by: Devasish Dey v2->v3: - Using UDS sockets for virtual PTP ports. v1->v2: - Amended the commit message. --- clock.c | 58 - config.c| 2 ++ configs/default.cfg | 2 +- port.c | 10 ++-- ptp4l.8 | 5 sk.c| 1 + transport.c | 1 + transport.h | 1 + uds.c | 33 +++--- util.c | 2 ++ 10 files changed, 102 insertions(+), 13 deletions(-) diff --git a/clock.c b/clock.c index d37bb87..eba0833 100644 --- a/clock.c +++ b/clock.c @@ -97,9 +97,10 @@ struct clock { LIST_HEAD(ports_head, port) ports; struct port *uds_rw_port; struct port *uds_ro_port; + struct port *vport_port; struct pollfd *pollfd; int pollfd_valid; - int nports; /* does not include the two UDS ports */ + int nports; /* does not include the two UDS ports + 1 Virtual Port */ int last_port_number; int sde; int free_running; @@ -133,6 +134,7 @@ struct clock { struct clockcheck *sanity_check; struct interface *uds_rw_if; struct interface *uds_ro_if; + struct interface *vport_if; LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers; struct monitor *slave_event_monitor; int step_window_counter; @@ -272,6 +274,7 @@ void clock_destroy(struct clock *c) interface_destroy(c->uds_rw_if); interface_destroy(c->uds_ro_if); + interface_destroy(c->vport_if); clock_flush_subscriptions(c); LIST_FOREACH_SAFE(p, >ports, list, tmp) { clock_remove_port(c, p); @@ -901,6 +904,7 @@ struct clock *clock_create(enum clock_type type, struct config *config, int phc_index, conf_phc_index, required_modes = 0; struct clock *c = _clock; const char *uds_ifname; + const char *vport_ifname; struct port *p; unsigned char oui[OUI_LEN]; struct interface *iface; @@ -1094,6 +1098,32 @@ struct clock *clock_create(enum clock_type type, struct config *config, return NULL; } + /* Configure the Virtual Port. */ + vport_ifname = config_get_string(config, NULL, "vport_address"); + if (vport_ifname && vport_ifname[0]) { + c->vport_if = interface_create(vport_ifname); + if (config_set_section_int(config, interface_name(c->vport_if), + "announceReceiptTimeout", 2)) { + return NULL; + } + if (config_set_section_int(config, + interface_name(c->vport_if), + "delay_mechanism", + DM_NO_MECHANISM)) { + return NULL; + } + if (config_set_section_int(config, + interface_name(c->vport_if), + "network_transport", + TRANS_VPORT)) { + return NULL; + } + if (config_set_section_int(config, interface_name(c->vport_if), + "delay_filter_length", 1)) { + return NULL; + } + } + c->config = config; c->free_running = config_get_int(config, NULL, "free_running"); c->freq_est_interval = config_get_int(config, NULL, "freq_est_interval"); @@ -1231,6 +1261,17 @@ struct clock *clock_create(enum clock_type type, struct config *config, pr_err("failed to open the UDS-RO port"); return NULL; } + + if (c->vport_if) { + c->vport_port = port_open(phc_device, phc_index, timestamping, 0, + c->vport_if, c); + if (!c->vport_port) { + pr_err("failed to open the Virtual port"); + return NULL; + } + LIST_INSERT_HEAD(>ports, c->vport_port, list); + c->nports++; + } clock_fda_changed(c);
[Linuxptp-devel] [PATCH v2 1/4] Adding virtual PTP port support
Virtual PTP port is for unidirectional tranfer of phase/time interface on a PTP clock. When associated with an external input signal, a virtual PTP port allows this external interface to participate in the PTP protocol. As an input, this external port can participate in the source selection with an associated virtual Erbest using the associated virtual PTP port. As per G.8275 (Annex-B) including virtual PTP ports on a PTP clock. This virtual port will be used to support Assisted Partial Timing Support (APTS), Inter Working Function (IWF) between different clock_domains. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Vipin Sharma Signed-off-by: Devasish Dey v1->v2: - Amended the commit message. --- makefile | 2 +- vport.c | 140 +++ vport.h | 20 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 vport.c create mode 100644 vport.h diff --git a/makefile b/makefile index 5295b60..7d8c0d3 100644 --- a/makefile +++ b/makefile @@ -25,7 +25,7 @@ LDLIBS= -lm -lrt -pthread $(EXTRA_LDFLAGS) PRG= ptp4l hwstamp_ctl nsm phc2sys phc_ctl pmc timemaster ts2phc FILTERS= filter.o mave.o mmedian.o SERVOS = linreg.o ntpshm.o nullf.o pi.o servo.o -TRANSP = raw.o transport.o udp.o udp6.o uds.o +TRANSP = raw.o transport.o udp.o udp6.o uds.o vport.o TS2PHC = ts2phc.o lstab.o nmea.o serial.o sock.o ts2phc_generic_pps_source.o \ ts2phc_nmea_pps_source.o ts2phc_phc_pps_source.o ts2phc_pps_sink.o ts2phc_pps_source.o OBJ= bmc.o clock.o clockadj.o clockcheck.o config.o designated_fsm.o \ diff --git a/vport.c b/vport.c new file mode 100644 index 000..89d4105 --- /dev/null +++ b/vport.c @@ -0,0 +1,140 @@ +/** + * @file vport.c + * @note Copyright (C) 2022 SyncMonk Technologies + * @note SPDX-License-Identifier: GPL-2.0+ + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "address.h" +#include "contain.h" +#include "print.h" +#include "transport_private.h" +#include "vport.h" + +#define VPORT_FILEMODE (0660) /*0660*/ + +struct vport { + struct transport t; + struct address address; +}; + +static int vport_close(struct transport *t, struct fdarray *fda) +{ + struct sockaddr_un sa; + socklen_t len = sizeof(sa); + + if (!getsockname(fda->fd[FD_GENERAL], + (struct sockaddr *) , ) && + sa.sun_family == AF_LOCAL) { + unlink(sa.sun_path); + } + + close(fda->fd[FD_GENERAL]); + return 0; +} + +static int vport_open(struct transport *t, + struct interface *iface, + struct fdarray *fda, + enum timestamp_type tt) +{ + char *vport_path = config_get_string(t->cfg, NULL, "vport_address"); + struct vport *vport = container_of(t, struct vport, t); + const char *name = interface_name(iface); + struct sockaddr_un sa; + int fd, err; + + fd = socket(AF_LOCAL, SOCK_DGRAM, 0); + if (fd < 0) { + pr_err("vport: failed to create socket: %m"); + return -1; + } + memset(, 0, sizeof(sa)); + sa.sun_family = AF_LOCAL; + strncpy(sa.sun_path, name, sizeof(sa.sun_path) - 1); + + unlink(name); + + err = bind(fd, (struct sockaddr *) , sizeof(sa)); + if (err < 0) { + pr_err("vport: bind failed: %m"); + close(fd); + return -1; + } + + /* For client use, pre load the server path. */ + memset(, 0, sizeof(sa)); + sa.sun_family = AF_LOCAL; + strncpy(sa.sun_path, vport_path, sizeof(sa.sun_path) - 1); + vport->address.sun = sa; + vport->address.len = sizeof(sa); + + chmod(name, VPORT_FILEMODE); + fda->fd[FD_EVENT] = -1; + fda->fd[FD_GENERAL] = fd; + return 0; +} + +static int vport_recv(struct transport *t, int fd, void *buf, int buflen, + struct address *addr, struct hw_timestamp *hwts) +{ + int cnt; + struct vport *vport = container_of(t, struct vport, t); + + addr->len = sizeof(addr->sun); + cnt = recvfrom(fd, buf, buflen, 0, >sa, >len); + if (cnt <= 0) { + pr_err("vport: recvfrom failed: %m"); + return cnt; + } + vport->address = *addr; + return cnt; +} + +static int vport_send(struct transport *t, struct fdarray *fda, + enum transport_event event, int peer, void *buf, + int buflen, struct address *addr, + struct hw_timestamp *hwts) +{ + int cnt, fd = fda->fd[FD_GENERAL]; + struct vport *vport = container_of(t, struct vport, t); + + if (!addr) + addr = >
[Linuxptp-devel] [PATCH v2 2/4] Integrating virtual PTP ports with ptp4l
When associated with an external input signal, a virtual PTP port allows this external interface to participate in the PTP protocol. As an input, this external port can participate in the source selection with an associated virtual Erbest using the associated virtual PTP port. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Vipin Sharma Signed-off-by: Devasish Dey v1->v2: - updated ptp4l.8 - amended commit message. --- clock.c | 59 - config.c| 2 ++ interface.c | 7 +++ interface.h | 6 ++ port.c | 10 +++-- ptp4l.8 | 5 + sk.c| 1 + transport.c | 4 transport.h | 1 + util.c | 2 ++ 10 files changed, 94 insertions(+), 3 deletions(-) diff --git a/clock.c b/clock.c index d37bb87..314eebf 100644 --- a/clock.c +++ b/clock.c @@ -43,6 +43,7 @@ #include "tlv.h" #include "tsproc.h" #include "uds.h" +#include "vport.h" #include "util.h" #define N_CLOCK_PFD (N_POLLFD + 1) /* one extra per port, for the fault timer */ @@ -97,9 +98,10 @@ struct clock { LIST_HEAD(ports_head, port) ports; struct port *uds_rw_port; struct port *uds_ro_port; + struct port *vport_port; struct pollfd *pollfd; int pollfd_valid; - int nports; /* does not include the two UDS ports */ + int nports; /* does not include the two UDS ports + 1 Virtual Port */ int last_port_number; int sde; int free_running; @@ -133,6 +135,7 @@ struct clock { struct clockcheck *sanity_check; struct interface *uds_rw_if; struct interface *uds_ro_if; + struct interface *vport_if; LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers; struct monitor *slave_event_monitor; int step_window_counter; @@ -272,6 +275,7 @@ void clock_destroy(struct clock *c) interface_destroy(c->uds_rw_if); interface_destroy(c->uds_ro_if); + interface_destroy(c->vport_if); clock_flush_subscriptions(c); LIST_FOREACH_SAFE(p, >ports, list, tmp) { clock_remove_port(c, p); @@ -901,6 +905,7 @@ struct clock *clock_create(enum clock_type type, struct config *config, int phc_index, conf_phc_index, required_modes = 0; struct clock *c = _clock; const char *uds_ifname; + const char *vport_ifname; struct port *p; unsigned char oui[OUI_LEN]; struct interface *iface; @@ -1094,6 +1099,32 @@ struct clock *clock_create(enum clock_type type, struct config *config, return NULL; } + /* Configure the Virtual Port. */ + vport_ifname = config_get_string(config, NULL, "vport_address"); + if (vport_ifname && vport_ifname[0]) { + c->vport_if = interface_create(vport_ifname); + if (config_set_section_int(config, interface_name(c->vport_if), + "announceReceiptTimeout", 2)) { + return NULL; + } + if (config_set_section_int(config, + interface_name(c->vport_if), + "delay_mechanism", + DM_NO_MECHANISM)) { + return NULL; + } + if (config_set_section_int(config, + interface_name(c->vport_if), + "network_transport", + TRANS_VPORT)) { + return NULL; + } + if (config_set_section_int(config, interface_name(c->vport_if), + "delay_filter_length", 1)) { + return NULL; + } + } + c->config = config; c->free_running = config_get_int(config, NULL, "free_running"); c->freq_est_interval = config_get_int(config, NULL, "freq_est_interval"); @@ -1231,6 +1262,17 @@ struct clock *clock_create(enum clock_type type, struct config *config, pr_err("failed to open the UDS-RO port"); return NULL; } + + if (c->vport_if) { + c->vport_port = port_open(phc_device, phc_index, timestamping, 0, + c->vport_if, c); + if (!c->vport_port) { + pr_err("failed to open the Virtual port"); + return NULL; + } + LIST_INSERT_HEAD(>ports, c->vport_port, list); + c->nports++; + } clock_fda_changed(c); c->slave_event_monitor = monitor_create(config, c->uds_rw_port); @@ -1254,6 +1296,9 @@ struct clock *clock_create(enum clock_type type, struct config *config, } port_dispatch(c->uds_rw_port, EV_INITIALIZE, 0);
[Linuxptp-devel] [PATCH v2 4/4] Adding support for passing announce message from external source
The announce message from the External source is passed by virtual port for BMCA participation so that it becomes a selection source along with other ports for linuxPTP. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Vipin Sharma Signed-off-by: Devasish Dey v1->v2: - amended commit message --- ts2phc_phc_pps_source.c | 23 +++ ts2phc_phc_pps_source.h | 2 ++ ts2phc_pps_sink.c | 6 +- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/ts2phc_phc_pps_source.c b/ts2phc_phc_pps_source.c index 5f15e8e..0546913 100644 --- a/ts2phc_phc_pps_source.c +++ b/ts2phc_phc_pps_source.c @@ -14,10 +14,12 @@ #include "print.h" #include "ts2phc_phc_pps_source.h" #include "ts2phc_pps_source_private.h" +#include "ts2phc_vport.h" #include "util.h" struct ts2phc_phc_pps_source { struct ts2phc_pps_source pps_source; + struct ts2phc_vport *vport; clockid_t clkid; int channel; int fd; @@ -71,6 +73,9 @@ static void ts2phc_phc_pps_source_destroy(struct ts2phc_pps_source *src) pr_err(PTP_PEROUT_REQUEST_FAILED); } posix_clock_close(m->clkid); + if (m->vport) { + free(m->vport); + } free(m); } @@ -82,11 +87,21 @@ static int ts2phc_phc_pps_source_getppstime(struct ts2phc_pps_source *src, return clock_gettime(s->clkid, ts); } +int ts2phc_phc_pps_source_vport_transmit(struct ts2phc_pps_source *src, + struct timespec *ts) +{ + struct ts2phc_phc_pps_source *s = + container_of(src, struct ts2phc_phc_pps_source, pps_source); + return ts2phc_vport_tx_announce(s->vport); +} + + struct ts2phc_pps_source *ts2phc_phc_pps_source_create(struct config *cfg, const char *dev) { struct ts2phc_phc_pps_source *s; int junk; + const char *iface_name; s = calloc(1, sizeof(*s)); if (!s) { @@ -95,6 +110,14 @@ struct ts2phc_pps_source *ts2phc_phc_pps_source_create(struct config *cfg, s->pps_source.destroy = ts2phc_phc_pps_source_destroy; s->pps_source.getppstime = ts2phc_phc_pps_source_getppstime; + iface_name = config_get_string(cfg, NULL, "vport_address"); + if (iface_name && iface_name[0]) { + s->vport = ts2phc_vport_create(cfg); + if (!s->vport) { + pr_warning("Error in vport creation: %s\n", iface_name); + } + } + s->clkid = posix_clock_open(dev, ); if (s->clkid == CLOCK_INVALID) { free(s); diff --git a/ts2phc_phc_pps_source.h b/ts2phc_phc_pps_source.h index c9ab54e..01c1d8d 100644 --- a/ts2phc_phc_pps_source.h +++ b/ts2phc_phc_pps_source.h @@ -11,4 +11,6 @@ struct ts2phc_pps_source *ts2phc_phc_pps_source_create(struct config *cfg, const char *dev); +int ts2phc_phc_pps_source_vport_transmit(struct ts2phc_pps_source *src, +struct timespec *ts); #endif diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c index 91bd7c9..6e6acc0 100644 --- a/ts2phc_pps_sink.c +++ b/ts2phc_pps_sink.c @@ -23,6 +23,7 @@ #include "servo.h" #include "ts2phc_pps_sink.h" #include "ts2phc_pps_source.h" +#include "ts2phc_phc_pps_source.h" #include "util.h" #define NS_PER_SEC 10LL @@ -426,7 +427,10 @@ int ts2phc_pps_sink_poll(struct ts2phc_pps_source *src) err = ts2phc_pps_source_getppstime(src, _ts.ts); source_ts.valid = err ? false : true; - + if (source_ts.valid) { + /* Send Announce and Sync Message on Virtual Port */ + ts2phc_phc_pps_source_vport_transmit(src, _ts.ts); + } for (i = 0; i < ts2phc_n_sinks; i++) { if (polling_array.pfd[i].revents & (POLLIN|POLLPRI)) { ts2phc_pps_sink_event(polling_array.sink[i], source_ts); -- 2.25.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH v2 3/4] adding virtual port support to ts2phc
Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Vipin Sharma Signed-off-by: Devasish Dey v1->v2: - amended commit message - updated ts2phc.8 --- makefile | 6 +- ts2phc.8 | 70 ts2phc_vport.c | 282 + ts2phc_vport.h | 28 + 4 files changed, 383 insertions(+), 3 deletions(-) create mode 100644 ts2phc_vport.c create mode 100644 ts2phc_vport.h diff --git a/makefile b/makefile index 7d8c0d3..3631f1d 100644 --- a/makefile +++ b/makefile @@ -27,7 +27,7 @@ FILTERS = filter.o mave.o mmedian.o SERVOS = linreg.o ntpshm.o nullf.o pi.o servo.o TRANSP = raw.o transport.o udp.o udp6.o uds.o vport.o TS2PHC = ts2phc.o lstab.o nmea.o serial.o sock.o ts2phc_generic_pps_source.o \ - ts2phc_nmea_pps_source.o ts2phc_phc_pps_source.o ts2phc_pps_sink.o ts2phc_pps_source.o + ts2phc_nmea_pps_source.o ts2phc_phc_pps_source.o ts2phc_pps_sink.o ts2phc_pps_source.o ts2phc_vport.o OBJ= bmc.o clock.o clockadj.o clockcheck.o config.o designated_fsm.o \ e2e_tc.o fault.o $(FILTERS) fsm.o hash.o interface.o monitor.o msg.o phc.o \ port.o port_signaling.o pqueue.o print.o ptp4l.o p2p_tc.o rtnl.o $(SERVOS) \ @@ -68,8 +68,8 @@ phc_ctl: phc_ctl.o phc.o sk.o util.o clockadj.o sysoff.o print.o version.o timemaster: phc.o print.o rtnl.o sk.o timemaster.o util.o version.o -ts2phc: config.o clockadj.o hash.o interface.o phc.o print.o $(SERVOS) sk.o \ - $(TS2PHC) util.o version.o +ts2phc: config.o clockadj.o hash.o msg.o tlv.o interface.o phc.o print.o $(SERVOS) sk.o \ + $(TS2PHC) $(TRANSP) util.o version.o version.o: .version version.sh $(filter-out version.d,$(DEPEND)) diff --git a/ts2phc.8 b/ts2phc.8 index 690c462..4166766 100644 --- a/ts2phc.8 +++ b/ts2phc.8 @@ -145,6 +145,76 @@ by changing the clock frequency instead of stepping the clock. When set to 0.0, the servo will never step the clock except on start. The default is 0.0. .TP +.B vport_address +Specifies the address of the UNIX domain socket for communicating with the +virtual PTP port to a PTP clock as defined in the G.8275 Annex B. The default +is NULL +.TP +.B utc_offset +The current offset between TAI and UTC. +The default is 37. +.TP +.B transportSpecific +The transport specific field. Must be in the range 0 to 255. +The default is 0. +.TP +.B domainNumber +The domain attribute of the local clock. +The default is 0. +.TP +.B logSyncInterval +The mean time interval between Sync messages. A shorter interval may improve +accuracy of the local clock. It's specified as a power of two in seconds. +The default is 0 (1 second). +.TP +.B logAnnounceInterval +The mean time interval between Announce messages. A shorter interval makes +ptp4l react faster to the changes in the client/server hierarchy. The interval +should be the same in the whole domain. It's specified as a power of two in +seconds. +.TP +.B priorty1 +The priority1 attribute of the local clock. It is used in the PTP server +selection algorithm, lower values take precedence. Must be in the range 0 to +255. +The default is 128. +.TP +.B priorty2 +The priority2 attribute of the local clock. It is used in the PTP server +selection algorithm, lower values take precedence. Must be in the range 0 to +255. +The default is 128. +.TP +.B timeSource +The time source is a single byte code that gives an idea of the kind +of local clock in use. The value is purely informational, having no +effect on the outcome of the Best Master Clock algorithm, and is +advertised when the clock becomes grand master. +.TP +.B clockClass +The clockClass attribute of the local clock. It denotes the traceability of the +time distributed by the grandmaster clock. +The default is 248. +.TP +.B clockAccuracy +The clockAccuracy attribute of the local clock. It is used in the PTP server +selection algorithm. +The default is 0xFE. +.TP +.B clockIdenitity +The clockIdentity attribute of the local clock. +The clockIdentity is an 8-octet array and should in this configuration be +written in textual form, see default. It should be unique since it is used to +identify the specific clock. +If default is used or if not set at all, the clockIdentity will be automtically +generated. +The default is "00..00" +.TP +.B offsetScaledLogVariance +The offsetScaledLogVariance attribute of the local clock. It characterizes the +stability of the clock. +The default is 0x. +.TP .B ts2phc.nmea_remote_host, ts2phc.nmea_remote_port Specifies the remote host providing ToD information when using the "nmea" PPS signal source. Note that if these two options are both diff --git a/ts2phc_vport.c b/ts2phc_vport.c new file mode 100644 index 000..ae9cbe9 --- /dev/null +++ b/ts2phc_vport.c @@ -0,0 +1,282 @@ +/** + * @file ts2phc_vport.c + * @note Copyright (C) 2022 SyncMonk Technologies + * @note SPDX-License-Identifier: GPL-2.0+ + * + */ +#include +#include + +#include "address.h" +#include &q
[Linuxptp-devel] [PATCH 3/4] APTS support
Adding virtual port support for ts2phc. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Vipin Sharma Signed-off-by: Devasish Dey --- makefile | 6 +- ts2phc_vport.c | 282 + ts2phc_vport.h | 28 + 3 files changed, 313 insertions(+), 3 deletions(-) create mode 100644 ts2phc_vport.c create mode 100644 ts2phc_vport.h diff --git a/makefile b/makefile index 7d8c0d3..3631f1d 100644 --- a/makefile +++ b/makefile @@ -27,7 +27,7 @@ FILTERS = filter.o mave.o mmedian.o SERVOS = linreg.o ntpshm.o nullf.o pi.o servo.o TRANSP = raw.o transport.o udp.o udp6.o uds.o vport.o TS2PHC = ts2phc.o lstab.o nmea.o serial.o sock.o ts2phc_generic_pps_source.o \ - ts2phc_nmea_pps_source.o ts2phc_phc_pps_source.o ts2phc_pps_sink.o ts2phc_pps_source.o + ts2phc_nmea_pps_source.o ts2phc_phc_pps_source.o ts2phc_pps_sink.o ts2phc_pps_source.o ts2phc_vport.o OBJ= bmc.o clock.o clockadj.o clockcheck.o config.o designated_fsm.o \ e2e_tc.o fault.o $(FILTERS) fsm.o hash.o interface.o monitor.o msg.o phc.o \ port.o port_signaling.o pqueue.o print.o ptp4l.o p2p_tc.o rtnl.o $(SERVOS) \ @@ -68,8 +68,8 @@ phc_ctl: phc_ctl.o phc.o sk.o util.o clockadj.o sysoff.o print.o version.o timemaster: phc.o print.o rtnl.o sk.o timemaster.o util.o version.o -ts2phc: config.o clockadj.o hash.o interface.o phc.o print.o $(SERVOS) sk.o \ - $(TS2PHC) util.o version.o +ts2phc: config.o clockadj.o hash.o msg.o tlv.o interface.o phc.o print.o $(SERVOS) sk.o \ + $(TS2PHC) $(TRANSP) util.o version.o version.o: .version version.sh $(filter-out version.d,$(DEPEND)) diff --git a/ts2phc_vport.c b/ts2phc_vport.c new file mode 100644 index 000..ae9cbe9 --- /dev/null +++ b/ts2phc_vport.c @@ -0,0 +1,282 @@ +/** + * @file ts2phc_vport.c + * @note Copyright (C) 2022 SyncMonk Technologies + * @note SPDX-License-Identifier: GPL-2.0+ + * + */ +#include +#include + +#include "address.h" +#include "ts2phc_vport.h" +#include "print.h" +#include "port.h" +#include "transport.h" + +#define RECORDS_PER_MESSAGE 1 + +struct ts2phc_vport_message { + struct ptp_message *msg; + int records_per_msg; + int count; +}; + +struct ts2phc_vport { + struct fdarray fda; + struct transport *trp; + struct interface *iface; + struct ts2phc_vport_message announce; + struct ts2phc_vport_message sync; + struct { + UInteger16 announce; + UInteger16 sync; + } seqnum; + struct PortIdentity portIdentity; + Integer16 utcOffset; + UInteger8 priority1; + struct ClockQuality clockQuality; + UInteger8 priority2; + struct ClockIdentity clockIdentity; + UInteger8 transportSpecific; + UInteger8 domainNumber; + UInteger8 flags; + Integer8 logAnnounceInterval; + Integer8 logSyncInterval; + Enumeration8 timeSource; +}; + +static bool ts2phc_vport_active(struct ts2phc_vport *ts2phc_vport) +{ + return ts2phc_vport->trp ? true : false; +} + +static int ts2phc_vport_forward(struct ts2phc_vport *port, struct ptp_message *msg) +{ + int cnt; + if (msg_pre_send(msg)) { + return -1; + } + cnt = transport_sendto(port->trp, >fda, TRANS_GENERAL, msg); + if (cnt <= 0) { + pr_debug("failed to send message to ts2phc_vport: "); + } + + msg->header.sequenceId++; + return 0; +} + +static int ts2phc_vport_init_announce(struct ts2phc_vport *p, + struct address address) +{ + + struct ptp_message *msg; + + msg = msg_allocate(); + if (!msg) { + return -1; + } + + msg->hwts.type = TS_ONESTEP; + msg->header.tsmt = ANNOUNCE | p->transportSpecific; + msg->header.ver= PTP_VERSION; + msg->header.messageLength = sizeof(struct announce_msg); + msg->header.domainNumber = p->domainNumber; + msg->header.sourcePortIdentity = p->portIdentity; + msg->header.sequenceId = p->seqnum.announce++; + msg->header.control= CTL_OTHER; + msg->header.logMessageInterval = p->logAnnounceInterval; + msg->header.flagField[1] = p->flags | PTP_TIMESCALE; + + msg->announce.currentUtcOffset= p->utcOffset; + msg->announce.grandmasterPriority1= p->priority1; + msg->announce.grandmasterClockQuality = p->clockQuality; + msg->announce.grandmasterPriority2= p->priority2; + msg->announce.grandmasterIdentity = p->clockIdentity; + msg->announce.stepsRemoved= 0; + msg->announce.timeSource = p->timeSource; + msg->address = address; + + p->announce.msg
[Linuxptp-devel] [PATCH 2/4] APTS support
Adding virtual port support to ptp4l Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Vipin Sharma Signed-off-by: Devasish Dey --- clock.c | 59 - config.c| 2 ++ interface.c | 7 +++ interface.h | 6 ++ port.c | 10 +++-- ptp4l.8 | 4 sk.c| 1 + transport.c | 4 transport.h | 1 + util.c | 2 ++ 10 files changed, 93 insertions(+), 3 deletions(-) diff --git a/clock.c b/clock.c index d37bb87..314eebf 100644 --- a/clock.c +++ b/clock.c @@ -43,6 +43,7 @@ #include "tlv.h" #include "tsproc.h" #include "uds.h" +#include "vport.h" #include "util.h" #define N_CLOCK_PFD (N_POLLFD + 1) /* one extra per port, for the fault timer */ @@ -97,9 +98,10 @@ struct clock { LIST_HEAD(ports_head, port) ports; struct port *uds_rw_port; struct port *uds_ro_port; + struct port *vport_port; struct pollfd *pollfd; int pollfd_valid; - int nports; /* does not include the two UDS ports */ + int nports; /* does not include the two UDS ports + 1 Virtual Port */ int last_port_number; int sde; int free_running; @@ -133,6 +135,7 @@ struct clock { struct clockcheck *sanity_check; struct interface *uds_rw_if; struct interface *uds_ro_if; + struct interface *vport_if; LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers; struct monitor *slave_event_monitor; int step_window_counter; @@ -272,6 +275,7 @@ void clock_destroy(struct clock *c) interface_destroy(c->uds_rw_if); interface_destroy(c->uds_ro_if); + interface_destroy(c->vport_if); clock_flush_subscriptions(c); LIST_FOREACH_SAFE(p, >ports, list, tmp) { clock_remove_port(c, p); @@ -901,6 +905,7 @@ struct clock *clock_create(enum clock_type type, struct config *config, int phc_index, conf_phc_index, required_modes = 0; struct clock *c = _clock; const char *uds_ifname; + const char *vport_ifname; struct port *p; unsigned char oui[OUI_LEN]; struct interface *iface; @@ -1094,6 +1099,32 @@ struct clock *clock_create(enum clock_type type, struct config *config, return NULL; } + /* Configure the Virtual Port. */ + vport_ifname = config_get_string(config, NULL, "vport_address"); + if (vport_ifname && vport_ifname[0]) { + c->vport_if = interface_create(vport_ifname); + if (config_set_section_int(config, interface_name(c->vport_if), + "announceReceiptTimeout", 2)) { + return NULL; + } + if (config_set_section_int(config, + interface_name(c->vport_if), + "delay_mechanism", + DM_NO_MECHANISM)) { + return NULL; + } + if (config_set_section_int(config, + interface_name(c->vport_if), + "network_transport", + TRANS_VPORT)) { + return NULL; + } + if (config_set_section_int(config, interface_name(c->vport_if), + "delay_filter_length", 1)) { + return NULL; + } + } + c->config = config; c->free_running = config_get_int(config, NULL, "free_running"); c->freq_est_interval = config_get_int(config, NULL, "freq_est_interval"); @@ -1231,6 +1262,17 @@ struct clock *clock_create(enum clock_type type, struct config *config, pr_err("failed to open the UDS-RO port"); return NULL; } + + if (c->vport_if) { + c->vport_port = port_open(phc_device, phc_index, timestamping, 0, + c->vport_if, c); + if (!c->vport_port) { + pr_err("failed to open the Virtual port"); + return NULL; + } + LIST_INSERT_HEAD(>ports, c->vport_port, list); + c->nports++; + } clock_fda_changed(c); c->slave_event_monitor = monitor_create(config, c->uds_rw_port); @@ -1254,6 +1296,9 @@ struct clock *clock_create(enum clock_type type, struct config *config, } port_dispatch(c->uds_rw_port, EV_INITIALIZE, 0); port_dispatch(c->uds_ro_port, EV_INITIALIZE, 0); + if (c->vport_port) { + port_dispatch(c->vport_port, EV_INITIALIZE, 0); + } return c; } @@ -1670,6 +1715,18 @@ int clock_poll(struct clock *c) /* sde is not expected on the UDS-RO port */
[Linuxptp-devel] [PATCH 4/4] APTS support
adding APTS to participate in BMCA Passing the announce message for external source to ptp4l using virtual port to avoid selection of master from PTP source. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Vipin Sharma Signed-off-by: Devasish Dey --- ts2phc_phc_pps_source.c | 16 ts2phc_phc_pps_source.h | 2 ++ ts2phc_pps_sink.c | 6 +- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/ts2phc_phc_pps_source.c b/ts2phc_phc_pps_source.c index 5f15e8e..fa9d286 100644 --- a/ts2phc_phc_pps_source.c +++ b/ts2phc_phc_pps_source.c @@ -14,10 +14,12 @@ #include "print.h" #include "ts2phc_phc_pps_source.h" #include "ts2phc_pps_source_private.h" +#include "ts2phc_vport.h" #include "util.h" struct ts2phc_phc_pps_source { struct ts2phc_pps_source pps_source; + struct ts2phc_vport *vport; clockid_t clkid; int channel; int fd; @@ -82,6 +84,15 @@ static int ts2phc_phc_pps_source_getppstime(struct ts2phc_pps_source *src, return clock_gettime(s->clkid, ts); } +int ts2phc_phc_pps_source_vport_transmit(struct ts2phc_pps_source *src, + struct timespec *ts) +{ + struct ts2phc_phc_pps_source *s = + container_of(src, struct ts2phc_phc_pps_source, pps_source); + return ts2phc_vport_tx_announce(s->vport); +} + + struct ts2phc_pps_source *ts2phc_phc_pps_source_create(struct config *cfg, const char *dev) { @@ -94,6 +105,11 @@ struct ts2phc_pps_source *ts2phc_phc_pps_source_create(struct config *cfg, } s->pps_source.destroy = ts2phc_phc_pps_source_destroy; s->pps_source.getppstime = ts2phc_phc_pps_source_getppstime; + s->vport = ts2phc_vport_create(cfg); + if (!s->vport) { + free(s); + return NULL; + } s->clkid = posix_clock_open(dev, ); if (s->clkid == CLOCK_INVALID) { diff --git a/ts2phc_phc_pps_source.h b/ts2phc_phc_pps_source.h index c9ab54e..01c1d8d 100644 --- a/ts2phc_phc_pps_source.h +++ b/ts2phc_phc_pps_source.h @@ -11,4 +11,6 @@ struct ts2phc_pps_source *ts2phc_phc_pps_source_create(struct config *cfg, const char *dev); +int ts2phc_phc_pps_source_vport_transmit(struct ts2phc_pps_source *src, +struct timespec *ts); #endif diff --git a/ts2phc_pps_sink.c b/ts2phc_pps_sink.c index 91bd7c9..6e6acc0 100644 --- a/ts2phc_pps_sink.c +++ b/ts2phc_pps_sink.c @@ -23,6 +23,7 @@ #include "servo.h" #include "ts2phc_pps_sink.h" #include "ts2phc_pps_source.h" +#include "ts2phc_phc_pps_source.h" #include "util.h" #define NS_PER_SEC 10LL @@ -426,7 +427,10 @@ int ts2phc_pps_sink_poll(struct ts2phc_pps_source *src) err = ts2phc_pps_source_getppstime(src, _ts.ts); source_ts.valid = err ? false : true; - + if (source_ts.valid) { + /* Send Announce and Sync Message on Virtual Port */ + ts2phc_phc_pps_source_vport_transmit(src, _ts.ts); + } for (i = 0; i < ts2phc_n_sinks; i++) { if (polling_array.pfd[i].revents & (POLLIN|POLLPRI)) { ts2phc_pps_sink_event(polling_array.sink[i], source_ts); -- 2.25.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH 1/4] APTS support
Adding virtual PTP port support As per G.8275 (Annex-B) including virtual PTP ports on a PTP clock. This virtual port will be used to support APTS, IWF between different clock_domains. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Vipin Sharma Signed-off-by: Devasish Dey --- makefile | 2 +- vport.c | 140 +++ vport.h | 20 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 vport.c create mode 100644 vport.h diff --git a/makefile b/makefile index 5295b60..7d8c0d3 100644 --- a/makefile +++ b/makefile @@ -25,7 +25,7 @@ LDLIBS= -lm -lrt -pthread $(EXTRA_LDFLAGS) PRG= ptp4l hwstamp_ctl nsm phc2sys phc_ctl pmc timemaster ts2phc FILTERS= filter.o mave.o mmedian.o SERVOS = linreg.o ntpshm.o nullf.o pi.o servo.o -TRANSP = raw.o transport.o udp.o udp6.o uds.o +TRANSP = raw.o transport.o udp.o udp6.o uds.o vport.o TS2PHC = ts2phc.o lstab.o nmea.o serial.o sock.o ts2phc_generic_pps_source.o \ ts2phc_nmea_pps_source.o ts2phc_phc_pps_source.o ts2phc_pps_sink.o ts2phc_pps_source.o OBJ= bmc.o clock.o clockadj.o clockcheck.o config.o designated_fsm.o \ diff --git a/vport.c b/vport.c new file mode 100644 index 000..89d4105 --- /dev/null +++ b/vport.c @@ -0,0 +1,140 @@ +/** + * @file vport.c + * @note Copyright (C) 2022 SyncMonk Technologies + * @note SPDX-License-Identifier: GPL-2.0+ + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "address.h" +#include "contain.h" +#include "print.h" +#include "transport_private.h" +#include "vport.h" + +#define VPORT_FILEMODE (0660) /*0660*/ + +struct vport { + struct transport t; + struct address address; +}; + +static int vport_close(struct transport *t, struct fdarray *fda) +{ + struct sockaddr_un sa; + socklen_t len = sizeof(sa); + + if (!getsockname(fda->fd[FD_GENERAL], + (struct sockaddr *) , ) && + sa.sun_family == AF_LOCAL) { + unlink(sa.sun_path); + } + + close(fda->fd[FD_GENERAL]); + return 0; +} + +static int vport_open(struct transport *t, + struct interface *iface, + struct fdarray *fda, + enum timestamp_type tt) +{ + char *vport_path = config_get_string(t->cfg, NULL, "vport_address"); + struct vport *vport = container_of(t, struct vport, t); + const char *name = interface_name(iface); + struct sockaddr_un sa; + int fd, err; + + fd = socket(AF_LOCAL, SOCK_DGRAM, 0); + if (fd < 0) { + pr_err("vport: failed to create socket: %m"); + return -1; + } + memset(, 0, sizeof(sa)); + sa.sun_family = AF_LOCAL; + strncpy(sa.sun_path, name, sizeof(sa.sun_path) - 1); + + unlink(name); + + err = bind(fd, (struct sockaddr *) , sizeof(sa)); + if (err < 0) { + pr_err("vport: bind failed: %m"); + close(fd); + return -1; + } + + /* For client use, pre load the server path. */ + memset(, 0, sizeof(sa)); + sa.sun_family = AF_LOCAL; + strncpy(sa.sun_path, vport_path, sizeof(sa.sun_path) - 1); + vport->address.sun = sa; + vport->address.len = sizeof(sa); + + chmod(name, VPORT_FILEMODE); + fda->fd[FD_EVENT] = -1; + fda->fd[FD_GENERAL] = fd; + return 0; +} + +static int vport_recv(struct transport *t, int fd, void *buf, int buflen, + struct address *addr, struct hw_timestamp *hwts) +{ + int cnt; + struct vport *vport = container_of(t, struct vport, t); + + addr->len = sizeof(addr->sun); + cnt = recvfrom(fd, buf, buflen, 0, >sa, >len); + if (cnt <= 0) { + pr_err("vport: recvfrom failed: %m"); + return cnt; + } + vport->address = *addr; + return cnt; +} + +static int vport_send(struct transport *t, struct fdarray *fda, + enum transport_event event, int peer, void *buf, + int buflen, struct address *addr, + struct hw_timestamp *hwts) +{ + int cnt, fd = fda->fd[FD_GENERAL]; + struct vport *vport = container_of(t, struct vport, t); + + if (!addr) + addr = >address; + + cnt = sendto(fd, buf, buflen, 0, >sa, addr->len); + if (cnt < 1) { + return -errno; + } + return cnt; +} + +static void vport_release(struct transport *t) +{ + struct vport *vport = container_of(t, struct vport, t); + + free(vport); +} + +struct transport *vport_transport_create(void) +{ + struct vport *vport; + + vport = calloc(1, sizeof(*
[Linuxptp-devel] [PATCH 3/3] Packet Timing Signal Fail (PTSF)(G.8275.2 Section 6.7.11)
adding TLV support for PORT_PTSF_UNUSABLE Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- pmc.c| 6 ++ pmc_common.c | 23 +++ port.c | 23 +++ tlv.c| 12 tlv.h| 6 ++ 5 files changed, 70 insertions(+) diff --git a/pmc.c b/pmc.c index 34c9609..35300b4 100644 --- a/pmc.c +++ b/pmc.c @@ -176,6 +176,7 @@ static void pmc_show(struct ptp_message *msg, FILE *fp) struct currentDS *cds; struct parentDS *pds; struct portDS *p; + struct port_ptsf_unusable_np *ptsf; struct port_ptsf_data_np *ptsf_data; struct TLV *tlv; uint8_t *buf; @@ -608,6 +609,11 @@ static void pmc_show(struct ptp_message *msg, FILE *fp) fprintf(fp, "LOG_MIN_PDELAY_REQ_INTERVAL " IFMT "logMinPdelayReqInterval %hhd", mtd->val); break; + case MID_PORT_PTSF_UNUSABLE_NP: + ptsf = (struct port_ptsf_unusable_np *) mgt->data; + fprintf(fp, "PORT_PTSF_UNUSABLE_NP " + IFMT "unusable %hu", ptsf->ptsf_unusable); + break; case MID_PORT_PTSF_DATA_NP: ptsf_data = (struct port_ptsf_data_np *) mgt->data; fprintf(fp, "PORT_PTSF_DATA_NP " diff --git a/pmc_common.c b/pmc_common.c index 9570841..528bd43 100644 --- a/pmc_common.c +++ b/pmc_common.c @@ -154,6 +154,7 @@ struct management_id idtab[] = { { "PORT_SERVICE_STATS_NP", MID_PORT_SERVICE_STATS_NP, do_get_action }, { "UNICAST_MASTER_TABLE_NP", MID_UNICAST_MASTER_TABLE_NP, do_get_action }, { "PORT_HWCLOCK_NP", MID_PORT_HWCLOCK_NP, do_get_action }, + { "PORT_PTSF_UNUSABLE_NP", MID_PORT_PTSF_UNUSABLE_NP, do_set_action }, { "PORT_PTSF_DATA_NP", MID_PORT_PTSF_DATA_NP, do_get_action }, }; @@ -173,6 +174,7 @@ static void do_set_action(struct pmc *pmc, int action, int index, char *str) struct management_tlv_datum mtd; struct subscribe_events_np sen; struct port_ds_np pnp; + struct port_ptsf_unusable_np ptsf; char onoff_port_state[4] = "off"; char onoff_time_status[4] = "off"; @@ -303,6 +305,27 @@ static void do_set_action(struct pmc *pmc, int action, int index, char *str) } pmc_send_set_action(pmc, code, , sizeof(pnp)); break; + case MID_PORT_PTSF_UNUSABLE_NP: + cnt = sscanf(str, " %*s %*s %hu %hu", +_unusable, +); + if (cnt != 2) { + fprintf(stderr, "%s SET needs 2 value\n", + idtab[index].name); + break; + } + switch (ptsf.ptsf_unusable) { + case TRUE: + case FALSE: + pmc_send_set_action(pmc, code, , sizeof(ptsf)); + break; + default: + fprintf(stderr, "\nusage:" + "set PORT_PTSF_UNUSABLE_NP%hhu (false) or" + "%hhu (true) \n\n", + FALSE, TRUE); + } + break; } } diff --git a/port.c b/port.c index ff00e46..d0997f8 100644 --- a/port.c +++ b/port.c @@ -852,6 +852,7 @@ static int port_management_fill_response(struct port *target, struct PortIdentity pid; const char *ts_label; struct portDS *pds; + struct port_ptsf_unusable_np *ptsf; struct port_ptsf_data_np *ptsf_data; uint16_t u16; uint8_t *buf; @@ -1075,6 +1076,13 @@ static int port_management_fill_response(struct port *target, PORT_HWCLOCK_VCLOCK : 0; datalen = sizeof(*phn); break; + case MID_PORT_PTSF_UNUSABLE_NP: + ptsf = (struct port_ptsf_unusable_np *)tlv->data; + ptsf->portIdentity = target->portIdentity; + ptsf->ptsf_unusable = + (target->signalFail & PDS_PTSF_UNUSABLE) ? 1 : 0; + datalen = sizeof(*ptsf); + break; case MID_PORT_PTSF_DATA_NP: ptsf_data = (struct port_ptsf_data_np *)tlv->data; ptsf_data->portIdentity = target->portIdentity; @@ -1125,6 +1133,8 @@ static int port_management_set(struct port *target, int respond = 0; struct management_tlv *tlv; struct port_ds_np *pdsnp; + struct port_ptsf_unusable_np *ptsf; + UInteger16 signalFail; tlv = (struct management_tlv *) req->management.suffix; @@ -1134,6 +1144,19 @@ static int port_management_set(struct port *target, target->neighborPropDelayThresh = pdsnp->neighborPropDelayThresh; respond = 1; break; + case
[Linuxptp-devel] [PATCH 1/3] Packet Timing Signal Fail (PTSF)(G.8275.2 Section 6.7.11)
- adding sync receipt timeout, delay response timeout and signal fail support to portDS as per G.8275.2. - This also sets the signal fail condition for timeout. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- ds.h | 9 + pmc.c | 9 +++-- port.c | 16 +++- port_private.h | 1 + 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/ds.h b/ds.h index dff6d5e..5136bb2 100644 --- a/ds.h +++ b/ds.h @@ -95,6 +95,11 @@ struct timePropertiesDS { Enumeration8 timeSource; } PACKED; + +#define PDS_PTSF_LOSS_SYNC(1<<0) +#define PDS_PTSF_UNUSABLE (1<<1) +#define PDS_PTSF_LOSS_DELAY_RESP (1<<2) + struct portDS { struct PortIdentity portIdentity; Enumeration8portState; @@ -106,6 +111,10 @@ struct portDS { Enumeration8delayMechanism; Integer8logMinPdelayReqInterval; UInteger8 versionNumber; + UInteger8 localPriority; + UInteger8 signalFail; + UInteger8 syncReceiptTimeout; + UInteger8 delayRespReceiptTimeout; } PACKED; #define FRI_ASAP (-128) diff --git a/pmc.c b/pmc.c index e218ca4..cdc76c8 100644 --- a/pmc.c +++ b/pmc.c @@ -438,16 +438,21 @@ static void pmc_show(struct ptp_message *msg, FILE *fp) IFMT "peerMeanPathDelay %" PRId64 IFMT "logAnnounceInterval %hhd" IFMT "announceReceiptTimeout %hhu" + IFMT "syncReceiptTimeout %hhu" + IFMT "delayRespReceiptTimeout %hhu" IFMT "logSyncInterval %hhd" IFMT "delayMechanism %hhu" IFMT "logMinPdelayReqInterval %hhd" - IFMT "versionNumber %u", + IFMT "versionNumber %u" + IFMT "signalFail %d", pid2str(>portIdentity), ps_str[p->portState], p->logMinDelayReqInterval, p->peerMeanPathDelay >> 16, p->logAnnounceInterval, p->announceReceiptTimeout, + p->syncReceiptTimeout, p->delayRespReceiptTimeout, p->logSyncInterval, p->delayMechanism, p->logMinPdelayReqInterval, - p->versionNumber & MAJOR_VERSION_MASK); + p->versionNumber & MAJOR_VERSION_MASK, + p->signalFail ? 1 : 0); break; case MID_PORT_DATA_SET_NP: pnp = (struct port_ds_np *) mgt->data; diff --git a/port.c b/port.c index 871ad68..8075896 100644 --- a/port.c +++ b/port.c @@ -951,6 +951,9 @@ static int port_management_fill_response(struct port *target, } pds->logMinPdelayReqInterval = target->logMinPdelayReqInterval; pds->versionNumber = target->versionNumber; + pds->syncReceiptTimeout = target->syncReceiptTimeout; + pds->delayRespReceiptTimeout = target->delay_response_timeout; + pds->signalFail = target->signalFail; datalen = sizeof(*pds); break; case MID_LOG_ANNOUNCE_INTERVAL: @@ -1115,7 +1118,6 @@ static int port_management_set(struct port *target, int respond = 0; struct management_tlv *tlv; struct port_ds_np *pdsnp; - tlv = (struct management_tlv *) req->management.suffix; switch (id) { @@ -1284,6 +1286,7 @@ static void port_synchronize(struct port *p, enum servo_state state, last_state; tmv_t t1, t1c, t2, c1, c2; + p->signalFail &= ~PDS_PTSF_LOSS_SYNC; port_set_sync_rx_tmo(p); t1 = timestamp_to_tmv(origin_ts); @@ -1995,6 +1998,12 @@ int process_announce(struct port *p, struct ptp_message *m) return result; } + if (p->signalFail) { + pr_debug("%s: Announce message ignored for signal fail\n", + p->name); + return result; + } + if (m->announce.grandmasterClockQuality.clockClass > clock_get_clock_class_threshold(p->clock)) { pl_err(60, "%s: Master clock quality received is " @@ -2089,6 +2098,9 @@ void process_delay_resp(struct port *p, struct ptp_message *m) struct ptp_message *req; tmv_t c3, t3, t4, t4c; + /* clear delay response time out. */ + p->signalFail &= ~PDS_PTSF_LOSS_DELAY_RESP; + if (p->state != PS_UNCALIBRATED && p->state != PS_SLAVE) { return; } @@ -2780,6 +2792,7 @@ static enum fsm_event bc_event(struct port *p, int fd_index) if (fd_index == FD_SYNC_RX_TIMER) {
[Linuxptp-devel] [PATCH 2/3] Packet Timing Signal Fail (PTSF)(G.8275.2 Section 6.7.11)
adding TLV support for MID_PORT_PTSF_DATA_NP Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- pmc.c| 16 pmc_common.c | 1 + port.c | 8 tlv.c| 11 +++ tlv.h| 5 + 5 files changed, 41 insertions(+) diff --git a/pmc.c b/pmc.c index cdc76c8..34c9609 100644 --- a/pmc.c +++ b/pmc.c @@ -176,6 +176,7 @@ static void pmc_show(struct ptp_message *msg, FILE *fp) struct currentDS *cds; struct parentDS *pds; struct portDS *p; + struct port_ptsf_data_np *ptsf_data; struct TLV *tlv; uint8_t *buf; int action; @@ -607,6 +608,21 @@ static void pmc_show(struct ptp_message *msg, FILE *fp) fprintf(fp, "LOG_MIN_PDELAY_REQ_INTERVAL " IFMT "logMinPdelayReqInterval %hhd", mtd->val); break; + case MID_PORT_PTSF_DATA_NP: + ptsf_data = (struct port_ptsf_data_np *) mgt->data; + fprintf(fp, "PORT_PTSF_DATA_NP " + IFMT "signalFail%hu" + IFMT "PTSF.lossSync %d" + IFMT "PTSF.syncMsgLoss %d" + IFMT "PTSF.delayRespMsgLoss %d" + IFMT "PTSF.unusable %d", + ptsf_data->signalFail ? 1 : 0, + ((ptsf_data->signalFail & PDS_PTSF_LOSS_SYNC) | +(ptsf_data->signalFail & PDS_PTSF_LOSS_DELAY_RESP)) ? 1 : 0, + ptsf_data->signalFail & PDS_PTSF_LOSS_SYNC ? 1 : 0, + ptsf_data->signalFail & PDS_PTSF_LOSS_DELAY_RESP ? 1 : 0, + ptsf_data->signalFail & PDS_PTSF_UNUSABLE ? 1 : 0); + break; } out: fprintf(fp, "\n"); diff --git a/pmc_common.c b/pmc_common.c index 1dd89f6..9570841 100644 --- a/pmc_common.c +++ b/pmc_common.c @@ -154,6 +154,7 @@ struct management_id idtab[] = { { "PORT_SERVICE_STATS_NP", MID_PORT_SERVICE_STATS_NP, do_get_action }, { "UNICAST_MASTER_TABLE_NP", MID_UNICAST_MASTER_TABLE_NP, do_get_action }, { "PORT_HWCLOCK_NP", MID_PORT_HWCLOCK_NP, do_get_action }, + { "PORT_PTSF_DATA_NP", MID_PORT_PTSF_DATA_NP, do_get_action }, }; static void do_get_action(struct pmc *pmc, int action, int index, char *str) diff --git a/port.c b/port.c index 8075896..ff00e46 100644 --- a/port.c +++ b/port.c @@ -852,6 +852,7 @@ static int port_management_fill_response(struct port *target, struct PortIdentity pid; const char *ts_label; struct portDS *pds; + struct port_ptsf_data_np *ptsf_data; uint16_t u16; uint8_t *buf; int datalen; @@ -1074,6 +1075,12 @@ static int port_management_fill_response(struct port *target, PORT_HWCLOCK_VCLOCK : 0; datalen = sizeof(*phn); break; + case MID_PORT_PTSF_DATA_NP: + ptsf_data = (struct port_ptsf_data_np *)tlv->data; + ptsf_data->portIdentity = target->portIdentity; + ptsf_data->signalFail = target->signalFail; + datalen = sizeof(*ptsf_data); + break; default: /* The caller should *not* respond to this message. */ tlv_extra_recycle(extra); @@ -1118,6 +1125,7 @@ static int port_management_set(struct port *target, int respond = 0; struct management_tlv *tlv; struct port_ds_np *pdsnp; + tlv = (struct management_tlv *) req->management.suffix; switch (id) { diff --git a/tlv.c b/tlv.c index 1c13460..745c96a 100644 --- a/tlv.c +++ b/tlv.c @@ -130,6 +130,7 @@ static int mgt_post_recv(struct management_tlv *m, uint16_t data_len, struct defaultDS *dds; struct parentDS *pds; struct portDS *p; + struct port_ptsf_data_np *ptsf_data; uint8_t *buf; uint16_t u16; @@ -407,6 +408,10 @@ static int mgt_post_recv(struct management_tlv *m, uint16_t data_len, if (data_len != 0) goto bad_length; break; + case MID_PORT_PTSF_DATA_NP: + ptsf_data = (struct port_ptsf_data_np *) m->data; + ptsf_data->portIdentity.portNumber = ntohs(ptsf_data->portIdentity.portNumber); + break; } if (extra_len) { if (extra_len % 2) @@ -437,6 +442,7 @@ static void mgt_pre_send(struct management_tlv *m, struct tlv_extra *extra) struct currentDS *cds; struct parentDS *pds; struct portDS *p; + struct port_ptsf_data_np *ptsf_data; uint8_t *buf; int i; @@ -569,6 +575,11 @@ static void mgt_pre_send(struct management_tlv *m, struct tlv_extra *extra) phn->portIdentity.portNumber = htons(phn->portIdentity.portNumber);
[Linuxptp-devel] [PATCH 2/2] Alternate master support
adding alternate master support for linuxptp A PTP Master Clock, which is not the Best Master, may act as a master with the Alternate Master flag set on the messages it sends. Need to support Alternate Master, including using Slave Event Monitoring channel for the alternate connections (to pass along timestamps to external servo). See ITU-T G.8275.2 Appendix III & V. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- clock.c| 5 +++ clock.h| 7 config.c | 1 + msg.h | 10 + port.c | 100 - port_private.h | 1 + 6 files changed, 107 insertions(+), 17 deletions(-) diff --git a/clock.c b/clock.c index d37bb87..428a1e5 100644 --- a/clock.c +++ b/clock.c @@ -1715,6 +1715,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; diff --git a/clock.h b/clock.h index 0534f21..a869fae 100644 --- a/clock.h +++ b/clock.h @@ -289,6 +289,13 @@ int clock_slave_only(struct clock *c); */ UInteger8 clock_max_steps_removed(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); + /** * Obtain the clock class threshold field from a clock's default data set. * @param c The clock instance. diff --git a/config.c b/config.c index b5cf397..ce8a3ae 100644 --- a/config.c +++ b/config.c @@ -226,6 +226,7 @@ static struct config_enum bmca_enu[] = { }; struct config_item config_tab[] = { + PORT_ITEM_INT("altMaster", 0, 1, 1), PORT_ITEM_INT("announceReceiptTimeout", 3, 2, UINT8_MAX), PORT_ITEM_ENU("asCapable", AS_CAPABLE_AUTO, as_capable_enu), GLOB_ITEM_INT("assume_two_step", 0, 0, 1), diff --git a/msg.h b/msg.h index b7423ee..22dfbeb 100644 --- a/msg.h +++ b/msg.h @@ -461,6 +461,16 @@ static inline Boolean one_step(struct ptp_message *m) return !field_is_set(m, 0, TWO_STEP); } +/** + * Test whether a message from ALTERNATE Master. + * @param m Message to test. + * @return One if the alt_master flag in message is set, zero otherwise. + */ +static inline Boolean alt_master(struct ptp_message *m) +{ + return field_is_set(m, 0, ALT_MASTER); +} + /** * Convert a 64 bit word into network byte order. */ diff --git a/port.c b/port.c index 871ad68..4ff3ab8 100644 --- a/port.c +++ b/port.c @@ -1293,11 +1293,16 @@ static void port_synchronize(struct port *p, t1c = tmv_add(t1, tmv_add(c1, c2)); switch (p->state) { + case PS_MASTER: + return; case PS_UNCALIBRATED: case PS_SLAVE: monitor_sync(p->slave_event_monitor, clock_parent_identity(p->clock), seqid, t1, tmv_add(c1, c2), t2); + monitor_computed(p->slave_event_monitor, +clock_parent_identity(p->clock), seqid, +tmv_sub(t2, t1c), tmv_sub(t2, t1c), 0, 1); break; default: break; @@ -1509,6 +1514,7 @@ out: int port_delay_request(struct port *p) { struct ptp_message *msg; + struct ptp_message *dst; /* Time to send a new request, forget current pdelay resp and fup */ if (p->peer_delay_resp) { @@ -1541,10 +1547,20 @@ int port_delay_request(struct port *p) msg->header.control= CTL_DELAY_REQ; msg->header.logMessageInterval = 0x7f; - if (p->hybrid_e2e) { - struct ptp_message *dst = TAILQ_FIRST(>best->messages); + if (p->hybrid_e2e && p->state != PS_MASTER) { + dst = TAILQ_FIRST(>best->messages); msg->address = dst->address; msg->header.flagField[0] |= UNICAST; + } else if (p->altMaster) { + struct foreign_clock *fc; + fc = LIST_FIRST(>foreign_masters); + if (fc) { + dst = TAILQ_FIRST(>messages); + if (dst) { + msg->address = dst->address; + msg->header.flagField[0] |= UNICAST; + } + } } if (port_prepare_and_send(p, msg, TRANS_EVENT)) { @@ -1595,6 +1611,10 @@ int port_tx_announce(struct port *p, struct address *dst, uint16_t sequence_id) msg->header.flagField[1] = tp.flags; + if (p->state != PS_MASTER && clock_telecom_profile(p->clock)) { + msg->header.flagField[0] |= ALT_MASTER; + } + if (dst) { msg->address = *dst;
[Linuxptp-devel] [PATCH 1/2] Alternate master support
Slave Event Monitoring channel for the alternate connections Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- monitor.c | 63 +++ monitor.h | 3 +++ pmc.c | 31 +++ tlv.h | 21 +++ 4 files changed, 118 insertions(+) diff --git a/monitor.c b/monitor.c index ed451ac..1965a89 100644 --- a/monitor.c +++ b/monitor.c @@ -21,8 +21,10 @@ struct monitor_message { struct monitor { struct port *dst_port; struct slave_rx_sync_timing_data_tlv *sync_tlv; + struct slave_rx_sync_computed_data_tlv *computed_tlv; struct slave_delay_timing_data_tlv *delay_tlv; struct monitor_message delay; + struct monitor_message computed; struct monitor_message sync; }; @@ -115,6 +117,23 @@ static int monitor_init_sync(struct monitor *monitor, struct address address) return 0; } +static int monitor_init_computed(struct monitor *monitor, struct address address) +{ + const size_t tlv_size = sizeof(struct slave_rx_sync_computed_data_tlv) + + sizeof(struct slave_rx_sync_computed_record) * RECORDS_PER_MESSAGE; + struct tlv_extra *extra; + + extra = monitor_init_message(>computed, monitor->dst_port, +TLV_SLAVE_RX_SYNC_COMPUTED_DATA, tlv_size, +address); + if (!extra) { + return -1; + } + monitor->computed_tlv = (struct slave_rx_sync_computed_data_tlv *) extra->tlv; + + return 0; +} + struct monitor *monitor_create(struct config *config, struct port *dst) { struct monitor *monitor; @@ -148,6 +167,12 @@ struct monitor *monitor_create(struct config *config, struct port *dst) free(monitor); return NULL; } + if (monitor_init_computed(monitor, address)) { + msg_put(monitor->sync.msg); + msg_put(monitor->delay.msg); + free(monitor); + return NULL; + } return monitor; } @@ -193,6 +218,9 @@ void monitor_destroy(struct monitor *monitor) if (monitor->sync.msg) { msg_put(monitor->sync.msg); } + if (monitor->computed.msg) { + msg_put(monitor->computed.msg); + } free(monitor); } @@ -229,3 +257,38 @@ int monitor_sync(struct monitor *monitor, struct PortIdentity source_pid, } return 0; } + +int monitor_computed(struct monitor *monitor, struct PortIdentity source_pid, +uint16_t seqid, tmv_t offset, tmv_t pathdelay, int32_t ratio, +uint8_t best_master) +{ + struct slave_rx_sync_computed_record *record; + struct ptp_message *msg; + + if (!monitor_active(monitor)) { + return 0; + } + + msg = monitor->computed.msg; + + if (!pid_eq(>computed_tlv->sourcePortIdentity, _pid)) { + /* There was a change in remote master. Drop stale records. */ + memcpy(>computed_tlv->sourcePortIdentity, _pid, + sizeof(monitor->computed_tlv->sourcePortIdentity)); + monitor->computed.count = 0; + } + + record = monitor->computed_tlv->record + monitor->computed.count; + monitor->computed_tlv->reserved= 0; + record->sequenceId = seqid; + record->offsetFromMaster = tmv_to_TimeInterval(offset); + record->meanPathDelay = tmv_to_TimeInterval(pathdelay); + record->scaledNeighborRateRatio= ratio; + + monitor->computed.count++; + if (monitor->computed.count == monitor->computed.records_per_msg) { + monitor->computed.count = 0; + return monitor_forward(monitor->dst_port, msg); + } + return 0; +} diff --git a/monitor.h b/monitor.h index c489aa9..9beb57e 100644 --- a/monitor.h +++ b/monitor.h @@ -22,4 +22,7 @@ void monitor_destroy(struct monitor *monitor); int monitor_sync(struct monitor *monitor, struct PortIdentity source_pid, uint16_t seqid, tmv_t t1, tmv_t corr, tmv_t t2); +int monitor_computed(struct monitor *monitor, struct PortIdentity source_pid, +uint16_t seqid, tmv_t offset, tmv_t pathdelay, int32_t ratio, +uint8_t best_master); #endif diff --git a/pmc.c b/pmc.c index e218ca4..b6227dd 100644 --- a/pmc.c +++ b/pmc.c @@ -88,6 +88,19 @@ static void pmc_show_rx_sync_timing(struct slave_rx_sync_timing_record *record, SHOW_TIMESTAMP(record->syncEventIngressTimestamp)); } +static void pmc_show_rx_sync_computed_data(struct slave_rx_sync_computed_record *record, + FILE *fp) +{ + fprintf(fp, + IFMT "sequenceId %hu" + IFMT "offsetFromMaster %" PRId64 +
[Linuxptp-devel] [PATCH 2/2] adding alternate master support for linuxptp
A PTP Master Clock, which is not the Best Master, may act as a master with the Alternate Master flag set on the messages it sends. Need to support Alternate Master, including using Slave Event Monitoring channel for the alternate connections (to pass along timestamps to external servo). See ITU-T G.8275.2 Appendix III & V. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- clock.c| 5 +++ clock.h| 7 config.c | 1 + msg.h | 10 + port.c | 100 - port_private.h | 1 + 6 files changed, 107 insertions(+), 17 deletions(-) diff --git a/clock.c b/clock.c index d37bb87..428a1e5 100644 --- a/clock.c +++ b/clock.c @@ -1715,6 +1715,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; diff --git a/clock.h b/clock.h index 0534f21..a869fae 100644 --- a/clock.h +++ b/clock.h @@ -289,6 +289,13 @@ int clock_slave_only(struct clock *c); */ UInteger8 clock_max_steps_removed(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); + /** * Obtain the clock class threshold field from a clock's default data set. * @param c The clock instance. diff --git a/config.c b/config.c index b5cf397..ce8a3ae 100644 --- a/config.c +++ b/config.c @@ -226,6 +226,7 @@ static struct config_enum bmca_enu[] = { }; struct config_item config_tab[] = { + PORT_ITEM_INT("altMaster", 0, 1, 1), PORT_ITEM_INT("announceReceiptTimeout", 3, 2, UINT8_MAX), PORT_ITEM_ENU("asCapable", AS_CAPABLE_AUTO, as_capable_enu), GLOB_ITEM_INT("assume_two_step", 0, 0, 1), diff --git a/msg.h b/msg.h index b7423ee..22dfbeb 100644 --- a/msg.h +++ b/msg.h @@ -461,6 +461,16 @@ static inline Boolean one_step(struct ptp_message *m) return !field_is_set(m, 0, TWO_STEP); } +/** + * Test whether a message from ALTERNATE Master. + * @param m Message to test. + * @return One if the alt_master flag in message is set, zero otherwise. + */ +static inline Boolean alt_master(struct ptp_message *m) +{ + return field_is_set(m, 0, ALT_MASTER); +} + /** * Convert a 64 bit word into network byte order. */ diff --git a/port.c b/port.c index 871ad68..4ff3ab8 100644 --- a/port.c +++ b/port.c @@ -1293,11 +1293,16 @@ static void port_synchronize(struct port *p, t1c = tmv_add(t1, tmv_add(c1, c2)); switch (p->state) { + case PS_MASTER: + return; case PS_UNCALIBRATED: case PS_SLAVE: monitor_sync(p->slave_event_monitor, clock_parent_identity(p->clock), seqid, t1, tmv_add(c1, c2), t2); + monitor_computed(p->slave_event_monitor, +clock_parent_identity(p->clock), seqid, +tmv_sub(t2, t1c), tmv_sub(t2, t1c), 0, 1); break; default: break; @@ -1509,6 +1514,7 @@ out: int port_delay_request(struct port *p) { struct ptp_message *msg; + struct ptp_message *dst; /* Time to send a new request, forget current pdelay resp and fup */ if (p->peer_delay_resp) { @@ -1541,10 +1547,20 @@ int port_delay_request(struct port *p) msg->header.control= CTL_DELAY_REQ; msg->header.logMessageInterval = 0x7f; - if (p->hybrid_e2e) { - struct ptp_message *dst = TAILQ_FIRST(>best->messages); + if (p->hybrid_e2e && p->state != PS_MASTER) { + dst = TAILQ_FIRST(>best->messages); msg->address = dst->address; msg->header.flagField[0] |= UNICAST; + } else if (p->altMaster) { + struct foreign_clock *fc; + fc = LIST_FIRST(>foreign_masters); + if (fc) { + dst = TAILQ_FIRST(>messages); + if (dst) { + msg->address = dst->address; + msg->header.flagField[0] |= UNICAST; + } + } } if (port_prepare_and_send(p, msg, TRANS_EVENT)) { @@ -1595,6 +1611,10 @@ int port_tx_announce(struct port *p, struct address *dst, uint16_t sequence_id) msg->header.flagField[1] = tp.flags; + if (p->state != PS_MASTER && clock_telecom_profile(p->clock)) { + msg->header.flagField[0] |= ALT_MASTER; + } + if (dst) { msg->address = *dst; msg->header.flagField[0] |= UNICAST; @@ -1674,6 +1694,10 @@
[Linuxptp-devel] [PATCH 1/2] Slave Event Monitoring channel for the alternate connections
A PTP Master Clock, which is not the Best Master, may act as a master with the Alternate Master flag set on the messages it sends. Need to support Alternate Master, including using Slave Event Monitoring channel for the alternate connections (to pass along timestamps to external servo). See ITU-T G.8275.2 Appendix III & V. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- monitor.c | 63 +++ monitor.h | 3 +++ pmc.c | 31 +++ tlv.h | 21 +++ 4 files changed, 118 insertions(+) diff --git a/monitor.c b/monitor.c index ed451ac..1965a89 100644 --- a/monitor.c +++ b/monitor.c @@ -21,8 +21,10 @@ struct monitor_message { struct monitor { struct port *dst_port; struct slave_rx_sync_timing_data_tlv *sync_tlv; + struct slave_rx_sync_computed_data_tlv *computed_tlv; struct slave_delay_timing_data_tlv *delay_tlv; struct monitor_message delay; + struct monitor_message computed; struct monitor_message sync; }; @@ -115,6 +117,23 @@ static int monitor_init_sync(struct monitor *monitor, struct address address) return 0; } +static int monitor_init_computed(struct monitor *monitor, struct address address) +{ + const size_t tlv_size = sizeof(struct slave_rx_sync_computed_data_tlv) + + sizeof(struct slave_rx_sync_computed_record) * RECORDS_PER_MESSAGE; + struct tlv_extra *extra; + + extra = monitor_init_message(>computed, monitor->dst_port, +TLV_SLAVE_RX_SYNC_COMPUTED_DATA, tlv_size, +address); + if (!extra) { + return -1; + } + monitor->computed_tlv = (struct slave_rx_sync_computed_data_tlv *) extra->tlv; + + return 0; +} + struct monitor *monitor_create(struct config *config, struct port *dst) { struct monitor *monitor; @@ -148,6 +167,12 @@ struct monitor *monitor_create(struct config *config, struct port *dst) free(monitor); return NULL; } + if (monitor_init_computed(monitor, address)) { + msg_put(monitor->sync.msg); + msg_put(monitor->delay.msg); + free(monitor); + return NULL; + } return monitor; } @@ -193,6 +218,9 @@ void monitor_destroy(struct monitor *monitor) if (monitor->sync.msg) { msg_put(monitor->sync.msg); } + if (monitor->computed.msg) { + msg_put(monitor->computed.msg); + } free(monitor); } @@ -229,3 +257,38 @@ int monitor_sync(struct monitor *monitor, struct PortIdentity source_pid, } return 0; } + +int monitor_computed(struct monitor *monitor, struct PortIdentity source_pid, +uint16_t seqid, tmv_t offset, tmv_t pathdelay, int32_t ratio, +uint8_t best_master) +{ + struct slave_rx_sync_computed_record *record; + struct ptp_message *msg; + + if (!monitor_active(monitor)) { + return 0; + } + + msg = monitor->computed.msg; + + if (!pid_eq(>computed_tlv->sourcePortIdentity, _pid)) { + /* There was a change in remote master. Drop stale records. */ + memcpy(>computed_tlv->sourcePortIdentity, _pid, + sizeof(monitor->computed_tlv->sourcePortIdentity)); + monitor->computed.count = 0; + } + + record = monitor->computed_tlv->record + monitor->computed.count; + monitor->computed_tlv->reserved= 0; + record->sequenceId = seqid; + record->offsetFromMaster = tmv_to_TimeInterval(offset); + record->meanPathDelay = tmv_to_TimeInterval(pathdelay); + record->scaledNeighborRateRatio= ratio; + + monitor->computed.count++; + if (monitor->computed.count == monitor->computed.records_per_msg) { + monitor->computed.count = 0; + return monitor_forward(monitor->dst_port, msg); + } + return 0; +} diff --git a/monitor.h b/monitor.h index c489aa9..9beb57e 100644 --- a/monitor.h +++ b/monitor.h @@ -22,4 +22,7 @@ void monitor_destroy(struct monitor *monitor); int monitor_sync(struct monitor *monitor, struct PortIdentity source_pid, uint16_t seqid, tmv_t t1, tmv_t corr, tmv_t t2); +int monitor_computed(struct monitor *monitor, struct PortIdentity source_pid, +uint16_t seqid, tmv_t offset, tmv_t pathdelay, int32_t ratio, +uint8_t best_master); #endif diff --git a/pmc.c b/pmc.c index e218ca4..b6227dd 100644 --- a/pmc.c +++ b/pmc.c @@ -88,6 +88,19 @@ static void pmc_show_rx_sync_timing(struct slave_rx_sync_timing_record *record, SHOW_TIMESTAMP(record->syncEventIngressTimestamp)); } +static void
[Linuxptp-devel] [PATCH 1/4] [Interface Rate TLV] function to support get interface speed via ethtool
When master and slave instance interacting with each other operating at different interface speed, delay assymetry needs to be compensated as described in G.8271 appendix V. In this patch we are adding changes to get the interface speed using ethtool. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- sk.c | 69 sk.h | 18 2 files changed, 87 insertions(+) diff --git a/sk.c b/sk.c index 80075be..d372fef 100644 --- a/sk.c +++ b/sk.c @@ -205,6 +205,75 @@ failed: return -1; } +int sk_get_if_info(const char *name, struct sk_if_info *if_info) +{ +#ifdef ETHTOOL_GLINKSETTINGS + struct ifreq ifr; + int fd, err; + + struct { + struct ethtool_link_settings req; + /* link_mode_data consists of supported[], advertising[] +* and lp_advertising[] with size up to 127 each. +* The actual size is provided by the kernel. +*/ + __u32 link_mode_data[3 * 127]; + } ecmd; + + memset(, 0, sizeof(ifr)); + memset(, 0, sizeof(ecmd)); + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + goto failed; + } + + ecmd.req.cmd = ETHTOOL_GLINKSETTINGS; + + strncpy(ifr.ifr_name, name, IFNAMSIZ - 1); + ifr.ifr_data = (char *) + + /* Handshake with kernel to determine number of words for link +* mode bitmaps. When requested number of bitmap words is not +* the one expected by kernel, the latter returns the integer +* opposite of what it is expecting. We request length 0 below +* (aka. invalid bitmap length) to get this info. +*/ + err = ioctl(fd, SIOCETHTOOL, ); + if (err < 0) { + pr_err("ioctl SIOCETHTOOL failed: %m"); + close(fd); + goto failed; + } + + if (ecmd.req.link_mode_masks_nwords >= 0 || + ecmd.req.cmd != ETHTOOL_GLINKSETTINGS) { + return 1; + } + ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords; + + err = ioctl(fd, SIOCETHTOOL, ); + if (err < 0) { + pr_err("ioctl SIOCETHTOOL failed: %m"); + close(fd); + goto failed; + } + + close(fd); + + /* copy the necessary data to sk_info */ + memset(if_info, 0, sizeof(struct sk_if_info)); + if_info->valid = 1; + if_info->speed = ecmd.req.speed; + + return 0; +failed: +#endif + /* clear data and ensure it is not marked valid */ + memset(if_info, 0, sizeof(struct sk_if_info)); + return -1; +} + static int sk_interface_guidaddr(const char *name, unsigned char *guid) { char file_name[64], buf[64], addr[8]; diff --git a/sk.h b/sk.h index 486dbc4..853aadf 100644 --- a/sk.h +++ b/sk.h @@ -49,6 +49,16 @@ struct sk_ts_info { unsigned int rx_filters; }; +/** + * Contains interface information returned by theGLINKSETTINGS ioctl. + * @valid:set to non-zero when the info struct contains valid data. + * @speed:interface speed. + */ +struct sk_if_info { + int valid; + int speed; +}; + /** * Obtains a socket suitable for use with sk_interface_index(). * @return An open socket on success, -1 otherwise. @@ -78,6 +88,14 @@ int sk_general_init(int fd); */ int sk_get_ts_info(const char *name, struct sk_ts_info *sk_info); +/** + * Obtain supporte interface information + * @param name The name of the interface + * @param info Struct containing obtained interface information. + * @return zero on success, negative on failure. + */ +int sk_get_if_info(const char *name, struct sk_if_info *sk_info); + /** * Obtain the MAC address of a network interface. * @param name The name of the interface -- 2.17.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH 4/4] [Interface Rate TLV] adding delay asymmetry calculation
Delay asymmetry calculation based on the PTP port interface speed of master obtained from TLV and the slave interface rate obtained by ethtool. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- interface.c | 9 + interface.h | 7 +++ port_private.h| 1 + port_signaling.c | 33 - ptp4l.8 | 6 ++ unicast_service.c | 34 ++ 6 files changed, 89 insertions(+), 1 deletion(-) diff --git a/interface.c b/interface.c index 9bcb343..ec8964c 100644 --- a/interface.c +++ b/interface.c @@ -93,3 +93,12 @@ 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 1/ iface->if_info.speed; +} diff --git a/interface.h b/interface.h index 5289a7f..e1dc0e8 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. + * @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/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 PortStatsstats; struct PortServiceStatsservice_stats; /* foreignMasterDS */ diff --git a/port_signaling.c b/port_signaling.c index ed217c0..4b86b7e 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; + doublensDelay; + Integer64 slaveBitPeriod; + Integer64 masterBitPeriod; + + if (clock_interface_rate_tlv (p->clock) && + 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 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 1268802..140523c 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,
[Linuxptp-devel] [PATCH 3/4] [Interface Rate TLV] organization TLV support for interface rate
adding interface rate TLV as defined by ITU-T G.8275.2 Annex D to enable master to communicate PTP port interface rate to slave. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- clock.c | 7 +++ clock.h | 7 +++ config.c | 1 + pdt.h| 1 + tlv.c| 1 + tlv.h| 14 ++ 6 files changed, 31 insertions(+) diff --git a/clock.c b/clock.c index de69c52..cee469b 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; @@ -1106,6 +1107,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; @@ -2087,3 +2089,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..b393c3e 100644 --- a/clock.h +++ b/clock.h @@ -388,4 +388,11 @@ 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); + #endif diff --git a/config.c b/config.c index b5cf397..76dd755 100644 --- a/config.c +++ b/config.c @@ -241,6 +241,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/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/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; + UInteger16length; + Octet id[3]; + Octet subtype[3]; + UInteger64interfaceBitPeriod; + UInteger16numberOfBitsBeforeTimestamp; + UInteger16numberOfBitsAfterTimestamp; +} PACKED; + /** * Allocates a new tlv_extra structure. * @return Pointer to a new structure on success or NULL otherwise. -- 2.17.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH 2/4] [Interface Rate TLV] adding speed field information for interface
Get the interface speed related information using ethtool Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- clock.c | 2 ++ interface.c | 11 +++ interface.h | 14 ++ port.c | 5 + 4 files changed, 32 insertions(+) diff --git a/clock.c b/clock.c index d37bb87..de69c52 100644 --- a/clock.c +++ b/clock.c @@ -1004,6 +1004,8 @@ struct clock *clock_create(enum clock_type type, struct config *config, memset(ts_label, 0, sizeof(ts_label)); if (!rtnl_get_ts_device(interface_name(iface), ts_label)) interface_set_label(iface, ts_label); + /* Interface speed information */ + interface_get_ifinfo(iface); interface_get_tsinfo(iface); if (interface_tsinfo_valid(iface) && !interface_tsmodes_supported(iface, required_modes)) { diff --git a/interface.c b/interface.c index 6c2630c..9bcb343 100644 --- a/interface.c +++ b/interface.c @@ -12,6 +12,7 @@ struct interface { char name[MAX_IFNAME_SIZE + 1]; char ts_label[MAX_IFNAME_SIZE + 1]; struct sk_ts_info ts_info; + struct sk_if_info if_info; int vclock; }; @@ -40,6 +41,11 @@ int interface_get_tsinfo(struct interface *iface) return sk_get_ts_info(iface->ts_label, >ts_info); } +int interface_get_ifinfo(struct interface *iface) +{ + return sk_get_if_info(iface->ts_label, >if_info); +} + const char *interface_label(struct interface *iface) { return iface->ts_label; @@ -65,6 +71,11 @@ bool interface_tsinfo_valid(struct interface *iface) return iface->ts_info.valid ? true : false; } +bool interface_ifinfo_valid(struct interface *iface) +{ + return iface->if_info.valid ? true : false; +} + bool interface_tsmodes_supported(struct interface *iface, int modes) { if ((iface->ts_info.so_timestamping & modes) == modes) { diff --git a/interface.h b/interface.h index 5fc7836..5289a7f 100644 --- a/interface.h +++ b/interface.h @@ -40,6 +40,13 @@ void interface_destroy(struct interface *iface); */ int interface_get_tsinfo(struct interface *iface); +/** + * Populate the time stamping information of a given interface. + * @param iface The interface of interest. + * @return zero on success, negative on failure. + */ +int interface_get_ifinfo(struct interface *iface); + /** * Obtain the time stamping label of a network interface. This can be * different from the name of the interface when bonding is in effect. @@ -77,6 +84,13 @@ void interface_set_label(struct interface *iface, const char *label); */ bool interface_tsinfo_valid(struct interface *iface); +/** + * Tests whether an interface's interface information is valid or not. + * @param iface The interface of interest. + * @return True if the interface information is valid, false otherwise. + */ +bool interface_ifinfo_valid(struct interface *iface); + /** * Tests whether an interface supports a set of given time stamping modes. * @param iface The interface of interest. diff --git a/port.c b/port.c index 871ad68..2232b69 100644 --- a/port.c +++ b/port.c @@ -2726,6 +2726,11 @@ void port_link_status(void *ctx, int linkup, int ts_index) p->link_status = link_state; } else { p->link_status = link_state | LINK_STATE_CHANGED; + /* Update Interface speed information on Link up*/ + if (linkup) { + interface_get_ifinfo(p->iface); + } + pr_notice("%s: link %s", p->log_name, linkup ? "up" : "down"); } -- 2.17.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH 3/4] [Interface Rate TLV] organization TLV support for interface rate
adding interface rate TLV as defined by ITU-T G.8275.2 Annex D to enable master to communicate PTP port interface rate to slave. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- clock.c | 7 +++ clock.h | 7 +++ config.c | 1 + pdt.h| 1 + tlv.c| 1 + tlv.h| 14 ++ 6 files changed, 31 insertions(+) diff --git a/clock.c b/clock.c index de69c52..cee469b 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; @@ -1106,6 +1107,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; @@ -2087,3 +2089,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..b393c3e 100644 --- a/clock.h +++ b/clock.h @@ -388,4 +388,11 @@ 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); + #endif diff --git a/config.c b/config.c index b5cf397..76dd755 100644 --- a/config.c +++ b/config.c @@ -241,6 +241,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/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/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; + UInteger16length; + Octet id[3]; + Octet subtype[3]; + UInteger64interfaceBitPeriod; + UInteger16numberOfBitsBeforeTimestamp; + UInteger16numberOfBitsAfterTimestamp; +} PACKED; + /** * Allocates a new tlv_extra structure. * @return Pointer to a new structure on success or NULL otherwise. -- 2.17.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH 4/4] [Interface Rate TLV] adding delay asymmetry calculation
Delay asymmetry calculation based on the PTP port interface speed of master obtained from TLV and the slave interface rate obtained by ethtool. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- interface.c | 9 + interface.h | 7 +++ port_private.h| 1 + port_signaling.c | 33 - ptp4l.8 | 6 ++ unicast_service.c | 34 ++ 6 files changed, 89 insertions(+), 1 deletion(-) diff --git a/interface.c b/interface.c index 9bcb343..ec8964c 100644 --- a/interface.c +++ b/interface.c @@ -93,3 +93,12 @@ 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 1/ iface->if_info.speed; +} diff --git a/interface.h b/interface.h index 5289a7f..e1dc0e8 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. + * @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/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 PortStatsstats; struct PortServiceStatsservice_stats; /* foreignMasterDS */ diff --git a/port_signaling.c b/port_signaling.c index ed217c0..4b86b7e 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; + doublensDelay; + Integer64 slaveBitPeriod; + Integer64 masterBitPeriod; + + if (clock_interface_rate_tlv (p->clock) && + 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 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 1268802..140523c 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,
[Linuxptp-devel] [PATCH 1/4] [Interface Rate TLV] function to support get interface speed via ethtool
When master and slave instance interacting with each other operating at different interface speed, delay assymetry needs to be compensated as described in G.8271 appendix V. In this patch we are adding changes to get the interface speed using ethtool. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- sk.c | 65 sk.h | 18 + 2 files changed, 83 insertions(+) diff --git a/sk.c b/sk.c index 80075be..7df14db 100644 --- a/sk.c +++ b/sk.c @@ -205,6 +205,71 @@ failed: return -1; } +int sk_get_if_info(const char *name, struct sk_if_info *if_info) +{ +#ifdef ETHTOOL_GLINKSETTINGS + struct ifreq ifr; + int fd, err; + + struct { + struct ethtool_link_settings req; + __u32 link_mode_data[3 * 127]; + } ecmd; + + memset(, 0, sizeof(ifr)); + memset(, 0, sizeof(ecmd)); + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + goto failed; + } + + ecmd.req.cmd = ETHTOOL_GLINKSETTINGS; + + strncpy(ifr.ifr_name, name, IFNAMSIZ - 1); + ifr.ifr_data = (char *) + + /* Handshake with kernel to determine number of words for link +* mode bitmaps. When requested number of bitmap words is not +* the one expected by kernel, the latter returns the integer +* opposite of what it is expecting. We request length 0 below +* (aka. invalid bitmap length) to get this info. +*/ + err = ioctl(fd, SIOCETHTOOL, ); + if (err < 0) { + pr_err("ioctl SIOCETHTOOL failed: %m"); + close(fd); + goto failed; + } + + if (ecmd.req.link_mode_masks_nwords >= 0 || + ecmd.req.cmd != ETHTOOL_GLINKSETTINGS) { + return 1; + } + ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords; + + err = ioctl(fd, SIOCETHTOOL, ); + if (err < 0) { + pr_err("ioctl SIOCETHTOOL failed: %m"); + close(fd); + goto failed; + } + + close(fd); + + /* copy the necessary data to sk_info */ + memset(if_info, 0, sizeof(struct sk_if_info)); + if_info->valid = 1; + if_info->speed = ecmd.req.speed; + + return 0; +failed: +#endif + /* clear data and ensure it is not marked valid */ + memset(if_info, 0, sizeof(struct sk_if_info)); + return -1; +} + static int sk_interface_guidaddr(const char *name, unsigned char *guid) { char file_name[64], buf[64], addr[8]; diff --git a/sk.h b/sk.h index 486dbc4..853aadf 100644 --- a/sk.h +++ b/sk.h @@ -49,6 +49,16 @@ struct sk_ts_info { unsigned int rx_filters; }; +/** + * Contains interface information returned by theGLINKSETTINGS ioctl. + * @valid:set to non-zero when the info struct contains valid data. + * @speed:interface speed. + */ +struct sk_if_info { + int valid; + int speed; +}; + /** * Obtains a socket suitable for use with sk_interface_index(). * @return An open socket on success, -1 otherwise. @@ -78,6 +88,14 @@ int sk_general_init(int fd); */ int sk_get_ts_info(const char *name, struct sk_ts_info *sk_info); +/** + * Obtain supporte interface information + * @param name The name of the interface + * @param info Struct containing obtained interface information. + * @return zero on success, negative on failure. + */ +int sk_get_if_info(const char *name, struct sk_if_info *sk_info); + /** * Obtain the MAC address of a network interface. * @param name The name of the interface -- 2.17.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH 2/4] [Interface Rate TLV] adding speed field information for interface
Get the interface speed related information using ethtool Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- clock.c | 2 ++ interface.c | 11 +++ interface.h | 14 ++ port.c | 5 + 4 files changed, 32 insertions(+) diff --git a/clock.c b/clock.c index d37bb87..de69c52 100644 --- a/clock.c +++ b/clock.c @@ -1004,6 +1004,8 @@ struct clock *clock_create(enum clock_type type, struct config *config, memset(ts_label, 0, sizeof(ts_label)); if (!rtnl_get_ts_device(interface_name(iface), ts_label)) interface_set_label(iface, ts_label); + /* Interface speed information */ + interface_get_ifinfo(iface); interface_get_tsinfo(iface); if (interface_tsinfo_valid(iface) && !interface_tsmodes_supported(iface, required_modes)) { diff --git a/interface.c b/interface.c index 6c2630c..9bcb343 100644 --- a/interface.c +++ b/interface.c @@ -12,6 +12,7 @@ struct interface { char name[MAX_IFNAME_SIZE + 1]; char ts_label[MAX_IFNAME_SIZE + 1]; struct sk_ts_info ts_info; + struct sk_if_info if_info; int vclock; }; @@ -40,6 +41,11 @@ int interface_get_tsinfo(struct interface *iface) return sk_get_ts_info(iface->ts_label, >ts_info); } +int interface_get_ifinfo(struct interface *iface) +{ + return sk_get_if_info(iface->ts_label, >if_info); +} + const char *interface_label(struct interface *iface) { return iface->ts_label; @@ -65,6 +71,11 @@ bool interface_tsinfo_valid(struct interface *iface) return iface->ts_info.valid ? true : false; } +bool interface_ifinfo_valid(struct interface *iface) +{ + return iface->if_info.valid ? true : false; +} + bool interface_tsmodes_supported(struct interface *iface, int modes) { if ((iface->ts_info.so_timestamping & modes) == modes) { diff --git a/interface.h b/interface.h index 5fc7836..5289a7f 100644 --- a/interface.h +++ b/interface.h @@ -40,6 +40,13 @@ void interface_destroy(struct interface *iface); */ int interface_get_tsinfo(struct interface *iface); +/** + * Populate the time stamping information of a given interface. + * @param iface The interface of interest. + * @return zero on success, negative on failure. + */ +int interface_get_ifinfo(struct interface *iface); + /** * Obtain the time stamping label of a network interface. This can be * different from the name of the interface when bonding is in effect. @@ -77,6 +84,13 @@ void interface_set_label(struct interface *iface, const char *label); */ bool interface_tsinfo_valid(struct interface *iface); +/** + * Tests whether an interface's interface information is valid or not. + * @param iface The interface of interest. + * @return True if the interface information is valid, false otherwise. + */ +bool interface_ifinfo_valid(struct interface *iface); + /** * Tests whether an interface supports a set of given time stamping modes. * @param iface The interface of interest. diff --git a/port.c b/port.c index 871ad68..2232b69 100644 --- a/port.c +++ b/port.c @@ -2726,6 +2726,11 @@ void port_link_status(void *ctx, int linkup, int ts_index) p->link_status = link_state; } else { p->link_status = link_state | LINK_STATE_CHANGED; + /* Update Interface speed information on Link up*/ + if (linkup) { + interface_get_ifinfo(p->iface); + } + pr_notice("%s: link %s", p->log_name, linkup ? "up" : "down"); } -- 2.17.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH] G.8275.2 support for delay_mechanism NO_MECHANISM
As per IEEE1588-2019, Table 21 adding NO_MECHANISM support. In this case port does not implement the delay mechanism. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- clock.c | 4 +++- config.c | 1 + dm.h | 3 +++ port.c | 8 port.h | 7 +++ ptp4l.8 | 2 +- unicast_client.c | 11 --- 7 files changed, 31 insertions(+), 5 deletions(-) diff --git a/clock.c b/clock.c index 16ca6ed..d37bb87 100644 --- a/clock.c +++ b/clock.c @@ -1998,8 +1998,10 @@ static void handle_state_decision_event(struct clock *c) if (c->sanity_check) clockcheck_reset(c->sanity_check); tsproc_reset(c->tsproc, 1); - if (!tmv_is_zero(c->initial_delay)) + if (!tmv_is_zero(c->initial_delay) || (best && + port_delay_mechanism(best->port) == DM_NO_MECHANISM)) { tsproc_set_delay(c->tsproc, c->initial_delay); + } c->ingress_ts = tmv_zero(); c->path_delay = c->initial_delay; c->master_local_rr = 1.0; diff --git a/config.c b/config.c index 6ba9996..b5cf397 100644 --- a/config.c +++ b/config.c @@ -171,6 +171,7 @@ static struct config_enum delay_mech_enu[] = { { "Auto", DM_AUTO }, { "E2E", DM_E2E }, { "P2P", DM_P2P }, + { "NONE", DM_NO_MECHANISM }, { NULL, 0 }, }; diff --git a/dm.h b/dm.h index 2491c63..47bd847 100644 --- a/dm.h +++ b/dm.h @@ -33,6 +33,9 @@ enum delay_mechanism { /** Peer delay mechanism. */ DM_P2P, + + /** No Delay Mechanism. */ + DM_NO_MECHANISM = 0xFE, }; #endif diff --git a/port.c b/port.c index ce1ff33..15af41a 100644 --- a/port.c +++ b/port.c @@ -1854,6 +1854,9 @@ int port_initialize(struct port *p) pr_err("inhibit_delay_req can only be set when asCapable == 'true'."); return -1; } + if (port_delay_mechanism(p) == DM_NO_MECHANISM) { + p->inhibit_delay_req = 1; + } for (i = 0; i < N_TIMER_FDS; i++) { fd[i] = -1; @@ -3396,6 +3399,11 @@ enum port_state port_state(struct port *port) return port->state; } +enum delay_mechanism port_delay_mechanism(struct port *port) +{ + return port->delayMechanism; +} + int port_state_update(struct port *p, enum fsm_event event, int mdiff) { enum port_state next = p->state_machine(p->state, event, mdiff); diff --git a/port.h b/port.h index 37a4e19..4854698 100644 --- a/port.h +++ b/port.h @@ -227,6 +227,13 @@ struct ptp_message *port_signaling_construct(struct port *p, */ enum port_state port_state(struct port *port); +/** + * Return port's delay mechanism method. + * @param port A port instance. + * @return one of the @ref delay_mechanism values. + */ +enum delay_mechanism port_delay_mechanism(struct port *port); + /** * Update a port's current state based on a given event. * @param pA pointer previously obtained via port_open(). diff --git a/ptp4l.8 b/ptp4l.8 index e33454a..1268802 100644 --- a/ptp4l.8 +++ b/ptp4l.8 @@ -245,7 +245,7 @@ the fault be reset immediately. The default is 16 seconds. .TP .B delay_mechanism -Select the delay mechanism. Possible values are E2E, P2P and Auto. +Select the delay mechanism. Possible values are E2E, P2P, NONE and Auto. The default is E2E. .TP .B hybrid_e2e diff --git a/unicast_client.c b/unicast_client.c index 8ebe06f..20f9558 100644 --- a/unicast_client.c +++ b/unicast_client.c @@ -26,6 +26,7 @@ #define E2E_SYDY_MASK (1 << ANNOUNCE | 1 << SYNC | 1 << DELAY_RESP) #define P2P_SYDY_MASK (1 << ANNOUNCE | 1 << SYNC) +#define E2E_SY_MASK (1 << ANNOUNCE | 1 << SYNC) static int attach_ack(struct ptp_message *msg, uint8_t message_type_flags) { @@ -200,7 +201,8 @@ static int unicast_client_renew(struct port *p, if (err) { goto out; } - if (p->delayMechanism != DM_P2P) { + if (p->delayMechanism != DM_P2P && + p->delayMechanism != DM_NO_MECHANISM) { err = attach_request(msg, p->logMinDelayReqInterval, DELAY_RESP, p->unicast_req_duration); @@ -253,9 +255,10 @@ static int unicast_client_sydy(struct port *p, if (err) { goto out; } - if (p->delayMechanism != DM_P2P) { + if (p->delayMechanism != DM_P2P && + p->delayMechanism != DM_NO_MECHANISM) { err = attach_request(msg, p->logMinDelayReqInterval, DELAY_RESP, -p->unicast_req_duration); + p->unicast_req_duration); if (err) { goto out;
[Linuxptp-devel] [PATCH 3/3] [Interface Rate TLV] adding TLV support
- adding organizational TLV support for interface rate - delay asymmetry calculation for master and slave Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- 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 = 0x0DE0B6B3A764; + + if (!iface->if_info.valid) { + return 0; + } + + if_atto_sec_bit_period /= iface->if_info.speed; + if_atto_sec_bit_period /= 100; /* 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
[Linuxptp-devel] [PATCH 2/3] [Interface Rate TLV] adding speed field information for interface
Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- clock.c | 2 ++ interface.c | 11 +++ interface.h | 14 ++ port.c | 5 + 4 files changed, 32 insertions(+) diff --git a/clock.c b/clock.c index f808b35..8f328e5 100644 --- a/clock.c +++ b/clock.c @@ -1005,6 +1005,8 @@ struct clock *clock_create(enum clock_type type, struct config *config, rtnl_get_ts_device(interface_name(iface), ts_label); interface_set_label(iface, ts_label); interface_ensure_tslabel(iface); + /* Interface speed information */ + interface_get_ifinfo(iface); interface_get_tsinfo(iface); if (interface_tsinfo_valid(iface) && !interface_tsmodes_supported(iface, required_modes)) { diff --git a/interface.c b/interface.c index 445a270..44d6588 100644 --- a/interface.c +++ b/interface.c @@ -12,6 +12,7 @@ struct interface { char name[MAX_IFNAME_SIZE + 1]; char ts_label[MAX_IFNAME_SIZE + 1]; struct sk_ts_info ts_info; + struct sk_if_info if_info; int vclock; }; @@ -46,6 +47,11 @@ int interface_get_tsinfo(struct interface *iface) return sk_get_ts_info(iface->ts_label, >ts_info); } +int interface_get_ifinfo(struct interface *iface) +{ + return sk_get_if_info(iface->ts_label, >if_info); +} + const char *interface_label(struct interface *iface) { return iface->ts_label; @@ -71,6 +77,11 @@ bool interface_tsinfo_valid(struct interface *iface) return iface->ts_info.valid ? true : false; } +bool interface_ifinfo_valid(struct interface *iface) +{ + return iface->if_info.valid ? true : false; +} + bool interface_tsmodes_supported(struct interface *iface, int modes) { if ((iface->ts_info.so_timestamping & modes) == modes) { diff --git a/interface.h b/interface.h index 752f4f1..fbbe919 100644 --- a/interface.h +++ b/interface.h @@ -46,6 +46,13 @@ void interface_ensure_tslabel(struct interface *iface); */ int interface_get_tsinfo(struct interface *iface); +/** + * Populate the time stamping information of a given interface. + * @param iface The interface of interest. + * @return zero on success, negative on failure. + */ +int interface_get_ifinfo(struct interface *iface); + /** * Obtain the time stamping label of a network interface. This can be * different from the name of the interface when bonding is in effect. @@ -83,6 +90,13 @@ void interface_set_label(struct interface *iface, const char *label); */ bool interface_tsinfo_valid(struct interface *iface); +/** + * Tests whether an interface's interface information is valid or not. + * @param iface The interface of interest. + * @return True if the interface information is valid, false otherwise. + */ +bool interface_ifinfo_valid(struct interface *iface); + /** * Tests whether an interface supports a set of given time stamping modes. * @param iface The interface of interest. diff --git a/port.c b/port.c index d9dac38..b93225b 100644 --- a/port.c +++ b/port.c @@ -2690,6 +2690,11 @@ void port_link_status(void *ctx, int linkup, int ts_index) p->link_status = link_state; } else { p->link_status = link_state | LINK_STATE_CHANGED; + /* Update Interface speed information on Link up*/ + if (linkup) { + interface_get_ifinfo(p->iface); + } + pr_notice("%s: link %s", p->log_name, linkup ? "up" : "down"); } -- 2.17.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH 1/3] [Interface Rate TLV] function to support get interface speed via ethtool
When master and slave instance interacting with each other operating at different interface speed, delay assymetry needs to be compensated as described in G.8271 appendix V. In this patch we are adding changes to get the interface speed using ethtool. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- sk.c | 65 sk.h | 18 + 2 files changed, 83 insertions(+) diff --git a/sk.c b/sk.c index b55d6b5..6a0fc5e 100644 --- a/sk.c +++ b/sk.c @@ -200,6 +200,71 @@ failed: return -1; } +int sk_get_if_info(const char *name, struct sk_if_info *if_info) +{ +#ifdef ETHTOOL_GLINKSETTINGS + struct ifreq ifr; + int fd, err; + + struct { + struct ethtool_link_settings req; + __u32 link_mode_data[3 * 127]; + } ecmd; + + memset(, 0, sizeof(ifr)); + memset(, 0, sizeof(ecmd)); + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + goto failed; + } + + ecmd.req.cmd = ETHTOOL_GLINKSETTINGS; + + strncpy(ifr.ifr_name, name, IFNAMSIZ - 1); + ifr.ifr_data = (char *) + + /* Handshake with kernel to determine number of words for link +* mode bitmaps. When requested number of bitmap words is not +* the one expected by kernel, the latter returns the integer +* opposite of what it is expecting. We request length 0 below +* (aka. invalid bitmap length) to get this info. +*/ + err = ioctl(fd, SIOCETHTOOL, ); + if (err < 0) { + pr_err("ioctl SIOCETHTOOL failed: %m"); + close(fd); + goto failed; + } + + if (ecmd.req.link_mode_masks_nwords >= 0 || + ecmd.req.cmd != ETHTOOL_GLINKSETTINGS) { + return 1; + } + ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords; + + err = ioctl(fd, SIOCETHTOOL, ); + if (err < 0) { + pr_err("ioctl SIOCETHTOOL failed: %m"); + close(fd); + goto failed; + } + + close(fd); + + /* copy the necessary data to sk_info */ + memset(if_info, 0, sizeof(struct sk_if_info)); + if_info->valid = 1; + if_info->speed = ecmd.req.speed; + + return 0; +failed: +#endif + /* clear data and ensure it is not marked valid */ + memset(if_info, 0, sizeof(struct sk_if_info)); + return -1; +} + static int sk_interface_guidaddr(const char *name, unsigned char *guid) { char file_name[64], buf[64], addr[8]; diff --git a/sk.h b/sk.h index 486dbc4..853aadf 100644 --- a/sk.h +++ b/sk.h @@ -49,6 +49,16 @@ struct sk_ts_info { unsigned int rx_filters; }; +/** + * Contains interface information returned by theGLINKSETTINGS ioctl. + * @valid:set to non-zero when the info struct contains valid data. + * @speed:interface speed. + */ +struct sk_if_info { + int valid; + int speed; +}; + /** * Obtains a socket suitable for use with sk_interface_index(). * @return An open socket on success, -1 otherwise. @@ -78,6 +88,14 @@ int sk_general_init(int fd); */ int sk_get_ts_info(const char *name, struct sk_ts_info *sk_info); +/** + * Obtain supporte interface information + * @param name The name of the interface + * @param info Struct containing obtained interface information. + * @return zero on success, negative on failure. + */ +int sk_get_if_info(const char *name, struct sk_if_info *sk_info); + /** * Obtain the MAC address of a network interface. * @param name The name of the interface -- 2.17.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH 1/3] [Interface Rate TLV] function to support get interface speed via ethtool
When master and slave instance interacting with each other operating at different interface speed, delay assymetry needs to be compensated as described in G.8271 appendix V. In this patch we are adding changes to get the interface speed using ethtool. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- sk.c | 65 sk.h | 18 + 2 files changed, 83 insertions(+) diff --git a/sk.c b/sk.c index b55d6b5..6a0fc5e 100644 --- a/sk.c +++ b/sk.c @@ -200,6 +200,71 @@ failed: return -1; } +int sk_get_if_info(const char *name, struct sk_if_info *if_info) +{ +#ifdef ETHTOOL_GLINKSETTINGS + struct ifreq ifr; + int fd, err; + + struct { + struct ethtool_link_settings req; + __u32 link_mode_data[3 * 127]; + } ecmd; + + memset(, 0, sizeof(ifr)); + memset(, 0, sizeof(ecmd)); + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + goto failed; + } + + ecmd.req.cmd = ETHTOOL_GLINKSETTINGS; + + strncpy(ifr.ifr_name, name, IFNAMSIZ - 1); + ifr.ifr_data = (char *) + + /* Handshake with kernel to determine number of words for link +* mode bitmaps. When requested number of bitmap words is not +* the one expected by kernel, the latter returns the integer +* opposite of what it is expecting. We request length 0 below +* (aka. invalid bitmap length) to get this info. +*/ + err = ioctl(fd, SIOCETHTOOL, ); + if (err < 0) { + pr_err("ioctl SIOCETHTOOL failed: %m"); + close(fd); + goto failed; + } + + if (ecmd.req.link_mode_masks_nwords >= 0 || + ecmd.req.cmd != ETHTOOL_GLINKSETTINGS) { + return 1; + } + ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords; + + err = ioctl(fd, SIOCETHTOOL, ); + if (err < 0) { + pr_err("ioctl SIOCETHTOOL failed: %m"); + close(fd); + goto failed; + } + + close(fd); + + /* copy the necessary data to sk_info */ + memset(if_info, 0, sizeof(struct sk_if_info)); + if_info->valid = 1; + if_info->speed = ecmd.req.speed; + + return 0; +failed: +#endif + /* clear data and ensure it is not marked valid */ + memset(if_info, 0, sizeof(struct sk_if_info)); + return -1; +} + static int sk_interface_guidaddr(const char *name, unsigned char *guid) { char file_name[64], buf[64], addr[8]; diff --git a/sk.h b/sk.h index 486dbc4..853aadf 100644 --- a/sk.h +++ b/sk.h @@ -49,6 +49,16 @@ struct sk_ts_info { unsigned int rx_filters; }; +/** + * Contains interface information returned by theGLINKSETTINGS ioctl. + * @valid:set to non-zero when the info struct contains valid data. + * @speed:interface speed. + */ +struct sk_if_info { + int valid; + int speed; +}; + /** * Obtains a socket suitable for use with sk_interface_index(). * @return An open socket on success, -1 otherwise. @@ -78,6 +88,14 @@ int sk_general_init(int fd); */ int sk_get_ts_info(const char *name, struct sk_ts_info *sk_info); +/** + * Obtain supporte interface information + * @param name The name of the interface + * @param info Struct containing obtained interface information. + * @return zero on success, negative on failure. + */ +int sk_get_if_info(const char *name, struct sk_if_info *sk_info); + /** * Obtain the MAC address of a network interface. * @param name The name of the interface -- 2.17.1 ___ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel
[Linuxptp-devel] [PATCH] Inclusion of a virtual PTP port on a PTP clock
As per G.8275 (Annex-B) including virtual PTP ports on a PTP clock. This virtual port will be used to support APTS, IWF between different clock_domains. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Vipin Sharma Signed-off-by: Devasish Dey --- makefile | 6 +-- vport.c | 136 +++ vport.h | 20 3 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 vport.c create mode 100644 vport.h diff --git a/makefile b/makefile index 5295b60..cd1f3ef 100644 --- a/makefile +++ b/makefile @@ -25,7 +25,7 @@ LDLIBS= -lm -lrt -pthread $(EXTRA_LDFLAGS) PRG= ptp4l hwstamp_ctl nsm phc2sys phc_ctl pmc timemaster ts2phc FILTERS= filter.o mave.o mmedian.o SERVOS = linreg.o ntpshm.o nullf.o pi.o servo.o -TRANSP = raw.o transport.o udp.o udp6.o uds.o +TRANSP = raw.o transport.o udp.o udp6.o uds.o vport.o TS2PHC = ts2phc.o lstab.o nmea.o serial.o sock.o ts2phc_generic_pps_source.o \ ts2phc_nmea_pps_source.o ts2phc_phc_pps_source.o ts2phc_pps_sink.o ts2phc_pps_source.o OBJ= bmc.o clock.o clockadj.o clockcheck.o config.o designated_fsm.o \ @@ -68,8 +68,8 @@ phc_ctl: phc_ctl.o phc.o sk.o util.o clockadj.o sysoff.o print.o version.o timemaster: phc.o print.o rtnl.o sk.o timemaster.o util.o version.o -ts2phc: config.o clockadj.o hash.o interface.o phc.o print.o $(SERVOS) sk.o \ - $(TS2PHC) util.o version.o +ts2phc: config.o clockadj.o hash.o msg.o tlv.o interface.o phc.o print.o $(SERVOS) sk.o \ + $(TS2PHC) $(TRANSP) util.o version.o version.o: .version version.sh $(filter-out version.d,$(DEPEND)) diff --git a/vport.c b/vport.c new file mode 100644 index 000..58241ea --- /dev/null +++ b/vport.c @@ -0,0 +1,136 @@ +/** + * @file vport.c + * @note Copyright (C) 2022 SyncMonk Technologies + * @note SPDX-License-Identifier: GPL-2.0+ + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "address.h" +#include "contain.h" +#include "print.h" +#include "transport_private.h" +#include "vport.h" + +#define VPORT_FILEMODE (0660) /*0660*/ + +struct vport { + struct transport t; + struct address address; +}; + +static int vport_close(struct transport *t, struct fdarray *fda) +{ + struct sockaddr_un sa; + socklen_t len = sizeof(sa); + + if (!getsockname(fda->fd[FD_GENERAL], (struct sockaddr *) , ) && + sa.sun_family == AF_LOCAL) { + unlink(sa.sun_path); + } + + close(fda->fd[FD_GENERAL]); + return 0; +} + +static int vport_open(struct transport *t, struct interface *iface, struct fdarray *fda, + enum timestamp_type tt) +{ + char *vport_path = config_get_string(t->cfg, NULL, "vport_address"); + struct vport *vport = container_of(t, struct vport, t); + const char *name = interface_name(iface); + struct sockaddr_un sa; + int fd, err; + + fd = socket(AF_LOCAL, SOCK_DGRAM, 0); + if (fd < 0) { + pr_err("vport: failed to create socket: %m"); + return -1; + } + memset(, 0, sizeof(sa)); + sa.sun_family = AF_LOCAL; + strncpy(sa.sun_path, name, sizeof(sa.sun_path) - 1); + + unlink(name); + + err = bind(fd, (struct sockaddr *) , sizeof(sa)); + if (err < 0) { + pr_err("vport: bind failed: %m"); + close(fd); + return -1; + } + + /* For client use, pre load the server path. */ + memset(, 0, sizeof(sa)); + sa.sun_family = AF_LOCAL; + strncpy(sa.sun_path, vport_path, sizeof(sa.sun_path) - 1); + vport->address.sun = sa; + vport->address.len = sizeof(sa); + + chmod(name, VPORT_FILEMODE); + fda->fd[FD_EVENT] = -1; + fda->fd[FD_GENERAL] = fd; + return 0; +} + +static int vport_recv(struct transport *t, int fd, void *buf, int buflen, + struct address *addr, struct hw_timestamp *hwts) +{ + int cnt; + struct vport *vport = container_of(t, struct vport, t); + + addr->len = sizeof(addr->sun); + cnt = recvfrom(fd, buf, buflen, 0, >sa, >len); + if (cnt <= 0) { + pr_err("vport: recvfrom failed: %m"); + return cnt; + } + vport->address = *addr; + return cnt; +} + +static int vport_send(struct transport *t, struct fdarray *fda, + enum transport_event event, int peer, void *buf, int buflen, + struct address *addr, struct hw_timestamp *hwts) +{ + int cnt, fd = fda->fd[FD_GENERAL]; + struct vport *vport = container_of(t, struct vport, t); + + if (!addr) + addr = >address; + + cnt = sendto(fd, buf, buflen, 0, >sa, addr->len); + if (
[Linuxptp-devel] [PATCH] (G.8275.2 Annex D) TLV support for interface rate
When master and slave instance interacting with each other operating at different interface speed, delay assymetry needs to be compensated as described in G.8271 appendix V. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- clock.c | 14 ++ clock.h | 14 ++ config.c| 1 + configs/default.cfg | 1 + interface.c | 50 ++ interface.h | 21 +++ pdt.h | 1 + port.c | 5 port_private.h | 1 + port_signaling.c| 34 sk.c| 65 + sk.h| 18 + tlv.c | 1 + tlv.h | 16 +++ unicast_service.c | 33 +++ 15 files changed, 275 insertions(+) diff --git a/clock.c b/clock.c index f808b35..695f818 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; @@ -1005,6 +1006,8 @@ struct clock *clock_create(enum clock_type type, struct config *config, rtnl_get_ts_device(interface_name(iface), ts_label); interface_set_label(iface, ts_label); interface_ensure_tslabel(iface); + /* Interface speed information */ + interface_get_ifinfo(iface); interface_get_tsinfo(iface); if (interface_tsinfo_valid(iface) && !interface_tsmodes_supported(iface, required_modes)) { @@ -1105,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; @@ -1716,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; @@ -2081,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..9b2738a 100644 --- a/clock.h +++ b/clock.h @@ -289,6 +289,13 @@ int clock_slave_only(struct clock *c); */ UInteger8 clock_max_steps_removed(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); + /** * Obtain the clock class threshold field from a clock's default data set. * @param c The clock instance. @@ -388,4 +395,11 @@ 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); + #endif diff --git a/config.c b/config.c index 6ba9996..0419423 100644 --- a/config.c +++ b/config.c @@ -266,6 +266,7 @@ struct config_item config_tab[] = { PORT_ITEM_INT("inhibit_delay_req", 0, 0, 1), PORT_ITEM_INT("inhibit_multicast_service", 0, 0, 1), GLOB_ITEM_INT("initial_delay", 0, 0, INT_MAX), + GLOB_ITEM_INT("interface_rate_tlv", 0, 0, 1), GLOB_ITEM_INT("kernel_leap", 1, 0, 1), GLOB_ITEM_STR("leapfile", NULL), PORT_ITEM_INT("logAnnounceInterval", 1, INT8_MIN, INT8_MAX), diff --git a/configs/default.cfg b/configs/default.cfg index 1b5b806..4c40a03 100644 --- a/configs/default.cfg +++ b/configs/default.cfg @@ -19,6 +19,7 @@ dscp_general 0 dataset_comparison ieee1588 G.8275.defaultDS.localPriority 128 maxStepsRemoved255 +interface_rate_tlv 0 # # Port Data Set # diff --git a/interface.c b/interface.c index 445a270..8559f62 100644 --- a/interface.c +++ b/interface.c @@ -12,6 +12,7 @@ struct interface { char name[MAX_IFNAME_SIZE + 1]; char ts_label[MAX_IFNAME_SIZE + 1]; struct sk_ts_info ts_info; + struct sk_if_info if_info; int vclock; }; @@ -46,6 +47,11 @@ int interface_get_tsinfo(struct interface *iface) return sk_get_ts_info(iface->ts_label, >ts_info); } +int interface_get_ifinfo(struct interface *iface) +{ + return
[Linuxptp-devel] [PATCH] G.8275.2 support for delay_mechanism NO_MECHANISM
As per IEEE1588-2019, Table 21 adding NO_MECHANISM support. In this case port does not implement the delay mechanism. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- clock.c | 4 +++- config.c | 1 + dm.h | 3 +++ port.c | 12 ++-- port.h | 7 +++ ptp4l.8 | 7 ++- ptp4l.c | 10 -- unicast_client.c | 11 --- 8 files changed, 46 insertions(+), 9 deletions(-) diff --git a/clock.c b/clock.c index f808b35..56adea7 100644 --- a/clock.c +++ b/clock.c @@ -1996,8 +1996,10 @@ static void handle_state_decision_event(struct clock *c) if (c->sanity_check) clockcheck_reset(c->sanity_check); tsproc_reset(c->tsproc, 1); - if (!tmv_is_zero(c->initial_delay)) + if (!tmv_is_zero(c->initial_delay) || (best && + port_delay_mechanism(best->port) == DM_NO_MECHANISM)) { tsproc_set_delay(c->tsproc, c->initial_delay); + } c->ingress_ts = tmv_zero(); c->path_delay = c->initial_delay; c->master_local_rr = 1.0; diff --git a/config.c b/config.c index 6ba9996..b5cf397 100644 --- a/config.c +++ b/config.c @@ -171,6 +171,7 @@ static struct config_enum delay_mech_enu[] = { { "Auto", DM_AUTO }, { "E2E", DM_E2E }, { "P2P", DM_P2P }, + { "NONE", DM_NO_MECHANISM }, { NULL, 0 }, }; diff --git a/dm.h b/dm.h index 2491c63..47bd847 100644 --- a/dm.h +++ b/dm.h @@ -33,6 +33,9 @@ enum delay_mechanism { /** Peer delay mechanism. */ DM_P2P, + + /** No Delay Mechanism. */ + DM_NO_MECHANISM = 0xFE, }; #endif diff --git a/port.c b/port.c index d9dac38..4ec7a02 100644 --- a/port.c +++ b/port.c @@ -1195,7 +1195,7 @@ int port_set_announce_tmo(struct port *p) int port_set_delay_tmo(struct port *p) { - if (p->inhibit_delay_req) { + if (p->inhibit_delay_req || p->delayMechanism == DM_NO_MECHANISM) { return 0; } @@ -2031,7 +2031,10 @@ static int process_delay_req(struct port *p, struct ptp_message *m) return 0; } - if (p->delayMechanism == DM_P2P) { + if (p->delayMechanism == DM_NO_MECHANISM) { + pr_warning("port %hu: delay request not supported", portnum(p)); + return 0; + } else if (p->delayMechanism == DM_P2P) { pr_warning("%s: delay request on P2P port", p->log_name); return 0; } @@ -3383,6 +3386,11 @@ enum port_state port_state(struct port *port) return port->state; } +enum delay_mechanism port_delay_mechanism(struct port *port) +{ + return port->delayMechanism; +} + int port_state_update(struct port *p, enum fsm_event event, int mdiff) { enum port_state next = p->state_machine(p->state, event, mdiff); diff --git a/port.h b/port.h index 37a4e19..4854698 100644 --- a/port.h +++ b/port.h @@ -227,6 +227,13 @@ struct ptp_message *port_signaling_construct(struct port *p, */ enum port_state port_state(struct port *port); +/** + * Return port's delay mechanism method. + * @param port A port instance. + * @return one of the @ref delay_mechanism values. + */ +enum delay_mechanism port_delay_mechanism(struct port *port); + /** * Update a port's current state based on a given event. * @param pA pointer previously obtained via port_open(). diff --git a/ptp4l.8 b/ptp4l.8 index e33454a..d0a8cff 100644 --- a/ptp4l.8 +++ b/ptp4l.8 @@ -42,6 +42,11 @@ port using the E2E mechanism. Select the peer delay (P2P) mechanism. A warning will be printed when a delay request is received on port using the P2P mechanism. .TP +.B \-N +Select the NONE mechanism. The PTP port does not support delay mechanism. +This is used when PTP instance supports only frequency transfer or path delay +is neglected by the PTP instance. +.TP .B \-2 Select the IEEE 802.3 network transport. .TP @@ -245,7 +250,7 @@ the fault be reset immediately. The default is 16 seconds. .TP .B delay_mechanism -Select the delay mechanism. Possible values are E2E, P2P and Auto. +Select the delay mechanism. Possible values are E2E, P2P, NONE and Auto. The default is E2E. .TP .B hybrid_e2e diff --git a/ptp4l.c b/ptp4l.c index c61175b..de04bb9 100644 --- a/ptp4l.c +++ b/ptp4l.c @@ -43,7 +43,8 @@ static void usage(char *progname) " Delay Mechanism\n\n" " -AAuto, starting with E2E\n" " -EE2E, delay request-response (default)\n" - " -PP2P, peer delay mechanism\n\n" + " -PP2P, peer delay mechanism\n" + " -NNO_MECHANISM, no mechanism\n\n" " Network Transport\n\n" " -2IEEE 802.3\n" " -4
[Linuxptp-devel] [PATCH] G.8275.2 support for delay_mechanism NO_MECHANISM
As per IEEE1588-2019, Table 21 adding NO_MECHANISM support. In this case port does not implement the delay mechanism. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- clock.c | 4 +++- config.c | 15 --- dm.h | 3 +++ port.c | 12 ++-- port.h | 7 +++ ptp4l.8 | 15 ++- ptp4l.c | 10 -- unicast_client.c | 11 --- 8 files changed, 57 insertions(+), 20 deletions(-) diff --git a/clock.c b/clock.c index f808b35..1c68071 100644 --- a/clock.c +++ b/clock.c @@ -1996,8 +1996,10 @@ static void handle_state_decision_event(struct clock *c) if (c->sanity_check) clockcheck_reset(c->sanity_check); tsproc_reset(c->tsproc, 1); - if (!tmv_is_zero(c->initial_delay)) + if (!tmv_is_zero(c->initial_delay) || (best && + port_delay_mechanism(best->port) == DM_NONE)) { tsproc_set_delay(c->tsproc, c->initial_delay); + } c->ingress_ts = tmv_zero(); c->path_delay = c->initial_delay; c->master_local_rr = 1.0; diff --git a/config.c b/config.c index 6ba9996..b30d22e 100644 --- a/config.c +++ b/config.c @@ -168,9 +168,10 @@ static struct config_enum delay_filter_enu[] = { }; static struct config_enum delay_mech_enu[] = { - { "Auto", DM_AUTO }, - { "E2E", DM_E2E }, - { "P2P", DM_P2P }, + { "Auto", DM_AUTO }, + { "E2E", DM_E2E }, + { "P2P", DM_P2P }, + { "NO_MECHANISM", DM_NONE }, { NULL, 0 }, }; @@ -205,10 +206,10 @@ static struct config_enum timestamping_enu[] = { }; static struct config_enum tsproc_enu[] = { - { "filter",TSPROC_FILTER}, - { "raw", TSPROC_RAW }, - { "filter_weight", TSPROC_FILTER_WEIGHT }, - { "raw_weight",TSPROC_RAW_WEIGHT}, + { "filter",TSPROC_FILTER}, + { "raw", TSPROC_RAW }, + { "filter_weight", TSPROC_FILTER_WEIGHT }, + { "raw_weight",TSPROC_RAW_WEIGHT}, { NULL, 0 }, }; diff --git a/dm.h b/dm.h index 2491c63..9f76915 100644 --- a/dm.h +++ b/dm.h @@ -33,6 +33,9 @@ enum delay_mechanism { /** Peer delay mechanism. */ DM_P2P, + + /** No Delay Mechanism. */ + DM_NONE = 0xFE, }; #endif diff --git a/port.c b/port.c index d9dac38..3d5cb41 100644 --- a/port.c +++ b/port.c @@ -1195,7 +1195,7 @@ int port_set_announce_tmo(struct port *p) int port_set_delay_tmo(struct port *p) { - if (p->inhibit_delay_req) { + if (p->inhibit_delay_req || p->delayMechanism == DM_NONE) { return 0; } @@ -2031,7 +2031,10 @@ static int process_delay_req(struct port *p, struct ptp_message *m) return 0; } - if (p->delayMechanism == DM_P2P) { + if (p->delayMechanism == DM_NONE) { + pr_warning("port %hu: delay request not supported", portnum(p)); + return 0; + } else if (p->delayMechanism == DM_P2P) { pr_warning("%s: delay request on P2P port", p->log_name); return 0; } @@ -3383,6 +3386,11 @@ enum port_state port_state(struct port *port) return port->state; } +enum delay_mechanism port_delay_mechanism(struct port *port) +{ + return port->delayMechanism; +} + int port_state_update(struct port *p, enum fsm_event event, int mdiff) { enum port_state next = p->state_machine(p->state, event, mdiff); diff --git a/port.h b/port.h index 37a4e19..4854698 100644 --- a/port.h +++ b/port.h @@ -227,6 +227,13 @@ struct ptp_message *port_signaling_construct(struct port *p, */ enum port_state port_state(struct port *port); +/** + * Return port's delay mechanism method. + * @param port A port instance. + * @return one of the @ref delay_mechanism values. + */ +enum delay_mechanism port_delay_mechanism(struct port *port); + /** * Update a port's current state based on a given event. * @param pA pointer previously obtained via port_open(). diff --git a/ptp4l.8 b/ptp4l.8 index e33454a..cdb9d42 100644 --- a/ptp4l.8 +++ b/ptp4l.8 @@ -42,6 +42,10 @@ port using the E2E mechanism. Select the peer delay (P2P) mechanism. A warning will be printed when a delay request is received on port using the P2P mechanism. .TP +.B \-N +The PTP port does not support delay mechanism. This is used when PTP instance +supports only frequency transfer or path delay is neglected by the PTP instance. +.TP .B \-2 Select the IEEE 802.3 network transport. .TP @@ -245,7 +249,8 @@ the fault be reset immediately. The default is 16 seconds. .TP .B delay_mechanism -Select the delay mechanism. Possible values are E2E, P2P and Auto. +Select the
[Linuxptp-devel] [PATCH] v1.1 G.8275.2 support for delay_mechanism NO_MECHANISM
As per IEEE1588-2019, Table 21 adding NO_MECHANISM support. In this case port does not implement the delay mechanism. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- config.c | 16 +--- dm.h | 3 +++ port.c | 7 +-- ptp4l.8 | 15 ++- ptp4l.c | 10 -- tsproc.c | 5 + tsproc.h | 1 + unicast_client.c | 11 --- 8 files changed, 49 insertions(+), 19 deletions(-) diff --git a/config.c b/config.c index 6ba9996..fe48b46 100644 --- a/config.c +++ b/config.c @@ -168,9 +168,10 @@ static struct config_enum delay_filter_enu[] = { }; static struct config_enum delay_mech_enu[] = { - { "Auto", DM_AUTO }, - { "E2E", DM_E2E }, - { "P2P", DM_P2P }, + { "Auto", DM_AUTO }, + { "E2E", DM_E2E }, + { "P2P", DM_P2P }, + { "NO_MECHANISM", DM_NO_MECHANISM }, { NULL, 0 }, }; @@ -205,10 +206,11 @@ static struct config_enum timestamping_enu[] = { }; static struct config_enum tsproc_enu[] = { - { "filter",TSPROC_FILTER}, - { "raw", TSPROC_RAW }, - { "filter_weight", TSPROC_FILTER_WEIGHT }, - { "raw_weight",TSPROC_RAW_WEIGHT}, + { "filter",TSPROC_FILTER}, + { "raw", TSPROC_RAW }, + { "filter_weight", TSPROC_FILTER_WEIGHT }, + { "raw_weight",TSPROC_RAW_WEIGHT}, + { "no_delay", TSPROC_NO_DELAY_MECHANISM}, { NULL, 0 }, }; diff --git a/dm.h b/dm.h index 2491c63..47bd847 100644 --- a/dm.h +++ b/dm.h @@ -33,6 +33,9 @@ enum delay_mechanism { /** Peer delay mechanism. */ DM_P2P, + + /** No Delay Mechanism. */ + DM_NO_MECHANISM = 0xFE, }; #endif diff --git a/port.c b/port.c index d9dac38..cba48ae 100644 --- a/port.c +++ b/port.c @@ -1195,7 +1195,7 @@ int port_set_announce_tmo(struct port *p) int port_set_delay_tmo(struct port *p) { - if (p->inhibit_delay_req) { + if (p->inhibit_delay_req || p->delayMechanism == DM_NO_MECHANISM) { return 0; } @@ -2031,7 +2031,10 @@ static int process_delay_req(struct port *p, struct ptp_message *m) return 0; } - if (p->delayMechanism == DM_P2P) { + if (p->delayMechanism == DM_NO_MECHANISM) { + pr_warning("port %hu: delay request not supported", portnum(p)); + return 0; + } else if (p->delayMechanism == DM_P2P) { pr_warning("%s: delay request on P2P port", p->log_name); return 0; } diff --git a/ptp4l.8 b/ptp4l.8 index e33454a..cdb9d42 100644 --- a/ptp4l.8 +++ b/ptp4l.8 @@ -42,6 +42,10 @@ port using the E2E mechanism. Select the peer delay (P2P) mechanism. A warning will be printed when a delay request is received on port using the P2P mechanism. .TP +.B \-N +The PTP port does not support delay mechanism. This is used when PTP instance +supports only frequency transfer or path delay is neglected by the PTP instance. +.TP .B \-2 Select the IEEE 802.3 network transport. .TP @@ -245,7 +249,8 @@ the fault be reset immediately. The default is 16 seconds. .TP .B delay_mechanism -Select the delay mechanism. Possible values are E2E, P2P and Auto. +Select the delay mechanism. Possible values are E2E, P2P, NO_MECHANISM +and Auto. The default is E2E. .TP .B hybrid_e2e @@ -338,10 +343,10 @@ smaller than this value the port is marked as not 802.1AS capable. .TP .B tsproc_mode Select the time stamp processing mode used to calculate offset and delay. -Possible values are filter, raw, filter_weight, raw_weight. Raw modes perform -well when the rate of sync messages (logSyncInterval) is similar to the rate of -delay messages (logMinDelayReqInterval or logMinPdelayReqInterval). Weighting -is useful with larger network jitters (e.g. software time stamping). +Possible values are filter, raw, filter_weight, raw_weight, no_delay. Raw modes +perform well when the rate of sync messages (logSyncInterval) is similar to the +rate of delay messages (logMinDelayReqInterval or logMinPdelayReqInterval). +Weighting is useful with larger network jitters (e.g. software time stamping). The default is filter. .TP .B delay_filter diff --git a/ptp4l.c b/ptp4l.c index c61175b..1763c6a 100644 --- a/ptp4l.c +++ b/ptp4l.c @@ -43,7 +43,8 @@ static void usage(char *progname) " Delay Mechanism\n\n" " -AAuto, starting with E2E\n" " -EE2E, delay request-response (default)\n" - " -PP2P, peer delay mechanism\n\n" + " -PP2P, peer delay mechanism\n" + " -NNO_MECHANISM, no mechanism\n" " Network Transport\n\n" " -2IEEE 802.3\n" " -4
[Linuxptp-devel] [PATCH] G.8275.2 support for delay_mechanism NO_MECHANISM
As per IEEE1588-2019, Table 21 adding NO_MECHANISM support. In this case port does not implement the delay mechanism. Signed-off-by: Greg Armstrong Signed-off-by: Leon Goldin Signed-off-by: Devasish Dey Signed-off-by: Vipin Sharma --- config.c | 16 +--- dm.h | 3 +++ port.c | 7 +-- ptp4l.c | 8 +++- tsproc.c | 5 + tsproc.h | 1 + unicast_client.c | 11 --- 7 files changed, 38 insertions(+), 13 deletions(-) diff --git a/config.c b/config.c index 6ba9996..fe48b46 100644 --- a/config.c +++ b/config.c @@ -168,9 +168,10 @@ static struct config_enum delay_filter_enu[] = { }; static struct config_enum delay_mech_enu[] = { - { "Auto", DM_AUTO }, - { "E2E", DM_E2E }, - { "P2P", DM_P2P }, + { "Auto", DM_AUTO }, + { "E2E", DM_E2E }, + { "P2P", DM_P2P }, + { "NO_MECHANISM", DM_NO_MECHANISM }, { NULL, 0 }, }; @@ -205,10 +206,11 @@ static struct config_enum timestamping_enu[] = { }; static struct config_enum tsproc_enu[] = { - { "filter",TSPROC_FILTER}, - { "raw", TSPROC_RAW }, - { "filter_weight", TSPROC_FILTER_WEIGHT }, - { "raw_weight",TSPROC_RAW_WEIGHT}, + { "filter",TSPROC_FILTER}, + { "raw", TSPROC_RAW }, + { "filter_weight", TSPROC_FILTER_WEIGHT }, + { "raw_weight",TSPROC_RAW_WEIGHT}, + { "no_delay", TSPROC_NO_DELAY_MECHANISM}, { NULL, 0 }, }; diff --git a/dm.h b/dm.h index 2491c63..47bd847 100644 --- a/dm.h +++ b/dm.h @@ -33,6 +33,9 @@ enum delay_mechanism { /** Peer delay mechanism. */ DM_P2P, + + /** No Delay Mechanism. */ + DM_NO_MECHANISM = 0xFE, }; #endif diff --git a/port.c b/port.c index d9dac38..cba48ae 100644 --- a/port.c +++ b/port.c @@ -1195,7 +1195,7 @@ int port_set_announce_tmo(struct port *p) int port_set_delay_tmo(struct port *p) { - if (p->inhibit_delay_req) { + if (p->inhibit_delay_req || p->delayMechanism == DM_NO_MECHANISM) { return 0; } @@ -2031,7 +2031,10 @@ static int process_delay_req(struct port *p, struct ptp_message *m) return 0; } - if (p->delayMechanism == DM_P2P) { + if (p->delayMechanism == DM_NO_MECHANISM) { + pr_warning("port %hu: delay request not supported", portnum(p)); + return 0; + } else if (p->delayMechanism == DM_P2P) { pr_warning("%s: delay request on P2P port", p->log_name); return 0; } diff --git a/ptp4l.c b/ptp4l.c index c61175b..3e88e87 100644 --- a/ptp4l.c +++ b/ptp4l.c @@ -43,7 +43,8 @@ static void usage(char *progname) " Delay Mechanism\n\n" " -AAuto, starting with E2E\n" " -EE2E, delay request-response (default)\n" - " -PP2P, peer delay mechanism\n\n" + " -PP2P, peer delay mechanism\n" + " -NNO_MECHANISM, no mechanism\n" " Network Transport\n\n" " -2IEEE 802.3\n" " -4UDP IPV4 (default)\n" @@ -108,6 +109,11 @@ int main(int argc, char *argv[]) if (config_set_int(cfg, "delay_mechanism", DM_P2P)) goto out; break; + case 'N': + if (config_set_int(cfg, + "delay_mechanism", DM_NO_MECHANISM)) + goto out; + break; case '2': if (config_set_int(cfg, "network_transport", TRANS_IEEE_802_3)) diff --git a/tsproc.c b/tsproc.c index a871049..feb0ea5 100644 --- a/tsproc.c +++ b/tsproc.c @@ -52,6 +52,7 @@ static int weighting(struct tsproc *tsp) switch (tsp->mode) { case TSPROC_FILTER: case TSPROC_RAW: + case TSPROC_NO_DELAY_MECHANISM: return 0; case TSPROC_FILTER_WEIGHT: case TSPROC_RAW_WEIGHT: @@ -74,6 +75,7 @@ struct tsproc *tsproc_create(enum tsproc_mode mode, case TSPROC_RAW: case TSPROC_FILTER_WEIGHT: case TSPROC_RAW_WEIGHT: + case TSPROC_NO_DELAY_MECHANISM: tsp->mode = mode; break; default: @@ -171,6 +173,7 @@ int tsproc_update_delay(struct tsproc *tsp, tmv_t *delay) break; case TSPROC_RAW: case TSPROC_RAW_WEIGHT: + case TSPROC_NO_DELAY_MECHANISM: *delay = raw_delay; break; } @@ -207,6 +210,8 @@ int tsproc_update_offset(struct tsproc *tsp, tmv_t *offset, double *weight) raw_delay = get_raw_delay(tsp); delay = tsp->filtered_delay;
[Linuxptp-devel] [PATCH] Adding following features to support Telecom profile G.8275.2
From: SyncMonk 1. Inclusion of virtual PTP port on a PTP clock. (G.8275 Annex B) 2. Alternate master support (G.8275.2 Section 6.9 and G.8275.2 Appendix III) 3. TLV support for interface rate (G.8275.2 Annex D) When master and slave instance interacting with each other operating at different interface speed, delay assymetry needs to be compensated as described in G.8271 appendix V. 4. Delay mechanism As per IEEE1588-2019, Table 21 adding NO_MECHANISM support. In this case port does not implement the delay mechanism. 5. Packet Timing Signal Fail (PTSF)(G.8275.2 Section 6.7.11) - PTSF-lossSync signal raised due to lack of reception of PTP Sycn, Followup or delay response messages - PTSF-unusable unusable PTP packet timing signal received by the request-port, exceeding the input tolerance of the request-port 6. Dynamic data set updates for external servo. - defaultDS.clockQuality.clockClass To support holdover in the T-BC-P/A and T-GM. - timePropertiesDS.frequencyTraceable To support availability of a PRC-traceable physical layer frequency input signal - PTSF Unusable. Signed-off-by: Greg Armstrong ; Signed-off-by: Vipin Sharma ; Signed-off-by: Devasish Dey ; Signed-off-by: Leon Goldin --- clock.c | 77 ++- clock.h | 23 config.c| 30 - configs/default.cfg | 3 + dm.h| 18 +++ ds.h| 17 +++ interface.c | 58 interface.h | 29 makefile| 8 +- monitor.c | 71 ++ monitor.h | 3 + msg.h | 17 +++ pdt.h | 9 ++ pmc.c | 69 +- pmc_common.c| 29 port.c | 194 +++ port_private.h | 16 ++- port_signaling.c| 41 ++ ptp4l.8 | 11 +- ptp4l.c | 19 ++- sk.c| 74 +++ sk.h| 26 tlv.c | 48 +++ tlv.h | 54 transport.c | 12 ++ transport.h | 9 ++ ts2phc_phc_pps_source.c | 24 ts2phc_phc_pps_source.h | 4 + ts2phc_pps_sink.c | 14 +- ts2phc_vport.c | 288 ts2phc_vport.h | 31 + tsproc.c| 13 ++ tsproc.h| 9 ++ unicast_client.c| 18 ++- unicast_service.c | 41 +- util.c | 9 ++ vport.c | 142 vport.h | 26 38 files changed, 1530 insertions(+), 54 deletions(-) create mode 100644 ts2phc_vport.c create mode 100644 ts2phc_vport.h create mode 100644 vport.c create mode 100644 vport.h diff --git a/clock.c b/clock.c index f808b35..2e854d8 100644 --- a/clock.c +++ b/clock.c @@ -15,6 +15,14 @@ * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * @note Copyright (C) 2022 SyncMonk Technologies + * Also, for each author's protection and ours, we want to make certain that + * everyone understands that there is no warranty for this free software. + * If the software is modified by someone else and passed on, we want its + * recipients to know that what they have is not the original, so that any + * problems introduced by others will not reflect on the original authors' + * reputations. */ #include #include @@ -43,6 +51,7 @@ #include "tlv.h" #include "tsproc.h" #include "uds.h" +#include "vport.h" #include "util.h" #define N_CLOCK_PFD (N_POLLFD + 1) /* one extra per port, for the fault timer */ @@ -97,9 +106,10 @@ struct clock { LIST_HEAD(ports_head, port) ports; struct port *uds_rw_port; struct port *uds_ro_port; + struct port *vport_port; struct pollfd *pollfd; int pollfd_valid; - int nports; /* does not include the two UDS ports */ + int nports; /* does not include the two UDS ports + 1 Virtual Port */ int last_port_number; int sde; int free_running; @@ -133,10 +143,12 @@ struct clock { struct clockcheck *sanity_check; struct interface *uds_rw_if; struct interface *uds_ro_if; + struct interface *vport_if; LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers; struct monitor *slave_event_monitor; int step_window_counter; int step_window; + bool interface_rate_tlv_support; }; struct clock the_clock; @@ -272,6 +284,7 @@ void clock_destroy(struct clock *c) interface_destroy(c->uds_rw_if); interfa