From: Kishen Maloor <[email protected]>
Signed-off-by: Richard Cochran <[email protected]>
---
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel