Virtual PTP port is for unidirectional tranfer of phase/time interface on a PTP clock. When associated with an external input signal, a virtual PTP port allows this external interface to participate in the PTP protocol. As an input, this external port can participate in the source selection with an associated virtual Erbest using the associated virtual PTP port.
As per G.8275 (Annex-B) including virtual PTP ports on a PTP clock. This virtual port will be used to support Assisted Partial Timing Support (APTS), Inter Working Function (IWF) between different clock_domains. 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> v1->v2: - Amended the commit message. --- makefile | 2 +- vport.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ vport.h | 20 ++++++++ 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 vport.c create mode 100644 vport.h diff --git a/makefile b/makefile index 5295b60..7d8c0d3 100644 --- a/makefile +++ b/makefile @@ -25,7 +25,7 @@ LDLIBS = -lm -lrt -pthread $(EXTRA_LDFLAGS) PRG = ptp4l hwstamp_ctl nsm phc2sys phc_ctl pmc timemaster ts2phc 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 +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 OBJ = bmc.o clock.o clockadj.o clockcheck.o config.o designated_fsm.o \ diff --git a/vport.c b/vport.c new file mode 100644 index 0000000..89d4105 --- /dev/null +++ b/vport.c @@ -0,0 +1,140 @@ +/** + * @file vport.c + * @note Copyright (C) 2022 SyncMonk Technologies <servi...@syncmonk.net> + * @note SPDX-License-Identifier: GPL-2.0+ + * + */ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/un.h> +#include <unistd.h> + +#include "address.h" +#include "contain.h" +#include "print.h" +#include "transport_private.h" +#include "vport.h" + +#define VPORT_FILEMODE (0660) /*0660*/ + +struct vport { + struct transport t; + struct address address; +}; + +static int vport_close(struct transport *t, struct fdarray *fda) +{ + struct sockaddr_un sa; + socklen_t len = sizeof(sa); + + if (!getsockname(fda->fd[FD_GENERAL], + (struct sockaddr *) &sa, &len) && + sa.sun_family == AF_LOCAL) { + unlink(sa.sun_path); + } + + close(fda->fd[FD_GENERAL]); + return 0; +} + +static int vport_open(struct transport *t, + struct interface *iface, + struct fdarray *fda, + enum timestamp_type tt) +{ + char *vport_path = config_get_string(t->cfg, NULL, "vport_address"); + struct vport *vport = container_of(t, struct vport, t); + const char *name = interface_name(iface); + struct sockaddr_un sa; + int fd, err; + + fd = socket(AF_LOCAL, SOCK_DGRAM, 0); + if (fd < 0) { + pr_err("vport: failed to create socket: %m"); + return -1; + } + memset(&sa, 0, sizeof(sa)); + sa.sun_family = AF_LOCAL; + strncpy(sa.sun_path, name, sizeof(sa.sun_path) - 1); + + unlink(name); + + err = bind(fd, (struct sockaddr *) &sa, sizeof(sa)); + if (err < 0) { + pr_err("vport: bind failed: %m"); + close(fd); + return -1; + } + + /* For client use, pre load the server path. */ + memset(&sa, 0, sizeof(sa)); + sa.sun_family = AF_LOCAL; + strncpy(sa.sun_path, vport_path, sizeof(sa.sun_path) - 1); + vport->address.sun = sa; + vport->address.len = sizeof(sa); + + chmod(name, VPORT_FILEMODE); + fda->fd[FD_EVENT] = -1; + fda->fd[FD_GENERAL] = fd; + return 0; +} + +static int vport_recv(struct transport *t, int fd, void *buf, int buflen, + struct address *addr, struct hw_timestamp *hwts) +{ + int cnt; + struct vport *vport = container_of(t, struct vport, t); + + addr->len = sizeof(addr->sun); + cnt = recvfrom(fd, buf, buflen, 0, &addr->sa, &addr->len); + if (cnt <= 0) { + pr_err("vport: recvfrom failed: %m"); + return cnt; + } + vport->address = *addr; + return cnt; +} + +static int vport_send(struct transport *t, struct fdarray *fda, + enum transport_event event, int peer, void *buf, + int buflen, struct address *addr, + struct hw_timestamp *hwts) +{ + int cnt, fd = fda->fd[FD_GENERAL]; + struct vport *vport = container_of(t, struct vport, t); + + if (!addr) + addr = &vport->address; + + cnt = sendto(fd, buf, buflen, 0, &addr->sa, addr->len); + if (cnt < 1) { + return -errno; + } + return cnt; +} + +static void vport_release(struct transport *t) +{ + struct vport *vport = container_of(t, struct vport, t); + + free(vport); +} + +struct transport *vport_transport_create(void) +{ + struct vport *vport; + + vport = calloc(1, sizeof(*vport)); + if (!vport) + return NULL; + vport->t.close = vport_close; + vport->t.open = vport_open; + vport->t.recv = vport_recv; + vport->t.send = vport_send; + vport->t.release = vport_release; + return &vport->t; +} diff --git a/vport.h b/vport.h new file mode 100644 index 0000000..a479fe7 --- /dev/null +++ b/vport.h @@ -0,0 +1,20 @@ +/** + * @file vport.h + * @note Copyright (C) 2022 SyncMonk Technologies <servi...@syncmonk.net> + * @note SPDX-License-Identifier: GPL-2.0+ + * + */ +#ifndef HAVE_VPORT_H +#define HAVE_VPORT_H + +#include "config.h" +#include "fd.h" +#include "transport.h" + +/** + * Allocate an instance of a VPORT transport. + * @return Pointer to a new transport instance on success, NULL otherwise. + */ +struct transport *vport_transport_create(void); + +#endif -- 2.25.1 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel