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

Reply via email to