Adding virtual PTP port support As per G.8275 (Annex-B) including virtual PTP ports on a PTP clock. This virtual port will be used to support APTS, 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> --- 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