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> v2->v3: - Using UDS sockets for virtual PTP ports. v1->v2: - Amended the commit message. --- clock.c | 58 ++++++++++++++++++++++++++++++++++++++++++++- config.c | 2 ++ configs/default.cfg | 2 +- port.c | 10 ++++++-- ptp4l.8 | 5 ++++ sk.c | 1 + transport.c | 1 + transport.h | 1 + uds.c | 33 +++++++++++++++++++------- util.c | 2 ++ 10 files changed, 102 insertions(+), 13 deletions(-) diff --git a/clock.c b/clock.c index d37bb87..eba0833 100644 --- a/clock.c +++ b/clock.c @@ -97,9 +97,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 +134,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 +274,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 +904,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 +1098,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 +1261,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 +1295,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 +1714,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/configs/default.cfg b/configs/default.cfg index 1b5b806..ea1fa79 100644 --- a/configs/default.cfg +++ b/configs/default.cfg @@ -94,7 +94,7 @@ udp6_scope 0x0E uds_address /var/run/ptp4l uds_file_mode 0660 uds_ro_address /var/run/ptp4lro -uds_ro_file_mode 0666 +uds_ro_file_mode 0666 # # Default interface options # 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..a0479f6 100644 --- a/ptp4l.8 +++ b/ptp4l.8 @@ -658,6 +658,11 @@ 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 the UNIX domain socket for communicating with the +virtual PTP port on a PTP clock as defined in the 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..3fdb6c2 100644 --- a/transport.c +++ b/transport.c @@ -104,6 +104,7 @@ struct transport *transport_create(struct config *cfg, struct transport *t = NULL; switch (type) { case TRANS_UDS: + case TRANS_VPORT: t = uds_transport_create(); break; case TRANS_UDP_IPV4: 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/uds.c b/uds.c index 6d39dc8..a890c38 100644 --- a/uds.c +++ b/uds.c @@ -31,6 +31,7 @@ #include "transport_private.h" #include "uds.h" +#define VPORT_FILE_MODE (0660) struct uds { struct transport t; struct address address; @@ -50,11 +51,13 @@ static int uds_close(struct transport *t, struct fdarray *fda) return 0; } -static int uds_open(struct transport *t, struct interface *iface, struct fdarray *fda, +static int uds_open(struct transport *t, + struct interface *iface, + struct fdarray *fda, enum timestamp_type tt) { - char *uds_ro_path = config_get_string(t->cfg, NULL, "uds_ro_address"); - char *uds_path = config_get_string(t->cfg, NULL, "uds_address"); + char *uds_ro_path; + char *uds_path; struct uds *uds = container_of(t, struct uds, t); const char *name = interface_name(iface); const char* file_mode_cfg; @@ -62,6 +65,24 @@ static int uds_open(struct transport *t, struct interface *iface, struct fdarray mode_t file_mode; int fd, err; + switch (t->type) { + case TRANS_UDS: + uds_ro_path = config_get_string(t->cfg, NULL, "uds_ro_address"); + uds_path = config_get_string(t->cfg, NULL, "uds_address"); + file_mode_cfg = "uds_file_mode"; + // The RO UDS socket has a separate configuration for file mode + if (0 == strncmp(name, uds_ro_path, MAX_IFNAME_SIZE)) + file_mode_cfg = "uds_ro_file_mode"; + file_mode = (mode_t)config_get_int(t->cfg, name, file_mode_cfg); + break; + case TRANS_VPORT: + uds_path = config_get_string(t->cfg, NULL, "vport_address"); + file_mode = VPORT_FILE_MODE; + break; + default: + break; + } + fd = socket(AF_LOCAL, SOCK_DGRAM, 0); if (fd < 0) { pr_err("uds: failed to create socket: %m"); @@ -80,12 +101,6 @@ static int uds_open(struct transport *t, struct interface *iface, struct fdarray return -1; } - file_mode_cfg = "uds_file_mode"; - // The RO UDS socket has a separate configuration for file mode - if (0 == strncmp(name, uds_ro_path, MAX_IFNAME_SIZE)) - file_mode_cfg = "uds_ro_file_mode"; - file_mode = (mode_t)config_get_int(t->cfg, name, file_mode_cfg); - /* For client use, pre load the server path. */ memset(&sa, 0, sizeof(sa)); sa.sun_family = AF_LOCAL; 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