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