Adding virtual port support to ptp4l

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>
---
 clock.c     | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 config.c    |  2 ++
 interface.c |  7 +++++++
 interface.h |  6 ++++++
 port.c      | 10 +++++++--
 ptp4l.8     |  4 ++++
 sk.c        |  1 +
 transport.c |  4 ++++
 transport.h |  1 +
 util.c      |  2 ++
 10 files changed, 93 insertions(+), 3 deletions(-)

diff --git a/clock.c b/clock.c
index d37bb87..314eebf 100644
--- a/clock.c
+++ b/clock.c
@@ -43,6 +43,7 @@
 #include "tlv.h"
 #include "tsproc.h"
 #include "uds.h"
+#include "vport.h"
 #include "util.h"
 
 #define N_CLOCK_PFD (N_POLLFD + 1) /* one extra per port, for the fault timer 
*/
@@ -97,9 +98,10 @@ struct clock {
        LIST_HEAD(ports_head, port) ports;
        struct port *uds_rw_port;
        struct port *uds_ro_port;
+       struct port *vport_port;
        struct pollfd *pollfd;
        int pollfd_valid;
-       int nports; /* does not include the two UDS ports */
+       int nports; /* does not include the two UDS ports + 1 Virtual Port */
        int last_port_number;
        int sde;
        int free_running;
@@ -133,6 +135,7 @@ struct clock {
        struct clockcheck *sanity_check;
        struct interface *uds_rw_if;
        struct interface *uds_ro_if;
+       struct interface *vport_if;
        LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers;
        struct monitor *slave_event_monitor;
        int step_window_counter;
@@ -272,6 +275,7 @@ void clock_destroy(struct clock *c)
 
        interface_destroy(c->uds_rw_if);
        interface_destroy(c->uds_ro_if);
+       interface_destroy(c->vport_if);
        clock_flush_subscriptions(c);
        LIST_FOREACH_SAFE(p, &c->ports, list, tmp) {
                clock_remove_port(c, p);
@@ -901,6 +905,7 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
        int phc_index, conf_phc_index, required_modes = 0;
        struct clock *c = &the_clock;
        const char *uds_ifname;
+       const char *vport_ifname;
        struct port *p;
        unsigned char oui[OUI_LEN];
        struct interface *iface;
@@ -1094,6 +1099,32 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
                return NULL;
        }
 
+       /* Configure the Virtual Port. */
+       vport_ifname = config_get_string(config, NULL, "vport_address");
+       if (vport_ifname && vport_ifname[0]) {
+               c->vport_if = interface_create(vport_ifname);
+               if (config_set_section_int(config, interface_name(c->vport_if),
+                                          "announceReceiptTimeout", 2)) {
+                       return NULL;
+               }
+               if (config_set_section_int(config,
+                                          interface_name(c->vport_if),
+                                          "delay_mechanism",
+                                          DM_NO_MECHANISM)) {
+                       return NULL;
+               }
+               if (config_set_section_int(config,
+                                          interface_name(c->vport_if),
+                                          "network_transport",
+                                          TRANS_VPORT)) {
+                       return NULL;
+               }
+               if (config_set_section_int(config, interface_name(c->vport_if),
+                                          "delay_filter_length", 1)) {
+                       return NULL;
+               }
+       }
+
        c->config = config;
        c->free_running = config_get_int(config, NULL, "free_running");
        c->freq_est_interval = config_get_int(config, NULL, 
"freq_est_interval");
@@ -1231,6 +1262,17 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
                pr_err("failed to open the UDS-RO port");
                return NULL;
        }
+
+       if (c->vport_if) {
+               c->vport_port = port_open(phc_device, phc_index, timestamping, 
0,
+                                          c->vport_if, c);
+               if (!c->vport_port) {
+                       pr_err("failed to open the Virtual port");
+                       return NULL;
+               }
+               LIST_INSERT_HEAD(&c->ports, c->vport_port, list);
+               c->nports++;
+       }
        clock_fda_changed(c);
 
        c->slave_event_monitor = monitor_create(config, c->uds_rw_port);
@@ -1254,6 +1296,9 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
        }
        port_dispatch(c->uds_rw_port, EV_INITIALIZE, 0);
        port_dispatch(c->uds_ro_port, EV_INITIALIZE, 0);
+       if (c->vport_port) {
+               port_dispatch(c->vport_port, EV_INITIALIZE, 0);
+       }
 
        return c;
 }
@@ -1670,6 +1715,18 @@ int clock_poll(struct clock *c)
                        /* sde is not expected on the UDS-RO port */
                }
        }
+       /* Check the Virtual port. */
+       if (c->vport_port) {
+               cur += N_CLOCK_PFD;
+               for (i = 0; i < N_POLLFD; i++) {
+                       if (cur[i].revents & (POLLIN|POLLPRI)) {
+                               event = port_event(c->vport_port, i);
+                               if (event == EV_STATE_DECISION_EVENT) {
+                                       c->sde = 1;
+                               }
+                       }
+               }
+       }
 
        if (c->sde) {
                handle_state_decision_event(c);
diff --git a/config.c b/config.c
index b5cf397..aeae356 100644
--- a/config.c
+++ b/config.c
@@ -193,6 +193,7 @@ static struct config_enum nw_trans_enu[] = {
        { "L2",    TRANS_IEEE_802_3 },
        { "UDPv4", TRANS_UDP_IPV4   },
        { "UDPv6", TRANS_UDP_IPV6   },
+       { "vPort", TRANS_VPORT   },
        { NULL, 0 },
 };
 
@@ -345,6 +346,7 @@ struct config_item config_tab[] = {
        GLOB_ITEM_STR("userDescription", ""),
        GLOB_ITEM_INT("utc_offset", CURRENT_UTC_OFFSET, 0, INT_MAX),
        GLOB_ITEM_INT("verbose", 0, 0, 1),
+       GLOB_ITEM_STR("vport_address", ""),
        GLOB_ITEM_INT("write_phase_mode", 0, 0, 1),
 };
 
diff --git a/interface.c b/interface.c
index 6c2630c..9506097 100644
--- a/interface.c
+++ b/interface.c
@@ -35,6 +35,13 @@ void interface_destroy(struct interface *iface)
        free(iface);
 }
 
