Adding virtual port support for ts2phc. Signed-off-by: Greg Armstrong <greg.armstrong...@renesas.com> Signed-off-by: Leon Goldin <leon.goldin...@renesas.com> Signed-off-by: Vipin Sharma <vipin.sha...@syncmonk.net> Signed-off-by: Devasish Dey <devasish....@syncmonk.net> --- makefile | 6 +- ts2phc_vport.c | 282 +++++++++++++++++++++++++++++++++++++++++++++++++ ts2phc_vport.h | 28 +++++ 3 files changed, 313 insertions(+), 3 deletions(-) create mode 100644 ts2phc_vport.c create mode 100644 ts2phc_vport.h
diff --git a/makefile b/makefile index 7d8c0d3..3631f1d 100644 --- a/makefile +++ b/makefile @@ -27,7 +27,7 @@ FILTERS = filter.o mave.o mmedian.o SERVOS = linreg.o ntpshm.o nullf.o pi.o servo.o TRANSP = raw.o transport.o udp.o udp6.o uds.o vport.o 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 + ts2phc_nmea_pps_source.o ts2phc_phc_pps_source.o ts2phc_pps_sink.o ts2phc_pps_source.o ts2phc_vport.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) \ @@ -68,8 +68,8 @@ phc_ctl: phc_ctl.o phc.o sk.o util.o clockadj.o sysoff.o print.o version.o timemaster: phc.o print.o rtnl.o sk.o timemaster.o util.o version.o -ts2phc: config.o clockadj.o hash.o interface.o phc.o print.o $(SERVOS) sk.o \ - $(TS2PHC) util.o version.o +ts2phc: config.o clockadj.o hash.o msg.o tlv.o interface.o phc.o print.o $(SERVOS) sk.o \ + $(TS2PHC) $(TRANSP) util.o version.o version.o: .version version.sh $(filter-out version.d,$(DEPEND)) diff --git a/ts2phc_vport.c b/ts2phc_vport.c new file mode 100644 index 0000000..ae9cbe9 --- /dev/null +++ b/ts2phc_vport.c @@ -0,0 +1,282 @@ +/** + * @file ts2phc_vport.c + * @note Copyright (C) 2022 SyncMonk Technologies <servi...@syncmonk.net> + * @note SPDX-License-Identifier: GPL-2.0+ + * + */ +#include <stdbool.h> +#include <stdlib.h> + +#include "address.h" +#include "ts2phc_vport.h" +#include "print.h" +#include "port.h" +#include "transport.h" + +#define RECORDS_PER_MESSAGE 1 + +struct ts2phc_vport_message { + struct ptp_message *msg; + int records_per_msg; + int count; +}; + +struct ts2phc_vport { + struct fdarray fda; + struct transport *trp; + struct interface *iface; + struct ts2phc_vport_message announce; + struct ts2phc_vport_message sync; + struct { + UInteger16 announce; + UInteger16 sync; + } seqnum; + struct PortIdentity portIdentity; + Integer16 utcOffset; + UInteger8 priority1; + struct ClockQuality clockQuality; + UInteger8 priority2; + struct ClockIdentity clockIdentity; + UInteger8 transportSpecific; + UInteger8 domainNumber; + UInteger8 flags; + Integer8 logAnnounceInterval; + Integer8 logSyncInterval; + Enumeration8 timeSource; +}; + +static bool ts2phc_vport_active(struct ts2phc_vport *ts2phc_vport) +{ + return ts2phc_vport->trp ? true : false; +} + +static int ts2phc_vport_forward(struct ts2phc_vport *port, struct ptp_message *msg) +{ + int cnt; + if (msg_pre_send(msg)) { + return -1; + } + cnt = transport_sendto(port->trp, &port->fda, TRANS_GENERAL, msg); + if (cnt <= 0) { + pr_debug("failed to send message to ts2phc_vport: "); + } + + msg->header.sequenceId++; + return 0; +} + +static int ts2phc_vport_init_announce(struct ts2phc_vport *p, + struct address address) +{ + + struct ptp_message *msg; + + msg = msg_allocate(); + if (!msg) { + return -1; + } + + msg->hwts.type = TS_ONESTEP; + msg->header.tsmt = ANNOUNCE | p->transportSpecific; + msg->header.ver = PTP_VERSION; + msg->header.messageLength = sizeof(struct announce_msg); + msg->header.domainNumber = p->domainNumber; + msg->header.sourcePortIdentity = p->portIdentity; + msg->header.sequenceId = p->seqnum.announce++; + msg->header.control = CTL_OTHER; + msg->header.logMessageInterval = p->logAnnounceInterval; + msg->header.flagField[1] = p->flags | PTP_TIMESCALE; + + msg->announce.currentUtcOffset = p->utcOffset; + msg->announce.grandmasterPriority1 = p->priority1; + msg->announce.grandmasterClockQuality = p->clockQuality; + msg->announce.grandmasterPriority2 = p->priority2; + msg->announce.grandmasterIdentity = p->clockIdentity; + msg->announce.stepsRemoved = 0; + msg->announce.timeSource = p->timeSource; + msg->address = address; + + p->announce.msg = msg; + + return 0; +} + +static int ts2phc_vport_init_sync(struct ts2phc_vport *p, + struct address address) +{ + + struct ptp_message *msg; + + msg = msg_allocate(); + if (!msg) { + return -1; + } + msg->hwts.type = TS_ONESTEP; + msg->header.tsmt = SYNC | p->transportSpecific; + msg->header.ver = PTP_VERSION; + msg->header.messageLength = sizeof(struct sync_msg); + msg->header.domainNumber = p->domainNumber; + msg->header.sourcePortIdentity = p->portIdentity; + msg->header.sequenceId = p->seqnum.sync++; + msg->header.control = CTL_SYNC; + msg->header.logMessageInterval = p->logSyncInterval; + msg->address = address; + + p->sync.msg = msg; + + return 0; +} + +struct ts2phc_vport *ts2phc_vport_create(struct config *config) +{ + struct ts2phc_vport *ts2phc_vport; + struct address address; + struct sockaddr_un sa; + + ts2phc_vport = calloc(1, sizeof(*ts2phc_vport)); + if (!ts2phc_vport) { + return NULL; + } + const char *iface_name; + + iface_name = config_get_string(config, NULL, "vport_address"); + if (!iface_name || !iface_name[0]) { + /* Return an inactive ts2phc_vport. */ + return ts2phc_vport; + } + memset(&sa, 0, sizeof(sa)); + sa.sun_family = AF_LOCAL; + snprintf(sa.sun_path, sizeof(sa.sun_path) - 1, "%s", iface_name); + address.sun = sa; + address.len = sizeof(sa); + + ts2phc_vport->trp = transport_create(config, TRANS_VPORT); + if (!ts2phc_vport->trp) { + pr_err("failed to create transport"); + free(ts2phc_vport); + return NULL; + } + + ts2phc_vport->iface = interface_create(iface_name); + if (!ts2phc_vport->iface) { + pr_err("failed to create interface"); + goto failed; + } + interface_ensure_tslabel(ts2phc_vport->iface); + + if (transport_open(ts2phc_vport->trp, ts2phc_vport->iface, + &ts2phc_vport->fda, TS_SOFTWARE)) { + pr_err("failed to open transport"); + goto no_trans_open; + } + + ts2phc_vport->utcOffset = + config_get_int(config, NULL, "utc_offset"); + ts2phc_vport->transportSpecific = + config_get_int(config, NULL, "transportSpecific") << 4; + ts2phc_vport->domainNumber = + config_get_int(config, NULL, "domainNumber"); + + ts2phc_vport->logSyncInterval = + config_get_int(config, NULL, "logSyncInterval"); + ts2phc_vport->logAnnounceInterval = + config_get_int(config, NULL, "logAnnounceInterval"); + + ts2phc_vport->priority1 = + config_get_int(config, NULL, "priority1"); + ts2phc_vport->priority2 = + config_get_int(config, NULL, "priority2"); + ts2phc_vport->timeSource = + config_get_int(config, NULL, "timeSource"); + + ts2phc_vport->clockQuality.clockClass = + config_get_int(config, NULL, "clockClass"); + ts2phc_vport->clockQuality.clockAccuracy = + config_get_int(config, NULL, "clockAccuracy"); + ts2phc_vport->clockQuality.offsetScaledLogVariance = + config_get_int(config, NULL, "offsetScaledLogVariance"); + + if (strcmp(config_get_string(config, NULL, "clockIdentity"), + "000000.0000.000000") == 0) { + pr_warning("vPort clockIdentity 000000.0000.000000"); + } else { + if (str2cid(config_get_string(config, NULL, "clockIdentity"), + &ts2phc_vport->clockIdentity)) { + pr_err("failed to set clock identity"); + return NULL; + } + } + + ts2phc_vport->portIdentity.clockIdentity = ts2phc_vport->clockIdentity; + + if (ts2phc_vport_init_announce(ts2phc_vport, address)) { + goto no_trans_open; + } + if (ts2phc_vport_init_sync(ts2phc_vport, address)) { + msg_put(ts2phc_vport->announce.msg); + goto no_trans_open; + } + + return ts2phc_vport; + +no_trans_open: + interface_destroy(ts2phc_vport->iface); +failed: + if (ts2phc_vport->trp) + transport_destroy(ts2phc_vport->trp); + free(ts2phc_vport); + return NULL; +} + +void ts2phc_vport_destroy(struct ts2phc_vport *ts2phc_vport) +{ + if (ts2phc_vport->announce.msg) { + msg_put(ts2phc_vport->announce.msg); + } + if (ts2phc_vport->sync.msg) { + msg_put(ts2phc_vport->sync.msg); + } + free(ts2phc_vport); +} + +int ts2phc_vport_tx_sync(struct ts2phc_vport *ts2phc_vport, + tmv_t t1, tmv_t corr, tmv_t t2) +{ + struct ptp_message *msg; + int err; + struct address address; + + if (!ts2phc_vport_active(ts2phc_vport)) { + return 0; + } + + msg = ts2phc_vport->sync.msg; + address = msg->address; + ts2phc_vport->sync.count++; + + err = ts2phc_vport_forward(ts2phc_vport, msg); + msg_put(msg); + ts2phc_vport_init_announce(ts2phc_vport, address); + return err; +} + + +int ts2phc_vport_tx_announce(struct ts2phc_vport *ts2phc_vport) +{ + struct ptp_message *msg; + int err; + struct address address; + + if (!ts2phc_vport_active(ts2phc_vport)) { + return 0; + } + + msg = ts2phc_vport->announce.msg; + address = msg->address; + ts2phc_vport->announce.count++; + + err = ts2phc_vport_forward(ts2phc_vport, msg); + msg_put(msg); + ts2phc_vport_init_announce(ts2phc_vport, address); + return err; +} diff --git a/ts2phc_vport.h b/ts2phc_vport.h new file mode 100644 index 0000000..de97fbd --- /dev/null +++ b/ts2phc_vport.h @@ -0,0 +1,28 @@ +/** + * @file ts2phc_vport.h + * @note Copyright (C) 2021 SyncMonk Technologies <servi...@syncmonk.net> + * @note SPDX-License-Identifier: GPL-2.0+ + * + * Also, for each author's protection and ours, we want to make certain that + * everyone understands that there is no warranty for this free software. + * If the software is modified by someone else and passed on, we want its + * recipients to know that what they have is not the original, so that any + * problems introduced by others will not reflect on the original authors' + * reputations. + */ +#ifndef HAVE_TS2PHC_VPORT_H +#define HAVE_TS2PHC_VPORT_H + +#include "config.h" +#include "port.h" +#include "tmv.h" + +struct ts2phc_vport; + +struct ts2phc_vport *ts2phc_vport_create(struct config *config); + +void ts2phc_vport_destroy(struct ts2phc_vport *ts2phc_vport); + +int ts2phc_vport_tx_announce (struct ts2phc_vport *ts2phc_vport); + +#endif -- 2.25.1 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel