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