+void interface_ensure_tslabel(struct interface *iface)
+{
+       if (!iface->ts_label[0]) {
+               memcpy(iface->ts_label, iface->name, MAX_IFNAME_SIZE);
+       }
+}
+
 int interface_get_tsinfo(struct interface *iface)
 {
        return sk_get_ts_info(iface->ts_label, &iface->ts_info);
diff --git a/interface.h b/interface.h
index 5fc7836..752f4f1 100644
--- a/interface.h
+++ b/interface.h
@@ -33,6 +33,12 @@ struct interface *interface_create(const char *name);
  */
 void interface_destroy(struct interface *iface);
 
+/**
+ * Ensures that an interface has a proper time stamping label.
+ * @param iface  The interface of interest.
+ */
+void interface_ensure_tslabel(struct interface *iface);
+
 /**
  * Populate the time stamping information of a given interface.
  * @param iface  The interface of interest.
diff --git a/port.c b/port.c
index 871ad68..020e2c5 100644
--- a/port.c
+++ b/port.c
@@ -57,6 +57,7 @@ enum syfu_event {
 
 static int port_is_ieee8021as(struct port *p);
 static int port_is_uds(struct port *p);
+static int port_is_vport(struct port *p);
 static void port_nrate_initialize(struct port *p);
 
 static int announce_compare(struct ptp_message *m1, struct ptp_message *m2)
@@ -822,6 +823,11 @@ static int port_is_uds(struct port *p)
        return transport_type(p->trp) == TRANS_UDS;
 }
 
+static int port_is_vport(struct port *p)
+{
+       return transport_type(p->trp) == TRANS_VPORT;
+}
+
 static void port_management_send_error(struct port *p, struct port *ingress,
                                       struct ptp_message *msg, int error_id)
 {
@@ -3266,8 +3272,8 @@ struct port *port_open(const char *phc_device,
                p->state_machine = clock_slave_only(clock) ? ptp_slave_fsm : 
ptp_fsm;
        }
 
-       if (port_is_uds(p)) {
-               ; /* UDS cannot have a PHC. */
+       if (port_is_uds(p) || port_is_vport(p)) {
+               ; /* UDS & VPORT cannot have a PHC. */
        } else if (!interface_tsinfo_valid(interface)) {
                pr_warning("%s: get_ts_info not supported", p->log_name);
        } else if (p->phc_index >= 0 &&
diff --git a/ptp4l.8 b/ptp4l.8
index 1268802..dd72ca8 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -658,6 +658,10 @@ File mode of the second (read-only) UNIX domain socket 
used for receiving
 local management messages. The mode should be specified as an octal number,
 i.e. it should start with a 0 literal. The default mode is 0666.
 .TP
+.B vport_address
+Specifies the address of UNIX domain socket for virtual port as referred in
+G.8275 (Annex-B). The default is NULL.
+.TP
 .B dscp_event
 Defines the Differentiated Services Codepoint (DSCP) to be used for PTP
 event messages. Must be a value between 0 and 63. There are several media
diff --git a/sk.c b/sk.c
index 80075be..d24fc4c 100644
--- a/sk.c
+++ b/sk.c
@@ -508,6 +508,7 @@ int sk_timestamping_init(int fd, const char *device, enum 
timestamp_type type,
                case TRANS_CONTROLNET:
                case TRANS_PROFINET:
                case TRANS_UDS:
+               case TRANS_VPORT:
                        return -1;
                }
                err = hwts_init(fd, device, filter1, filter2, tx_type);
diff --git a/transport.c b/transport.c
index 9366fbf..86b9576 100644
--- a/transport.c
+++ b/transport.c
@@ -25,6 +25,7 @@
 #include "udp.h"
 #include "udp6.h"
 #include "uds.h"
+#include "vport.h"
 
 int transport_close(struct transport *t, struct fdarray *fda)
 {
@@ -115,6 +116,9 @@ struct transport *transport_create(struct config *cfg,
        case TRANS_IEEE_802_3:
                t = raw_transport_create();
                break;
+       case TRANS_VPORT:
+               t = vport_transport_create();
+               break;
        case TRANS_DEVICENET:
        case TRANS_CONTROLNET:
        case TRANS_PROFINET:
diff --git a/transport.h b/transport.h
index 7a7f87b..a4c73d3 100644
--- a/transport.h
+++ b/transport.h
@@ -39,6 +39,7 @@ enum transport_type {
        TRANS_DEVICENET,
        TRANS_CONTROLNET,
        TRANS_PROFINET,
+       TRANS_VPORT,
 };
 
 /**
diff --git a/util.c b/util.c
index a59b559..8077084 100644
--- a/util.c
+++ b/util.c
@@ -114,6 +114,7 @@ int addreq(enum transport_type type, struct address *a, 
struct address *b)
        case TRANS_DEVICENET:
        case TRANS_CONTROLNET:
        case TRANS_PROFINET:
+       case TRANS_VPORT:
        default:
                pr_err("sorry, cannot compare addresses for this transport");
                return 0;
@@ -280,6 +281,7 @@ int str2addr(enum transport_type type, const char *s, 
struct address *addr)
        case TRANS_DEVICENET:
        case TRANS_CONTROLNET:
        case TRANS_PROFINET:
+       case TRANS_VPORT:
                pr_err("sorry, cannot convert addresses for this transport");
                return -1;
        case TRANS_UDP_IPV4:
-- 
2.25.1



_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to