From: Kishen Maloor <kishen.mal...@intel.com>

Signed-off-by: Richard Cochran <richardcoch...@gmail.com>
---
 config.c       |   4 ++
 dm.h           |   3 +
 fd.h           |   1 +
 makefile       |   4 +-
 port.c         | 166 +++++++++++++++++++++++++++++++++++++++++++++++--
 port_private.h |   3 +
 6 files changed, 174 insertions(+), 7 deletions(-)

diff --git a/config.c b/config.c
index fe65b76..05ffd3c 100644
--- a/config.c
+++ b/config.c
@@ -171,6 +171,7 @@ static struct config_enum delay_filter_enu[] = {
 
 static struct config_enum delay_mech_enu[] = {
        { "Auto", DM_AUTO },
+       { "COMMON_P2P", DM_COMMON_P2P },
        { "E2E",  DM_E2E },
        { "P2P",  DM_P2P },
        { "NONE", DM_NO_MECHANISM },
@@ -249,6 +250,9 @@ struct config_item config_tab[] = {
        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),
+       PORT_ITEM_STR("cmlds_client_address", "/var/run/cmlds_cleint"),
+       PORT_ITEM_INT("cmlds_port", 1, 1, UINT16_MAX),
+       PORT_ITEM_STR("cmlds_server_address", "/var/run/cmlds_server"),
        GLOB_ITEM_ENU("dataset_comparison", DS_CMP_IEEE1588, dataset_comp_enu),
        PORT_ITEM_INT("delayAsymmetry", 0, INT_MIN, INT_MAX),
        PORT_ITEM_ENU("delay_filter", FILTER_MOVING_MEDIAN, delay_filter_enu),
diff --git a/dm.h b/dm.h
index 47bd847..80d1ce5 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/fd.h b/fd.h
index 16420d7..9a072ab 100644
--- a/fd.h
+++ b/fd.h
@@ -39,6 +39,7 @@ enum {
        FD_SYNC_TX_TIMER,
        FD_UNICAST_REQ_TIMER,
        FD_UNICAST_SRV_TIMER,
+       FD_CMLDS,
        FD_RTNL,
        N_POLLFD,
 };
diff --git a/makefile b/makefile
index 7fc5f6f..e9c1ccc 100644
--- a/makefile
+++ b/makefile
@@ -30,8 +30,8 @@ TS2PHC        = ts2phc.o lstab.o nmea.o serial.o sock.o 
ts2phc_generic_pps_source.o \
  ts2phc_nmea_pps_source.o ts2phc_phc_pps_source.o ts2phc_pps_sink.o 
ts2phc_pps_source.o
 OBJ    = bmc.o clock.o clockadj.o clockcheck.o config.o designated_fsm.o \
  e2e_tc.o fault.o $(FILTERS) fsm.o hash.o interface.o monitor.o msg.o phc.o \
- port.o port_signaling.o pqueue.o print.o ptp4l.o p2p_tc.o rtnl.o $(SERVOS) \
- sk.o stats.o tc.o $(TRANSP) telecom.o tlv.o tsproc.o unicast_client.o \
+ pmc_common.o port.o port_signaling.o pqueue.o print.o ptp4l.o p2p_tc.o rtnl.o 
\
+ $(SERVOS) sk.o stats.o tc.o $(TRANSP) telecom.o tlv.o tsproc.o 
unicast_client.o \
  unicast_fsm.o unicast_service.o util.o version.o
 
 OBJECTS        = $(OBJ) hwstamp_ctl.o nsm.o phc2sys.o phc_ctl.o pmc.o 
pmc_agent.o \
diff --git a/port.c b/port.c
index 8afe1b2..75b4dd8 100644
--- a/port.c
+++ b/port.c
@@ -963,7 +963,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);
@@ -1868,6 +1869,33 @@ static void port_clear_fda(struct port *p, int count)
                p->fda.fd[i] = -1;
 }
 
+static int port_cmlds_initialize(struct port *p)
+{
+       struct config *cfg = clock_config(p->clock);
+       struct subscribe_events_np sen = {0};
+       const int zero_datalen = 1;
+       const UInteger8 hops = 0;
+
+       p->cmlds_port = config_get_int(cfg, p->name, "cmlds_port");
+       p->cmlds_pmc = pmc_create(cfg, TRANS_UDS,
+                                 config_get_string(cfg, p->name, 
"cmlds_client_address"),
+                                 config_get_string(cfg, p->name, 
"cmlds_server_address"),
+                                 hops,
+                                 config_get_int(cfg, NULL, "domainNumber"),
+                                 config_get_int(cfg, p->name, 
"transportSpecific") << 4,
+                                 zero_datalen);
+       if (!p->cmlds_pmc) {
+               return -1;
+       }
+
+       event_bitmask_set(sen.bitmask, NOTIFY_CMLDS, TRUE);
+       sen.duration = 3600;
+       p->fda.fd[FD_CMLDS] = pmc_get_transport_fd(p->cmlds_pmc);
+       pmc_send_set_action(p->cmlds_pmc, MID_SUBSCRIBE_EVENTS_NP, &sen, 
sizeof(sen));
+
+       return 0;
+}
+
 void port_disable(struct port *p)
 {
        int i;
@@ -1885,6 +1913,12 @@ void port_disable(struct port *p)
                close(p->fda.fd[FD_FIRST_TIMER + i]);
        }
 
+       if (p->cmlds_pmc) {
+               pmc_destroy(p->cmlds_pmc);
+               p->fda.fd[FD_CMLDS] = -1;
+               p->cmlds_pmc = NULL;
+       }
+
        /* Keep rtnl socket to get link status info. */
        port_clear_fda(p, FD_RTNL);
        clock_fda_changed(p->clock);
@@ -1932,7 +1966,8 @@ int port_initialize(struct port *p)
                pr_err("inhibit_delay_req can only be set when asCapable == 
'true'.");
                return -1;
        }
-       if (port_delay_mechanism(p) == DM_NO_MECHANISM) {
+       if (port_delay_mechanism(p) == DM_COMMON_P2P ||
+           port_delay_mechanism(p) == DM_NO_MECHANISM) {
                p->inhibit_delay_req = 1;
        }
 
@@ -1960,6 +1995,10 @@ int port_initialize(struct port *p)
                goto no_tmo;
        }
 
+       if (port_delay_mechanism(p) == DM_COMMON_P2P && 
port_cmlds_initialize(p)) {
+               goto no_tmo;
+       }
+
        /* No need to open rtnl socket on UDS port. */
        if (!port_is_uds(p)) {
                /*
@@ -2101,6 +2140,65 @@ int process_announce(struct port *p, struct ptp_message 
*m)
        return result;
 }
 
+static int process_cmlds(struct port *p)
+{
+       struct cmlds_info_np *cmlds;
+       struct management_tlv *mgt;
+       struct ptp_message *msg;
+       struct TLV *tlv;
+       int err = 0;
+
+       msg = pmc_recv(p->cmlds_pmc);
+       if (!msg) {
+               pr_err("%s: pmc_recv failed", p->log_name);
+               return -1;
+       }
+       if (msg_type(msg) != MANAGEMENT) {
+               pr_err("%s: pmc_recv bad message", p->log_name);
+               err = -1;
+               goto out;
+       }
+       tlv = (struct TLV *) msg->management.suffix;
+       if (tlv->type != TLV_MANAGEMENT) {
+               pr_err("%s: pmc_recv bad message", p->log_name);
+               err = -1;
+               goto out;
+       }
+       mgt = (struct management_tlv *) msg->management.suffix;
+       if (mgt->length == 2 && mgt->id != MID_NULL_MANAGEMENT) {
+               pr_err("%s: pmc_recv bad length", p->log_name);
+               goto out;
+       }
+
+       switch (mgt->id) {
+       case MID_CMLDS_INFO_NP:
+               if (msg->header.sourcePortIdentity.portNumber != p->cmlds_port) 
{
+                       break;
+               }
+               cmlds = (struct cmlds_info_np *) mgt->data;
+               p->peer_delay = nanoseconds_to_tmv(cmlds->meanLinkDelay >> 16);
+               p->peerMeanPathDelay = tmv_to_TimeInterval(p->peer_delay);
+
+               if (p->state == PS_UNCALIBRATED || p->state == PS_SLAVE) {
+                       const struct timestamp dummy = {0};
+                       const tmv_t tx = timestamp_to_tmv(dummy);
+                       clock_peer_delay(p->clock, p->peer_delay, tx, tx,
+                                        p->nrate.ratio);
+               }
+               break;
+       case MID_SUBSCRIBE_EVENTS_NP:
+               break;
+       default:
+               pr_err("%s: pmc_recv bad mgt id 0x%x", p->log_name, mgt->id);
+               err = -1;
+               break;
+       }
+
+out:
+       msg_put(msg);
+       return err;
+}
+
 static int process_delay_req(struct port *p, struct ptp_message *m)
 {
        struct ptp_message *msg;
@@ -2112,7 +2210,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;
        }
@@ -2277,6 +2375,9 @@ int process_pdelay_req(struct port *p, struct ptp_message 
*m)
                return -1;
        }
 
+       if (p->delayMechanism == DM_COMMON_P2P) {
+               return 0;
+       }
        if (p->delayMechanism == DM_E2E) {
                pr_warning("%s: pdelay_req on E2E port", p->log_name);
                return 0;
@@ -2472,6 +2573,9 @@ calc:
 
 int process_pdelay_resp(struct port *p, struct ptp_message *m)
 {
+       if (p->delayMechanism == DM_COMMON_P2P) {
+               return 0;
+       }
        if (p->peer_delay_resp) {
                 if (!p->multiple_pdr_detected) {
                         pr_err("%s: multiple peer responses", p->log_name);
@@ -2642,6 +2746,48 @@ struct foreign_clock *port_compute_best(struct port *p)
        return p->best;
 }
 
+static void port_cmlds_transition(struct port *p, enum port_state next)
+{
+       port_clr_tmo(p->fda.fd[FD_ANNOUNCE_TIMER]);
+       port_clr_tmo(p->fda.fd[FD_SYNC_RX_TIMER]);
+       port_clr_tmo(p->fda.fd[FD_DELAY_TIMER]);
+       port_clr_tmo(p->fda.fd[FD_QUALIFICATION_TIMER]);
+       port_clr_tmo(p->fda.fd[FD_MANNO_TIMER]);
+       port_clr_tmo(p->fda.fd[FD_SYNC_TX_TIMER]);
+       /* Leave FD_UNICAST_REQ_TIMER running. */
+
+       switch (next) {
+       case PS_INITIALIZING:
+               break;
+       case PS_FAULTY:
+       case PS_DISABLED:
+               port_disable(p);
+               break;
+       case PS_LISTENING:
+               port_set_announce_tmo(p);
+               break;
+       case PS_PRE_MASTER:
+               port_set_qualification_tmo(p);
+               break;
+       case PS_MASTER:
+       case PS_GRAND_MASTER:
+               if (!p->inhibit_announce) {
+                       set_tmo_log(p->fda.fd[FD_MANNO_TIMER], 1, -10); /*~1ms*/
+               }
+               port_set_sync_tx_tmo(p);
+               break;
+       case PS_PASSIVE:
+               port_set_announce_tmo(p);
+               break;
+       case PS_UNCALIBRATED:
+               flush_last_sync(p);
+               /* fall through */
+       case PS_SLAVE:
+               port_set_announce_tmo(p);
+               break;
+       };
+}
+
 static void port_e2e_transition(struct port *p, enum port_state next)
 {
        port_clr_tmo(p->fda.fd[FD_ANNOUNCE_TIMER]);
@@ -2747,10 +2893,16 @@ static void bc_dispatch(struct port *p, enum fsm_event 
event, int mdiff)
                return;
        }
 
-       if (p->delayMechanism == DM_P2P) {
+       switch (p->delayMechanism) {
+       case DM_P2P:
                port_p2p_transition(p, p->state);
-       } else {
+               break;
+       case DM_COMMON_P2P:
+               port_cmlds_transition(p, p->state);
+               break;
+       default:
                port_e2e_transition(p, p->state);
+               break;
        }
 
        if (p->jbod && p->state == PS_UNCALIBRATED && p->phc_index >= 0 ) {
@@ -2944,6 +3096,10 @@ static enum fsm_event bc_event(struct port *p, int 
fd_index)
                p->service_stats.unicast_request_timeout++;
                return unicast_client_timer(p) ? EV_FAULT_DETECTED : EV_NONE;
 
+       case FD_CMLDS:
+               pr_debug("%s: CMLDS push notification", p->log_name);
+               return process_cmlds(p) ? EV_FAULT_DETECTED : EV_NONE;
+
        case FD_RTNL:
                pr_debug("%s: received link status notification", p->log_name);
                rtnl_link_status(fd, p->name, port_link_status, p);
diff --git a/port_private.h b/port_private.h
index 1ef816a..7c8fcd9 100644
--- a/port_private.h
+++ b/port_private.h
@@ -26,6 +26,7 @@
 #include "fsm.h"
 #include "monitor.h"
 #include "msg.h"
+#include "pmc_common.h"
 #include "power_profile.h"
 #include "tmv.h"
 
@@ -165,6 +166,8 @@ struct port {
        /* slave event monitoring */
        struct monitor *slave_event_monitor;
        bool unicast_state_dirty;
+       struct pmc *cmlds_pmc;
+       int cmlds_port;
 };
 
 #define portnum(p) (p->portIdentity.portNumber)
-- 
2.39.2



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

Reply via email to