Adding virtual port support to ptp4l
Signed-off-by: Greg Armstrong <[email protected]>
Signed-off-by: Leon Goldin <[email protected]>
Signed-off-by: Vipin Sharma <[email protected]>
Signed-off-by: Devasish Dey <[email protected]>
---
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel