This commit implements asCapableAcrossDomains and neighborGptpCapable, as specified in IEEE 802.1AS-2020 Section 11.2.2.
In scenario with multiple PTP domains, a domain is asCapable only when both asCapableAcrossDomains and neighborGptpCapable are TRUE. The determination of asCapableAcrossDomains relies on the Common Mean Link Delay Service (CMLDS). Simultaneously, neighborGptpCapable is set to TRUE upon receiving periodic gPTP-Capable TLV signaling messages from the peer, adhering to the logGptpCapableMessageInterval value set in the message. The introduction of the `domain_zero_capable` function ensures backward compatibility with AS-2011, specifically addressing Condition (f)(2) of IEEE 802.1AS-2020 Section 11.2.2. Signed-off-by: Chwee-Lin Choong <chwee.lin.cho...@intel.com> --- port.c | 65 ++++++++++++++++++++++++++++++++++---------------- port_private.h | 3 +++ 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/port.c b/port.c index e468805..c20e503 100644 --- a/port.c +++ b/port.c @@ -695,6 +695,13 @@ static int peer_prepare_and_send(struct port *p, struct ptp_message *msg, return 0; } +void domain_zero_capable(struct port *p, struct ptp_message *msg) { + if (clock_domain_number(p->clock) == 0x0 && + msg_transport_specific(msg) == 0x10) { + p->neighborGptpCapable = true; + } +} + int port_capable(struct port *p) { if (!port_is_ieee8021as(p)) { @@ -703,7 +710,7 @@ int port_capable(struct port *p) } if (tmv_to_nanoseconds(p->peer_delay) > p->neighborPropDelayThresh) { - if (p->asCapable) + if (p->asCapableAcrossDomains) pr_debug("%s: peer_delay (%" PRId64 ") > neighborPropDelayThresh " "(%" PRId32 "), resetting asCapable", p->log_name, tmv_to_nanoseconds(p->peer_delay), @@ -712,7 +719,7 @@ int port_capable(struct port *p) } if (tmv_to_nanoseconds(p->peer_delay) < p->min_neighbor_prop_delay) { - if (p->asCapable) + if (p->asCapableAcrossDomains) pr_debug("%s: peer_delay (%" PRId64 ") < min_neighbor_prop_delay " "(%" PRId32 "), resetting asCapable", p->log_name, tmv_to_nanoseconds(p->peer_delay), @@ -721,46 +728,59 @@ int port_capable(struct port *p) } if (p->pdr_missing > ALLOWED_LOST_RESPONSES) { - if (p->asCapable) + if (p->asCapableAcrossDomains) pr_debug("%s: missed %d peer delay resp, " "resetting asCapable", p->log_name, p->pdr_missing); goto not_capable; } if (p->multiple_seq_pdr_count) { - if (p->asCapable) + if (p->asCapableAcrossDomains) pr_debug("%s: multiple sequential peer delay resp, " "resetting asCapable", p->log_name); goto not_capable; } if (!p->peer_portid_valid) { - if (p->asCapable) + if (p->asCapableAcrossDomains) pr_debug("%s: invalid peer port id, " "resetting asCapable", p->log_name); goto not_capable; } if (!p->nrate.ratio_valid) { - if (p->asCapable) + if (p->asCapableAcrossDomains) pr_debug("%s: invalid nrate, " "resetting asCapable", p->log_name); goto not_capable; } -capable: - if (p->asCapable == NOT_CAPABLE) { - pr_debug("%s: setting asCapable", p->log_name); - p->asCapable = AS_CAPABLE; + capable: + if (p->asCapableAcrossDomains == NOT_CAPABLE) { + pr_debug("%s: setting asCapable", p->log_name); + p->asCapableAcrossDomains = AS_CAPABLE; } - return 1; -not_capable: - if (p->asCapable) - port_nrate_initialize(p); - p->asCapable = NOT_CAPABLE; - return 0; -} + if (p->asCapable == ALWAYS_CAPABLE) { + return 1; + } + + if (p->neighborGptpCapable == true) { + p->asCapable = AS_CAPABLE; + return 1; + } else { + p->asCapable = NOT_CAPABLE; + return 0; + } + + not_capable: + if (p->asCapable || p->asCapableAcrossDomains) + port_nrate_initialize(p); + p->asCapableAcrossDomains = NOT_CAPABLE; + p->asCapable = NOT_CAPABLE; + + return 0; + } int port_clr_tmo(int fd) { @@ -1576,9 +1596,8 @@ static int port_pdelay_request(struct port *p) } if (p->peer_delay_req) { - if (port_capable(p)) { - p->pdr_missing++; - } + p->pdr_missing++; + port_capable(p); msg_put(p->peer_delay_req); } p->peer_delay_req = msg; @@ -2318,6 +2337,8 @@ int process_pdelay_req(struct port *p, struct ptp_message *m) pid2str(&p->peer_portid)); } + domain_zero_capable(p, m); + rsp = msg_allocate(); if (!rsp) { return -1; @@ -2519,6 +2540,8 @@ int process_pdelay_resp(struct port *p, struct ptp_message *m) pid2str(&p->peer_portid)); } + domain_zero_capable(p, m); + if (p->peer_delay_resp) { msg_put(p->peer_delay_resp); } @@ -2534,6 +2557,8 @@ void process_pdelay_resp_fup(struct port *p, struct ptp_message *m) return; } + domain_zero_capable(p, m); + if (p->peer_delay_fup) { msg_put(p->peer_delay_fup); } diff --git a/port_private.h b/port_private.h index 5ef9d62..e9180de 100644 --- a/port_private.h +++ b/port_private.h @@ -110,6 +110,7 @@ struct port { enum port_state state; /*portState*/ Integer64 asymmetry; enum as_capable asCapable; + bool asCapableAcrossDomains; Integer8 logMinDelayReqInterval; TimeInterval peerMeanPathDelay; Integer8 initialLogAnnounceInterval; @@ -152,6 +153,7 @@ struct port { struct PortServiceStats service_stats; Integer8 logGptpCapableMessageInterval; Integer8 gPtpCapableReceiptTimeout; + Boolean neighborGptpCapable; /* foreignMasterDS */ LIST_HEAD(fm, foreign_clock) foreign_masters; /* TC book keeping */ @@ -178,6 +180,7 @@ enum fsm_event p2p_event(struct port *p, int fd_index); int clear_fault_asap(struct fault_interval *faint); void delay_req_prune(struct port *p); +void domain_zero_capable(struct port *p, struct ptp_message *msg); void fc_clear(struct foreign_clock *fc); void flush_delay_req(struct port *p); void flush_last_sync(struct port *p); -- 2.42.0 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel