Thread: [Linuxptp-devel] [RFC PATCH v1 0/8] Common Mean Link Delay Service (CMLDS)
PTP IEEE 1588 stack for Linux
Brought to you by:
rcochran
From: Kishen M. <kis...@in...> - 2023-03-20 02:37:18
|
This patch series presents a functional implementation of the Common Mean Link Delay Service (CMLDS). CMLDS is optional in IEEE 1588-2019/clause 16.6, and mandatory in the IEEE 802.1AS-2020 PTP Profile/clause 11.2.17 for time-aware systems that implement multiple domains. Accordingly, this implementation draws upon both standards documents. A gPTP domain 0 ptp4l instance may be configured to expose CMLDS over one or more links and queried by other gPTP domains (ptp4l instances) on its node to retrieve link delay measurements using the COMMON_P2P delay mechanism. Communications between the ptp4l instances is facilitated by the UDS. Note: We are currently working towards Avnu test compliance for this feature. Summary: * CMLDS is enabled and accessed by ptp4l instances through settings in their respective config files. * A per-port 'run_cmlds' setting exposes CMLDS on a Link Port in a ptp4l instance which consequently executes CMLDS Pdelay transactions using transportSpecific/majorSdoId of 0x2 and domainNumber=0 over its link. The PTP Port continues to respond to PdelayReqs in its domain. * A per-port 'cmlds_portNumber' setting assigns a CMLDS Link Port portNumber that is used to identify a CMLDS Link Port. * A global 'cmlds_clockIdentity' setting assigns a unique clockIdentity for CMLDS in ptp4l instances with one or more CMLDS Link Ports. * A new management TLV: MID_CMLDS_INFO_NP for CMLDS Link Ports to convey link delay measurements to requesting PTP Ports. * A per-port 'cmlds_uds_address' setting in PTP Ports (which query the CMLDS) is used to specify the 'uds_address' of the ptp4l instance that exposes the CMLDS Link Port. You may test as below on two PTP nodes (1, 2): * Bring up two ptp4l instances on node 1 (with 2 vclocks): * gPTP-cmlds.cfg configures a ptp4l instance for gPTP domain 0 with a single CMLDS Link Port. * gPTP-common-p2p.cfg configures a ptp4l instance for gPTP domain 1 with a single PTP Port that queries the CMLDS and uses the COMMON_P2P delay mechanism. * Specify the correct interface name and 'phc_index' (to the vclocks) in the config files. * Bring up two ptp4l instances as above on node 2. * In addition to the interface name and 'phc_index', modify 'cmlds_clockIdentity' in gPTP-cmlds.cfg, and 'clockIdentity' in gPTP-common-p2p.cfg so that they are distinct from node 1's configuration. #TODO: * Document the new configuration options in ptp4l.8. Andrew Zaborowski (1): Implement the COMMON_P2P delay mechanism Kishen Maloor (7): Add new TLV for CommonMeanLinkDelayInformation Add configuration options for CMLDS Add DM_COMMON_P2P Update the PdelayReq/Res flows for CMLDS Link Ports Add port_cmlds_ignore() Add plumbing for interacting with the CMLDS Sample config files for testing CMLDS clock.c | 11 +- clock.h | 6 + config.c | 5 + configs/gPTP-cmlds.cfg | 34 ++++ configs/gPTP-common-p2p.cfg | 35 ++++ dm.h | 3 + msg.h | 2 + pmc.c | 13 ++ pmc_common.c | 1 + port.c | 363 ++++++++++++++++++++++++++++++++++-- port.h | 8 + port_private.h | 8 + tlv.c | 18 ++ tlv.h | 11 ++ unicast_client.c | 10 +- 15 files changed, 508 insertions(+), 20 deletions(-) create mode 100644 configs/gPTP-cmlds.cfg create mode 100644 configs/gPTP-common-p2p.cfg base-commit: c4117705a96d1eaa89ac224559f217909dd6d882 -- 2.31.1 |
From: Kishen M. <kis...@in...> - 2023-05-15 22:26:28
|
This patch series presents a functional implementation of the Common Mean Link Delay Service (CMLDS). CMLDS is optional in IEEE 1588-2019/clause 16.6, and mandatory in the IEEE 802.1AS-2020 PTP Profile/clause 11.2.17 for time-aware systems that implement multiple domains. Accordingly, this implementation draws upon both standards documents. A gPTP domain 0 ptp4l instance may be configured to expose CMLDS over one or more links and queried by other gPTP domains (ptp4l instances) on its node to retrieve link delay measurements using the COMMON_P2P delay mechanism. Communications between the ptp4l instances for this query/response occurs over the UDS. Summary: * CMLDS is enabled and accessed by ptp4l instances through settings in their respective config files. * A per-port 'run_cmlds' option exposes CMLDS on a Link Port in a ptp4l instance which consequently executes CMLDS Pdelay transactions using transportSpecific/majorSdoId of 0x2 and domainNumber=0 over its link. The PTP Port continues to respond to PdelayReqs in its domain. * A per-port 'cmlds_portNumber' option assigns a CMLDS Link Port portNumber that is used to identify a CMLDS Link Port. * A global 'cmlds_clockIdentity' option assigns a unique clockIdentity for CMLDS in ptp4l instances with one or more CMLDS Link Ports. * A new management TLV: MID_CMLDS_INFO_NP for CMLDS Link Ports to convey link delay measurements to requesting PTP Ports over the UDS. * A per-port 'cmlds_uds_address' option in PTP Ports (which query the CMLDS) is used to specify the 'uds_address' of the ptp4l instance that exposes the target CMLDS Link Port. * The user is expected to appropriately configure the time-aware system with CMLDS to functional and standards compliance: CMLDS is enabled only once per physical port, CMLDS is exposed in gPTP domain 0 ptp4l instances, unique vclock assignments, domain and CMLDS clockIdentities, and uds_address for all ptp4l instances. You may test as below on two PTP nodes (1, 2): * Bring up two ptp4l instances on node 1 (with 2 vclocks): * gPTP-cmlds.cfg configures a ptp4l instance for gPTP domain 0 with a single CMLDS Link Port. * gPTP-common-p2p.cfg configures a ptp4l instance for gPTP domain 1 with a single PTP Port that queries the CMLDS and uses the COMMON_P2P delay mechanism. * Specify the correct interface name and 'phc_index' (to the vclocks) in the config files. * Bring up two ptp4l instances as above on node 2. * In addition to the interface name and 'phc_index', modify 'cmlds_clockIdentity' in gPTP-cmlds.cfg, and 'clockIdentity' in gPTP-common-p2p.cfg so that they are distinct from node 1's configuration. Patches 1-8 comprise the CMLDS implementation summarized above. Patch 9 is an independent change to make 'allowedLostResponses' a configurable parameter. This was to meet a general 802.1AS-2020 conformance requirement. --- v2: * Minor canges for Avnu test conformance. * Addressed v1 review comments received from Erez. * Documented newly added config file options in ptp4l.8. Andrew Zaborowski (1): Implement the COMMON_P2P delay mechanism Kishen Maloor (8): Add new TLV for CommonMeanLinkDelayInformation Add configuration options for CMLDS Add DM_COMMON_P2P Update the PdelayReq/Res flows for CMLDS Link Ports Add port_cmlds_ignore() Add plumbing for interacting with the CMLDS Sample config files for testing CMLDS Make allowedLostResponses configurable clock.c | 11 +- clock.h | 6 + config.c | 6 + configs/gPTP-cmlds.cfg | 34 ++++ configs/gPTP-common-p2p.cfg | 35 ++++ dm.h | 3 + msg.h | 2 + pmc.c | 13 ++ pmc_common.c | 1 + port.c | 372 ++++++++++++++++++++++++++++++++++-- port.h | 8 + port_private.h | 9 + ptp4l.8 | 28 +++ tlv.c | 18 ++ tlv.h | 11 ++ unicast_client.c | 10 +- 16 files changed, 542 insertions(+), 25 deletions(-) create mode 100644 configs/gPTP-cmlds.cfg create mode 100644 configs/gPTP-common-p2p.cfg -- 2.31.1 |
From: Kishen M. <kis...@in...> - 2023-05-15 22:26:29
|
This change adds COMMON_P2P (IEEE 802.1AS-2020, clause 14.8.5) to the enumeration of delay mechanisms and incorporates it into existing code paths pertaining to DM_P2P to (where appropriate) maintain parity with DM_P2P. Co-authored-by: Andrew Zaborowski <and...@in...> Signed-off-by: Kishen Maloor <kis...@in...> --- config.c | 1 + dm.h | 3 +++ port.c | 15 +++++++++------ unicast_client.c | 10 +++++++--- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/config.c b/config.c index 3e7587ba81ab..0482554feb28 100644 --- a/config.c +++ b/config.c @@ -173,6 +173,7 @@ static struct config_enum delay_mech_enu[] = { { "Auto", DM_AUTO }, { "E2E", DM_E2E }, { "P2P", DM_P2P }, + { "COMMON_P2P", DM_COMMON_P2P }, { "NONE", DM_NO_MECHANISM }, { NULL, 0 }, }; diff --git a/dm.h b/dm.h index 47bd8474ca0d..80d1ce551166 100644 --- a/dm.h +++ b/dm.h @@ -34,6 +34,9 @@ enum delay_mechanism { /** Peer delay mechanism. */ DM_P2P, + /** Peer delay as measured by CMLDS. */ + DM_COMMON_P2P, + /** No Delay Mechanism. */ DM_NO_MECHANISM = 0xFE, }; diff --git a/port.c b/port.c index 94ce037871f1..87780fd39caa 100644 --- a/port.c +++ b/port.c @@ -967,7 +967,8 @@ static int port_management_fill_response(struct port *target, ptp_text_copy(cd->userDescription, &desc->userDescription); buf += sizeof(struct PTPText) + cd->userDescription->length; - if (target->delayMechanism == DM_P2P) { + if (target->delayMechanism == DM_P2P || + target->delayMechanism == DM_COMMON_P2P) { memcpy(buf, profile_id_p2p, PROFILE_ID_LEN); } else { struct config *cfg = clock_config(target->clock); @@ -1291,7 +1292,7 @@ int port_set_delay_tmo(struct port *p) return 0; } - if (p->delayMechanism == DM_P2P) { + if (p->delayMechanism == DM_P2P || p->delayMechanism == DM_COMMON_P2P) { return set_tmo_log(p->fda.fd[FD_DELAY_TIMER], 1, p->logPdelayReqInterval); } else { @@ -2128,7 +2129,7 @@ static int process_delay_req(struct port *p, struct ptp_message *m) return 0; } - if (p->delayMechanism == DM_P2P) { + if (p->delayMechanism == DM_P2P || p->delayMechanism == DM_COMMON_P2P) { pr_warning("%s: delay request on P2P port", p->log_name); return 0; } @@ -2293,8 +2294,9 @@ int process_pdelay_req(struct port *p, struct ptp_message *m) return -1; } - if (p->delayMechanism == DM_E2E) { - pr_warning("%s: pdelay_req on E2E port", p->log_name); + if (p->delayMechanism == DM_E2E || + p->delayMechanism == DM_COMMON_P2P) { + pr_warning("%s: pdelay_req on E2E or COMMON_P2P port", p->log_name); return 0; } if (p->delayMechanism == DM_AUTO) { @@ -2756,7 +2758,7 @@ static void bc_dispatch(struct port *p, enum fsm_event event, int mdiff) return; } - if (p->delayMechanism == DM_P2P) { + if (p->delayMechanism == DM_P2P || p->delayMechanism == DM_COMMON_P2P) { port_p2p_transition(p, p->state); } else { port_e2e_transition(p, p->state); @@ -2895,6 +2897,7 @@ static enum fsm_event bc_event(struct port *p, int fd_index) delay_req_prune(p); if (clock_slave_only(p->clock) && p->delayMechanism != DM_P2P && + p->delayMechanism != DM_COMMON_P2P && port_renew_transport(p)) { return EV_FAULT_DETECTED; } diff --git a/unicast_client.c b/unicast_client.c index 0843554e355a..9053acc0b599 100644 --- a/unicast_client.c +++ b/unicast_client.c @@ -202,6 +202,7 @@ static int unicast_client_renew(struct port *p, goto out; } if (p->delayMechanism != DM_P2P && + p->delayMechanism != DM_COMMON_P2P && p->delayMechanism != DM_NO_MECHANISM) { err = attach_request(msg, p->logMinDelayReqInterval, DELAY_RESP, @@ -256,6 +257,7 @@ static int unicast_client_sydy(struct port *p, goto out; } if (p->delayMechanism != DM_P2P && + p->delayMechanism != DM_COMMON_P2P && p->delayMechanism != DM_NO_MECHANISM) { err = attach_request(msg, p->logMinDelayReqInterval, DELAY_RESP, p->unicast_req_duration); @@ -404,7 +406,8 @@ int unicast_client_initialize(struct port *p) pr_warning("%s: unicast master transport mismatch", p->log_name); } - if (p->delayMechanism == DM_P2P) { + if (p->delayMechanism == DM_P2P || + p->delayMechanism == DM_COMMON_P2P) { master->sydymsk = P2P_SYDY_MASK; } else if (p->delayMechanism == DM_NO_MECHANISM) { master->sydymsk = E2E_SY_MASK; @@ -463,7 +466,7 @@ void unicast_client_grant(struct port *p, struct ptp_message *m, pr_debug("%s: unicast %s granted for %u sec", p->log_name, msg_type_string(mtype), g->durationField); - if (p->delayMechanism == DM_P2P) { + if (p->delayMechanism == DM_P2P || p->delayMechanism == DM_COMMON_P2P) { switch (mtype) { case DELAY_RESP: return; @@ -579,7 +582,8 @@ int unicast_client_timer(struct port *p) err = unicast_client_renew(p, master); break; } - if (p->delayMechanism == DM_P2P) { + if (p->delayMechanism == DM_P2P || + p->delayMechanism == DM_COMMON_P2P) { unicast_client_peer_renew(p); } } -- 2.31.1 |
From: Richard C. <ric...@gm...> - 2023-11-16 04:54:08
|
On Mon, May 15, 2023 at 06:26:06PM -0400, Kishen Maloor wrote: > This change adds COMMON_P2P (IEEE 802.1AS-2020, clause 14.8.5) to the > enumeration of delay mechanisms and incorporates it into existing code > paths pertaining to DM_P2P to (where appropriate) maintain parity with > DM_P2P. > > Co-authored-by: Andrew Zaborowski <and...@in...> > Signed-off-by: Kishen Maloor <kis...@in...> > --- > config.c | 1 + > dm.h | 3 +++ > port.c | 15 +++++++++------ > unicast_client.c | 10 +++++++--- > 4 files changed, 20 insertions(+), 9 deletions(-) > > diff --git a/config.c b/config.c > index 3e7587ba81ab..0482554feb28 100644 > --- a/config.c > +++ b/config.c > @@ -173,6 +173,7 @@ static struct config_enum delay_mech_enu[] = { > { "Auto", DM_AUTO }, > { "E2E", DM_E2E }, > { "P2P", DM_P2P }, > + { "COMMON_P2P", DM_COMMON_P2P }, Preserve alphabetical order please. > { "NONE", DM_NO_MECHANISM }, > { NULL, 0 }, > }; |
From: Kishen M. <kis...@in...> - 2023-05-15 22:26:30
|
In a setup with multiple gPTP domains, the Common Mean Link Delay Service (CMLDS) (IEEE 1588/16.6.3) performs link delay measurements in a single domain and must (somehow) convey those to other domains. IEEE 1588 does not specify this interface and flags it as an implementation detail (IEEE 1588/16.6.1). Accordningly, this change introduces a new TLV to convey link delay measurements by the CMLDS over the management interface. In addition to the parameters suggested in IEEE 1588/16.6.3.2, the TLV also conveys the latest 'up measurements' (req and rx timestamps) recorded in the CMLDS. These values collectively aid other gPTP domains to complete their delay/offset computations via the COMMON_P2P delay mechanism. Updated 'pmc' to support the new MID, MID_CMLDS_INFO_NP. Co-authored-by: Andrew Zaborowski <and...@in...> Signed-off-by: Kishen Maloor <kis...@in...> --- clock.c | 1 - msg.h | 2 ++ pmc.c | 13 +++++++++++++ pmc_common.c | 1 + port.c | 22 ++++++++++++++++++++++ port_private.h | 2 ++ tlv.c | 18 ++++++++++++++++++ tlv.h | 11 +++++++++++ 8 files changed, 69 insertions(+), 1 deletion(-) diff --git a/clock.c b/clock.c index fe08d48ed8f8..c74a6baa9f61 100644 --- a/clock.c +++ b/clock.c @@ -47,7 +47,6 @@ #include "util.h" #define N_CLOCK_PFD (N_POLLFD + 1) /* one extra per port, for the fault timer */ -#define POW2_41 ((double)(1ULL << 41)) struct interface { STAILQ_ENTRY(interface) list; diff --git a/msg.h b/msg.h index cbd09e75a2aa..db12e249f89f 100644 --- a/msg.h +++ b/msg.h @@ -69,6 +69,8 @@ #define SIGNAL_NO_CHANGE -128 #define SIGNAL_SET_INITIAL 126 +#define POW2_41 ((double)(1ULL << 41)) + enum timestamp_type { TS_SOFTWARE, TS_HARDWARE, diff --git a/pmc.c b/pmc.c index 00e691f0c244..cac06fb5b41d 100644 --- a/pmc.c +++ b/pmc.c @@ -169,6 +169,7 @@ static void pmc_show(struct ptp_message *msg, FILE *fp) struct subscribe_events_np *sen; struct port_properties_np *ppn; struct port_hwclock_np *phn; + struct cmlds_info_np *cmlds; struct timePropertiesDS *tp; struct management_tlv *mgt; struct time_status_np *tsn; @@ -651,6 +652,18 @@ 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_CMLDS_INFO_NP: + cmlds = (struct cmlds_info_np *) mgt->data; + fprintf(fp, "CMLDS INFO " + IFMT "serviceMeasurementValid %i" + IFMT "meanLinkDelay %" PRId64 + IFMT "scaledNeighborRateRatio %" PRId32 + IFMT "egress_ts %" PRId64 + IFMT "rx_ts %" PRId64, + cmlds->serviceMeasurementValid, cmlds->meanLinkDelay, + cmlds->scaledNeighborRateRatio, + cmlds->egress_ts, cmlds->rx_ts); + break; } out: fprintf(fp, "\n"); diff --git a/pmc_common.c b/pmc_common.c index 9e251c43e95b..d7a6114dcd62 100644 --- a/pmc_common.c +++ b/pmc_common.c @@ -156,6 +156,7 @@ struct management_id idtab[] = { { "UNICAST_MASTER_TABLE_NP", MID_UNICAST_MASTER_TABLE_NP, do_get_action }, { "PORT_HWCLOCK_NP", MID_PORT_HWCLOCK_NP, do_get_action }, { "POWER_PROFILE_SETTINGS_NP", MID_POWER_PROFILE_SETTINGS_NP, do_set_action }, + { "CMLDS_INFO_NP", MID_CMLDS_INFO_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 8b2eb04a855a..d467a69e519a 100644 --- a/port.c +++ b/port.c @@ -887,6 +887,7 @@ static int port_management_fill_response(struct port *target, struct clock_description *desc; struct port_properties_np *ppn; struct port_hwclock_np *phn; + struct cmlds_info_np *cmlds; struct management_tlv *tlv; struct port_stats_np *psn; struct foreign_clock *fc; @@ -1129,6 +1130,27 @@ static int port_management_fill_response(struct port *target, memcpy(pwr, &target->pwr, sizeof(*pwr)); datalen = sizeof(*pwr); break; + case MID_CMLDS_INFO_NP: + cmlds = (struct cmlds_info_np *)tlv->data; + /* IEEE1588-2019 16.6.3.2 h) 1) && nrate.ratio_valid because + * we have no extra field to convey that separately. + */ + cmlds->serviceMeasurementValid = + target->peer_portid_valid && !target->pdr_missing && + !target->multiple_pdr_detected && + target->nrate.ratio_valid; + cmlds->meanLinkDelay = target->peerMeanPathDelay; + cmlds->scaledNeighborRateRatio = + (Integer32) (target->nrate.ratio * POW2_41 - POW2_41); + /* 16.6.3.2: "Upon receipt of a request for information, the + * Common Mean Link Delay Service may in addition return the + * raw measurement data gathered by the service for use in + * estimating the <meanLinkDelay> and <neighborRateRatio>." + */ + cmlds->egress_ts = tmv_to_nanoseconds(target->peer_delay_t1); + cmlds->rx_ts = tmv_to_nanoseconds(target->peer_delay_t2); + datalen = sizeof(*cmlds); + break; default: /* The caller should *not* respond to this message. */ tlv_extra_recycle(extra); diff --git a/port_private.h b/port_private.h index 3b02d2fe45c4..c9b02bc799f5 100644 --- a/port_private.h +++ b/port_private.h @@ -99,6 +99,8 @@ struct port { unsigned int pdr_missing; unsigned int multiple_seq_pdr_count; unsigned int multiple_pdr_detected; + tmv_t peer_delay_t1; + tmv_t peer_delay_t2; enum port_state (*state_machine)(enum port_state state, enum fsm_event event, int mdiff); int bmca; diff --git a/tlv.c b/tlv.c index 79400126cbc4..8b97d2cfc9f5 100644 --- a/tlv.c +++ b/tlv.c @@ -176,6 +176,7 @@ static int mgt_post_recv(struct management_tlv *m, uint16_t data_len, struct port_properties_np *ppn; struct port_hwclock_np *phn; struct timePropertiesDS *tp; + struct cmlds_info_np *cmlds; struct time_status_np *tsn; struct port_stats_np *psn; int extra_len = 0, i, len; @@ -490,6 +491,15 @@ static int mgt_post_recv(struct management_tlv *m, uint16_t data_len, if (data_len != 0) goto bad_length; break; + case MID_CMLDS_INFO_NP: + if (data_len < sizeof(struct cmlds_info_np)) + goto bad_length; + cmlds = (struct cmlds_info_np *)m->data; + net2host64_unaligned(&cmlds->meanLinkDelay); + NTOHL(cmlds->scaledNeighborRateRatio); + net2host64_unaligned(&cmlds->egress_ts); + net2host64_unaligned(&cmlds->rx_ts); + break; } if (extra_len) { if (extra_len % 2) @@ -514,6 +524,7 @@ static void mgt_pre_send(struct management_tlv *m, struct tlv_extra *extra) struct subscribe_events_np *sen; struct port_properties_np *ppn; struct port_hwclock_np *phn; + struct cmlds_info_np *cmlds; struct timePropertiesDS *tp; struct time_status_np *tsn; struct port_stats_np *psn; @@ -672,6 +683,13 @@ static void mgt_pre_send(struct management_tlv *m, struct tlv_extra *extra) HTONL(pwr->networkTimeInaccuracy); HTONL(pwr->totalTimeInaccuracy); break; + case MID_CMLDS_INFO_NP: + cmlds = (struct cmlds_info_np *)m->data; + host2net64_unaligned(&cmlds->meanLinkDelay); + HTONL(cmlds->scaledNeighborRateRatio); + host2net64_unaligned(&cmlds->egress_ts); + host2net64_unaligned(&cmlds->rx_ts); + break; } } diff --git a/tlv.h b/tlv.h index 8b51ffd88816..6446fc068488 100644 --- a/tlv.h +++ b/tlv.h @@ -130,6 +130,9 @@ enum management_action { #define MID_PORT_HWCLOCK_NP 0xC009 #define MID_POWER_PROFILE_SETTINGS_NP 0xC00A +/* CMLDS management ID values */ +#define MID_CMLDS_INFO_NP 0xC00B + /* Management error ID values */ #define MID_RESPONSE_TOO_BIG 0x0001 #define MID_NO_SUCH_ID 0x0002 @@ -473,6 +476,14 @@ struct msg_interface_rate_tlv { UInteger16 numberOfBitsAfterTimestamp; } PACKED; +struct cmlds_info_np { + Integer8 serviceMeasurementValid; + TimeInterval meanLinkDelay; + Integer32 scaledNeighborRateRatio; + Integer64 egress_ts; + Integer64 rx_ts; +} PACKED; + /** * Allocates a new tlv_extra structure. * @return Pointer to a new structure on success or NULL otherwise. -- 2.31.1 |
From: Richard C. <ric...@gm...> - 2023-11-16 04:32:07
|
On Mon, May 15, 2023 at 06:26:04PM -0400, Kishen Maloor wrote: > @@ -473,6 +476,14 @@ struct msg_interface_rate_tlv { > UInteger16 numberOfBitsAfterTimestamp; > } PACKED; > > +struct cmlds_info_np { > + Integer8 serviceMeasurementValid; > + TimeInterval meanLinkDelay; > + Integer32 scaledNeighborRateRatio; > + Integer64 egress_ts; > + Integer64 rx_ts; > +} PACKED; This layout is very poor for packed formats -- think about alignment! Please order the fields according to size, from largest to smallest. Thanks, Richard |
From: Richard C. <ric...@gm...> - 2023-11-16 04:38:32
|
On Mon, May 15, 2023 at 06:26:04PM -0400, Kishen Maloor wrote: > @@ -651,6 +652,18 @@ 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_CMLDS_INFO_NP: > + cmlds = (struct cmlds_info_np *) mgt->data; > + fprintf(fp, "CMLDS INFO " > + IFMT "serviceMeasurementValid %i" > + IFMT "meanLinkDelay %" PRId64 > + IFMT "scaledNeighborRateRatio %" PRId32 > + IFMT "egress_ts %" PRId64 > + IFMT "rx_ts %" PRId64, > + cmlds->serviceMeasurementValid, cmlds->meanLinkDelay, > + cmlds->scaledNeighborRateRatio, > + cmlds->egress_ts, cmlds->rx_ts); > + break; Nit: please place this after MID_POWER_PROFILE_SETTINGS_NP rather than tacking on the end of the switch/case. Thanks, Richard |
From: Richard C. <ric...@gm...> - 2023-11-16 04:42:11
|
On Mon, May 15, 2023 at 06:26:04PM -0400, Kishen Maloor wrote: > @@ -490,6 +491,15 @@ static int mgt_post_recv(struct management_tlv *m, uint16_t data_len, > if (data_len != 0) > goto bad_length; > break; > + case MID_CMLDS_INFO_NP: > + if (data_len < sizeof(struct cmlds_info_np)) > + goto bad_length; > + cmlds = (struct cmlds_info_np *)m->data; > + net2host64_unaligned(&cmlds->meanLinkDelay); > + NTOHL(cmlds->scaledNeighborRateRatio); > + net2host64_unaligned(&cmlds->egress_ts); > + net2host64_unaligned(&cmlds->rx_ts); > + break; Place after MID_POWER_PROFILE_SETTINGS_NP please. > } > if (extra_len) { > if (extra_len % 2) Thanks, Richard |
From: Kishen M. <kis...@in...> - 2023-05-15 22:26:28
|
This change adds cofig file parameters to configure CMLDS support and access in PTP instances. 'cmlds_clockIdentity': This global setting assigns a CMLDS clockIdentity to be used by a ptp4l instance on a PTP node that exposes CMLDS over one or more links. 'run_cmlds': This per-port setting (0/1) declares that a port will perform the role of a CMLDS Link Port (IEEE 1588, clause 16.6.1) and execute CMLDS Pdelay transactions to conduct link delay measurements and further convey those measurements to other PTP instances on its node via MID_CMLDS_INFO_NP. Said another way, this port will expose CMLDS. 'cmlds_portNumber': This per-port setting in a PTP instance specifies the CMLDS Link Port portNumber. Note that this is distinct from and independent of the portNumber associated with the PTP Port. In a PTP instance that exposes the CMLDS via a CMLDS Link Port, this setting assigns the CMLDS Link Port portNumber. In PTP instances that consume the CMLDS (using the COMMON_P2P delay mechanism), this setting is used to target MID_CMLDS_INFO_NP queries to a specific CMLDS Link Port. 'cmlds_uds_address': This per-port setting in ptp4l instances specifies the 'uds_address' of a ptp4l instance on the PTP node that exposes the CMLDS. A port which employs the COMMON_P2P delay mechanism would communicate with the CMLDS over the UDS. Co-authored-by: Andrew Zaborowski <and...@in...> Signed-off-by: Kishen Maloor <kis...@in...> --- config.c | 4 ++++ port.c | 28 ++++++++++++++++++++++++++++ port.h | 8 ++++++++ port_private.h | 4 ++++ ptp4l.8 | 22 ++++++++++++++++++++++ 5 files changed, 66 insertions(+) diff --git a/config.c b/config.c index b104f1bb521a..3e7587ba81ab 100644 --- a/config.c +++ b/config.c @@ -245,6 +245,10 @@ struct config_item config_tab[] = { GLOB_ITEM_INT("clockAccuracy", 0xfe, 0, UINT8_MAX), GLOB_ITEM_INT("clockClass", 248, 0, UINT8_MAX), GLOB_ITEM_STR("clockIdentity", "000000.0000.000000"), + GLOB_ITEM_STR("cmlds_clockIdentity", "000000.0000.000000"), + PORT_ITEM_INT("run_cmlds", 0, 0, 1), + PORT_ITEM_INT("cmlds_portNumber", 0, 0, UINT16_MAX), + PORT_ITEM_STR("cmlds_uds_address", "/var/run/ptp4l"), GLOB_ITEM_INT("clock_class_threshold", CLOCK_CLASS_THRESHOLD_DEFAULT, 6, CLOCK_CLASS_THRESHOLD_DEFAULT), GLOB_ITEM_ENU("clock_servo", CLOCK_SERVO_PI, clock_servo_enu), GLOB_ITEM_ENU("clock_type", CLOCK_TYPE_ORDINARY, clock_type_enu), diff --git a/port.c b/port.c index d467a69e519a..94ce037871f1 100644 --- a/port.c +++ b/port.c @@ -3301,6 +3301,8 @@ struct port *port_open(const char *phc_device, enum clock_type type = clock_type(clock); struct config *cfg = clock_config(clock); struct port *p = malloc(sizeof(*p)); + char *cmlds_uds_address; + const char *cmlds_cid; int i; if (!p) { @@ -3481,6 +3483,27 @@ struct port *port_open(const char *phc_device, goto err_tsproc; } } + + /* Store CMLDS parameters */ + p->cmlds_enabled = config_get_int(cfg, p->name, "run_cmlds"); + + p->cmlds_portIdentity.portNumber = config_get_int(cfg, p->name, "cmlds_portNumber"); + + cmlds_uds_address = config_get_string(cfg, p->name, "cmlds_uds_address"); + memset(&p->cmlds_uds_address, 0, sizeof(struct address)); + p->cmlds_uds_address.sun.sun_family = AF_LOCAL; + strncpy(p->cmlds_uds_address.sun.sun_path, cmlds_uds_address, + sizeof(p->cmlds_uds_address.sun.sun_path) - 1); + p->cmlds_uds_address.len = sizeof(struct sockaddr_un); + + cmlds_cid = config_get_string(cfg, NULL, "cmlds_clockIdentity"); + if (strcmp(cmlds_cid, "000000.0000.000000") != 0) { + if (str2cid(cmlds_cid, &p->cmlds_portIdentity.clockIdentity)) { + pr_err("failed to parse CMLDS clock identity"); + return NULL; + } + } + return p; err_tsproc: @@ -3508,6 +3531,11 @@ enum delay_mechanism port_delay_mechanism(struct port *port) return port->delayMechanism; } +int port_cmlds_enabled(struct port *port) +{ + return port->cmlds_enabled; +} + 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 57c8c2ffeb9e..96e0cf8aa970 100644 --- a/port.h +++ b/port.h @@ -364,4 +364,12 @@ void tc_cleanup(void); */ void port_update_unicast_state(struct port *p); +/** + * Query if a port exposes CMLDS. + * + * @param port A port instance. + * @return One if CMLDS is exposed, zero otherwise. + */ +int port_cmlds_enabled(struct port *port); + #endif diff --git a/port_private.h b/port_private.h index c9b02bc799f5..f5543076f76e 100644 --- a/port_private.h +++ b/port_private.h @@ -166,6 +166,10 @@ struct port { /* slave event monitoring */ struct monitor *slave_event_monitor; bool unicast_state_dirty; + /* CMLDS parameters */ + int cmlds_enabled; + struct PortIdentity cmlds_portIdentity; + struct address cmlds_uds_address; }; #define portnum(p) (p->portIdentity.portNumber) diff --git a/ptp4l.8 b/ptp4l.8 index 09ff108af102..d999352cd45a 100644 --- a/ptp4l.8 +++ b/ptp4l.8 @@ -159,6 +159,16 @@ collection of clocks must be synchronized by an external program, for example phc2sys(8) in "automatic" mode. The default is 0 (disabled). +.TP +.B cmlds_portNumber +Specifies the CMLDS Link Port portNumber. +The default is 0. + +.TP +.B cmlds_uds_address +Specifies the 'uds_address' of a ptp4l instance on the +PTP node that exposes the CMLDS. The default is /var/run/ptp4l. + .TP .B delayAsymmetry The time difference in nanoseconds of the transmit and receive @@ -407,6 +417,12 @@ Relevant only with L2 transport. The default is 01:1B:19:00:00:00. The MAC address to which peer delay messages should be sent. Relevant only with L2 transport. The default is 01:80:C2:00:00:0E. +.TP +.B run_cmlds +Declares that a port will perform the role of a CMLDS Link Port (IEEE 1588, +clause 16.6.1) and execute CMLDS Pdelay transactions to conduct link delay +measurements. The default is zero or false. + .TP .B serverOnly Setting this option to one (1) prevents the port from entering the @@ -557,6 +573,12 @@ clock, and "E2E_TC" for end to end transparent clock. An multi-port ordinary clock will automatically be configured as a boundary clock. The default is "OC". +.TP +.B cmlds_clockIdentity +Assigns a CMLDS clockIdentity to be used by a ptp4l instance on a PTP +node that exposes CMLDS over one or more links. +The default is "000000.0000.000000". + .TP .B dataset_comparison Specifies the method to be used when comparing data sets during the -- 2.31.1 |
From: Richard C. <ric...@gm...> - 2023-11-16 04:51:21
|
On Mon, May 15, 2023 at 06:26:05PM -0400, Kishen Maloor wrote: > 'cmlds_clockIdentity': This global setting assigns a CMLDS > clockIdentity to be used by a ptp4l instance on a PTP node that exposes > CMLDS over one or more links. Don't really need this. I know it is specified in 1588, but it is never exposed in any way, and so please omit it. > 'run_cmlds': This per-port setting (0/1) declares that a port > will perform the role of a CMLDS Link Port (IEEE 1588, clause 16.6.1) > and execute CMLDS Pdelay transactions to conduct link > delay measurements and further convey those measurements to other > PTP instances on its node via MID_CMLDS_INFO_NP. Said another way, > this port will expose CMLDS. This isn't needed. Just let every every ptp4l instance publish the TLV for each port not using DM_COMMON_P2P via its UDS port. This should be automatic. > 'cmlds_portNumber': This per-port setting in a PTP instance > specifies the CMLDS Link Port portNumber. Again this is useless. Please drop it. > 'cmlds_uds_address': This per-port setting in ptp4l instances specifies > the 'uds_address' of a ptp4l instance on the PTP node that exposes the > CMLDS. A port which employs the COMMON_P2P delay mechanism would > communicate with the CMLDS over the UDS. This option is needed. But you need one more option: the port index of the ptp4l instance which reports the TLV. Maybe something like "cmlds_port_index" ? Thanks, Richard |
From: Kishen M. <kis...@in...> - 2023-05-15 22:26:32
|
port_cmlds_ignore() assesses incoming messages per the following policy: * All messages that bear the CMLDS sdoid/domainNumber are directed to a CMLDS Link Port context and processed by this function. All other messages go through the regular flow (i.e. port_ignore() and beyond) based on the the ptp4l instance configuration. * PDELAY_REQ, PDELAY_RESP, PDELAY_RESP_FOLLOW_UP and management messages for MID_CMLDS_INFO_NP are the only expected message types at a CMLDS Link Port. All other received messages at a CMLDS Link Port (i.e., bearing the CMLDS sdoid/domainNumber) are ignored. Signed-off-by: Kishen Maloor <kis...@in...> --- port.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/port.c b/port.c index 435d9ab543c7..acce160b6499 100644 --- a/port.c +++ b/port.c @@ -772,9 +772,62 @@ int port_clr_tmo(int fd) return timerfd_settime(fd, 0, &tmo, NULL); } +static int port_cmlds_ignore(struct port *p, struct ptp_message *m) +{ + struct management_tlv *mgt = (struct management_tlv *) + m->management.suffix; + + /* Messages that do not bear the CMLDS sdoid/domainNumber + * are unrelated to CMLDS. + */ + if (msg_transport_specific(m) != CMLDS_TRANSPORTSPECIFIC || + m->header.domainNumber != CMLDS_DOMAINNUMBER) { + /* MID_CMLDS_INFO_NP may only be accessed using the CMLDS + * sdoid/domainNumber. + */ + if (msg_type(m) == MANAGEMENT && + mgt->id == MID_CMLDS_INFO_NP) { + return -1; + } + return 0; + } + + /* CMLDS messages */ + if (msg_transport_specific(m) == CMLDS_TRANSPORTSPECIFIC) { + /* Only MID_CMLDS_INFO_NP may be accessed using the CMLDS + * sdoid/domainNumber. Ignore anything else. + */ + if (msg_type(m) == MANAGEMENT && + mgt->id != MID_CMLDS_INFO_NP) + return -1; + + /* Ignore CMLDS messages received at a port that does + * not expose CMLDS. + * Note: Messages across ptp4l instacnes to/from + * MID_CMLDS_INFO_NP currently propagate over the UDS. + */ + if (!port_is_uds(p) && !port_cmlds_enabled(p)) { + return -1; + } + + /* Only the following message types are permitted to/from + * the CMLDS. Ignore anything else. + */ + if (msg_type(m) != MANAGEMENT && + msg_type(m) != PDELAY_REQ && + msg_type(m) != PDELAY_RESP && + msg_type(m) != PDELAY_RESP_FOLLOW_UP) { + return -1; + } + } + /* This is a permitted CMLDS PDELAY or MANAGEMENT message */ + return 1; +} + static int port_ignore(struct port *p, struct ptp_message *m) { struct ClockIdentity c1, c2; + int cmlds = 0; if (port_is_uds(p) && msg_type(m) != MANAGEMENT) { return 1; @@ -785,14 +838,24 @@ static int port_ignore(struct port *p, struct ptp_message *m) if (path_trace_ignore(p, m)) { return 1; } - if (p->match_transport_specific && + + /* Ignore non-permitted CMLDS messages */ + if ((cmlds = port_cmlds_ignore(p, m)) == -1) + return 1; + + /* Suppress transportSpecific/domainNumber matching below for + * mesaages to/from the CMLDS as the requisite checks have + * already been performed by port_cmlds_ignore() + */ + if (!cmlds && p->match_transport_specific && msg_transport_specific(m) != p->transportSpecific) { return 1; } if (pid_eq(&m->header.sourcePortIdentity, &p->portIdentity)) { return 1; } - if (m->header.domainNumber != clock_domain_number(p->clock)) { + if (!cmlds && + m->header.domainNumber != clock_domain_number(p->clock)) { return 1; } -- 2.31.1 |
From: Richard C. <ric...@gm...> - 2023-11-16 05:01:08
|
On Mon, May 15, 2023 at 06:26:08PM -0400, Kishen Maloor wrote: > port_cmlds_ignore() assesses incoming messages per the following > policy: > > * All messages that bear the CMLDS sdoid/domainNumber are directed > to a CMLDS Link Port context and processed by this function. All other > messages go through the regular flow (i.e. port_ignore() and beyond) > based on the the ptp4l instance configuration. > > * PDELAY_REQ, PDELAY_RESP, PDELAY_RESP_FOLLOW_UP and management > messages for MID_CMLDS_INFO_NP are the only expected message types > at a CMLDS Link Port. All other received messages at a CMLDS Link Port > (i.e., bearing the CMLDS sdoid/domainNumber) are ignored. This patch should be dropped as well. Who cares whether the peer even implements cmlds? We just want to measure the peer delay once, and share it locally. Thanks, Richard |
From: Kishen M. <kis...@in...> - 2023-05-15 22:26:33
|
This change furnishes the plumbing for interacting with CMLDS Link Ports (i.e. ports with "run_cmlds=1"). It adds internal functions for PTP Ports which employ the COMMON_P2P delay mechanism to issue requests to a CMLDS Link Port at MID_CMLDS_INFO_NP and handle the response. port_request_cmlds_info() encodes the CMLDS Link Port portNumber associated with its physical port as read from its config file. The request is sent to the configured cmlds_uds_address, i.e. the uds_address of a ptp4l instance that hosts the CMLDS Link Port. Upon receiving a request for MID_CMLDS_INFO_NP, the receiving ptp4l instance matches the target portNumber against the CMLDS Link Port portNumber that was assigned in its own config file and invokes process_cmlds_response(). Ports that do not expose the CMLDS ('run_cmlds' set to 0) will not respond to MID_CMLDS_INFO_NP queries. Co-authored-by: Andrew Zaborowski <and...@in...> Signed-off-by: Kishen Maloor <kis...@in...> --- clock.c | 10 ++++ clock.h | 6 +++ port.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++- port_private.h | 2 + 4 files changed, 149 insertions(+), 2 deletions(-) diff --git a/clock.c b/clock.c index c74a6baa9f61..810d57d849d1 100644 --- a/clock.c +++ b/clock.c @@ -1650,6 +1650,11 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg) return changed; } break; + case RESPONSE: + /* Let the destined Port handle a response from CMLDS */ + if (mgt->id == MID_CMLDS_INFO_NP) + break; + return changed; default: return changed; } @@ -2282,3 +2287,8 @@ enum servo_state clock_servo_state(struct clock *c) { return c->servo_state; } + +struct port *clock_uds_rw_port(struct clock *c) +{ + return c->uds_rw_port; +} diff --git a/clock.h b/clock.h index ce9ae913eaaf..deb827f0afad 100644 --- a/clock.h +++ b/clock.h @@ -396,4 +396,10 @@ void clock_check_ts(struct clock *c, uint64_t ts); */ double clock_rate_ratio(struct clock *c); +/** + * Return a handle to the UDS RW port. + * @param c The clock instance. + */ +struct port *clock_uds_rw_port(struct clock *c); + #endif diff --git a/port.c b/port.c index acce160b6499..ad13a919f161 100644 --- a/port.c +++ b/port.c @@ -1216,6 +1216,12 @@ static int port_management_fill_response(struct port *target, cmlds->egress_ts = tmv_to_nanoseconds(target->peer_delay_t1); cmlds->rx_ts = tmv_to_nanoseconds(target->peer_delay_t2); datalen = sizeof(*cmlds); + /* Reflect the CMLDS sdoid/domainNumber/port id in + * MID_CMLDS_INFO_NP responses + */ + rsp->header.tsmt = MANAGEMENT | CMLDS_TRANSPORTSPECIFIC; + rsp->header.domainNumber = CMLDS_DOMAINNUMBER; + rsp->header.sourcePortIdentity = target->cmlds_portIdentity; break; default: /* The caller should *not* respond to this message. */ @@ -3244,10 +3250,26 @@ int port_manage(struct port *p, struct port *ingress, struct ptp_message *msg) struct management_tlv *mgt; UInteger16 target = msg->management.targetPortIdentity.portNumber; - if (target != portnum(p) && target != 0xffff) { + mgt = (struct management_tlv *) msg->management.suffix; + + /* Given a query to CMLDS and this port exposes CMLDS, try to match + * the target portNumber with the CMLDS Link Port PortNumber. + */ + if (mgt->id == MID_CMLDS_INFO_NP && + management_action(msg) == GET) { + if (port_cmlds_enabled(p)) { + if (target != 0xffff && + target != p->cmlds_portIdentity.portNumber) + return 0; + } else { + /* Do not respond to MID_CMLDS_INFO_NP if this port + * does not expose CMLDS + */ + return 0; + } + } else if (target != portnum(p) && target != 0xffff) { return 0; } - mgt = (struct management_tlv *) msg->management.suffix; switch (management_action(msg)) { case GET: @@ -3260,6 +3282,12 @@ int port_manage(struct port *p, struct port *ingress, struct ptp_message *msg) break; case COMMAND: break; + case RESPONSE: + /* Handle a response from CMLDS */ + if (mgt->id == MID_CMLDS_INFO_NP) { + return process_cmlds_response(p, msg); + } + break; default: return -1; } @@ -3710,3 +3738,104 @@ void port_update_unicast_state(struct port *p) p->unicast_state_dirty = false; } } + +int process_cmlds_response(struct port *p, + struct ptp_message *msg) +{ + struct management_tlv *mgt = (struct management_tlv *) + msg->management.suffix; + struct cmlds_info_np *cmlds; + + if (port_delay_mechanism(p) != DM_COMMON_P2P || + msg_tlv_count(msg) != 1) { + return -1; + } + + pr_debug("Response\t%s seq %hu ", + pid2str(&msg->header.sourcePortIdentity), + msg->header.sequenceId); + + cmlds = (struct cmlds_info_np *) mgt->data; + + pr_debug("CMLDS INFO\n" + "\tserviceMeasurementValid %i\n" + "\tmeanLinkDelay %" PRId64 "\n" + "\tscaledNeighborRateRatio %" PRId32 "\n" + "\tegress_ts %" PRId64 "\n" + "\trx_ts %" PRId64, + cmlds->serviceMeasurementValid, cmlds->meanLinkDelay, + cmlds->scaledNeighborRateRatio, cmlds->egress_ts, + cmlds->rx_ts); + + /* COMMON_P2P DM implementation goes here */ + + return 0; +} + +int port_request_cmlds_info(struct port *p) +{ + struct port *uds = clock_uds_rw_port(p->clock); + struct management_tlv *mgt; + struct tlv_extra *extra; + struct ptp_message *msg; + int err; + + if (port_delay_mechanism(p) != DM_COMMON_P2P) { + return -1; + } + + msg = msg_allocate(); + if (!msg) + return -ENOMEM; + + msg->hwts.type = p->timestamping; + + msg->header.tsmt = MANAGEMENT | CMLDS_TRANSPORTSPECIFIC; + msg->header.ver = PTP_VERSION; + msg->header.domainNumber = CMLDS_DOMAINNUMBER; + msg->header.sourcePortIdentity = p->portIdentity; + msg->header.sequenceId = p->seqnum.delayreq++; + msg->header.logMessageInterval = 0x7f; + + /* Set the target cid to the wildcard as this request is being + * sent to the specific ptp4l instance that exposes the CMLDS + */ + msg->management.targetPortIdentity.clockIdentity = + (struct ClockIdentity){ + .id = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + }; + /* Set the target CMLDS Link Port portNumber */ + msg->management.targetPortIdentity.portNumber = p->cmlds_portIdentity.portNumber; + + msg->management.flags = GET; + + mgt = (struct management_tlv *) msg->management.suffix; + mgt->type = TLV_MANAGEMENT; + mgt->length = sizeof(mgt->id); + mgt->id = MID_CMLDS_INFO_NP; + msg->header.messageLength = sizeof(struct management_msg) + sizeof(*mgt); + + extra = tlv_extra_alloc(); + if (!extra) { + pr_err("failed to allocate TLV descriptor"); + msg_put(msg); + return -ENOMEM; + } + extra->tlv = (struct TLV *) msg->management.suffix; + msg_tlv_attach(msg, extra); + + err = msg_pre_send(msg); + if (err) { + pr_err("msg_pre_send failed"); + return -1; + } + + /* Set the target CMLDS UDS address */ + msg->address = p->cmlds_uds_address; + err = port_forward_to(uds, msg); + + pr_debug("CMLDS request sent: %s", strerror(err < 0 ? -err : 0)); + + msg_put(msg); + return err; +} diff --git a/port_private.h b/port_private.h index f5543076f76e..664d14944919 100644 --- a/port_private.h +++ b/port_private.h @@ -207,6 +207,8 @@ int port_tx_interval_request(struct port *p, Integer8 timeSyncInterval, Integer8 linkDelayInterval); int port_tx_sync(struct port *p, struct address *dst, uint16_t sequence_id); +int port_request_cmlds_info(struct port *p); +int process_cmlds_response(struct port *p, struct ptp_message *msg); int process_announce(struct port *p, struct ptp_message *m); void process_delay_resp(struct port *p, struct ptp_message *m); void process_follow_up(struct port *p, struct ptp_message *m); -- 2.31.1 |
From: Kishen M. <kis...@in...> - 2023-05-15 22:26:33
|
This adds two example config files to instantate a gPTP domain 0 instance that hosts a CMLDS Link Port (run_cmlds=1) and a gPTP domain 1 instance that invokes the CMLDS using the COMMON_P2P delay mechanism. Signed-off-by: Kishen Maloor <kis...@in...> --- configs/gPTP-cmlds.cfg | 34 ++++++++++++++++++++++++++++++++++ configs/gPTP-common-p2p.cfg | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 configs/gPTP-cmlds.cfg create mode 100644 configs/gPTP-common-p2p.cfg diff --git a/configs/gPTP-cmlds.cfg b/configs/gPTP-cmlds.cfg new file mode 100644 index 000000000000..d682e5b6c2cd --- /dev/null +++ b/configs/gPTP-cmlds.cfg @@ -0,0 +1,34 @@ +# +# 802.1AS example configuration containing those attributes which +# differ from the defaults. See the file, default.cfg, for the +# complete list of available options. +# +[global] +gmCapable 1 +priority1 248 +priority2 248 +logAnnounceInterval 0 +logSyncInterval -3 +syncReceiptTimeout 3 +neighborPropDelayThresh 800 +min_neighbor_prop_delay -20000000 +assume_two_step 1 +path_trace_enabled 1 +follow_up_info 1 +transportSpecific 0x1 +ptp_dst_mac 01:80:C2:00:00:0E +network_transport L2 +delay_mechanism P2P +phc_index 11 + +# Configure a distinct UDS for this PTP instance +uds_address /var/run/ptp4l.dom0 + +# Assign a CMLDS clock identity +cmlds_clockIdentity 123456.7890.abcdef + +[enp4s0] +# Declare that this port will expose the CMLDS +run_cmlds 1 +# Configure a CMLDS Link Port PortNumber for this link +cmlds_portNumber 20 \ No newline at end of file diff --git a/configs/gPTP-common-p2p.cfg b/configs/gPTP-common-p2p.cfg new file mode 100644 index 000000000000..e6a252648b76 --- /dev/null +++ b/configs/gPTP-common-p2p.cfg @@ -0,0 +1,35 @@ +# +# 802.1AS example configuration containing those attributes which +# differ from the defaults. See the file, default.cfg, for the +# complete list of available options. +# +[global] +gmCapable 1 +priority1 248 +priority2 248 +logAnnounceInterval 0 +logSyncInterval -3 +syncReceiptTimeout 3 +neighborPropDelayThresh 800 +min_neighbor_prop_delay -20000000 +assume_two_step 1 +path_trace_enabled 1 +follow_up_info 1 +transportSpecific 0x1 +ptp_dst_mac 01:80:C2:00:00:0E +network_transport L2 +phc_index 12 + +# Configure a distinct UDS for this PTP instance +uds_address /var/run/ptp4l.dom1 + +# Configure a clockIdentity for this PTP instance that is +# unique across the PTP network +clockIdentity 000001.0001.000001 +domainNumber 1 + +[enp4s0] +# Configure the CMLDS Link Port parameters for this link +cmlds_portNumber 20 +cmlds_uds_address /var/run/ptp4l.dom0 +delay_mechanism COMMON_P2P -- 2.31.1 |
From: Kishen M. <kis...@in...> - 2023-05-15 22:26:34
|
From: Andrew Zaborowski <and...@in...> This change implements the COMMON_P2P DM by issuing a request to the CMLDS for CommonMeanLinkDelayInformation upon expiry of the delay timer and handles the response to assimilate the received meanPathDelay and NRR. Signed-off-by: Andrew Zaborowski <and...@in...> --- port.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/port.c b/port.c index ad13a919f161..946b8235ecd5 100644 --- a/port.c +++ b/port.c @@ -1685,6 +1685,10 @@ int port_delay_request(struct port *p) { struct ptp_message *msg; + if (p->delayMechanism == DM_COMMON_P2P) { + return port_request_cmlds_info(p); + } + /* Time to send a new request, forget current pdelay resp and fup */ if (p->peer_delay_resp) { msg_put(p->peer_delay_resp); @@ -2597,6 +2601,9 @@ calc: p->nrate.ratio); } + p->peer_delay_t1 = t1; + p->peer_delay_t2 = t2; + msg_put(p->peer_delay_req); p->peer_delay_req = NULL; } @@ -3767,7 +3774,33 @@ int process_cmlds_response(struct port *p, cmlds->scaledNeighborRateRatio, cmlds->egress_ts, cmlds->rx_ts); - /* COMMON_P2P DM implementation goes here */ + if (!cmlds->serviceMeasurementValid) { + p->pdr_missing++; + port_capable(p); + return 0; + } + + /* Note: the CMLDS may be using a different local clock. Do not track + * the CMLDS-clock-to-local-clock rate ratio at this time as the + * difference should be small, or nul with vclocks. + */ + p->pdr_missing = 0; + p->peerMeanPathDelay = cmlds->meanLinkDelay; + p->peer_delay = nanoseconds_to_tmv(p->peerMeanPathDelay >> 16); + p->nrate.ratio = 1.0 + (double) cmlds->scaledNeighborRateRatio / POW2_41; + + /* Note: this determines the value of port_capable(p), however + * p->peer_portid itself is not actually used outside of the Pdelay FSM. + */ + p->peer_portid_valid = true; + p->nrate.ratio_valid = true; + + if (p->state == PS_UNCALIBRATED || p->state == PS_SLAVE) { + clock_peer_delay(p->clock, p->peer_delay, + nanoseconds_to_tmv(cmlds->egress_ts), + nanoseconds_to_tmv(cmlds->rx_ts), + p->nrate.ratio); + } return 0; } -- 2.31.1 |
From: Richard C. <ric...@gm...> - 2023-11-16 05:07:29
|
On Mon, May 15, 2023 at 06:26:10PM -0400, Kishen Maloor wrote: > From: Andrew Zaborowski <and...@in...> > > This change implements the COMMON_P2P DM by issuing a request > to the CMLDS for CommonMeanLinkDelayInformation upon expiry of > the delay timer and handles the response to assimilate the > received meanPathDelay and NRR. Cleints using COMMON_P2P don't need to do anything in the delay timer. Just use the latest pushed TLV from the server. Thanks, Richard |
From: Kishen M. <kis...@in...> - 2023-05-15 22:26:31
|
For ports that are configured with "run_cmlds=1", i.e. CMLDS Link Ports, this change updates port_pdelay_request(), process_pdelay_req() and port_peer_delay() to utilize the CMLDS sdoid/domainNumber/portId along code paths where necessary. It also ensures that neighborRateRatio is calculated on CMLDS Link Ports and is available to users of MID_CMLDS_INFO_NP. Further, process_pdelay_request() enforces two-step Pdelay when responding as CMLDS. These changes are in accordance to the requirements outlined in IEEE 1588, clause 16.6.3. In addition, CMLDS Link Ports respond with instance-specific peer delay messages to PdelayReqs with an sdoid/domainNumber that match their ptp4l instance configuration. This aims to address the requirement outlined above NOTE 3 in IEEE 802.1AS-2020, clause 11.2.17.1. Note that all these changes take effect only in ports with a "run_cmlds=1" setting. Default behavior applies otherwise. Co-authored-by: Andrew Zaborowski <and...@in...> Signed-off-by: Kishen Maloor <kis...@in...> --- port.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 8 deletions(-) diff --git a/port.c b/port.c index 87780fd39caa..435d9ab543c7 100644 --- a/port.c +++ b/port.c @@ -47,6 +47,8 @@ #define ALLOWED_LOST_RESPONSES 3 #define ANNOUNCE_SPAN 1 +#define CMLDS_TRANSPORTSPECIFIC 0x20 +#define CMLDS_DOMAINNUMBER 0 enum syfu_event { SYNC_MISMATCH, @@ -1544,6 +1546,9 @@ static void port_syfufsm(struct port *p, enum syfu_event event, static int port_pdelay_request(struct port *p) { + struct PortIdentity sourcePortIdentity = p->portIdentity; + UInteger8 domainNumber = clock_domain_number(p->clock); + UInteger8 transportSpecific = p->transportSpecific; struct ptp_message *msg; int err; @@ -1558,14 +1563,23 @@ static int port_pdelay_request(struct port *p) return -1; } + /* If this port exposes CMLDS, advertise the CMLDS sdoid, + * domainNumber and portId + */ + if (port_cmlds_enabled(p)) { + transportSpecific = CMLDS_TRANSPORTSPECIFIC; + domainNumber = CMLDS_DOMAINNUMBER; + sourcePortIdentity = p->cmlds_portIdentity; + } + msg->hwts.type = p->timestamping; - msg->header.tsmt = PDELAY_REQ | p->transportSpecific; + msg->header.tsmt = PDELAY_REQ | transportSpecific; msg->header.ver = PTP_VERSION; msg->header.messageLength = sizeof(struct pdelay_req_msg); - msg->header.domainNumber = clock_domain_number(p->clock); + msg->header.domainNumber = domainNumber; msg->header.correction = -p->asymmetry; - msg->header.sourcePortIdentity = p->portIdentity; + msg->header.sourcePortIdentity = sourcePortIdentity; msg->header.sequenceId = p->seqnum.delayreq++; msg->header.logMessageInterval = port_is_ieee8021as(p) ? p->logPdelayReqInterval : 0x7f; @@ -2305,7 +2319,16 @@ int process_pdelay_req(struct port *p, struct ptp_message *m) port_set_delay_tmo(p); } if (p->peer_portid_valid) { - if (!pid_eq(&p->peer_portid, &m->header.sourcePortIdentity)) { + /* The first subexpression bypasses port ID matching + * and the ensuing block in the specific case when + * a CMLDS Link Port receives a PdelayReq with the PTP + * instance's sdoid/domainNumber in order to + * issue PDELAY_RESP/RESP_FOLLOW_UP messages + * back to the requesting port. + */ + if ((!port_cmlds_enabled(p) || + msg_transport_specific(m) == CMLDS_TRANSPORTSPECIFIC) && + !pid_eq(&p->peer_portid, &m->header.sourcePortIdentity)) { pr_err("%s: received pdelay_req msg with " "unexpected peer port id %s", p->log_name, @@ -2341,11 +2364,22 @@ int process_pdelay_req(struct port *p, struct ptp_message *m) rsp->header.sequenceId = m->header.sequenceId; rsp->header.logMessageInterval = 0x7f; + /* If this is a CMLDS PdelayReq, then respond with the CMLDS + * sdoid/domainNumber/port id. + */ + if (msg_transport_specific(m) == CMLDS_TRANSPORTSPECIFIC) { + rsp->header.tsmt = PDELAY_RESP | CMLDS_TRANSPORTSPECIFIC; + rsp->header.domainNumber = CMLDS_DOMAINNUMBER; + rsp->header.sourcePortIdentity = p->cmlds_portIdentity; + } + /* * NB - We do not have any fraction nanoseconds for the correction * fields, neither in the response or the follow up. */ - if (p->timestamping == TS_P2P1STEP) { + if (p->timestamping == TS_P2P1STEP && + /* Enforce two-step Pdelay when responding as CMLDS */ + msg_transport_specific(m) != CMLDS_TRANSPORTSPECIFIC) { rsp->header.correction = m->header.correction; rsp->header.correction += p->tx_timestamp_offset; rsp->header.correction += p->rx_timestamp_offset; @@ -2393,6 +2427,15 @@ int process_pdelay_req(struct port *p, struct ptp_message *m) fup->pdelay_resp_fup.responseOriginTimestamp = tmv_to_Timestamp(rsp->hwts.ts); + /* If this is a CMLDS PdelayReq, then respond with the CMLDS + * sdoid/domainNumber/port id. + */ + if (msg_transport_specific(m) == CMLDS_TRANSPORTSPECIFIC) { + fup->header.tsmt = PDELAY_RESP_FOLLOW_UP | CMLDS_TRANSPORTSPECIFIC; + fup->header.domainNumber = CMLDS_DOMAINNUMBER; + fup->header.sourcePortIdentity = p->cmlds_portIdentity; + } + if (msg_unicast(m)) { fup->address = m->address; fup->header.flagField[0] |= UNICAST; @@ -2410,17 +2453,25 @@ out: static void port_peer_delay(struct port *p) { + struct PortIdentity portIdentity = p->portIdentity; tmv_t c1, c2, t1, t2, t3, t3c, t4; struct ptp_message *req = p->peer_delay_req; struct ptp_message *rsp = p->peer_delay_resp; struct ptp_message *fup = p->peer_delay_fup; + /* Following a CMLDS PDELAY transaction, use the CMLDS port id + * for comparisons below with the 'requestingPortIdentity'. + */ + if (msg_transport_specific(req) == CMLDS_TRANSPORTSPECIFIC) { + portIdentity = p->cmlds_portIdentity; + } + /* Check for response, validate port and sequence number. */ if (!rsp) return; - if (!pid_eq(&rsp->pdelay_resp.requestingPortIdentity, &p->portIdentity)) + if (!pid_eq(&rsp->pdelay_resp.requestingPortIdentity, &portIdentity)) return; if (rsp->header.sequenceId != ntohs(req->header.sequenceId)) @@ -2443,7 +2494,7 @@ static void port_peer_delay(struct port *p) if (!fup) return; - if (!pid_eq(&fup->pdelay_resp_fup.requestingPortIdentity, &p->portIdentity)) + if (!pid_eq(&fup->pdelay_resp_fup.requestingPortIdentity, &portIdentity)) return; if (fup->header.sequenceId != rsp->header.sequenceId) @@ -2459,7 +2510,8 @@ static void port_peer_delay(struct port *p) calc: t3c = tmv_add(t3, tmv_add(c1, c2)); - if (p->follow_up_info) + /* Always calculate the NRR when the port exposes CMLDS */ + if (p->follow_up_info || port_cmlds_enabled(p)) port_nrate_calculate(p, t3c, t4); tsproc_set_clock_rate_ratio(p->tsproc, p->nrate.ratio * -- 2.31.1 |
From: Richard C. <ric...@gm...> - 2023-11-16 05:17:48
|
On Mon, May 15, 2023 at 06:26:07PM -0400, Kishen Maloor wrote: > For ports that are configured with "run_cmlds=1", i.e. CMLDS Link > Ports, this change updates port_pdelay_request(), process_pdelay_req() and > port_peer_delay() to utilize the CMLDS sdoid/domainNumber/portId > along code paths where necessary. We already have options to configure those attributes. The use can simply configure the port that will do the p2p measurement accordingly. > It also ensures that > neighborRateRatio is calculated on CMLDS Link Ports and is available > to users of MID_CMLDS_INFO_NP. Further, process_pdelay_request() > enforces two-step Pdelay when responding as CMLDS. Again, we already have a way to configure this. Thanks, Richard |
From: Kishen M. <kis...@in...> - 2023-05-15 22:26:34
|
This change adds 'allowedLostResponses' as a per-port parameter with a default value of 3 (per IEEE 802.1AS-2011, clause 11.5.3). (Note that this matches the value of the previously #define'd ALLOWED_LOST_RESPONSES, so this change does not alter any prevailing behavior) It is now configurable to be able to comply with IEEE 802.1AS-2020, clause 11.5.3 which specifies a default value of 9 (and in the range of 1-255). Signed-off-by: Kishen Maloor <kis...@in...> --- config.c | 1 + port.c | 6 +++--- port_private.h | 1 + ptp4l.8 | 6 ++++++ 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/config.c b/config.c index 0482554feb28..5e68fc8ff65a 100644 --- a/config.c +++ b/config.c @@ -250,6 +250,7 @@ struct config_item config_tab[] = { PORT_ITEM_INT("run_cmlds", 0, 0, 1), PORT_ITEM_INT("cmlds_portNumber", 0, 0, UINT16_MAX), PORT_ITEM_STR("cmlds_uds_address", "/var/run/ptp4l"), + PORT_ITEM_INT("allowedLostResponses", 3, 1, 255), GLOB_ITEM_INT("clock_class_threshold", CLOCK_CLASS_THRESHOLD_DEFAULT, 6, CLOCK_CLASS_THRESHOLD_DEFAULT), GLOB_ITEM_ENU("clock_servo", CLOCK_SERVO_PI, clock_servo_enu), GLOB_ITEM_ENU("clock_type", CLOCK_TYPE_ORDINARY, clock_type_enu), diff --git a/port.c b/port.c index 946b8235ecd5..6bb13177f3fc 100644 --- a/port.c +++ b/port.c @@ -45,7 +45,6 @@ #include "unicast_service.h" #include "util.h" -#define ALLOWED_LOST_RESPONSES 3 #define ANNOUNCE_SPAN 1 #define CMLDS_TRANSPORTSPECIFIC 0x20 #define CMLDS_DOMAINNUMBER 0 @@ -722,7 +721,7 @@ int port_capable(struct port *p) goto not_capable; } - if (p->pdr_missing > ALLOWED_LOST_RESPONSES) { + if (p->pdr_missing > p->allowedLostResponses) { if (p->asCapable) pr_debug("%s: missed %d peer delay resp, " "resetting asCapable", p->log_name, p->pdr_missing); @@ -1338,7 +1337,7 @@ static void port_nrate_initialize(struct port *p) } /* We start in the 'incapable' state. */ - p->pdr_missing = ALLOWED_LOST_RESPONSES + 1; + p->pdr_missing = p->allowedLostResponses + 1; p->peer_portid_valid = 0; @@ -3576,6 +3575,7 @@ struct port *port_open(const char *phc_device, p->pwr.totalTimeInaccuracy = config_get_int(cfg, p->name, "power_profile.2017.totalTimeInaccuracy"); p->slave_event_monitor = clock_slave_monitor(clock); + p->allowedLostResponses = config_get_int(cfg, p->name, "allowedLostResponses"); if (!port_is_uds(p) && unicast_client_initialize(p)) { goto err_transport; diff --git a/port_private.h b/port_private.h index 664d14944919..16228ed4d530 100644 --- a/port_private.h +++ b/port_private.h @@ -148,6 +148,7 @@ struct port { UInteger8 versionNumber; /* UInteger4 */ UInteger8 delay_response_counter; UInteger8 delay_response_timeout; + UInteger8 allowedLostResponses; bool iface_rate_tlv; Integer64 portAsymmetry; struct PortStats stats; diff --git a/ptp4l.8 b/ptp4l.8 index d999352cd45a..d28fa98120be 100644 --- a/ptp4l.8 +++ b/ptp4l.8 @@ -484,6 +484,12 @@ The default is 3600 seconds or one hour. .SH PROGRAM AND CLOCK OPTIONS +.TP +.B allowedLostResponses +The number of Pdelay_Req messages without valid responses above which a port +is considered to be not exchanging peer delay messages with its neighbor. +The default value is 3. + .TP .B asCapable If set to 'true', all the checks which can unset asCapable variable (as -- 2.31.1 |
From: Richard C. <ric...@gm...> - 2023-11-16 05:10:10
|
On Mon, May 15, 2023 at 06:26:12PM -0400, Kishen Maloor wrote: > This change adds 'allowedLostResponses' as a per-port parameter > with a default value of 3 (per IEEE 802.1AS-2011, clause 11.5.3). > (Note that this matches the value of the previously #define'd > ALLOWED_LOST_RESPONSES, so this change does not alter any prevailing > behavior) This is not really in scope for the CMDLS feature. Did you see this recent post? 08.Nov'23 Chwee-Lin Choon [Linuxptp-devel] [PATCH 0/2] Enhanced Handling of Multiple Pdelay Responses 08.Nov'23 Chwee-Lin Choon ├─>[Linuxptp-devel] [PATCH 1/2] Make allowedLostResponses configurable 08.Nov'23 Chwee-Lin Choon └─>[Linuxptp-devel] [PATCH 2/2] port: Fix multiple pdelay response handling Please review it, as it also implements allowedLostResponses. Thanks, Richard |
From: Erez <ere...@gm...> - 2023-05-16 10:57:20
|
On Tue, 16 May 2023 at 00:29, Kishen Maloor <kis...@in...> wrote: > In a setup with multiple gPTP domains, the Common Mean Link Delay Service > (CMLDS) (IEEE 1588/16.6.3) performs link delay measurements in a single > domain and must (somehow) convey those to other domains. IEEE 1588 does not > specify this interface and flags it as an implementation > detail (IEEE 1588/16.6.1). Accordningly, this change introduces a new > TLV to convey link delay measurements by the CMLDS over the management > interface. > > In addition to the parameters suggested in IEEE 1588/16.6.3.2, > the TLV also conveys the latest 'up measurements' (req and rx timestamps) > recorded in the CMLDS. These values collectively aid other gPTP domains to > complete their delay/offset computations via the COMMON_P2P > delay mechanism. > > Updated 'pmc' to support the new MID, MID_CMLDS_INFO_NP. > > Co-authored-by: Andrew Zaborowski <and...@in...> > Signed-off-by: Kishen Maloor <kis...@in...> > --- > clock.c | 1 - > msg.h | 2 ++ > pmc.c | 13 +++++++++++++ > pmc_common.c | 1 + > port.c | 22 ++++++++++++++++++++++ > port_private.h | 2 ++ > tlv.c | 18 ++++++++++++++++++ > tlv.h | 11 +++++++++++ > 8 files changed, 69 insertions(+), 1 deletion(-) > > diff --git a/clock.c b/clock.c > index fe08d48ed8f8..c74a6baa9f61 100644 > --- a/clock.c > +++ b/clock.c > @@ -47,7 +47,6 @@ > #include "util.h" > > #define N_CLOCK_PFD (N_POLLFD + 1) /* one extra per port, for the fault > timer */ > -#define POW2_41 ((double)(1ULL << 41)) > > struct interface { > STAILQ_ENTRY(interface) list; > diff --git a/msg.h b/msg.h > index cbd09e75a2aa..db12e249f89f 100644 > --- a/msg.h > +++ b/msg.h > @@ -69,6 +69,8 @@ > #define SIGNAL_NO_CHANGE -128 > #define SIGNAL_SET_INITIAL 126 > > +#define POW2_41 ((double)(1ULL << 41)) > + > enum timestamp_type { > TS_SOFTWARE, > TS_HARDWARE, > diff --git a/pmc.c b/pmc.c > index 00e691f0c244..cac06fb5b41d 100644 > --- a/pmc.c > +++ b/pmc.c > @@ -169,6 +169,7 @@ static void pmc_show(struct ptp_message *msg, FILE *fp) > struct subscribe_events_np *sen; > struct port_properties_np *ppn; > struct port_hwclock_np *phn; > + struct cmlds_info_np *cmlds; > struct timePropertiesDS *tp; > struct management_tlv *mgt; > struct time_status_np *tsn; > @@ -651,6 +652,18 @@ 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_CMLDS_INFO_NP: > + cmlds = (struct cmlds_info_np *) mgt->data; > + fprintf(fp, "CMLDS INFO " > + IFMT "serviceMeasurementValid %i" > + IFMT "meanLinkDelay %" PRId64 > + IFMT "scaledNeighborRateRatio %" PRId32 > + IFMT "egress_ts %" PRId64 > + IFMT "rx_ts %" PRId64, > + cmlds->serviceMeasurementValid, > cmlds->meanLinkDelay, > + cmlds->scaledNeighborRateRatio, > + cmlds->egress_ts, cmlds->rx_ts); > + break; > } > out: > fprintf(fp, "\n"); > diff --git a/pmc_common.c b/pmc_common.c > index 9e251c43e95b..d7a6114dcd62 100644 > --- a/pmc_common.c > +++ b/pmc_common.c > @@ -156,6 +156,7 @@ struct management_id idtab[] = { > { "UNICAST_MASTER_TABLE_NP", MID_UNICAST_MASTER_TABLE_NP, > do_get_action }, > { "PORT_HWCLOCK_NP", MID_PORT_HWCLOCK_NP, do_get_action }, > { "POWER_PROFILE_SETTINGS_NP", MID_POWER_PROFILE_SETTINGS_NP, > do_set_action }, > + { "CMLDS_INFO_NP", MID_CMLDS_INFO_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 8b2eb04a855a..d467a69e519a 100644 > --- a/port.c > +++ b/port.c > @@ -887,6 +887,7 @@ static int port_management_fill_response(struct port > *target, > struct clock_description *desc; > struct port_properties_np *ppn; > struct port_hwclock_np *phn; > + struct cmlds_info_np *cmlds; > struct management_tlv *tlv; > struct port_stats_np *psn; > struct foreign_clock *fc; > @@ -1129,6 +1130,27 @@ static int port_management_fill_response(struct > port *target, > memcpy(pwr, &target->pwr, sizeof(*pwr)); > datalen = sizeof(*pwr); > break; > + case MID_CMLDS_INFO_NP: > + cmlds = (struct cmlds_info_np *)tlv->data; > + /* IEEE1588-2019 16.6.3.2 h) 1) && nrate.ratio_valid > because > + * we have no extra field to convey that separately. > + */ > + cmlds->serviceMeasurementValid = > + target->peer_portid_valid && !target->pdr_missing > && > + !target->multiple_pdr_detected && > + target->nrate.ratio_valid; > + cmlds->meanLinkDelay = target->peerMeanPathDelay; > + cmlds->scaledNeighborRateRatio = > + (Integer32) (target->nrate.ratio * POW2_41 - > POW2_41); > + /* 16.6.3.2: "Upon receipt of a request for information, > the > + * Common Mean Link Delay Service may in addition return > the > + * raw measurement data gathered by the service for use in > + * estimating the <meanLinkDelay> and <neighborRateRatio>." > + */ > + cmlds->egress_ts = > tmv_to_nanoseconds(target->peer_delay_t1); > + cmlds->rx_ts = tmv_to_nanoseconds(target->peer_delay_t2); > + datalen = sizeof(*cmlds); > + break; > default: > /* The caller should *not* respond to this message. */ > tlv_extra_recycle(extra); > diff --git a/port_private.h b/port_private.h > index 3b02d2fe45c4..c9b02bc799f5 100644 > --- a/port_private.h > +++ b/port_private.h > @@ -99,6 +99,8 @@ struct port { > unsigned int pdr_missing; > unsigned int multiple_seq_pdr_count; > unsigned int multiple_pdr_detected; > + tmv_t peer_delay_t1; > + tmv_t peer_delay_t2; > enum port_state (*state_machine)(enum port_state state, > enum fsm_event event, int mdiff); > int bmca; > diff --git a/tlv.c b/tlv.c > index 79400126cbc4..8b97d2cfc9f5 100644 > --- a/tlv.c > +++ b/tlv.c > @@ -176,6 +176,7 @@ static int mgt_post_recv(struct management_tlv *m, > uint16_t data_len, > struct port_properties_np *ppn; > struct port_hwclock_np *phn; > struct timePropertiesDS *tp; > + struct cmlds_info_np *cmlds; > struct time_status_np *tsn; > struct port_stats_np *psn; > int extra_len = 0, i, len; > @@ -490,6 +491,15 @@ static int mgt_post_recv(struct management_tlv *m, > uint16_t data_len, > if (data_len != 0) > goto bad_length; > break; > + case MID_CMLDS_INFO_NP: > + if (data_len < sizeof(struct cmlds_info_np)) > + goto bad_length; > + cmlds = (struct cmlds_info_np *)m->data; > + net2host64_unaligned(&cmlds->meanLinkDelay); > + NTOHL(cmlds->scaledNeighborRateRatio); > + net2host64_unaligned(&cmlds->egress_ts); > + net2host64_unaligned(&cmlds->rx_ts); > + break; > } > if (extra_len) { > if (extra_len % 2) > @@ -514,6 +524,7 @@ static void mgt_pre_send(struct management_tlv *m, > struct tlv_extra *extra) > struct subscribe_events_np *sen; > struct port_properties_np *ppn; > struct port_hwclock_np *phn; > + struct cmlds_info_np *cmlds; > struct timePropertiesDS *tp; > struct time_status_np *tsn; > struct port_stats_np *psn; > @@ -672,6 +683,13 @@ static void mgt_pre_send(struct management_tlv *m, > struct tlv_extra *extra) > HTONL(pwr->networkTimeInaccuracy); > HTONL(pwr->totalTimeInaccuracy); > break; > + case MID_CMLDS_INFO_NP: > + cmlds = (struct cmlds_info_np *)m->data; > + host2net64_unaligned(&cmlds->meanLinkDelay); > + HTONL(cmlds->scaledNeighborRateRatio); > + host2net64_unaligned(&cmlds->egress_ts); > + host2net64_unaligned(&cmlds->rx_ts); > + break; > } > } > > diff --git a/tlv.h b/tlv.h > index 8b51ffd88816..6446fc068488 100644 > --- a/tlv.h > +++ b/tlv.h > @@ -130,6 +130,9 @@ enum management_action { > #define MID_PORT_HWCLOCK_NP 0xC009 > #define MID_POWER_PROFILE_SETTINGS_NP 0xC00A > > +/* CMLDS management ID values */ > +#define MID_CMLDS_INFO_NP 0xC00B > + > /* Management error ID values */ > #define MID_RESPONSE_TOO_BIG 0x0001 > #define MID_NO_SUCH_ID 0x0002 > @@ -473,6 +476,14 @@ struct msg_interface_rate_tlv { > UInteger16 numberOfBitsAfterTimestamp; > } PACKED; > > +struct cmlds_info_np { > + Integer8 serviceMeasurementValid; > + TimeInterval meanLinkDelay; > + Integer32 scaledNeighborRateRatio; + Integer64 egress_ts; > + Integer64 rx_ts; > Not really sure what is better. But why not using Timestamp?, the annoying type from IEEE. Can you please add a remark here with cons and pros and a decision here? > +} PACKED; > + > /** > * Allocates a new tlv_extra structure. > * @return Pointer to a new structure on success or NULL otherwise. > -- > 2.31.1 > > > > _______________________________________________ > Linuxptp-devel mailing list > Lin...@li... > https://lists.sourceforge.net/lists/listinfo/linuxptp-devel > |
From: Kishen M. <kis...@in...> - 2023-05-16 21:43:23
|
On 5/16/23 3:56 AM, Erez wrote: > On Tue, 16 May 2023 at 00:29, Kishen Maloor <kis...@in...> wrote: > >> In a setup with multiple gPTP domains, the Common Mean Link Delay Service >> (CMLDS) (IEEE 1588/16.6.3) performs link delay measurements in a single >> domain and must (somehow) convey those to other domains. IEEE 1588 does not >> specify this interface and flags it as an implementation >> detail (IEEE 1588/16.6.1). Accordningly, this change introduces a new >> TLV to convey link delay measurements by the CMLDS over the management >> interface. >> >> In addition to the parameters suggested in IEEE 1588/16.6.3.2, >> the TLV also conveys the latest 'up measurements' (req and rx timestamps) >> recorded in the CMLDS. These values collectively aid other gPTP domains to >> complete their delay/offset computations via the COMMON_P2P >> delay mechanism. >> >> Updated 'pmc' to support the new MID, MID_CMLDS_INFO_NP. >> >> Co-authored-by: Andrew Zaborowski <and...@in...> >> Signed-off-by: Kishen Maloor <kis...@in...> >> --- >> clock.c | 1 - >> msg.h | 2 ++ >> pmc.c | 13 +++++++++++++ >> pmc_common.c | 1 + >> port.c | 22 ++++++++++++++++++++++ >> port_private.h | 2 ++ >> tlv.c | 18 ++++++++++++++++++ >> tlv.h | 11 +++++++++++ >> 8 files changed, 69 insertions(+), 1 deletion(-) >> >> diff --git a/clock.c b/clock.c >> index fe08d48ed8f8..c74a6baa9f61 100644 >> --- a/clock.c >> +++ b/clock.c >> @@ -47,7 +47,6 @@ >> #include "util.h" >> >> #define N_CLOCK_PFD (N_POLLFD + 1) /* one extra per port, for the fault >> timer */ >> -#define POW2_41 ((double)(1ULL << 41)) >> >> struct interface { >> STAILQ_ENTRY(interface) list; >> diff --git a/msg.h b/msg.h >> index cbd09e75a2aa..db12e249f89f 100644 >> --- a/msg.h >> +++ b/msg.h >> @@ -69,6 +69,8 @@ >> #define SIGNAL_NO_CHANGE -128 >> #define SIGNAL_SET_INITIAL 126 >> >> +#define POW2_41 ((double)(1ULL << 41)) >> + >> enum timestamp_type { >> TS_SOFTWARE, >> TS_HARDWARE, >> diff --git a/pmc.c b/pmc.c >> index 00e691f0c244..cac06fb5b41d 100644 >> --- a/pmc.c >> +++ b/pmc.c >> @@ -169,6 +169,7 @@ static void pmc_show(struct ptp_message *msg, FILE *fp) >> struct subscribe_events_np *sen; >> struct port_properties_np *ppn; >> struct port_hwclock_np *phn; >> + struct cmlds_info_np *cmlds; >> struct timePropertiesDS *tp; >> struct management_tlv *mgt; >> struct time_status_np *tsn; >> @@ -651,6 +652,18 @@ 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_CMLDS_INFO_NP: >> + cmlds = (struct cmlds_info_np *) mgt->data; >> + fprintf(fp, "CMLDS INFO " >> + IFMT "serviceMeasurementValid %i" >> + IFMT "meanLinkDelay %" PRId64 >> + IFMT "scaledNeighborRateRatio %" PRId32 >> + IFMT "egress_ts %" PRId64 >> + IFMT "rx_ts %" PRId64, >> + cmlds->serviceMeasurementValid, >> cmlds->meanLinkDelay, >> + cmlds->scaledNeighborRateRatio, >> + cmlds->egress_ts, cmlds->rx_ts); >> + break; >> } >> out: >> fprintf(fp, "\n"); >> diff --git a/pmc_common.c b/pmc_common.c >> index 9e251c43e95b..d7a6114dcd62 100644 >> --- a/pmc_common.c >> +++ b/pmc_common.c >> @@ -156,6 +156,7 @@ struct management_id idtab[] = { >> { "UNICAST_MASTER_TABLE_NP", MID_UNICAST_MASTER_TABLE_NP, >> do_get_action }, >> { "PORT_HWCLOCK_NP", MID_PORT_HWCLOCK_NP, do_get_action }, >> { "POWER_PROFILE_SETTINGS_NP", MID_POWER_PROFILE_SETTINGS_NP, >> do_set_action }, >> + { "CMLDS_INFO_NP", MID_CMLDS_INFO_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 8b2eb04a855a..d467a69e519a 100644 >> --- a/port.c >> +++ b/port.c >> @@ -887,6 +887,7 @@ static int port_management_fill_response(struct port >> *target, >> struct clock_description *desc; >> struct port_properties_np *ppn; >> struct port_hwclock_np *phn; >> + struct cmlds_info_np *cmlds; >> struct management_tlv *tlv; >> struct port_stats_np *psn; >> struct foreign_clock *fc; >> @@ -1129,6 +1130,27 @@ static int port_management_fill_response(struct >> port *target, >> memcpy(pwr, &target->pwr, sizeof(*pwr)); >> datalen = sizeof(*pwr); >> break; >> + case MID_CMLDS_INFO_NP: >> + cmlds = (struct cmlds_info_np *)tlv->data; >> + /* IEEE1588-2019 16.6.3.2 h) 1) && nrate.ratio_valid >> because >> + * we have no extra field to convey that separately. >> + */ >> + cmlds->serviceMeasurementValid = >> + target->peer_portid_valid && !target->pdr_missing >> && >> + !target->multiple_pdr_detected && >> + target->nrate.ratio_valid; >> + cmlds->meanLinkDelay = target->peerMeanPathDelay; >> + cmlds->scaledNeighborRateRatio = >> + (Integer32) (target->nrate.ratio * POW2_41 - >> POW2_41); >> + /* 16.6.3.2: "Upon receipt of a request for information, >> the >> + * Common Mean Link Delay Service may in addition return >> the >> + * raw measurement data gathered by the service for use in >> + * estimating the <meanLinkDelay> and <neighborRateRatio>." >> + */ >> + cmlds->egress_ts = >> tmv_to_nanoseconds(target->peer_delay_t1); >> + cmlds->rx_ts = tmv_to_nanoseconds(target->peer_delay_t2); >> + datalen = sizeof(*cmlds); >> + break; >> default: >> /* The caller should *not* respond to this message. */ >> tlv_extra_recycle(extra); >> diff --git a/port_private.h b/port_private.h >> index 3b02d2fe45c4..c9b02bc799f5 100644 >> --- a/port_private.h >> +++ b/port_private.h >> @@ -99,6 +99,8 @@ struct port { >> unsigned int pdr_missing; >> unsigned int multiple_seq_pdr_count; >> unsigned int multiple_pdr_detected; >> + tmv_t peer_delay_t1; >> + tmv_t peer_delay_t2; >> enum port_state (*state_machine)(enum port_state state, >> enum fsm_event event, int mdiff); >> int bmca; >> diff --git a/tlv.c b/tlv.c >> index 79400126cbc4..8b97d2cfc9f5 100644 >> --- a/tlv.c >> +++ b/tlv.c >> @@ -176,6 +176,7 @@ static int mgt_post_recv(struct management_tlv *m, >> uint16_t data_len, >> struct port_properties_np *ppn; >> struct port_hwclock_np *phn; >> struct timePropertiesDS *tp; >> + struct cmlds_info_np *cmlds; >> struct time_status_np *tsn; >> struct port_stats_np *psn; >> int extra_len = 0, i, len; >> @@ -490,6 +491,15 @@ static int mgt_post_recv(struct management_tlv *m, >> uint16_t data_len, >> if (data_len != 0) >> goto bad_length; >> break; >> + case MID_CMLDS_INFO_NP: >> + if (data_len < sizeof(struct cmlds_info_np)) >> + goto bad_length; >> + cmlds = (struct cmlds_info_np *)m->data; >> + net2host64_unaligned(&cmlds->meanLinkDelay); >> + NTOHL(cmlds->scaledNeighborRateRatio); >> + net2host64_unaligned(&cmlds->egress_ts); >> + net2host64_unaligned(&cmlds->rx_ts); >> + break; >> } >> if (extra_len) { >> if (extra_len % 2) >> @@ -514,6 +524,7 @@ static void mgt_pre_send(struct management_tlv *m, >> struct tlv_extra *extra) >> struct subscribe_events_np *sen; >> struct port_properties_np *ppn; >> struct port_hwclock_np *phn; >> + struct cmlds_info_np *cmlds; >> struct timePropertiesDS *tp; >> struct time_status_np *tsn; >> struct port_stats_np *psn; >> @@ -672,6 +683,13 @@ static void mgt_pre_send(struct management_tlv *m, >> struct tlv_extra *extra) >> HTONL(pwr->networkTimeInaccuracy); >> HTONL(pwr->totalTimeInaccuracy); >> break; >> + case MID_CMLDS_INFO_NP: >> + cmlds = (struct cmlds_info_np *)m->data; >> + host2net64_unaligned(&cmlds->meanLinkDelay); >> + HTONL(cmlds->scaledNeighborRateRatio); >> + host2net64_unaligned(&cmlds->egress_ts); >> + host2net64_unaligned(&cmlds->rx_ts); >> + break; >> } >> } >> >> diff --git a/tlv.h b/tlv.h >> index 8b51ffd88816..6446fc068488 100644 >> --- a/tlv.h >> +++ b/tlv.h >> @@ -130,6 +130,9 @@ enum management_action { >> #define MID_PORT_HWCLOCK_NP 0xC009 >> #define MID_POWER_PROFILE_SETTINGS_NP 0xC00A >> >> +/* CMLDS management ID values */ >> +#define MID_CMLDS_INFO_NP 0xC00B >> + >> /* Management error ID values */ >> #define MID_RESPONSE_TOO_BIG 0x0001 >> #define MID_NO_SUCH_ID 0x0002 >> @@ -473,6 +476,14 @@ struct msg_interface_rate_tlv { >> UInteger16 numberOfBitsAfterTimestamp; >> } PACKED; >> >> +struct cmlds_info_np { >> + Integer8 serviceMeasurementValid; >> + TimeInterval meanLinkDelay; >> + Integer32 scaledNeighborRateRatio; > > + Integer64 egress_ts; >> + Integer64 rx_ts; >> > > Not really sure what is better. > But why not using Timestamp?, the annoying type from IEEE. > Can you please add a remark here with cons and pros and a decision here? This TLV (and its conveyance method) is unspecified and is set by the implementation. So as such, we're handing these tmv_t timestamps as is to a requesting port, wherefrom they're directly passed in a call to clock_peer_delay(). I guess we didn't think to send these values as struct Timestamp instead because it wasn't necessary. > > >> +} PACKED; >> + >> /** >> * Allocates a new tlv_extra structure. >> * @return Pointer to a new structure on success or NULL otherwise. >> -- >> 2.31.1 >> >> >> >> _______________________________________________ >> Linuxptp-devel mailing list >> Lin...@li... >> https://lists.sourceforge.net/lists/listinfo/linuxptp-devel >> > |
From: Erez <ere...@gm...> - 2023-05-18 16:47:33
|
Thanks for the reply. Please add the explanation to the commit and to the structure. Personally, I do not have an opinion, yet I did not participate in the IEEE 1558 committee. Erez On Tue, 16 May 2023 at 23:43, Kishen Maloor <kis...@in...> wrote: > On 5/16/23 3:56 AM, Erez wrote: > > On Tue, 16 May 2023 at 00:29, Kishen Maloor <kis...@in...> > wrote: > > > >> In a setup with multiple gPTP domains, the Common Mean Link Delay > Service > >> (CMLDS) (IEEE 1588/16.6.3) performs link delay measurements in a single > >> domain and must (somehow) convey those to other domains. IEEE 1588 does > not > >> specify this interface and flags it as an implementation > >> detail (IEEE 1588/16.6.1). Accordningly, this change introduces a new > >> TLV to convey link delay measurements by the CMLDS over the management > >> interface. > >> > >> In addition to the parameters suggested in IEEE 1588/16.6.3.2, > >> the TLV also conveys the latest 'up measurements' (req and rx > timestamps) > >> recorded in the CMLDS. These values collectively aid other gPTP domains > to > >> complete their delay/offset computations via the COMMON_P2P > >> delay mechanism. > >> > >> Updated 'pmc' to support the new MID, MID_CMLDS_INFO_NP. > >> > >> Co-authored-by: Andrew Zaborowski <and...@in...> > >> Signed-off-by: Kishen Maloor <kis...@in...> > >> --- > >> clock.c | 1 - > >> msg.h | 2 ++ > >> pmc.c | 13 +++++++++++++ > >> pmc_common.c | 1 + > >> port.c | 22 ++++++++++++++++++++++ > >> port_private.h | 2 ++ > >> tlv.c | 18 ++++++++++++++++++ > >> tlv.h | 11 +++++++++++ > >> 8 files changed, 69 insertions(+), 1 deletion(-) > >> > >> diff --git a/clock.c b/clock.c > >> index fe08d48ed8f8..c74a6baa9f61 100644 > >> --- a/clock.c > >> +++ b/clock.c > >> @@ -47,7 +47,6 @@ > >> #include "util.h" > >> > >> #define N_CLOCK_PFD (N_POLLFD + 1) /* one extra per port, for the fault > >> timer */ > >> -#define POW2_41 ((double)(1ULL << 41)) > >> > >> struct interface { > >> STAILQ_ENTRY(interface) list; > >> diff --git a/msg.h b/msg.h > >> index cbd09e75a2aa..db12e249f89f 100644 > >> --- a/msg.h > >> +++ b/msg.h > >> @@ -69,6 +69,8 @@ > >> #define SIGNAL_NO_CHANGE -128 > >> #define SIGNAL_SET_INITIAL 126 > >> > >> +#define POW2_41 ((double)(1ULL << 41)) > >> + > >> enum timestamp_type { > >> TS_SOFTWARE, > >> TS_HARDWARE, > >> diff --git a/pmc.c b/pmc.c > >> index 00e691f0c244..cac06fb5b41d 100644 > >> --- a/pmc.c > >> +++ b/pmc.c > >> @@ -169,6 +169,7 @@ static void pmc_show(struct ptp_message *msg, FILE > *fp) > >> struct subscribe_events_np *sen; > >> struct port_properties_np *ppn; > >> struct port_hwclock_np *phn; > >> + struct cmlds_info_np *cmlds; > >> struct timePropertiesDS *tp; > >> struct management_tlv *mgt; > >> struct time_status_np *tsn; > >> @@ -651,6 +652,18 @@ 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_CMLDS_INFO_NP: > >> + cmlds = (struct cmlds_info_np *) mgt->data; > >> + fprintf(fp, "CMLDS INFO " > >> + IFMT "serviceMeasurementValid %i" > >> + IFMT "meanLinkDelay %" PRId64 > >> + IFMT "scaledNeighborRateRatio %" PRId32 > >> + IFMT "egress_ts %" PRId64 > >> + IFMT "rx_ts %" PRId64, > >> + cmlds->serviceMeasurementValid, > >> cmlds->meanLinkDelay, > >> + cmlds->scaledNeighborRateRatio, > >> + cmlds->egress_ts, cmlds->rx_ts); > >> + break; > >> } > >> out: > >> fprintf(fp, "\n"); > >> diff --git a/pmc_common.c b/pmc_common.c > >> index 9e251c43e95b..d7a6114dcd62 100644 > >> --- a/pmc_common.c > >> +++ b/pmc_common.c > >> @@ -156,6 +156,7 @@ struct management_id idtab[] = { > >> { "UNICAST_MASTER_TABLE_NP", MID_UNICAST_MASTER_TABLE_NP, > >> do_get_action }, > >> { "PORT_HWCLOCK_NP", MID_PORT_HWCLOCK_NP, do_get_action }, > >> { "POWER_PROFILE_SETTINGS_NP", MID_POWER_PROFILE_SETTINGS_NP, > >> do_set_action }, > >> + { "CMLDS_INFO_NP", MID_CMLDS_INFO_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 8b2eb04a855a..d467a69e519a 100644 > >> --- a/port.c > >> +++ b/port.c > >> @@ -887,6 +887,7 @@ static int port_management_fill_response(struct port > >> *target, > >> struct clock_description *desc; > >> struct port_properties_np *ppn; > >> struct port_hwclock_np *phn; > >> + struct cmlds_info_np *cmlds; > >> struct management_tlv *tlv; > >> struct port_stats_np *psn; > >> struct foreign_clock *fc; > >> @@ -1129,6 +1130,27 @@ static int port_management_fill_response(struct > >> port *target, > >> memcpy(pwr, &target->pwr, sizeof(*pwr)); > >> datalen = sizeof(*pwr); > >> break; > >> + case MID_CMLDS_INFO_NP: > >> + cmlds = (struct cmlds_info_np *)tlv->data; > >> + /* IEEE1588-2019 16.6.3.2 h) 1) && nrate.ratio_valid > >> because > >> + * we have no extra field to convey that separately. > >> + */ > >> + cmlds->serviceMeasurementValid = > >> + target->peer_portid_valid && > !target->pdr_missing > >> && > >> + !target->multiple_pdr_detected && > >> + target->nrate.ratio_valid; > >> + cmlds->meanLinkDelay = target->peerMeanPathDelay; > >> + cmlds->scaledNeighborRateRatio = > >> + (Integer32) (target->nrate.ratio * POW2_41 - > >> POW2_41); > >> + /* 16.6.3.2: "Upon receipt of a request for > information, > >> the > >> + * Common Mean Link Delay Service may in addition return > >> the > >> + * raw measurement data gathered by the service for use > in > >> + * estimating the <meanLinkDelay> and > <neighborRateRatio>." > >> + */ > >> + cmlds->egress_ts = > >> tmv_to_nanoseconds(target->peer_delay_t1); > >> + cmlds->rx_ts = > tmv_to_nanoseconds(target->peer_delay_t2); > >> + datalen = sizeof(*cmlds); > >> + break; > >> default: > >> /* The caller should *not* respond to this message. */ > >> tlv_extra_recycle(extra); > >> diff --git a/port_private.h b/port_private.h > >> index 3b02d2fe45c4..c9b02bc799f5 100644 > >> --- a/port_private.h > >> +++ b/port_private.h > >> @@ -99,6 +99,8 @@ struct port { > >> unsigned int pdr_missing; > >> unsigned int multiple_seq_pdr_count; > >> unsigned int multiple_pdr_detected; > >> + tmv_t peer_delay_t1; > >> + tmv_t peer_delay_t2; > >> enum port_state (*state_machine)(enum port_state state, > >> enum fsm_event event, int > mdiff); > >> int bmca; > >> diff --git a/tlv.c b/tlv.c > >> index 79400126cbc4..8b97d2cfc9f5 100644 > >> --- a/tlv.c > >> +++ b/tlv.c > >> @@ -176,6 +176,7 @@ static int mgt_post_recv(struct management_tlv *m, > >> uint16_t data_len, > >> struct port_properties_np *ppn; > >> struct port_hwclock_np *phn; > >> struct timePropertiesDS *tp; > >> + struct cmlds_info_np *cmlds; > >> struct time_status_np *tsn; > >> struct port_stats_np *psn; > >> int extra_len = 0, i, len; > >> @@ -490,6 +491,15 @@ static int mgt_post_recv(struct management_tlv *m, > >> uint16_t data_len, > >> if (data_len != 0) > >> goto bad_length; > >> break; > >> + case MID_CMLDS_INFO_NP: > >> + if (data_len < sizeof(struct cmlds_info_np)) > >> + goto bad_length; > >> + cmlds = (struct cmlds_info_np *)m->data; > >> + net2host64_unaligned(&cmlds->meanLinkDelay); > >> + NTOHL(cmlds->scaledNeighborRateRatio); > >> + net2host64_unaligned(&cmlds->egress_ts); > >> + net2host64_unaligned(&cmlds->rx_ts); > >> + break; > >> } > >> if (extra_len) { > >> if (extra_len % 2) > >> @@ -514,6 +524,7 @@ static void mgt_pre_send(struct management_tlv *m, > >> struct tlv_extra *extra) > >> struct subscribe_events_np *sen; > >> struct port_properties_np *ppn; > >> struct port_hwclock_np *phn; > >> + struct cmlds_info_np *cmlds; > >> struct timePropertiesDS *tp; > >> struct time_status_np *tsn; > >> struct port_stats_np *psn; > >> @@ -672,6 +683,13 @@ static void mgt_pre_send(struct management_tlv *m, > >> struct tlv_extra *extra) > >> HTONL(pwr->networkTimeInaccuracy); > >> HTONL(pwr->totalTimeInaccuracy); > >> break; > >> + case MID_CMLDS_INFO_NP: > >> + cmlds = (struct cmlds_info_np *)m->data; > >> + host2net64_unaligned(&cmlds->meanLinkDelay); > >> + HTONL(cmlds->scaledNeighborRateRatio); > >> + host2net64_unaligned(&cmlds->egress_ts); > >> + host2net64_unaligned(&cmlds->rx_ts); > >> + break; > >> } > >> } > >> > >> diff --git a/tlv.h b/tlv.h > >> index 8b51ffd88816..6446fc068488 100644 > >> --- a/tlv.h > >> +++ b/tlv.h > >> @@ -130,6 +130,9 @@ enum management_action { > >> #define MID_PORT_HWCLOCK_NP 0xC009 > >> #define MID_POWER_PROFILE_SETTINGS_NP 0xC00A > >> > >> +/* CMLDS management ID values */ > >> +#define MID_CMLDS_INFO_NP 0xC00B > >> + > >> /* Management error ID values */ > >> #define MID_RESPONSE_TOO_BIG 0x0001 > >> #define MID_NO_SUCH_ID 0x0002 > >> @@ -473,6 +476,14 @@ struct msg_interface_rate_tlv { > >> UInteger16 numberOfBitsAfterTimestamp; > >> } PACKED; > >> > >> +struct cmlds_info_np { > >> + Integer8 serviceMeasurementValid; > >> + TimeInterval meanLinkDelay; > >> + Integer32 scaledNeighborRateRatio; > > > > + Integer64 egress_ts; > >> + Integer64 rx_ts; > >> > > > > Not really sure what is better. > > But why not using Timestamp?, the annoying type from IEEE. > > Can you please add a remark here with cons and pros and a decision here? > > This TLV (and its conveyance method) is unspecified and is set by the > implementation. > So as such, we're handing these tmv_t timestamps as is to a requesting > port, wherefrom > they're directly passed in a call to clock_peer_delay(). > I guess we didn't think to send these values as struct Timestamp instead > because it wasn't > necessary. > > > > > > >> +} PACKED; > >> + > >> /** > >> * Allocates a new tlv_extra structure. > >> * @return Pointer to a new structure on success or NULL otherwise. > >> -- > >> 2.31.1 > >> > >> > >> > >> _______________________________________________ > >> Linuxptp-devel mailing list > >> Lin...@li... > >> https://lists.sourceforge.net/lists/listinfo/linuxptp-devel > >> > > > > |
From: Richard C. <ric...@gm...> - 2023-11-16 04:26:47
|
On Mon, May 15, 2023 at 06:26:04PM -0400, Kishen Maloor wrote: > @@ -1129,6 +1130,27 @@ static int port_management_fill_response(struct port *target, > memcpy(pwr, &target->pwr, sizeof(*pwr)); > datalen = sizeof(*pwr); > break; > + case MID_CMLDS_INFO_NP: > + cmlds = (struct cmlds_info_np *)tlv->data; > + /* IEEE1588-2019 16.6.3.2 h) 1) && nrate.ratio_valid because > + * we have no extra field to convey that separately. > + */ > + cmlds->serviceMeasurementValid = > + target->peer_portid_valid && !target->pdr_missing && > + !target->multiple_pdr_detected && > + target->nrate.ratio_valid; > + cmlds->meanLinkDelay = target->peerMeanPathDelay; > + cmlds->scaledNeighborRateRatio = > + (Integer32) (target->nrate.ratio * POW2_41 - POW2_41); > + /* 16.6.3.2: "Upon receipt of a request for information, the > + * Common Mean Link Delay Service may in addition return the > + * raw measurement data gathered by the service for use in > + * estimating the <meanLinkDelay> and <neighborRateRatio>." > + */ > + cmlds->egress_ts = tmv_to_nanoseconds(target->peer_delay_t1); > + cmlds->rx_ts = tmv_to_nanoseconds(target->peer_delay_t2); Please drop these two fields. They don't provide any benefit. If the clients don't trust the CMLDS values, then they are free to measure the p2p delay themselves! Thanks, Richard |
From: Richard C. <ric...@gm...> - 2023-11-16 04:59:07
|
On Mon, May 15, 2023 at 06:26:07PM -0400, Kishen Maloor wrote: > For ports that are configured with "run_cmlds=1", i.e. CMLDS Link > Ports, this change updates port_pdelay_request(), process_pdelay_req() and > port_peer_delay() to utilize the CMLDS sdoid/domainNumber/portId > along code paths where necessary. It also ensures that > neighborRateRatio is calculated on CMLDS Link Ports and is available > to users of MID_CMLDS_INFO_NP. Further, process_pdelay_request() > enforces two-step Pdelay when responding as CMLDS. > These changes are in accordance to the requirements outlined in > IEEE 1588, clause 16.6.3. > > In addition, CMLDS Link Ports respond with instance-specific peer delay > messages to PdelayReqs with an sdoid/domainNumber that match their ptp4l > instance configuration. This aims to address the requirement outlined > above NOTE 3 in IEEE 802.1AS-2020, clause 11.2.17.1. > > Note that all these changes take effect only in ports with a > "run_cmlds=1" setting. Default behavior applies otherwise. This patch can be dropped. The text of 1588 strongly suggests that the CMLDS service be stand alone daemon. However, we can provide the same functionality without the extra complexity, by simply letting ptp4l serve the measured peer delay to any local client. Thanks, Richard |