Hi Richard, I haven't tested this but here are some comments.
On Thu, 30 Nov 2023 at 08:58, Richard Cochran <richardcoch...@gmail.com> wrote: > 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"), I assume the use of this is simply to set unique names for per-port sockets. Maybe something like tempnam() could be used instead. > + 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"); Should this fall back to port_number(p)? > + 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, The sdoId is (by either IEEE 1588 or 802.1AS) different for the CMLDS than for a P2P_COMMON port, I think a check in port_ignore will discard the messages as a result. Maybe hardcode TS_CMLDS here? (with TS_CMLDS defined in msg.h next to TS_IEEE_8021AS) Using pmc here surely works but I wonder if it's not actually more work than reusing c->uds_port. > + 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); cmlds->meanLinkDelay is already a TimeInterval in case you want to use that. > + > + if (p->state == PS_UNCALIBRATED || p->state == PS_SLAVE) { > + const struct timestamp dummy = {0}; > + const tmv_t tx = timestamp_to_tmv(dummy); tmv_zero() could also be used. > + clock_peer_delay(p->clock, p->peer_delay, tx, tx, > + p->nrate.ratio); p->nrate.ratio hasn't been set yet, I think a line similar to this is missing: p->nrate.ratio = 1.0 + (double) cmlds->scaledNeighborRateRatio / POW2_41; The CMLDS port will also need to ensure that the NRR is calculated because now it's done conditionally. In Kishen's patch series struct cmlds_info_np also had a .serviceMeasurementValid which enabled the port_capable() logic to work and IIRC that is important at least for 802.1AS compliance. If that was to be re-added, the event would need to be emitted in an extra place in the CMLDS, perhaps where pdr_missing is incremented. Best regards _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel