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 <andrew.zaborow...@intel.com> Signed-off-by: Kishen Maloor <kishen.mal...@intel.com> --- port.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 8 deletions(-) diff --git a/port.c b/port.c index e31e697310c2..e632316aa492 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, @@ -1534,6 +1536,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; @@ -1548,14 +1553,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.control = CTL_OTHER; msg->header.logMessageInterval = port_is_ieee8021as(p) ? @@ -2300,7 +2314,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, @@ -2337,11 +2360,22 @@ int process_pdelay_req(struct port *p, struct ptp_message *m) rsp->header.control = CTL_OTHER; 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; @@ -2390,6 +2424,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; @@ -2407,17 +2450,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)) @@ -2440,7 +2491,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) @@ -2456,7 +2507,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 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel