Subject: [PATCH] Only forward responses to UDS port with corresponding requests 
on the UDS port, and always send management with a unique sequence count from 
uds.

1.      Only forward responses to UDS port with a corresponding requests on the 
UDS port.

The context of the issue/feature:  
See the problem description below.

The problem that needs fixing (or missing feature):
When ptp4l is configured as a boundary clock and a host on ethernet is issuing 
excessive management requests (a PTP monitoring tool) then the requests get 
forwarded across the boundary clock and the subsequent responses get forwarded 
to the UDS port.  The UDS code sends messages to the uds address of the last 
process it received a message from.  The phc2sys daemon is not expecting these 
responses which causes its receive buffers to get full and then the ptp4l send 
buffers get full which causes ptp4l to lock until phc2sys reads the messages 
from its uds port.  ptp4l will lock until phc2sys reads messages from the uds 
port which happens every 60sec.  

How the proposed solution fixes the problem:  
Ptp4l will only forward ptp management response messages to the uds port if it 
was requested by the uds port.  This will prevent the uds port buffers from 
getting full and causing ptp4l to hang until the buffers are read.



2.      PTP management messages originated from UDS (pmc) do not have the 
correct source clock id, and always have the same sequence count which prevents 
end nodes on ethernet from responding.


The context of the issue/feature:  
See the problem description below.

The problem that needs fixing (or missing feature):
PTP management messages originated from UDS (pmc) do not have the correct 
source clock id, and always have the same sequence count which prevents end 
nodes on ethernet from responding.

How the proposed solution fixes the problem:  
Ptp4l will now maintain a static sequence count and send PTP management 
messages using this sequence count so each PTP management message will have a 
unique sequential sequence count.  The correct source clock ID is also included 
in the management messages.



Signed-off-by: Eric Decker <edec...@oldi.com>

---
 clock.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 81 insertions(+), 5 deletions(-)

diff --git a/clock.c b/clock.c
index d428ae2..897a623 100644
--- a/clock.c
+++ b/clock.c
@@ -981,7 +981,7 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
        }
        c->default_dataset.localPriority =
                config_get_int(config, NULL, "G.8275.defaultDS.localPriority");
-       c->max_steps_removed = config_get_int(config, NULL,"maxStepsRemoved");
+       c->max_steps_removed = config_get_int(config, NULL, "maxStepsRemoved");
        c->clock_class_threshold = config_get_int(config, NULL, 
"clock_class_threshold");
 
        /* Harmonize the twoStepFlag with the time_stamping option. */
@@ -1381,7 +1381,9 @@ static int clock_do_forward_mgmt(struct clock *c,
                return 0;
 
        /* Don't forward any requests to the UDS-RW port
-          (the UDS-RO port doesn't allow any forwarding). */
+        *  (the UDS-RO port doesn't allow any forwarding).
+        *  Do forward responses.
+        */
        if (out == c->uds_rw_port) {
                switch (management_action(msg)) {
                case GET:
@@ -1393,7 +1395,8 @@ static int clock_do_forward_mgmt(struct clock *c,
 
        if (!*pre_sent) {
                /* delay calling msg_pre_send until
-                * actually forwarding */
+                * actually forwarding
+                */
                msg_pre_send(msg);
                *pre_sent = 1;
        }
@@ -1404,17 +1407,90 @@ static void clock_forward_mgmt_msg(struct clock *c, 
struct port *p, struct ptp_m
 {
        struct port *piter;
        int pdulen = 0, msg_ready = 0;
+       static UInteger16 mgmt_seq_count;
+       UInteger16 temp_seq_count = 0;
+
+       struct uds_mgmt_req {
+               UInteger16 seqId;
+               Enumeration16 id;
+       };
+       #define MGMT_REQ_Q_SIZE 4
+       static struct uds_mgmt_req uds_req[MGMT_REQ_Q_SIZE] = {0};
+       static unsigned int uds_req_index;
+       int forward_to_uds = 0;
+       struct management_tlv *mgt =
+               (struct management_tlv *) msg->management.suffix;
 
        if (forwarding(c, p) && msg->management.boundaryHops) {
                pdulen = msg->header.messageLength;
                msg->management.boundaryHops--;
+
+               if (p == c->uds_rw_port) {
+                       /* Send with a unique sequence count and correct clock 
identity.
+                        * If ingress port is uds port (pmc) increment sequence 
count.
+                        */
+                       temp_seq_count = msg->header.sequenceId;
+                       msg->header.sequenceId = mgmt_seq_count++;
+                       msg->header.sourcePortIdentity.clockIdentity = 
clock_identity(c);
+
+                       /* Record outgoing requests from uds port.
+                        * We will only forward responses to those requests to 
uds port.
+                        */
+                       switch (management_action(msg)) {
+                       case GET:
+                       case SET:
+                       case COMMAND:
+                               if (strstr(msg->address.sun.sun_path, "pmc") != 
NULL ||
+                                       strstr(msg->address.sun.sun_path, 
"phc2sys")) {
+                                       uds_req[uds_req_index].id = mgt->id;
+                                       uds_req[uds_req_index].seqId = 
msg->header.sequenceId;
+                                       uds_req_index++;
+                                       if (uds_req_index >= MGMT_REQ_Q_SIZE)
+                                               uds_req_index = 0;
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+               }
+
+               /* Only forward responses to UDS port with
+                *      corresponding requests on the UDS port.
+                */
+               switch (management_action(msg)) {
+               case GET:
+               case SET:
+               case COMMAND:
+                       break;
+               default:
+                       for (unsigned int x = 0; x < MGMT_REQ_Q_SIZE; x++) {
+                               /* We don't have a destination addresss yet.
+                                */
+                               if (uds_req[x].id == mgt->id &&
+                                   uds_req[x].seqId == msg->header.sequenceId) 
{
+                                       forward_to_uds = 1;
+                                       break;
+                               }
+                       }
+                       break;
+               }
+
                LIST_FOREACH(piter, &c->ports, list) {
                        if (clock_do_forward_mgmt(c, p, piter, msg, &msg_ready))
                                pr_err("%s: management forward failed",
                                       port_log_name(piter));
                }
-               if (clock_do_forward_mgmt(c, p, c->uds_rw_port, msg, 
&msg_ready))
-                       pr_err("uds port: management forward failed");
+
+               if (forward_to_uds == 1) {
+                       if (clock_do_forward_mgmt(c, p, c->uds_rw_port, msg, 
&msg_ready))
+                               pr_err("uds port: management forward failed");
+               }
+
+               /* If ingress port == uds port (pmc) restore old sequence count.
+                */
+               if (p == c->uds_rw_port)
+                       msg->header.sequenceId = temp_seq_count;
+
                if (msg_ready) {
                        msg_post_recv(msg, pdulen);
                        msg->management.boundaryHops++;
-- 
2.17.1



_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to