diff --git a/.gitignore b/.gitignore index 8069dde..b71a5b8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -SOURCES/clknetsim-ce89a1.tar.gz -SOURCES/linuxptp-1.8.tgz -SOURCES/linuxptp-testsuite-502e82.tar.gz +SOURCES/clknetsim-8b4842.tar.gz +SOURCES/linuxptp-2.0.tgz +SOURCES/linuxptp-testsuite-a7f6e1.tar.gz diff --git a/.linuxptp.metadata b/.linuxptp.metadata index bb51355..03e8cd2 100644 --- a/.linuxptp.metadata +++ b/.linuxptp.metadata @@ -1,3 +1,3 @@ -922f475728383b56b03eeadaf990c9231a51a9e3 SOURCES/clknetsim-ce89a1.tar.gz -449cf190347d24846440bd757570e391dd7dff96 SOURCES/linuxptp-1.8.tgz -1b6395c22a47a4af60db6963d063697ef6daae08 SOURCES/linuxptp-testsuite-502e82.tar.gz +b674017c26433870107fb18e160c7d88d7d2eb86 SOURCES/clknetsim-8b4842.tar.gz +592ca42c6146a79c1fcabed7c19fa7af4803d4f6 SOURCES/linuxptp-2.0.tgz +2b8edc55e4967660a0c4a3892c817c0e8f55c3bc SOURCES/linuxptp-testsuite-a7f6e1.tar.gz diff --git a/SOURCES/linuxptp-addreq.patch b/SOURCES/linuxptp-addreq.patch new file mode 100644 index 0000000..284f7ee --- /dev/null +++ b/SOURCES/linuxptp-addreq.patch @@ -0,0 +1,12 @@ +diff -up linuxptp-2.0/util.c.addreq linuxptp-2.0/util.c +--- linuxptp-2.0/util.c.addreq 2019-03-25 11:43:55.878146767 +0100 ++++ linuxptp-2.0/util.c 2019-03-25 11:44:38.215244483 +0100 +@@ -78,7 +78,7 @@ int addreq(enum transport_type type, str + case TRANS_UDP_IPV4: + bufa = &a->sin.sin_addr; + bufb = &b->sin.sin_addr; +- len = sizeof(a->sin); ++ len = sizeof(a->sin.sin_addr); + break; + case TRANS_IEEE_802_3: + bufa = &a->sll.sll_addr; diff --git a/SOURCES/linuxptp-bonding.patch b/SOURCES/linuxptp-bonding.patch deleted file mode 100644 index 6742d70..0000000 --- a/SOURCES/linuxptp-bonding.patch +++ /dev/null @@ -1,1867 +0,0 @@ -commit 17aa750a49ebaecfc7b063c770aa8d36f5078b2c -Author: Hangbin Liu -Date: Mon Jul 10 15:39:28 2017 +0800 - - rtnl: replace obsolete RTMGRP_LINK with RTNLGRP_LINK for nl groups - - Signed-off-by: Hangbin Liu - -diff --git a/rtnl.c b/rtnl.c -index 5cddc4b..d7a430d 100644 ---- a/rtnl.c -+++ b/rtnl.c -@@ -151,7 +151,7 @@ int rtnl_open(void) - - memset(&sa, 0, sizeof(sa)); - sa.nl_family = AF_NETLINK; -- sa.nl_groups = RTMGRP_LINK; -+ sa.nl_groups = RTNLGRP_LINK; - - fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (fd < 0) { -commit c149a3dbc1b38e833de783ae863038562baca0fe -Author: Hangbin Liu -Date: Mon Jul 10 15:39:29 2017 +0800 - - port: add FD_RTNL event to track per-port status - - With rtnl socket we can track link status per port(except UDS port). - - We can make sure we get the correct interface and latest status with function - port_link_status(). - - At the same time we need to set clock sde after link down. But we return - EV_FAULT_DETECTED in port_event(), which will not set clock sde. So we need - to set it in port_link_status(). - - Signed-off-by: Hangbin Liu - -diff --git a/clock.c b/clock.c -index b6afba9..4c5c4e3 100644 ---- a/clock.c -+++ b/clock.c -@@ -1469,6 +1469,11 @@ struct PortIdentity clock_parent_identity(struct clock *c) - return c->dad.pds.parentPortIdentity; - } - -+void clock_set_sde(struct clock *c, int sde) -+{ -+ c->sde = sde; -+} -+ - int clock_poll(struct clock *c) - { - int cnt, i; -diff --git a/clock.h b/clock.h -index fcd9328..49ecb76 100644 ---- a/clock.h -+++ b/clock.h -@@ -205,6 +205,13 @@ void clock_peer_delay(struct clock *c, tmv_t ppd, tmv_t req, tmv_t rx, - double nrr); - - /** -+ * Set clock sde -+ * @param c A pointer to a clock instance obtained with clock_create(). -+ * @param sde Pass one (1) if need a decision event and zero if not. -+ */ -+void clock_set_sde(struct clock *c, int sde); -+ -+/** - * Poll for events and dispatch them. - * @param c A pointer to a clock instance obtained with clock_create(). - * @return Zero on success, non-zero otherwise. -diff --git a/fd.h b/fd.h -index e328e98..23401f4 100644 ---- a/fd.h -+++ b/fd.h -@@ -31,6 +31,7 @@ enum { - FD_QUALIFICATION_TIMER, - FD_MANNO_TIMER, - FD_SYNC_TX_TIMER, -+ FD_RTNL, - N_POLLFD, - }; - -diff --git a/port.c b/port.c -index ec02825..2896d1a 100644 ---- a/port.c -+++ b/port.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - - #include "bmc.h" - #include "clock.h" -@@ -32,6 +33,7 @@ - #include "phc.h" - #include "port.h" - #include "print.h" -+#include "rtnl.h" - #include "sk.h" - #include "tlv.h" - #include "tmv.h" -@@ -1458,7 +1460,9 @@ static void port_disable(struct port *p) - for (i = 0; i < N_TIMER_FDS; i++) { - close(p->fda.fd[FD_ANNOUNCE_TIMER + i]); - } -- port_clear_fda(p, N_POLLFD); -+ -+ /* Keep rtnl socket to get link status info. */ -+ port_clear_fda(p, FD_RTNL); - clock_fda_changed(p->clock); - } - -@@ -1502,6 +1506,14 @@ static int port_initialize(struct port *p) - if (port_set_announce_tmo(p)) - goto no_tmo; - -+ /* No need to open rtnl socket on UDS port. */ -+ if (transport_type(p->trp) != TRANS_UDS) { -+ if (p->fda.fd[FD_RTNL] == -1) -+ p->fda.fd[FD_RTNL] = rtnl_open(); -+ if (p->fda.fd[FD_RTNL] >= 0) -+ rtnl_link_query(p->fda.fd[FD_RTNL]); -+ } -+ - port_nrate_initialize(p); - - clock_fda_changed(p->clock); -@@ -2025,6 +2037,10 @@ void port_close(struct port *p) - if (port_is_enabled(p)) { - port_disable(p); - } -+ -+ if (p->fda.fd[FD_RTNL] >= 0) -+ rtnl_close(p->fda.fd[FD_RTNL]); -+ - transport_destroy(p->trp); - tsproc_destroy(p->tsproc); - if (p->fault_fd >= 0) -@@ -2204,6 +2220,24 @@ void port_dispatch(struct port *p, enum fsm_event event, int mdiff) - } - } - -+static void port_link_status(void *ctx, int index, int linkup) -+{ -+ struct port *p = ctx; -+ -+ if (index != if_nametoindex(p->name) || p->link_status == linkup) -+ return; -+ -+ p->link_status = linkup; -+ pr_notice("port %hu: link %s", portnum(p), linkup ? "up" : "down"); -+ -+ /* -+ * A port going down can affect the BMCA result. -+ * Force a state decision event. -+ */ -+ if (!p->link_status) -+ clock_set_sde(p->clock, 1); -+} -+ - enum fsm_event port_event(struct port *p, int fd_index) - { - enum fsm_event event = EV_NONE; -@@ -2242,6 +2276,11 @@ enum fsm_event port_event(struct port *p, int fd_index) - pr_debug("port %hu: master sync timeout", portnum(p)); - port_set_sync_tx_tmo(p); - return port_tx_sync(p) ? EV_FAULT_DETECTED : EV_NONE; -+ -+ case FD_RTNL: -+ pr_debug("port %hu: received link status notification", portnum(p)); -+ rtnl_link_status(fd, port_link_status, p); -+ return port_link_status_get(p) ? EV_FAULT_CLEARED : EV_FAULT_DETECTED; - } - - msg = msg_allocate(); -commit 25ec8a3b4e2222b394794ff830bd3583e9cf6c71 -Author: Hangbin Liu -Date: Mon Jul 10 15:39:30 2017 +0800 - - clock: remove rtnl fd on clock - - Remove rtnl fd on clock since we track the link status per port now. - - Signed-off-by: Hangbin Liu - -diff --git a/clock.c b/clock.c -index 4c5c4e3..354f038 100644 ---- a/clock.c -+++ b/clock.c -@@ -39,7 +39,6 @@ - #include "servo.h" - #include "stats.h" - #include "print.h" --#include "rtnl.h" - #include "sk.h" - #include "tlv.h" - #include "tsproc.h" -@@ -274,9 +273,6 @@ void clock_destroy(struct clock *c) - LIST_FOREACH_SAFE(p, &c->ports, list, tmp) { - clock_remove_port(c, p); - } -- if (c->pollfd[0].fd >= 0) { -- rtnl_close(c->pollfd[0].fd); -- } - port_close(c->uds_port); - free(c->pollfd); - hash_destroy(c->index2port, NULL); -@@ -326,30 +322,6 @@ static void clock_freq_est_reset(struct clock *c) - c->fest.count = 0; - } - --static void clock_link_status(void *ctx, int index, int linkup) --{ -- struct clock *c = ctx; -- struct port *p; -- char key[16]; -- -- snprintf(key, sizeof(key), "%d", index); -- p = hash_lookup(c->index2port, key); -- if (!p) { -- return; -- } -- port_link_status_set(p, linkup); -- if (linkup) { -- port_dispatch(p, EV_FAULT_CLEARED, 0); -- } else { -- port_dispatch(p, EV_FAULT_DETECTED, 0); -- /* -- * A port going down can affect the BMCA result. -- * Force a state decision event. -- */ -- c->sde = 1; -- } --} -- - static void clock_management_send_error(struct port *p, - struct ptp_message *msg, int error_id) - { -@@ -1133,10 +1105,6 @@ struct clock *clock_create(enum clock_type type, struct config *config, - return NULL; - } - -- /* Open a RT netlink socket. */ -- c->pollfd[0].fd = rtnl_open(); -- c->pollfd[0].events = POLLIN|POLLPRI; -- - /* Create the UDS interface. */ - c->uds_port = port_open(phc_index, timestamping, 0, udsif, c); - if (!c->uds_port) { -@@ -1164,9 +1132,7 @@ struct clock *clock_create(enum clock_type type, struct config *config, - port_dispatch(p, EV_INITIALIZE, 0); - } - port_dispatch(c->uds_port, EV_INITIALIZE, 0); -- if (c->pollfd[0].fd >= 0) { -- rtnl_link_query(c->pollfd[0].fd); -- } -+ - return c; - } - -@@ -1231,12 +1197,9 @@ static int clock_resize_pollfd(struct clock *c, int new_nports) - { - struct pollfd *new_pollfd; - -- /* -- * Need to allocate one descriptor for RT netlink and one -- * whole extra block of fds for UDS. -- */ -+ /* Need to allocate one whole extra block of fds for UDS. */ - new_pollfd = realloc(c->pollfd, -- (1 + (new_nports + 1) * N_CLOCK_PFD) * -+ (new_nports + 1) * N_CLOCK_PFD * - sizeof(struct pollfd)); - if (!new_pollfd) - return -1; -@@ -1261,7 +1224,7 @@ static void clock_fill_pollfd(struct pollfd *dest, struct port *p) - static void clock_check_pollfd(struct clock *c) - { - struct port *p; -- struct pollfd *dest = c->pollfd + 1; -+ struct pollfd *dest = c->pollfd; - - if (c->pollfd_valid) - return; -@@ -1482,7 +1445,7 @@ int clock_poll(struct clock *c) - struct port *p; - - clock_check_pollfd(c); -- cnt = poll(c->pollfd, 1 + (c->nports + 1) * N_CLOCK_PFD, -1); -+ cnt = poll(c->pollfd, (c->nports + 1) * N_CLOCK_PFD, -1); - if (cnt < 0) { - if (EINTR == errno) { - return 0; -@@ -1494,13 +1457,8 @@ int clock_poll(struct clock *c) - return 0; - } - -- /* Check the RT netlink. */ - cur = c->pollfd; -- if (cur->revents & (POLLIN|POLLPRI)) { -- rtnl_link_status(cur->fd, clock_link_status, c); -- } - -- cur++; - LIST_FOREACH(p, &c->ports, list) { - /* Let the ports handle their events. */ - for (i = 0; i < N_POLLFD; i++) { -diff --git a/port.c b/port.c -index 2896d1a..34837cc 100644 ---- a/port.c -+++ b/port.c -@@ -2411,12 +2411,6 @@ int port_link_status_get(struct port *p) - return p->link_status; - } - --void port_link_status_set(struct port *p, int up) --{ -- p->link_status = up ? 1 : 0; -- pr_notice("port %hu: link %s", portnum(p), up ? "up" : "down"); --} -- - int port_manage(struct port *p, struct port *ingress, struct ptp_message *msg) - { - struct management_tlv *mgt; -diff --git a/port.h b/port.h -index b00bc64..60fd0a4 100644 ---- a/port.h -+++ b/port.h -@@ -132,13 +132,6 @@ int port_number(struct port *p); - int port_link_status_get(struct port *p); - - /** -- * Sets the link status for a port. -- * @param p A port instance. -- * @param up Pass one (1) if the link is up and zero if down. -- */ --void port_link_status_set(struct port *p, int up); -- --/** - * Manage a port according to a given message. - * @param p A pointer previously obtained via port_open(). - * @param ingress The port on which 'msg' was received. -commit 7c3f9579f0c230ee798644a26d664ebd3efc612f -Author: Hangbin Liu -Date: Mon Jul 10 15:39:31 2017 +0800 - - clock: remove hash table index2port - - Remove index2port since we don't need it now. - - Signed-off-by: Hangbin Liu - -diff --git a/clock.c b/clock.c -index 354f038..da15882 100644 ---- a/clock.c -+++ b/clock.c -@@ -31,7 +31,6 @@ - #include "clockcheck.h" - #include "foreign.h" - #include "filter.h" --#include "hash.h" - #include "missing.h" - #include "msg.h" - #include "phc.h" -@@ -39,7 +38,6 @@ - #include "servo.h" - #include "stats.h" - #include "print.h" --#include "sk.h" - #include "tlv.h" - #include "tsproc.h" - #include "uds.h" -@@ -96,7 +94,6 @@ struct clock { - int nports; /* does not include the UDS port */ - int last_port_number; - int sde; -- struct hash *index2port; - int free_running; - int freq_est_interval; - int grand_master_capable; /* for 802.1AS only */ -@@ -275,7 +272,6 @@ void clock_destroy(struct clock *c) - } - port_close(c->uds_port); - free(c->pollfd); -- hash_destroy(c->index2port, NULL); - if (c->clkid != CLOCK_REALTIME) { - phc_close(c->clkid); - } -@@ -773,8 +769,6 @@ static int clock_add_port(struct clock *c, int phc_index, - struct interface *iface) - { - struct port *p, *piter, *lastp = NULL; -- int fd, index; -- char key[16]; - - if (clock_resize_pollfd(c, c->nports + 1)) { - return -1; -@@ -795,24 +789,6 @@ static int clock_add_port(struct clock *c, int phc_index, - c->nports++; - clock_fda_changed(c); - -- /* Remember the index to port mapping, for link status tracking. */ -- fd = sk_interface_fd(); -- if (fd < 0) { -- return -1; -- } -- index = sk_interface_index(fd, iface->name); -- if (index < 0) { -- close(fd); -- return -1; -- } -- snprintf(key, sizeof(key), "%d", index); -- if (hash_insert(c->index2port, key, p)) { -- pr_err("failed to add port with index %d twice!", index); -- close(fd); -- return -1; -- } -- close(fd); -- - return 0; - } - -@@ -1113,11 +1089,6 @@ struct clock *clock_create(enum clock_type type, struct config *config, - } - clock_fda_changed(c); - -- c->index2port = hash_create(); -- if (!c->index2port) { -- pr_err("failed create index-to-port hash table"); -- return NULL; -- } - /* Create the ports. */ - STAILQ_FOREACH(iface, &config->interfaces, list) { - if (clock_add_port(c, phc_index, timestamping, iface)) { -commit 9e744d9e8a2dab6ec0ea5ece5ac25e7384264575 -Author: Hangbin Liu -Date: Mon Oct 9 22:31:39 2017 +0800 - - config: add new element ts_label in struct interface - - Add new element ts_label in struct interface to track real ts interface. - - Signed-off-by: Hangbin Liu - -diff --git a/config.h b/config.h -index 1cc7051..c79855e 100644 ---- a/config.h -+++ b/config.h -@@ -36,6 +36,7 @@ - struct interface { - STAILQ_ENTRY(interface) list; - char name[MAX_IFNAME_SIZE + 1]; -+ char ts_label[MAX_IFNAME_SIZE + 1]; - struct sk_ts_info ts_info; - }; - -commit 7e294a4d047654f746c3fcdff7bce512be149e37 -Author: Hangbin Liu -Date: Mon Oct 9 22:31:40 2017 +0800 - - port: track interface info in port - - Signed-off-by: Hangbin Liu - -diff --git a/port.c b/port.c -index 34837cc..849a7c1 100644 ---- a/port.c -+++ b/port.c -@@ -68,6 +68,7 @@ struct nrate_estimator { - struct port { - LIST_ENTRY(port) list; - char *name; -+ struct interface *iface; - struct clock *clock; - struct transport *trp; - enum timestamp_type timestamping; -@@ -2619,6 +2620,7 @@ struct port *port_open(int phc_index, - } - - p->name = interface->name; -+ p->iface = interface; - p->asymmetry = config_get_int(cfg, p->name, "delayAsymmetry"); - p->asymmetry <<= 16; - p->announce_span = transport == TRANS_UDS ? 0 : ANNOUNCE_SPAN; -commit 05bba46198cfc4ccfe0aff2e67e76d78898bbd96 -Author: Hangbin Liu -Date: Mon Oct 9 22:31:41 2017 +0800 - - rtnl: update rtgenmsg to ifinfomsg when request link info - - The previous function use general message and will dump all interfaces' - information. Now update with ifinfomsg so we could get specific interface's - information. - - We still could get all interfaces' info if set device to NULL. - - Signed-off-by: Hangbin Liu - -diff --git a/port.c b/port.c -index 849a7c1..5b85d87 100644 ---- a/port.c -+++ b/port.c -@@ -1512,7 +1512,7 @@ static int port_initialize(struct port *p) - if (p->fda.fd[FD_RTNL] == -1) - p->fda.fd[FD_RTNL] = rtnl_open(); - if (p->fda.fd[FD_RTNL] >= 0) -- rtnl_link_query(p->fda.fd[FD_RTNL]); -+ rtnl_link_query(p->fda.fd[FD_RTNL], p->iface->name); - } - - port_nrate_initialize(p); -diff --git a/rtnl.c b/rtnl.c -index d7a430d..8ecf6fe 100644 ---- a/rtnl.c -+++ b/rtnl.c -@@ -42,7 +42,7 @@ int rtnl_close(int fd) - return close(fd); - } - --int rtnl_link_query(int fd) -+int rtnl_link_query(int fd, char *device) - { - struct sockaddr_nl sa; - struct msghdr msg; -@@ -51,19 +51,21 @@ int rtnl_link_query(int fd) - - struct { - struct nlmsghdr hdr; -- struct rtgenmsg gen; -+ struct ifinfomsg ifm; - } __attribute__((packed)) request; - - memset(&sa, 0, sizeof(sa)); - sa.nl_family = AF_NETLINK; - - memset(&request, 0, sizeof(request)); -- request.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(request.gen)); -+ request.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(request.ifm)); - request.hdr.nlmsg_type = RTM_GETLINK; -- request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; -+ request.hdr.nlmsg_flags = NLM_F_REQUEST; - request.hdr.nlmsg_seq = 1; - request.hdr.nlmsg_pid = 0; -- request.gen.rtgen_family = AF_UNSPEC; -+ request.ifm.ifi_family = AF_UNSPEC; -+ request.ifm.ifi_index = if_nametoindex(device ? device : ""); -+ request.ifm.ifi_change = 0xffffffff; - - iov.iov_base = &request; - iov.iov_len = sizeof(request); -diff --git a/rtnl.h b/rtnl.h -index f1871f2..5c93eec 100644 ---- a/rtnl.h -+++ b/rtnl.h -@@ -31,10 +31,11 @@ int rtnl_close(int fd); - - /** - * Request the link status from the kernel. -- * @param fd A socket obtained via rtnl_open(). -- * @return Zero on success, non-zero otherwise. -+ * @param fd A socket obtained via rtnl_open(). -+ * @param device Interface name. Request all iface's status if set NULL. -+ * @return Zero on success, non-zero otherwise. - */ --int rtnl_link_query(int fd); -+int rtnl_link_query(int fd, char *device); - - /** - * Read kernel messages looking for a link up/down events. -Backport of commit 80bc4d4c2f4d1c3c246091aa6f103bb7943202ec -Author: Hangbin Liu -Date: Mon Oct 9 22:31:42 2017 +0800 - - rtnl: update function rtnl_link_status to get bond slave info - - Update function rtnl_link_status to get bond slave info. Pass the slave index - to call back functions. i.e. port_link_status. - - Also check the interface index of rtnl message in function rtnl_link_status. - Then we don't need to check it in port_link_status. - - [BACKPORT: not included] Add ifndef IFLA_BOND_MAX in case we build linuxptp - on kernel before v3.13-rc1. - - Signed-off-by: Hangbin Liu - -diff --git a/port.c b/port.c -index 5b85d87..05fc321 100644 ---- a/port.c -+++ b/port.c -@@ -2221,11 +2221,11 @@ void port_dispatch(struct port *p, enum fsm_event event, int mdiff) - } - } - --static void port_link_status(void *ctx, int index, int linkup) -+static void port_link_status(void *ctx, int linkup, int ts_index) - { - struct port *p = ctx; - -- if (index != if_nametoindex(p->name) || p->link_status == linkup) -+ if (p->link_status == linkup) - return; - - p->link_status = linkup; -@@ -2280,7 +2280,7 @@ enum fsm_event port_event(struct port *p, int fd_index) - - case FD_RTNL: - pr_debug("port %hu: received link status notification", portnum(p)); -- rtnl_link_status(fd, port_link_status, p); -+ rtnl_link_status(fd, p->name, port_link_status, p); - return port_link_status_get(p) ? EV_FAULT_CLEARED : EV_FAULT_DETECTED; - } - -diff --git a/rtnl.c b/rtnl.c -index 8ecf6fe..3419873 100644 ---- a/rtnl.c -+++ b/rtnl.c -@@ -84,15 +85,79 @@ int rtnl_link_query(int fd, char *device) - return 0; - } - --int rtnl_link_status(int fd, rtnl_callback cb, void *ctx) -+static inline __u32 rta_getattr_u32(const struct rtattr *rta) - { -- int index, len; -+ return *(__u32 *)RTA_DATA(rta); -+} -+ -+static inline const char *rta_getattr_str(const struct rtattr *rta) -+{ -+ return (const char *)RTA_DATA(rta); -+} -+ -+static int rtnl_rtattr_parse(struct rtattr *tb[], int max, struct rtattr *rta, int len) -+{ -+ unsigned short type; -+ -+ memset(tb, 0, sizeof(struct rtattr *) * max); -+ while (RTA_OK(rta, len)) { -+ type = rta->rta_type; -+ if ((type < max) && (!tb[type])) -+ tb[type] = rta; -+ rta = RTA_NEXT(rta, len); -+ } -+ if (len) { -+ pr_err("Length mismatch: len %d, rta_len=%d\n", len, rta->rta_len); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static inline int rtnl_nested_rtattr_parse(struct rtattr *tb[], int max, struct rtattr *rta) -+{ -+ return rtnl_rtattr_parse(tb, max, RTA_DATA(rta), RTA_PAYLOAD(rta)); -+} -+ -+static int rtnl_linkinfo_parse(struct rtattr *rta) -+{ -+ int index = -1; -+ const char *kind; -+ struct rtattr *linkinfo[IFLA_INFO_MAX]; -+ struct rtattr *bond[IFLA_BOND_MAX]; -+ -+ if (rtnl_nested_rtattr_parse(linkinfo, IFLA_INFO_MAX, rta) < 0) -+ return -1; -+ -+ if (linkinfo[IFLA_INFO_KIND]) { -+ kind = rta_getattr_str(linkinfo[IFLA_INFO_KIND]); -+ -+ if (kind && !strncmp(kind, "bond", 4) && -+ linkinfo[IFLA_INFO_DATA]) { -+ if (rtnl_nested_rtattr_parse(bond, IFLA_BOND_MAX, -+ linkinfo[IFLA_INFO_DATA]) < 0) -+ return -1; -+ -+ if (bond[IFLA_BOND_ACTIVE_SLAVE]) { -+ index = rta_getattr_u32(bond[IFLA_BOND_ACTIVE_SLAVE]); -+ } -+ } -+ } -+ return index; -+} -+ -+int rtnl_link_status(int fd, char *device, rtnl_callback cb, void *ctx) -+{ -+ int index, len, link_up; -+ int slave_index = -1; - struct iovec iov; - struct sockaddr_nl sa; - struct msghdr msg; - struct nlmsghdr *nh; - struct ifinfomsg *info = NULL; -+ struct rtattr *tb[IFLA_MAX+1]; - -+ index = if_nametoindex(device); - if (!rtnl_buf) { - rtnl_len = 4096; - rtnl_buf = malloc(rtnl_len); -@@ -135,14 +200,27 @@ int rtnl_link_status(int fd, rtnl_callback cb, void *ctx) - nh = (struct nlmsghdr *) rtnl_buf; - - for ( ; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { -- if (nh->nlmsg_type == RTM_NEWLINK) { -- info = NLMSG_DATA(nh); -- index = info->ifi_index; -- pr_debug("interface index %d is %s", index, -- info->ifi_flags & IFF_RUNNING ? "up" : "down"); -- cb(ctx, index, info->ifi_flags & IFF_RUNNING ? 1 : 0); -- } -+ if (nh->nlmsg_type != RTM_NEWLINK) -+ continue; -+ -+ info = NLMSG_DATA(nh); -+ if (index != info->ifi_index) -+ continue; -+ -+ link_up = info->ifi_flags & IFF_RUNNING ? 1 : 0; -+ pr_debug("interface index %d is %s", index, -+ link_up ? "up" : "down"); -+ -+ rtnl_rtattr_parse(tb, IFLA_MAX, IFLA_RTA(info), -+ IFLA_PAYLOAD(nh)); -+ -+ if (tb[IFLA_LINKINFO]) -+ slave_index = rtnl_linkinfo_parse(tb[IFLA_LINKINFO]); -+ -+ if (cb) -+ cb(ctx, link_up, slave_index); - } -+ - return 0; - } - -diff --git a/rtnl.h b/rtnl.h -index 5c93eec..6eced2d 100644 ---- a/rtnl.h -+++ b/rtnl.h -@@ -20,7 +20,7 @@ - #ifndef HAVE_RTNL_H - #define HAVE_RTNL_H - --typedef void (*rtnl_callback)(void *ctx, int index, int linkup); -+typedef void (*rtnl_callback)(void *ctx, int linkup, int ts_index); - - /** - * Close a RT netlink socket. -@@ -39,12 +39,13 @@ int rtnl_link_query(int fd, char *device); - - /** - * Read kernel messages looking for a link up/down events. -- * @param fd Readable socket obtained via rtnl_open(). -- * @param cb Callback function to be invoked on each event. -- * @param ctx Private context passed to the callback. -- * @return Zero on success, non-zero otherwise. -+ * @param fd Readable socket obtained via rtnl_open(). -+ * @param device The device which we need to get link info. -+ * @param cb Callback function to be invoked on each event. -+ * @param ctx Private context passed to the callback. -+ * @return Zero on success, non-zero otherwise. - */ --int rtnl_link_status(int fd, rtnl_callback cb, void *ctx); -+int rtnl_link_status(int fd, char *device, rtnl_callback cb, void *ctx); - - /** - * Open a RT netlink socket for monitoring link state. -commit 6d1e2a62bdb4f6353e3a9006f2d603031f4648e6 -Author: Hangbin Liu -Date: Mon Oct 9 22:31:43 2017 +0800 - - rtnl: add function rtnl_get_ts_label to get interface ts_label info - - Signed-off-by: Hangbin Liu - -diff --git a/rtnl.c b/rtnl.c -index 3419873..cea936b 100644 ---- a/rtnl.c -+++ b/rtnl.c -@@ -43,6 +43,37 @@ int rtnl_close(int fd) - return close(fd); - } - -+static void rtnl_get_ts_label_callback(void *ctx, int linkup, int ts_index) -+{ -+ int *dst = ctx; -+ *dst = ts_index; -+} -+ -+int rtnl_get_ts_label(struct interface *iface) -+{ -+ int err, fd; -+ int ts_index = -1; -+ -+ fd = rtnl_open(); -+ if (fd < 0) -+ return fd; -+ -+ err = rtnl_link_query(fd, iface->name); -+ if (err) { -+ goto no_info; -+ } -+ -+ rtnl_link_status(fd, iface->name, rtnl_get_ts_label_callback, &ts_index); -+ if (ts_index > 0 && if_indextoname(ts_index, iface->ts_label)) -+ err = 0; -+ else -+ err = -1; -+ -+no_info: -+ rtnl_close(fd); -+ return err; -+} -+ - int rtnl_link_query(int fd, char *device) - { - struct sockaddr_nl sa; -diff --git a/rtnl.h b/rtnl.h -index 6eced2d..2906d74 100644 ---- a/rtnl.h -+++ b/rtnl.h -@@ -20,6 +20,8 @@ - #ifndef HAVE_RTNL_H - #define HAVE_RTNL_H - -+#include "config.h" -+ - typedef void (*rtnl_callback)(void *ctx, int linkup, int ts_index); - - /** -@@ -30,6 +32,13 @@ typedef void (*rtnl_callback)(void *ctx, int linkup, int ts_index); - int rtnl_close(int fd); - - /** -+ * Get interface ts_label information -+ * @param iface struct interface. -+ * @return Zero on success, or -1 on error. -+ */ -+int rtnl_get_ts_label(struct interface *iface); -+ -+/** - * Request the link status from the kernel. - * @param fd A socket obtained via rtnl_open(). - * @param device Interface name. Request all iface's status if set NULL. -commit b65b1d5f3b5d8e85e47e9cf19c2e5aa6dc2ebd77 -Author: Hangbin Liu -Date: Mon Oct 9 22:31:44 2017 +0800 - - port: update port link_status to enum - - Besides link up and down, we may also receive other rtnl messages, like - bond slave changed info, which link state keeps the same. - - So we should return EV_FAULT_CLEARED only when both LINK_UP and - LINK_STATE_CHANGED. - - When the link state keep the same, we should return EV_NONE. - - Signed-off-by: Hangbin Liu - -diff --git a/port.c b/port.c -index 05fc321..81d52ff 100644 ---- a/port.c -+++ b/port.c -@@ -56,6 +56,12 @@ enum syfu_event { - FUP_MATCH, - }; - -+enum link_state { -+ LINK_DOWN = (1<<0), -+ LINK_UP = (1<<1), -+ LINK_STATE_CHANGED = (1<<3), -+}; -+ - struct nrate_estimator { - double ratio; - tmv_t origin1; -@@ -122,7 +128,7 @@ struct port { - int path_trace_enabled; - int rx_timestamp_offset; - int tx_timestamp_offset; -- int link_status; -+ enum link_state link_status; - struct fault_interval flt_interval_pertype[FT_CNT]; - enum fault_type last_fault_type; - unsigned int versionNumber; /*UInteger4*/ -@@ -2224,18 +2230,21 @@ void port_dispatch(struct port *p, enum fsm_event event, int mdiff) - static void port_link_status(void *ctx, int linkup, int ts_index) - { - struct port *p = ctx; -+ int link_state; - -- if (p->link_status == linkup) -- return; -- -- p->link_status = linkup; -- pr_notice("port %hu: link %s", portnum(p), linkup ? "up" : "down"); -+ link_state = linkup ? LINK_UP : LINK_DOWN; -+ if (p->link_status & link_state) { -+ p->link_status = link_state; -+ } else { -+ p->link_status = link_state | LINK_STATE_CHANGED; -+ pr_notice("port %hu: link %s", portnum(p), linkup ? "up" : "down"); -+ } - - /* - * A port going down can affect the BMCA result. - * Force a state decision event. - */ -- if (!p->link_status) -+ if (p->link_status & LINK_DOWN) - clock_set_sde(p->clock, 1); - } - -@@ -2281,7 +2290,12 @@ enum fsm_event port_event(struct port *p, int fd_index) - case FD_RTNL: - pr_debug("port %hu: received link status notification", portnum(p)); - rtnl_link_status(fd, p->name, port_link_status, p); -- return port_link_status_get(p) ? EV_FAULT_CLEARED : EV_FAULT_DETECTED; -+ if (p->link_status == (LINK_UP | LINK_STATE_CHANGED)) -+ return EV_FAULT_CLEARED; -+ else if (p->link_status == (LINK_DOWN | LINK_STATE_CHANGED)) -+ return EV_FAULT_DETECTED; -+ else -+ return EV_NONE; - } - - msg = msg_allocate(); -@@ -2409,7 +2423,7 @@ int port_number(struct port *p) - - int port_link_status_get(struct port *p) - { -- return p->link_status; -+ return !!(p->link_status & LINK_UP); - } - - int port_manage(struct port *p, struct port *ingress, struct ptp_message *msg) -@@ -2630,7 +2644,7 @@ struct port *port_open(int phc_index, - p->path_trace_enabled = config_get_int(cfg, p->name, "path_trace_enabled"); - p->rx_timestamp_offset = config_get_int(cfg, p->name, "ingressLatency"); - p->tx_timestamp_offset = config_get_int(cfg, p->name, "egressLatency"); -- p->link_status = 1; -+ p->link_status = LINK_UP; - p->clock = clock; - p->trp = transport_create(cfg, transport); - if (!p->trp) -commit 1440f093847a79d0e80ea6b4bca011ddd87090d0 -Author: Hangbin Liu -Date: Mon Oct 9 22:31:45 2017 +0800 - - clock: add clock_required_modes to obtain the required time stamping mode - - Separate required_modes setting from clock_create so we can obtain the - required time stamping flags from other place. - - Add enum timestamping in struct clock to store the time stamping mode. - - Signed-off-by: Hangbin Liu - -diff --git a/clock.c b/clock.c -index 9d224c9..5926a3c 100644 ---- a/clock.c -+++ b/clock.c -@@ -105,6 +105,7 @@ struct clock { - int time_flags; /* grand master role */ - int time_source; /* grand master role */ - enum servo_state servo_state; -+ enum timestamp_type timestamping; - tmv_t master_offset; - tmv_t path_delay; - tmv_t ingress_ts; -@@ -803,6 +804,34 @@ static void clock_remove_port(struct clock *c, struct port *p) - port_close(p); - } - -+int clock_required_modes(struct clock *c) -+{ -+ int required_modes = 0; -+ -+ switch (c->timestamping) { -+ case TS_SOFTWARE: -+ required_modes |= SOF_TIMESTAMPING_TX_SOFTWARE | -+ SOF_TIMESTAMPING_RX_SOFTWARE | -+ SOF_TIMESTAMPING_SOFTWARE; -+ break; -+ case TS_LEGACY_HW: -+ required_modes |= SOF_TIMESTAMPING_TX_HARDWARE | -+ SOF_TIMESTAMPING_RX_HARDWARE | -+ SOF_TIMESTAMPING_SYS_HARDWARE; -+ break; -+ case TS_HARDWARE: -+ case TS_ONESTEP: -+ required_modes |= SOF_TIMESTAMPING_TX_HARDWARE | -+ SOF_TIMESTAMPING_RX_HARDWARE | -+ SOF_TIMESTAMPING_RAW_HARDWARE; -+ break; -+ default: -+ break; -+ } -+ -+ return required_modes; -+} -+ - struct clock *clock_create(enum clock_type type, struct config *config, - const char *phc_device) - { -@@ -911,24 +940,8 @@ struct clock *clock_create(enum clock_type type, struct config *config, - } - - /* Check the time stamping mode on each interface. */ -- switch (timestamping) { -- case TS_SOFTWARE: -- required_modes |= SOF_TIMESTAMPING_TX_SOFTWARE | -- SOF_TIMESTAMPING_RX_SOFTWARE | -- SOF_TIMESTAMPING_SOFTWARE; -- break; -- case TS_LEGACY_HW: -- required_modes |= SOF_TIMESTAMPING_TX_HARDWARE | -- SOF_TIMESTAMPING_RX_HARDWARE | -- SOF_TIMESTAMPING_SYS_HARDWARE; -- break; -- case TS_HARDWARE: -- case TS_ONESTEP: -- required_modes |= SOF_TIMESTAMPING_TX_HARDWARE | -- SOF_TIMESTAMPING_RX_HARDWARE | -- SOF_TIMESTAMPING_RAW_HARDWARE; -- break; -- } -+ c->timestamping = timestamping; -+ required_modes = clock_required_modes(c); - STAILQ_FOREACH(iface, &config->interfaces, list) { - if (iface->ts_info.valid && - ((iface->ts_info.so_timestamping & required_modes) != required_modes)) { -diff --git a/clock.h b/clock.h -index 49ecb76..986d363 100644 ---- a/clock.h -+++ b/clock.h -@@ -73,6 +73,14 @@ UInteger8 clock_class(struct clock *c); - struct config *clock_config(struct clock *c); - - /** -+ * Obtains the required time stamping mode. -+ * @param c The clock instance. -+ * @return The value of required time stamping mode, which is a bit mask -+ * of SOF_TIMESTAMPING_ flags. -+ */ -+int clock_required_modes(struct clock *c); -+ -+/** - * Create a clock instance. There can only be one clock in any system, - * so subsequent calls will destroy the previous clock instance. - * -commit 536a71031d5c7689fd186ff550dc11cf743e02cb -Author: Hangbin Liu -Date: Mon Oct 9 22:31:46 2017 +0800 - - ptp4l: use ts label to get ts info - - Now the ts label will be either the bond active slave or the interface - name, which is the exactly interface we need to get ts info. - - When the link down/up or there is a fail over and ts_label changed, the - phc index may also changed. So we need to check get new ts info and check - clock_required_modes. We will set the link to LINK_DOWN by force if - the new ts_label's timestamp do not support required mode. - - If all good, then we set phc index to new one. Also sync clock interval - after switch phc. - - Signed-off-by: Hangbin Liu - -diff --git a/clock.c b/clock.c -index 5926a3c..41c8f81 100644 ---- a/clock.c -+++ b/clock.c -@@ -38,6 +38,7 @@ - #include "servo.h" - #include "stats.h" - #include "print.h" -+#include "rtnl.h" - #include "tlv.h" - #include "tsproc.h" - #include "uds.h" -@@ -832,6 +833,16 @@ int clock_required_modes(struct clock *c) - return required_modes; - } - -+/* -+ * If we do not have a slave or the rtnl query failed, then use our -+ * own interface name as the time stamping interface name. -+ */ -+static void ensure_ts_label(struct interface *iface) -+{ -+ if (iface->ts_label[0] == '\0') -+ strncpy(iface->ts_label, iface->name, MAX_IFNAME_SIZE); -+} -+ - struct clock *clock_create(enum clock_type type, struct config *config, - const char *phc_device) - { -@@ -943,6 +954,9 @@ struct clock *clock_create(enum clock_type type, struct config *config, - c->timestamping = timestamping; - required_modes = clock_required_modes(c); - STAILQ_FOREACH(iface, &config->interfaces, list) { -+ rtnl_get_ts_label(iface); -+ ensure_ts_label(iface); -+ sk_get_ts_info(iface->ts_label, &iface->ts_info); - if (iface->ts_info.valid && - ((iface->ts_info.so_timestamping & required_modes) != required_modes)) { - pr_err("interface '%s' does not support " -diff --git a/config.c b/config.c -index e6fe676..bbaf36e 100644 ---- a/config.c -+++ b/config.c -@@ -633,7 +633,6 @@ struct interface *config_create_interface(char *name, struct config *cfg) - } - - strncpy(iface->name, name, MAX_IFNAME_SIZE); -- sk_get_ts_info(iface->name, &iface->ts_info); - STAILQ_INSERT_TAIL(&cfg->interfaces, iface, list); - cfg->n_interfaces++; - -diff --git a/port.c b/port.c -index 81d52ff..615c800 100644 ---- a/port.c -+++ b/port.c -@@ -60,6 +60,7 @@ enum link_state { - LINK_DOWN = (1<<0), - LINK_UP = (1<<1), - LINK_STATE_CHANGED = (1<<3), -+ TS_LABEL_CHANGED = (1<<4), - }; - - struct nrate_estimator { -@@ -2231,6 +2232,8 @@ static void port_link_status(void *ctx, int linkup, int ts_index) - { - struct port *p = ctx; - int link_state; -+ char ts_label[MAX_IFNAME_SIZE + 1] = {0}; -+ int required_modes; - - link_state = linkup ? LINK_UP : LINK_DOWN; - if (p->link_status & link_state) { -@@ -2240,6 +2243,39 @@ static void port_link_status(void *ctx, int linkup, int ts_index) - pr_notice("port %hu: link %s", portnum(p), linkup ? "up" : "down"); - } - -+ /* ts_label changed */ -+ if (if_indextoname(ts_index, ts_label) && strcmp(p->iface->ts_label, ts_label)) { -+ strncpy(p->iface->ts_label, ts_label, MAX_IFNAME_SIZE); -+ p->link_status |= TS_LABEL_CHANGED; -+ pr_notice("port %hu: ts label changed to %s", portnum(p), ts_label); -+ } -+ -+ /* Both link down/up and change ts_label may change phc index. */ -+ if (p->link_status & LINK_UP && -+ (p->link_status & LINK_STATE_CHANGED || p->link_status & TS_LABEL_CHANGED)) { -+ sk_get_ts_info(p->iface->ts_label, &p->iface->ts_info); -+ -+ /* Only switch phc with HW time stamping mode */ -+ if (p->phc_index >= 0 && p->iface->ts_info.valid) { -+ required_modes = clock_required_modes(p->clock); -+ if ((p->iface->ts_info.so_timestamping & required_modes) != required_modes) { -+ pr_err("interface '%s' does not support requested " -+ "timestamping mode, set link status down by force.", -+ p->iface->ts_label); -+ p->link_status = LINK_DOWN | LINK_STATE_CHANGED; -+ } else if (p->phc_index != p->iface->ts_info.phc_index) { -+ p->phc_index = p->iface->ts_info.phc_index; -+ -+ if (clock_switch_phc(p->clock, p->phc_index)) { -+ p->last_fault_type = FT_SWITCH_PHC; -+ port_dispatch(p, EV_FAULT_DETECTED, 0); -+ return; -+ } -+ clock_sync_interval(p->clock, p->log_sync_interval); -+ } -+ } -+ } -+ - /* - * A port going down can affect the BMCA result. - * Force a state decision event. -@@ -2292,7 +2328,8 @@ enum fsm_event port_event(struct port *p, int fd_index) - rtnl_link_status(fd, p->name, port_link_status, p); - if (p->link_status == (LINK_UP | LINK_STATE_CHANGED)) - return EV_FAULT_CLEARED; -- else if (p->link_status == (LINK_DOWN | LINK_STATE_CHANGED)) -+ else if ((p->link_status == (LINK_DOWN | LINK_STATE_CHANGED)) || -+ (p->link_status & TS_LABEL_CHANGED)) - return EV_FAULT_DETECTED; - else - return EV_NONE; -commit 8923bcdf64c0c95bac7af977b867393bae69e7a1 -Author: Hangbin Liu -Date: Mon Oct 9 22:31:47 2017 +0800 - - transport: pass struct interface to transport_open - - Pass struct interface so we can use ts_iface in HW filter. - - Signed-off-by: Hangbin Liu - -diff --git a/pmc_common.c b/pmc_common.c -index d92b0cd..447cf99 100644 ---- a/pmc_common.c -+++ b/pmc_common.c -@@ -67,6 +67,7 @@ struct pmc *pmc_create(struct config *cfg, enum transport_type transport_type, - int zero_datalen) - { - struct pmc *pmc; -+ struct interface iface; - - pmc = calloc(1, sizeof *pmc); - if (!pmc) -@@ -90,7 +91,9 @@ struct pmc *pmc_create(struct config *cfg, enum transport_type transport_type, - pr_err("failed to create transport"); - goto failed; - } -- if (transport_open(pmc->transport, iface_name, -+ -+ strncpy(iface.name, iface_name, MAX_IFNAME_SIZE); -+ if (transport_open(pmc->transport, &iface, - &pmc->fdarray, TS_SOFTWARE)) { - pr_err("failed to open transport"); - goto failed; -diff --git a/port.c b/port.c -index 615c800..1e3f474 100644 ---- a/port.c -+++ b/port.c -@@ -1504,7 +1504,7 @@ static int port_initialize(struct port *p) - goto no_timers; - } - } -- if (transport_open(p->trp, p->name, &p->fda, p->timestamping)) -+ if (transport_open(p->trp, p->iface, &p->fda, p->timestamping)) - goto no_tropen; - - for (i = 0; i < N_TIMER_FDS; i++) { -@@ -1547,7 +1547,7 @@ static int port_renew_transport(struct port *p) - } - transport_close(p->trp, &p->fda); - port_clear_fda(p, FD_ANNOUNCE_TIMER); -- res = transport_open(p->trp, p->name, &p->fda, p->timestamping); -+ res = transport_open(p->trp, p->iface, &p->fda, p->timestamping); - /* Need to call clock_fda_changed even if transport_open failed in - * order to update clock to the now closed descriptors. */ - clock_fda_changed(p->clock); -diff --git a/raw.c b/raw.c -index 73e45b4..8b7bcf1 100644 ---- a/raw.c -+++ b/raw.c -@@ -198,15 +198,16 @@ static void addr_to_mac(void *mac, struct address *addr) - memcpy(mac, &addr->sll.sll_addr, MAC_LEN); - } - --static int raw_open(struct transport *t, const char *name, -+static int raw_open(struct transport *t, struct interface *iface, - struct fdarray *fda, enum timestamp_type ts_type) - { - struct raw *raw = container_of(t, struct raw, t); - unsigned char ptp_dst_mac[MAC_LEN]; - unsigned char p2p_dst_mac[MAC_LEN]; - int efd, gfd; -- char *str; -+ char *str, *name; - -+ name = iface->ts_label; - str = config_get_string(t->cfg, name, "ptp_dst_mac"); - if (str2mac(str, ptp_dst_mac)) { - pr_err("invalid ptp_dst_mac %s", str); -diff --git a/transport.c b/transport.c -index d24c05b..3541394 100644 ---- a/transport.c -+++ b/transport.c -@@ -31,10 +31,10 @@ int transport_close(struct transport *t, struct fdarray *fda) - return t->close(t, fda); - } - --int transport_open(struct transport *t, const char *name, -+int transport_open(struct transport *t, struct interface *iface, - struct fdarray *fda, enum timestamp_type tt) - { -- return t->open(t, name, fda, tt); -+ return t->open(t, iface, fda, tt); - } - - int transport_recv(struct transport *t, int fd, struct ptp_message *msg) -diff --git a/transport.h b/transport.h -index 5d6ba98..15616bb 100644 ---- a/transport.h -+++ b/transport.h -@@ -27,6 +27,7 @@ - #include "msg.h" - - struct config; -+struct interface; - - /* Values from networkProtocol enumeration 7.4.1 Table 3 */ - enum transport_type { -@@ -54,7 +55,7 @@ struct transport; - - int transport_close(struct transport *t, struct fdarray *fda); - --int transport_open(struct transport *t, const char *name, -+int transport_open(struct transport *t, struct interface *iface, - struct fdarray *fda, enum timestamp_type tt); - - int transport_recv(struct transport *t, int fd, struct ptp_message *msg); -diff --git a/transport_private.h b/transport_private.h -index b54f32a..7530896 100644 ---- a/transport_private.h -+++ b/transport_private.h -@@ -32,8 +32,8 @@ struct transport { - - int (*close)(struct transport *t, struct fdarray *fda); - -- int (*open)(struct transport *t, const char *name, struct fdarray *fda, -- enum timestamp_type tt); -+ int (*open)(struct transport *t, struct interface *iface, -+ struct fdarray *fda, enum timestamp_type tt); - - int (*recv)(struct transport *t, int fd, void *buf, int buflen, - struct address *addr, struct hw_timestamp *hwts); -diff --git a/udp.c b/udp.c -index 530a2ee..05c2ba0 100644 ---- a/udp.c -+++ b/udp.c -@@ -152,12 +152,13 @@ enum { MC_PRIMARY, MC_PDELAY }; - - static struct in_addr mcast_addr[2]; - --static int udp_open(struct transport *t, const char *name, struct fdarray *fda, -- enum timestamp_type ts_type) -+static int udp_open(struct transport *t, struct interface *iface, -+ struct fdarray *fda, enum timestamp_type ts_type) - { - struct udp *udp = container_of(t, struct udp, t); - uint8_t event_dscp, general_dscp; - int efd, gfd, ttl; -+ char *name = iface->name; - - ttl = config_get_int(t->cfg, name, "udp_ttl"); - udp->mac.len = 0; -@@ -180,7 +181,7 @@ static int udp_open(struct transport *t, const char *name, struct fdarray *fda, - if (gfd < 0) - goto no_general; - -- if (sk_timestamping_init(efd, name, ts_type, TRANS_UDP_IPV4)) -+ if (sk_timestamping_init(efd, iface->ts_label, ts_type, TRANS_UDP_IPV4)) - goto no_timestamping; - - if (sk_general_init(gfd)) -diff --git a/udp6.c b/udp6.c -index 89e27bf..7551e3f 100644 ---- a/udp6.c -+++ b/udp6.c -@@ -160,12 +160,13 @@ enum { MC_PRIMARY, MC_PDELAY }; - - static struct in6_addr mc6_addr[2]; - --static int udp6_open(struct transport *t, const char *name, struct fdarray *fda, -- enum timestamp_type ts_type) -+static int udp6_open(struct transport *t, struct interface *iface, -+ struct fdarray *fda, enum timestamp_type ts_type) - { - struct udp6 *udp6 = container_of(t, struct udp6, t); - uint8_t event_dscp, general_dscp; - int efd, gfd, hop_limit; -+ char *name = iface->name; - - hop_limit = config_get_int(t->cfg, name, "udp_ttl"); - udp6->mac.len = 0; -@@ -190,7 +191,7 @@ static int udp6_open(struct transport *t, const char *name, struct fdarray *fda, - if (gfd < 0) - goto no_general; - -- if (sk_timestamping_init(efd, name, ts_type, TRANS_UDP_IPV6)) -+ if (sk_timestamping_init(efd, iface->ts_label, ts_type, TRANS_UDP_IPV6)) - goto no_timestamping; - - if (sk_general_init(gfd)) -diff --git a/uds.c b/uds.c -index d5e8f50..7e11f63 100644 ---- a/uds.c -+++ b/uds.c -@@ -52,13 +52,14 @@ static int uds_close(struct transport *t, struct fdarray *fda) - return 0; - } - --static int uds_open(struct transport *t, const char *name, struct fdarray *fda, -+static int uds_open(struct transport *t, struct interface *iface, struct fdarray *fda, - enum timestamp_type tt) - { - int fd, err; - struct sockaddr_un sa; - struct uds *uds = container_of(t, struct uds, t); - char *uds_path = config_get_string(t->cfg, NULL, "uds_address"); -+ char *name = iface->name; - - fd = socket(AF_LOCAL, SOCK_DGRAM, 0); - if (fd < 0) { -commit cb53238d5d1a1b9319536b4df1edf237e428d931 -Author: Hangbin Liu -Date: Mon Oct 9 22:31:48 2017 +0800 - - phc2sys: split servo_add from function clock_add - - We also need this part in clock_reinit() later. So split it out of - function clock_add(). - - Signed-off-by: Hangbin Liu - -diff --git a/phc2sys.c b/phc2sys.c -index e2b5c47..0472c68 100644 ---- a/phc2sys.c -+++ b/phc2sys.c -@@ -162,12 +162,45 @@ static clockid_t clock_open(char *device, int *phc_index) - return clkid; - } - -+static struct servo *servo_add(struct node *node, struct clock *clock) -+{ -+ double ppb; -+ int max_ppb; -+ struct servo *servo; -+ -+ clockadj_init(clock->clkid); -+ ppb = clockadj_get_freq(clock->clkid); -+ /* The reading may silently fail and return 0, reset the frequency to -+ make sure ppb is the actual frequency of the clock. */ -+ clockadj_set_freq(clock->clkid, ppb); -+ if (clock->clkid == CLOCK_REALTIME) { -+ sysclk_set_leap(0); -+ max_ppb = sysclk_max_freq(); -+ } else { -+ max_ppb = phc_max_adj(clock->clkid); -+ if (!max_ppb) { -+ pr_err("clock is not adjustable"); -+ return NULL; -+ } -+ } -+ -+ servo = servo_create(phc2sys_config, node->servo_type, -+ -ppb, max_ppb, 0); -+ if (!servo) { -+ pr_err("Failed to create servo"); -+ return NULL; -+ } -+ -+ servo_sync_interval(servo, node->phc_interval); -+ -+ return servo; -+} -+ - static struct clock *clock_add(struct node *node, char *device) - { - struct clock *c; - clockid_t clkid = CLOCK_INVALID; -- int max_ppb, phc_index = -1; -- double ppb; -+ int phc_index = -1; - - if (device) { - clkid = clock_open(device, &phc_index); -@@ -211,25 +244,7 @@ static struct clock *clock_add(struct node *node, char *device) - } - } - -- clockadj_init(c->clkid); -- ppb = clockadj_get_freq(c->clkid); -- /* The reading may silently fail and return 0, reset the frequency to -- make sure ppb is the actual frequency of the clock. */ -- clockadj_set_freq(c->clkid, ppb); -- if (c->clkid == CLOCK_REALTIME) { -- sysclk_set_leap(0); -- max_ppb = sysclk_max_freq(); -- } else { -- max_ppb = phc_max_adj(c->clkid); -- if (!max_ppb) { -- pr_err("clock is not adjustable"); -- return NULL; -- } -- } -- -- c->servo = servo_create(phc2sys_config, node->servo_type, -- -ppb, max_ppb, 0); -- servo_sync_interval(c->servo, node->phc_interval); -+ c->servo = servo_add(node, c); - - if (clkid != CLOCK_REALTIME) - c->sysoff_supported = (SYSOFF_SUPPORTED == -commit 8a349e557c653d24b04b0545e2f179080e10731f -Author: Hangbin Liu -Date: Mon Oct 9 22:31:49 2017 +0800 - - phc2sys: re-create clock clkid and servo when phc index changed - - When the clock device or phc index changed, the new phc device may have - different maximum adjustment. So we need to create a new clkid and servo - in clock_reinit(). - - At the same time, we should not only do clock_reinit() when the new state - is PS_MASTER. We also need to reinit clock after a failover in slave mode( - the new state is PS_SLAVE). We can do clock_reinit() even in PS_FAULTY so - we can finish adjust offset before come back to PS_LISTENING. So I removed - the check and let's do clock_reinit() whenever there is a new state. - - And for servo reset, as Miroslav suggested, we will do it in these cases: - - the system clock is the new destination (master state) - - a PHC is the new destination (master state) - - a PHC is switched (in any state) - - Signed-off-by: Hangbin Liu - -diff --git a/phc2sys.c b/phc2sys.c -index 0472c68..5c54055 100644 ---- a/phc2sys.c -+++ b/phc2sys.c -@@ -128,6 +128,11 @@ static int clock_handle_leap(struct node *node, struct clock *clock, - static int run_pmc_get_utc_offset(struct node *node, int timeout); - static void run_pmc_events(struct node *node); - -+static int normalize_state(int state); -+static int run_pmc_port_properties(struct node *node, int timeout, -+ unsigned int port, -+ int *state, int *tstamping, char *iface); -+ - static clockid_t clock_open(char *device, int *phc_index) - { - struct sk_ts_info ts_info; -@@ -309,15 +314,62 @@ static struct port *port_add(struct node *node, unsigned int number, - return p; - } - --static void clock_reinit(struct clock *clock) -+static void clock_reinit(struct node *node, struct clock *clock, int new_state) - { -- servo_reset(clock->servo); -- clock->servo_state = SERVO_UNLOCKED; -+ int phc_index = -1, phc_switched = 0; -+ int state, timestamping, ret = -1; -+ struct port *p; -+ struct servo *servo; -+ struct sk_ts_info ts_info; -+ char iface[IFNAMSIZ]; -+ clockid_t clkid = CLOCK_INVALID; - -- if (clock->offset_stats) { -- stats_reset(clock->offset_stats); -- stats_reset(clock->freq_stats); -- stats_reset(clock->delay_stats); -+ LIST_FOREACH(p, &node->ports, list) { -+ if (p->clock == clock) { -+ ret = run_pmc_port_properties(node, 1000, p->number, -+ &state, ×tamping, -+ iface); -+ if (ret > 0) -+ p->state = normalize_state(state); -+ } -+ } -+ -+ if (ret > 0 && timestamping != TS_SOFTWARE) { -+ /* Check if device changed */ -+ if (strcmp(clock->device, iface)) { -+ free(clock->device); -+ clock->device = strdup(iface); -+ } -+ /* Check if phc index changed */ -+ if (!sk_get_ts_info(clock->device, &ts_info) && -+ clock->phc_index != ts_info.phc_index) { -+ clkid = clock_open(clock->device, &phc_index); -+ if (clkid == CLOCK_INVALID) -+ return; -+ -+ phc_close(clock->clkid); -+ clock->clkid = clkid; -+ clock->phc_index = phc_index; -+ -+ servo = servo_add(node, clock); -+ if (servo) { -+ servo_destroy(clock->servo); -+ clock->servo = servo; -+ } -+ -+ phc_switched = 1; -+ } -+ } -+ -+ if (new_state == PS_MASTER || phc_switched) { -+ servo_reset(clock->servo); -+ clock->servo_state = SERVO_UNLOCKED; -+ -+ if (clock->offset_stats) { -+ stats_reset(clock->offset_stats); -+ stats_reset(clock->freq_stats); -+ stats_reset(clock->delay_stats); -+ } - } - } - -@@ -336,9 +388,7 @@ static void reconfigure(struct node *node) - } - - if (c->new_state) { -- if (c->new_state == PS_MASTER) -- clock_reinit(c); -- -+ clock_reinit(node, c, c->new_state); - c->state = c->new_state; - c->new_state = 0; - } -@@ -403,7 +453,7 @@ static void reconfigure(struct node *node) - } else if (rt) { - if (rt->state != PS_MASTER) { - rt->state = PS_MASTER; -- clock_reinit(rt); -+ clock_reinit(node, rt, rt->state); - } - pr_info("selecting %s for synchronization", rt->device); - } -commit 7092db303028d84574138c8199375dfde0b4e232 -Author: Hangbin Liu -Date: Mon Oct 9 22:31:50 2017 +0800 - - port: return timestamping iface in port properties - - Signed-off-by: Hangbin Liu - -diff --git a/port.c b/port.c -index 1e3f474..d8e29d5 100644 ---- a/port.c -+++ b/port.c -@@ -861,7 +861,7 @@ static int port_management_fill_response(struct port *target, - else - ppn->port_state = target->state; - ppn->timestamping = target->timestamping; -- ptp_text_set(&ppn->interface, target->name); -+ ptp_text_set(&ppn->interface, target->iface->ts_label); - datalen = sizeof(*ppn) + ppn->interface.length; - respond = 1; - break; -commit 5ce04f9bf366c6d62db5344a6553f87a99ea52ff -Author: Hangbin Liu -Date: Wed Oct 18 20:31:38 2017 +0800 - - phc2sys: update '-s' option - - Add description about bond interface. - - Signed-off-by: Hangbin Liu - -diff --git a/phc2sys.8 b/phc2sys.8 -index 2559c74..4fc4fa3 100644 ---- a/phc2sys.8 -+++ b/phc2sys.8 -@@ -94,7 +94,11 @@ together with the - option, the master clock is used only to correct the offset by whole number of - seconds, which cannot be fixed with PPS alone. Not compatible with the - .B \-a --option. -+option. This option does not support bonded interface (e.g. bond0). If -+.B ptp4l -+has a port on an active-backup bond interface, the -+.B \-a -+option can be used to track the active interface. - .TP - .BI \-i " interface" - Performs the exact same function as - -Backport of -commit 742f8788211d2a861a0214e76449390b89ba55c2 -Author: Miroslav Lichvar -Date: Fri Apr 13 17:11:56 2018 +0200 - - rtnl: remove dependency on config.h. - - Change the rtnl_get_ts_label() function to accept the name of the master - interface and the buffer for the slave interface directly instead of the - struct interface from config.h. - - Also, rename the function to rtnl_get_ts_device(). - - Signed-off-by: Miroslav Lichvar - -diff --git a/clock.c b/clock.c -index 9ffb43e..afee960 100644 ---- a/clock.c -+++ b/clock.c -@@ -948,7 +948,7 @@ struct clock *clock_create(enum clock_type type, struct config *config, - c->timestamping = timestamping; - required_modes = clock_required_modes(c); - STAILQ_FOREACH(iface, &config->interfaces, list) { -- rtnl_get_ts_label(iface); -+ rtnl_get_ts_device(iface->name, iface->ts_label); - ensure_ts_label(iface); - sk_get_ts_info(iface->ts_label, &iface->ts_info); - if (iface->ts_info.valid && -diff --git a/rtnl.c b/rtnl.c -index cea936b..f9a572b 100644 ---- a/rtnl.c -+++ b/rtnl.c -@@ -43,13 +43,13 @@ int rtnl_close(int fd) - return close(fd); - } - --static void rtnl_get_ts_label_callback(void *ctx, int linkup, int ts_index) -+static void rtnl_get_ts_device_callback(void *ctx, int linkup, int ts_index) - { - int *dst = ctx; - *dst = ts_index; - } - --int rtnl_get_ts_label(struct interface *iface) -+int rtnl_get_ts_device(char *device, char *ts_device) - { - int err, fd; - int ts_index = -1; -@@ -58,13 +58,13 @@ int rtnl_get_ts_label(struct interface *iface) - if (fd < 0) - return fd; - -- err = rtnl_link_query(fd, iface->name); -+ err = rtnl_link_query(fd, device); - if (err) { - goto no_info; - } - -- rtnl_link_status(fd, iface->name, rtnl_get_ts_label_callback, &ts_index); -- if (ts_index > 0 && if_indextoname(ts_index, iface->ts_label)) -+ rtnl_link_status(fd, device, rtnl_get_ts_device_callback, &ts_index); -+ if (ts_index > 0 && if_indextoname(ts_index, ts_device)) - err = 0; - else - err = -1; -diff --git a/rtnl.h b/rtnl.h -index 2906d74..f877cd2 100644 ---- a/rtnl.h -+++ b/rtnl.h -@@ -20,8 +20,6 @@ - #ifndef HAVE_RTNL_H - #define HAVE_RTNL_H - --#include "config.h" -- - typedef void (*rtnl_callback)(void *ctx, int linkup, int ts_index); - - /** -@@ -32,11 +30,14 @@ typedef void (*rtnl_callback)(void *ctx, int linkup, int ts_index); - int rtnl_close(int fd); - - /** -- * Get interface ts_label information -- * @param iface struct interface. -- * @return Zero on success, or -1 on error. -+ * Get name of the slave interface which timestamps packets going through -+ * a master interface (e.g. bond0) -+ * @param device Name of the master interface. -+ * @param ts_device Buffer for the name of the slave interface, which must be -+ * at least IF_NAMESIZE bytes long. -+ * @return Zero on success, or -1 on error. - */ --int rtnl_get_ts_label(struct interface *iface); -+int rtnl_get_ts_device(char *device, char *ts_device); - - /** - * Request the link status from the kernel. - -commit e5ba2dae5f102a66e152b96f9cc7b06aff4b90b5 -Author: Miroslav Lichvar -Date: Fri Apr 13 17:11:57 2018 +0200 - - timemaster: add support for bonded interfaces. - - Use the rtnl_get_ts_device() function to get the name of the slave - interface which will be timestamping PTP packets and use it instead of - the master interface to check the timestamping capabilities and PHC. - - Signed-off-by: Miroslav Lichvar - -diff --git a/makefile b/makefile -index 6f5321c..17189e6 100644 ---- a/makefile -+++ b/makefile -@@ -60,7 +60,7 @@ hwstamp_ctl: hwstamp_ctl.o version.o - - phc_ctl: phc_ctl.o phc.o sk.o util.o clockadj.o sysoff.o print.o version.o - --timemaster: print.o sk.o timemaster.o util.o version.o -+timemaster: print.o rtnl.o sk.o timemaster.o util.o version.o - - version.o: .version version.sh $(filter-out version.d,$(DEPEND)) - -diff --git a/timemaster.c b/timemaster.c -index cda2d90..fc3ba31 100644 ---- a/timemaster.c -+++ b/timemaster.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -35,6 +36,7 @@ - #include - - #include "print.h" -+#include "rtnl.h" - #include "sk.h" - #include "util.h" - #include "version.h" -@@ -674,6 +676,7 @@ static int add_ptp_source(struct ptp_domain *source, - { - struct config_file *config_file; - char **command, *uds_path, **interfaces, *message_tag; -+ char ts_interface[IF_NAMESIZE]; - int i, j, num_interfaces, *phc, *phcs, hw_ts, sw_ts; - struct sk_ts_info ts_info; - -@@ -696,26 +699,38 @@ static int add_ptp_source(struct ptp_domain *source, - for (i = 0; i < num_interfaces; i++) { - phcs[i] = -1; - -+ /* -+ * if it is a bonded interface, use the name of the active -+ * slave interface (which will be timestamping packets) -+ */ -+ if (!rtnl_get_ts_device(source->interfaces[i], ts_interface)) { -+ pr_debug("slave interface of %s: %s", -+ source->interfaces[i], ts_interface); -+ } else { -+ snprintf(ts_interface, sizeof(ts_interface), "%s", -+ source->interfaces[i]); -+ } -+ - /* check if the interface has a usable PHC */ -- if (sk_get_ts_info(source->interfaces[i], &ts_info)) { -+ if (sk_get_ts_info(ts_interface, &ts_info)) { - pr_err("failed to get time stamping info for %s", -- source->interfaces[i]); -+ ts_interface); - free(phcs); - return 1; - } - - if (((ts_info.so_timestamping & hw_ts) != hw_ts)) { -- pr_debug("interface %s: no PHC", source->interfaces[i]); -+ pr_debug("interface %s: no PHC", ts_interface); - if ((ts_info.so_timestamping & sw_ts) != sw_ts) { - pr_err("time stamping not supported on %s", -- source->interfaces[i]); -+ ts_interface); - free(phcs); - return 1; - } - continue; - } - -- pr_debug("interface %s: PHC %d", source->interfaces[i], -+ pr_debug("interface %s: PHC %d", ts_interface, - ts_info.phc_index); - - /* and the PHC isn't already used in another source */ diff --git a/SOURCES/linuxptp-closesocket.patch b/SOURCES/linuxptp-closesocket.patch deleted file mode 100644 index 6b27b99..0000000 --- a/SOURCES/linuxptp-closesocket.patch +++ /dev/null @@ -1,38 +0,0 @@ -commit a3500e14ca4af38034d5ad2115ca7ac271c8c5b4 -Author: Miroslav Lichvar -Date: Mon Feb 6 15:43:00 2017 +0100 - - Fix leaks of sockets on errors. - - Signed-off-by: Miroslav Lichvar - -diff --git a/clock.c b/clock.c -index a6a1a1a..9481606 100644 ---- a/clock.c -+++ b/clock.c -@@ -824,11 +824,13 @@ static int clock_add_port(struct clock *c, int phc_index, - } - index = sk_interface_index(fd, iface->name); - if (index < 0) { -+ close(fd); - return -1; - } - snprintf(key, sizeof(key), "%d", index); - if (hash_insert(c->index2port, key, p)) { - pr_err("failed to add port with index %d twice!", index); -+ close(fd); - return -1; - } - close(fd); -diff --git a/rtnl.c b/rtnl.c -index 7f5dc45..251b5f3 100644 ---- a/rtnl.c -+++ b/rtnl.c -@@ -160,6 +160,7 @@ int rtnl_open(void) - } - if (bind(fd, (struct sockaddr *) &sa, sizeof(sa))) { - pr_err("failed to bind netlink socket: %m"); -+ close(fd); - return -1; - } - return fd; diff --git a/SOURCES/linuxptp-headers.patch b/SOURCES/linuxptp-headers.patch new file mode 100644 index 0000000..c1aca97 --- /dev/null +++ b/SOURCES/linuxptp-headers.patch @@ -0,0 +1,51 @@ +commit d663a483c40939bad58301c256d86da1f3da6cc0 +Author: Miroslav Lichvar +Date: Tue Nov 13 13:16:08 2018 +0100 + + Fix building with new kernel headers. + + net_tstamp.h in recent kernel versions requires time.h for clockid_t. + + Signed-off-by: Miroslav Lichvar + +diff --git a/clock.c b/clock.c +index 9c493c3..8533b39 100644 +--- a/clock.c ++++ b/clock.c +@@ -17,11 +17,11 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + #include ++#include + #include + #include + #include + #include +-#include + #include + + #include "address.h" +diff --git a/sk.c b/sk.c +index e2b1f28..30162eb 100644 +--- a/sk.c ++++ b/sk.c +@@ -18,6 +18,7 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + #include ++#include + #include + #include + #include +diff --git a/timemaster.c b/timemaster.c +index 058678f..00db59f 100644 +--- a/timemaster.c ++++ b/timemaster.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include diff --git a/SOURCES/linuxptp-ipoib.patch b/SOURCES/linuxptp-ipoib.patch deleted file mode 100644 index 1c62978..0000000 --- a/SOURCES/linuxptp-ipoib.patch +++ /dev/null @@ -1,225 +0,0 @@ -commit 7546434030d456b13b2eda6138f183ac3bf29751 -Author: Feras Daoud -Date: Wed Aug 9 18:27:32 2017 +0300 - - ptp4l: Add IPoIB interface support for ptp4l - - The current implementation of ptp4l always assumes 6 octets MAC - address, which is correct for Ethernet interfaces but not for IPoIB - interfaces (that have 20 octets MAC), therefore running ptp4l over - IPoIB interface does not function correctly. - - In Infiniband, every interface has three identifiers: - GUID, GID, and LID. - The GUID is similar in concept to a MAC address. From RFC4392: - The EUI-64 portion of a GID is referred to as the Global Unique - Identifier (GUID) and is the only persistent identifier of a port. - - Therefore, to support IPoIB interfaces, the GUID of the port should - be used instead of the MAC. - This patch checks the interface type before creating the clock identity, - for Infiniband ports, it retrieves the GUID of the port using sysfs - and use it to create the clock identity. - - sysfs method was chosen since the GUID is the 6 lsb bytes of - the 20 byte device address, and SIOCGIFHWADDR ioctl call returns - the 14 msb bytes of the device address, so it is not possible to - get the GUID using SIOCGIFHWADDR ioctl call. - - [ RC: fixed trivial coding style error, space after switch keyword. ] - - Signed-off-by: Feras Daoud - Reviewed-by: Alex Vesker - -diff --git a/address.h b/address.h -index 7578f91..35ef05f 100644 ---- a/address.h -+++ b/address.h -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - - struct address { - socklen_t len; -diff --git a/ether.h b/ether.h -index ce3d663..8ec9669 100644 ---- a/ether.h -+++ b/ether.h -@@ -22,7 +22,13 @@ - - #include - --#define MAC_LEN 6 -+#define EUI48 6 -+#define EUI64 8 -+ -+#define MAC_LEN EUI48 -+#define GUID_LEN EUI64 -+ -+#define GUID_OFFSET 36 - - typedef uint8_t eth_addr[MAC_LEN]; - -diff --git a/sk.c b/sk.c -index 63ec206..0cf55c5 100644 ---- a/sk.c -+++ b/sk.c -@@ -159,10 +159,55 @@ failed: - return -1; - } - -+static int sk_interface_guidaddr(const char *name, unsigned char *guid) -+{ -+ char file_name[64], buf[64], addr[8]; -+ FILE *f; -+ char *err; -+ int res; -+ -+ snprintf(file_name, sizeof buf, "/sys/class/net/%s/address", name); -+ f = fopen(file_name, "r"); -+ if (!f) { -+ pr_err("failed to open %s: %m", buf); -+ return -1; -+ } -+ -+ /* Set the file position to the beginning of the GUID */ -+ res = fseek(f, GUID_OFFSET, SEEK_SET); -+ if (res) { -+ pr_err("fseek failed: %m"); -+ goto error; -+ } -+ -+ err = fgets(buf, sizeof buf, f); -+ if (err == NULL) { -+ pr_err("fseek failed: %m"); -+ goto error; -+ } -+ -+ res = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", -+ &addr[0], &addr[1], &addr[2], &addr[3], -+ &addr[4], &addr[5], &addr[6], &addr[7]); -+ if (res != GUID_LEN) { -+ pr_err("sscanf failed: %m"); -+ goto error; -+ } -+ -+ memcpy(guid, addr, GUID_LEN); -+ fclose(f); -+ -+ return 0; -+ -+error: -+ fclose(f); -+ return -1; -+} -+ - int sk_interface_macaddr(const char *name, struct address *mac) - { - struct ifreq ifreq; -- int err, fd; -+ int err, fd, type; - - memset(&ifreq, 0, sizeof(ifreq)); - strncpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name) - 1); -@@ -180,9 +225,23 @@ int sk_interface_macaddr(const char *name, struct address *mac) - return -1; - } - -+ /* Get interface type */ -+ type = ifreq.ifr_hwaddr.sa_family; -+ switch (type) { -+ case ARPHRD_INFINIBAND: -+ err = sk_interface_guidaddr(name, mac->sll.sll_addr); -+ if (err) { -+ pr_err("fail to get address using sysfs: %m"); -+ return -1; -+ } -+ mac->sll.sll_halen = EUI64; -+ break; -+ default: -+ memcpy(mac->sll.sll_addr, &ifreq.ifr_hwaddr.sa_data, MAC_LEN); -+ mac->sll.sll_halen = EUI48; -+ } -+ - mac->sll.sll_family = AF_PACKET; -- mac->sll.sll_halen = MAC_LEN; -- memcpy(mac->sll.sll_addr, &ifreq.ifr_hwaddr.sa_data, MAC_LEN); - mac->len = sizeof(mac->sll); - close(fd); - return 0; -diff --git a/util.c b/util.c -index 2b880ff..62f2638 100644 ---- a/util.c -+++ b/util.c -@@ -135,14 +135,32 @@ int generate_clock_identity(struct ClockIdentity *ci, const char *name) - - if (sk_interface_macaddr(name, &addr)) - return -1; -- ci->id[0] = addr.sll.sll_addr[0]; -- ci->id[1] = addr.sll.sll_addr[1]; -- ci->id[2] = addr.sll.sll_addr[2]; -- ci->id[3] = 0xFF; -- ci->id[4] = 0xFE; -- ci->id[5] = addr.sll.sll_addr[3]; -- ci->id[6] = addr.sll.sll_addr[4]; -- ci->id[7] = addr.sll.sll_addr[5]; -+ -+ switch (addr.sll.sll_halen) { -+ case EUI48: -+ ci->id[0] = addr.sll.sll_addr[0]; -+ ci->id[1] = addr.sll.sll_addr[1]; -+ ci->id[2] = addr.sll.sll_addr[2]; -+ ci->id[3] = 0xFF; -+ ci->id[4] = 0xFE; -+ ci->id[5] = addr.sll.sll_addr[3]; -+ ci->id[6] = addr.sll.sll_addr[4]; -+ ci->id[7] = addr.sll.sll_addr[5]; -+ break; -+ case EUI64: -+ ci->id[0] = addr.sll.sll_addr[0]; -+ ci->id[1] = addr.sll.sll_addr[1]; -+ ci->id[2] = addr.sll.sll_addr[2]; -+ ci->id[3] = addr.sll.sll_addr[3]; -+ ci->id[4] = addr.sll.sll_addr[4]; -+ ci->id[5] = addr.sll.sll_addr[5]; -+ ci->id[6] = addr.sll.sll_addr[6]; -+ ci->id[7] = addr.sll.sll_addr[7]; -+ break; -+ default: -+ return -1; -+ } -+ - return 0; - } - -commit fd2646263f0fb1a31dde53e67ac24971ab1f90f4 -Author: Miroslav Lichvar -Date: Mon Oct 16 11:29:48 2017 +0200 - - sk: don't leak socket when reading of IB GUID fails. - - Signed-off-by: Miroslav Lichvar - -diff --git a/sk.c b/sk.c -index 0cf55c5..2c7593b 100644 ---- a/sk.c -+++ b/sk.c -@@ -225,6 +225,8 @@ int sk_interface_macaddr(const char *name, struct address *mac) - return -1; - } - -+ close(fd); -+ - /* Get interface type */ - type = ifreq.ifr_hwaddr.sa_family; - switch (type) { -@@ -243,7 +245,6 @@ int sk_interface_macaddr(const char *name, struct address *mac) - - mac->sll.sll_family = AF_PACKET; - mac->len = sizeof(mac->sll); -- close(fd); - return 0; - } - diff --git a/SOURCES/linuxptp-linkdown.patch b/SOURCES/linuxptp-linkdown.patch deleted file mode 100644 index 41c3918..0000000 --- a/SOURCES/linuxptp-linkdown.patch +++ /dev/null @@ -1,76 +0,0 @@ -commit 73318c5b99571c8da01474ad665e2e2e06ab12bb -Author: Richard Cochran -Date: Sun Feb 5 18:31:27 2017 +0100 - - clock: Force a BMC election when a port link goes down. - - Having one fewer port may affect the result of the BMCA. This patch - changes the main loop so that a link down event also causes a state - decision event. - - Signed-off-by: Richard Cochran - Reported-by: Henry Jesuiter - -diff --git a/clock.c b/clock.c -index f027305..6ec3e72 100644 ---- a/clock.c -+++ b/clock.c -@@ -96,6 +96,7 @@ struct clock { - int pollfd_valid; - int nports; /* does not include the UDS port */ - int last_port_number; -+ int sde; - struct hash *index2port; - int free_running; - int freq_est_interval; -@@ -341,6 +342,11 @@ static void clock_link_status(void *ctx, int index, int linkup) - port_dispatch(p, EV_FAULT_CLEARED, 0); - } else { - port_dispatch(p, EV_FAULT_DETECTED, 0); -+ /* -+ * A port going down can affect the BMCA result. -+ * Force a state decision event. -+ */ -+ c->sde = 1; - } - } - -@@ -1463,7 +1469,7 @@ struct PortIdentity clock_parent_identity(struct clock *c) - - int clock_poll(struct clock *c) - { -- int cnt, i, sde = 0; -+ int cnt, i; - enum fsm_event event; - struct pollfd *cur; - struct port *p; -@@ -1494,9 +1500,9 @@ int clock_poll(struct clock *c) - if (cur[i].revents & (POLLIN|POLLPRI)) { - event = port_event(p, i); - if (EV_STATE_DECISION_EVENT == event) -- sde = 1; -+ c->sde = 1; - if (EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES == event) -- sde = 1; -+ c->sde = 1; - port_dispatch(p, event, 0); - /* Clear any fault after a little while. */ - if (PS_FAULTY == port_state(p)) { -@@ -1525,13 +1531,14 @@ int clock_poll(struct clock *c) - if (cur[i].revents & (POLLIN|POLLPRI)) { - event = port_event(c->uds_port, i); - if (EV_STATE_DECISION_EVENT == event) -- sde = 1; -+ c->sde = 1; - } - } - -- if (sde) -+ if (c->sde) { - handle_state_decision_event(c); -- -+ c->sde = 0; -+ } - clock_prune_subscriptions(c); - return 0; - } diff --git a/SOURCES/linuxptp-messagetag.patch b/SOURCES/linuxptp-messagetag.patch deleted file mode 100644 index dc9caa8..0000000 --- a/SOURCES/linuxptp-messagetag.patch +++ /dev/null @@ -1,553 +0,0 @@ -commit 4e8dbd84925d36f1193a7339a542677d884d3ba1 -Author: Richard Cochran -Date: Tue Dec 6 19:40:36 2016 +0100 - - ptp4l: Accept any configuration option as a command line argument. - - This patch provides a way to use the entire table of configuration options - as "long" command line switches. - - Signed-off-by: Richard Cochran - -diff --git a/config.c b/config.c -index 5da5ecc..384b437 100644 ---- a/config.c -+++ b/config.c -@@ -329,6 +329,7 @@ static enum parser_result parse_section_line(char *s, enum config_section *secti - } - - static enum parser_result parse_item(struct config *cfg, -+ int commandline, - const char *section, - const char *option, - const char *value) -@@ -387,7 +388,7 @@ static enum parser_result parse_item(struct config *cfg, - return NOT_PARSED; - } - } -- } else if (cgi->flags & CFG_ITEM_LOCKED) { -+ } else if (!commandline && cgi->flags & CFG_ITEM_LOCKED) { - /* This global option was set on the command line. */ - return PARSED_OK; - } else { -@@ -415,6 +416,10 @@ static enum parser_result parse_item(struct config *cfg, - dst->flags |= CFG_ITEM_DYNSTR; - break; - } -+ -+ if (commandline) { -+ dst->flags &= CFG_ITEM_LOCKED; -+ } - return PARSED_OK; - } - -@@ -490,6 +495,25 @@ static void check_deprecated_options(const char **option) - } - } - -+static struct option *config_alloc_longopts(struct config *cfg) -+{ -+ struct config_item *ci; -+ struct option *opts; -+ int i; -+ -+ opts = calloc(1, (1 + N_CONFIG_ITEMS) * sizeof(*opts)); -+ if (!opts) { -+ return NULL; -+ } -+ for (i = 0; i < N_CONFIG_ITEMS; i++) { -+ ci = &config_tab[i]; -+ opts[i].name = ci->label; -+ opts[i].has_arg = required_argument; -+ } -+ -+ return opts; -+} -+ - int config_read(char *name, struct config *cfg) - { - enum config_section current_section = UNKNOWN_SECTION; -@@ -554,7 +578,7 @@ int config_read(char *name, struct config *cfg) - - check_deprecated_options(&option); - -- parser_res = parse_item(cfg, current_section == GLOBAL_SECTION ? -+ parser_res = parse_item(cfg, 0, current_section == GLOBAL_SECTION ? - NULL : current_port->name, option, value); - - switch (parser_res) { -@@ -627,8 +651,15 @@ struct config *config_create(void) - } - STAILQ_INIT(&cfg->interfaces); - -+ cfg->opts = config_alloc_longopts(cfg); -+ if (!cfg->opts) { -+ free(cfg); -+ return NULL; -+ } -+ - cfg->htab = hash_create(); - if (!cfg->htab) { -+ free(cfg->opts); - free(cfg); - return NULL; - } -@@ -657,6 +688,7 @@ struct config *config_create(void) - return cfg; - fail: - hash_destroy(cfg->htab, NULL); -+ free(cfg->opts); - free(cfg); - return NULL; - } -@@ -670,6 +702,7 @@ void config_destroy(struct config *cfg) - free(iface); - } - hash_destroy(cfg->htab, config_item_free); -+ free(cfg->opts); - free(cfg); - } - -@@ -720,6 +753,33 @@ char *config_get_string(struct config *cfg, const char *section, - return ci->val.s; - } - -+int config_parse_option(struct config *cfg, const char *opt, const char *val) -+{ -+ enum parser_result result; -+ -+ result = parse_item(cfg, 1, NULL, opt, val); -+ -+ switch (result) { -+ case PARSED_OK: -+ return 0; -+ case NOT_PARSED: -+ fprintf(stderr, "unknown option %s\n", opt); -+ break; -+ case BAD_VALUE: -+ fprintf(stderr, "%s is a bad value for option %s\n", val, opt); -+ break; -+ case MALFORMED: -+ fprintf(stderr, "%s is a malformed value for option %s\n", -+ val, opt); -+ break; -+ case OUT_OF_RANGE: -+ fprintf(stderr, "%s is an out of range value for option %s\n", -+ val, opt); -+ break; -+ } -+ return -1; -+} -+ - int config_set_double(struct config *cfg, const char *option, double val) - { - struct config_item *ci = config_find_item(cfg, NULL, option); -diff --git a/config.h b/config.h -index b02bde6..1cc7051 100644 ---- a/config.h -+++ b/config.h -@@ -20,6 +20,7 @@ - #ifndef HAVE_CONFIG_H - #define HAVE_CONFIG_H - -+#include - #include - - #include "ds.h" -@@ -43,6 +44,9 @@ struct config { - STAILQ_HEAD(interfaces_head, interface) interfaces; - int n_interfaces; - -+ /* for parsing command line options */ -+ struct option *opts; -+ - /* hash of all non-legacy items */ - struct hash *htab; - }; -@@ -64,6 +68,13 @@ int config_get_int(struct config *cfg, const char *section, - char *config_get_string(struct config *cfg, const char *section, - const char *option); - -+static inline struct option *config_long_options(struct config *cfg) -+{ -+ return cfg->opts; -+} -+ -+int config_parse_option(struct config *cfg, const char *opt, const char *val); -+ - int config_set_double(struct config *cfg, const char *option, double val); - - int config_set_section_int(struct config *cfg, const char *section, -diff --git a/ptp4l.c b/ptp4l.c -index a87e7e6..e90fcb2 100644 ---- a/ptp4l.c -+++ b/ptp4l.c -@@ -73,8 +73,9 @@ static void usage(char *progname) - int main(int argc, char *argv[]) - { - char *config = NULL, *req_phc = NULL, *progname; -- int c, err = -1, print_level; -+ int c, err = -1, index, print_level; - struct clock *clock = NULL; -+ struct option *opts; - struct config *cfg; - - if (handle_term_signals()) -@@ -84,12 +85,18 @@ int main(int argc, char *argv[]) - if (!cfg) { - return -1; - } -+ opts = config_long_options(cfg); - - /* Process the command line arguments. */ - progname = strrchr(argv[0], '/'); - progname = progname ? 1+progname : argv[0]; -- while (EOF != (c = getopt(argc, argv, "AEP246HSLf:i:p:sl:mqvh"))) { -+ while (EOF != (c = getopt_long(argc, argv, "AEP246HSLf:i:p:sl:mqvh", -+ opts, &index))) { - switch (c) { -+ case 0: -+ if (config_parse_option(cfg, opts[index].name, optarg)) -+ goto out; -+ break; - case 'A': - if (config_set_int(cfg, "delay_mechanism", DM_AUTO)) - goto out; - -commit e658982624bfd5cd998066fdf35b93cdcf8797ca -Author: Richard Cochran -Date: Tue Dec 13 19:55:39 2016 +0100 - - config: Fix bitwise copy-and-pasto for command line items. - - The recent change allowing every configuration option to appear on the - command line wrongly used bitwise AND to set a flag. This patch fixes - the bug by using the proper bitwise OR idiom. - - Signed-off-by: Richard Cochran - Reported-by: Miroslav Lichvar - Fixes: 4e8dbd8 ("ptp4l: Accept any configuration option as a command line argument.") - -diff --git a/config.c b/config.c -index 384b437..b19f3ad 100644 ---- a/config.c -+++ b/config.c -@@ -418,7 +418,7 @@ static enum parser_result parse_item(struct config *cfg, - } - - if (commandline) { -- dst->flags &= CFG_ITEM_LOCKED; -+ dst->flags |= CFG_ITEM_LOCKED; - } - return PARSED_OK; - } - -commit 4e966536c6253d73e1a3202e8b562ab0f518e33b -Author: Richard Cochran -Date: Tue Dec 13 20:49:22 2016 +0100 - - ptp4l: Document the "long" command line options in the man page. - - Signed-off-by: Richard Cochran - -diff --git a/ptp4l.8 b/ptp4l.8 -index 63e9abd..f53fc6e 100644 ---- a/ptp4l.8 -+++ b/ptp4l.8 -@@ -1,4 +1,4 @@ --.TH PTP4l 8 "July 2016" "linuxptp" -+.TH PTP4l 8 "December 2016" "linuxptp" - .SH NAME - ptp4l - PTP Boundary/Ordinary Clock - -@@ -15,6 +15,8 @@ ptp4l - PTP Boundary/Ordinary Clock - ] - [ - .BI \-i " interface" -+] [ -+.I long-options - ] - .I .\|.\|. - -@@ -94,6 +96,19 @@ Prints the software version and exits. - .BI \-h - Display a help message. - -+.SH LONG OPTIONS -+ -+Each and every configuration file option (see below) may also appear -+as a "long" style command line argument. For example, the slaveOnly -+option may be set using either of these two forms. -+ -+.RS -+\f(CW\-\-slaveOnly 1 \-\-slaveOnly=1\fP -+.RE -+ -+Option values given on the command line override values in the global -+section of the configuration file. -+ - .SH CONFIGURATION FILE - - The configuration file is divided into sections. Each section starts with a - -commit 0f6c6972c791813e0b9618e9158da3951a099737 -Author: Miroslav Lichvar -Date: Tue Jan 17 14:17:39 2017 +0100 - - Add options to tag ptp4l and phc2sys log messages. - - When running multiple instances of ptp4l or phc2sys, it's difficult to - tell which log message belongs to which instance. Add new options to - ptp4l and phc2sys which can specify a tag for all messages printed to - the standard output or system log, so messages from different instances - can have different tags. - - Signed-off-by: Miroslav Lichvar - -diff --git a/config.c b/config.c -index 7bb949d..e6fe676 100644 ---- a/config.c -+++ b/config.c -@@ -199,6 +199,7 @@ struct config_item config_tab[] = { - PORT_ITEM_INT("logMinPdelayReqInterval", 0, INT8_MIN, INT8_MAX), - PORT_ITEM_INT("logSyncInterval", 0, INT8_MIN, INT8_MAX), - GLOB_ITEM_INT("logging_level", LOG_INFO, PRINT_LEVEL_MIN, PRINT_LEVEL_MAX), -+ GLOB_ITEM_STR("message_tag", NULL), - GLOB_ITEM_STR("manufacturerIdentity", "00:00:00"), - GLOB_ITEM_INT("max_frequency", 900000000, 0, INT_MAX), - PORT_ITEM_INT("min_neighbor_prop_delay", -20000000, INT_MIN, -1), -diff --git a/phc2sys.8 b/phc2sys.8 -index 22d02c2..2559c74 100644 ---- a/phc2sys.8 -+++ b/phc2sys.8 -@@ -206,6 +206,10 @@ The default is /var/run/ptp4l. - Set the maximum syslog level of messages which should be printed or sent to - the system logger. The default is 6 (LOG_INFO). - .TP -+.BI \-t " message-tag" -+Specify the tag which is added to all messages printed to the standard output -+or system log. The default is an empty string. -+.TP - .B \-m - Print messages to the standard output. - .TP -diff --git a/phc2sys.c b/phc2sys.c -index 35cf6fa..aa4186b 100644 ---- a/phc2sys.c -+++ b/phc2sys.c -@@ -1209,6 +1209,7 @@ static void usage(char *progname) - " -x apply leap seconds by servo instead of kernel\n" - " -z [path] server address for UDS (/var/run/ptp4l)\n" - " -l [num] set the logging level to 'num' (6)\n" -+ " -t [tag] add tag to log messages\n" - " -m print messages to stdout\n" - " -q do not print messages to the syslog\n" - " -v prints the software version and exits\n" -@@ -1219,7 +1220,7 @@ static void usage(char *progname) - - int main(int argc, char *argv[]) - { -- char *progname; -+ char *progname, *message_tag = NULL; - char *src_name = NULL, *dst_name = NULL; - struct clock *src, *dst; - struct config *cfg; -@@ -1251,7 +1252,7 @@ int main(int argc, char *argv[]) - progname = strrchr(argv[0], '/'); - progname = progname ? 1+progname : argv[0]; - while (EOF != (c = getopt(argc, argv, -- "arc:d:s:E:P:I:S:F:R:N:O:L:M:i:u:wn:xz:l:mqvh"))) { -+ "arc:d:s:E:P:I:S:F:R:N:O:L:M:i:u:wn:xz:l:t:mqvh"))) { - switch (c) { - case 'a': - autocfg = 1; -@@ -1363,6 +1364,9 @@ int main(int argc, char *argv[]) - PRINT_LEVEL_MIN, PRINT_LEVEL_MAX)) - goto end; - break; -+ case 't': -+ message_tag = optarg; -+ break; - case 'm': - verbose = 1; - break; -@@ -1405,6 +1409,7 @@ int main(int argc, char *argv[]) - } - - print_set_progname(progname); -+ print_set_tag(message_tag); - print_set_verbose(verbose); - print_set_syslog(use_syslog); - print_set_level(print_level); -diff --git a/print.c b/print.c -index a82d0e7..6c48e1e 100644 ---- a/print.c -+++ b/print.c -@@ -28,12 +28,18 @@ static int verbose = 0; - static int print_level = LOG_INFO; - static int use_syslog = 1; - static const char *progname; -+static const char *message_tag; - - void print_set_progname(const char *name) - { - progname = name; - } - -+void print_set_tag(const char *tag) -+{ -+ message_tag = tag; -+} -+ - void print_set_syslog(int value) - { - use_syslog = value ? 1 : 0; -@@ -67,13 +73,17 @@ void print(int level, char const *format, ...) - - if (verbose) { - f = level >= LOG_NOTICE ? stdout : stderr; -- fprintf(f, "%s[%ld.%03ld]: %s\n", -+ fprintf(f, "%s[%ld.%03ld]: %s%s%s\n", - progname ? progname : "", -- ts.tv_sec, ts.tv_nsec / 1000000, buf); -+ ts.tv_sec, ts.tv_nsec / 1000000, -+ message_tag ? message_tag : "", message_tag ? " " : "", -+ buf); - fflush(f); - } - if (use_syslog) { -- syslog(level, "[%ld.%03ld] %s", -- ts.tv_sec, ts.tv_nsec / 1000000, buf); -+ syslog(level, "[%ld.%03ld] %s%s%s", -+ ts.tv_sec, ts.tv_nsec / 1000000, -+ message_tag ? message_tag : "", message_tag ? " " : "", -+ buf); - } - } -diff --git a/print.h b/print.h -index e8f2c8e..1723d8a 100644 ---- a/print.h -+++ b/print.h -@@ -33,6 +33,7 @@ __attribute__ ((format (printf, 2, 3))) - void print(int level, char const *format, ...); - - void print_set_progname(const char *name); -+void print_set_tag(const char *tag); - void print_set_syslog(int value); - void print_set_level(int level); - void print_set_verbose(int value); -diff --git a/ptp4l.8 b/ptp4l.8 -index 53d5f28..a724151 100644 ---- a/ptp4l.8 -+++ b/ptp4l.8 -@@ -485,6 +485,12 @@ is 0. - The maximum logging level of messages which should be printed. - The default is 6 (LOG_INFO). - .TP -+.B message_tag -+The tag which is added to all messages printed to the standard output or system -+log. -+The default is an empty string (which cannot be set in the configuration file -+as the option requires an argument). -+.TP - .B verbose - Print messages to the standard output if enabled. - The default is 0 (disabled). -diff --git a/ptp4l.c b/ptp4l.c -index e90fcb2..f01ff6f 100644 ---- a/ptp4l.c -+++ b/ptp4l.c -@@ -183,6 +183,7 @@ int main(int argc, char *argv[]) - } - - print_set_progname(progname); -+ print_set_tag(config_get_string(cfg, NULL, "message_tag")); - print_set_verbose(config_get_int(cfg, NULL, "verbose")); - print_set_syslog(config_get_int(cfg, NULL, "use_syslog")); - print_set_level(config_get_int(cfg, NULL, "logging_level")); - -commit e54158195b1eadfdb6275646bc3dfb7611dba5b6 -Author: Miroslav Lichvar -Date: Tue Jan 17 14:17:40 2017 +0100 - - timemaster: tag ptp4l and phc2sys messages. - - Use the new options of ptp4l and phc2sys to tag their log messages with - the PTP domain number and name(s) of interface(s) in the domain. - - Signed-off-by: Miroslav Lichvar - -diff --git a/timemaster.c b/timemaster.c -index 66ac521..880b2ab 100644 ---- a/timemaster.c -+++ b/timemaster.c -@@ -599,7 +599,8 @@ static char **get_ptp4l_command(struct program_config *config, - } - - static char **get_phc2sys_command(struct program_config *config, int domain, -- int poll, int shm_segment, char *uds_path) -+ int poll, int shm_segment, char *uds_path, -+ char *message_tag) - { - char **command = (char **)parray_new(); - -@@ -610,6 +611,7 @@ static char **get_phc2sys_command(struct program_config *config, int domain, - xstrdup("-R"), string_newf("%.2f", poll > 0 ? - 1.0 / (1 << poll) : 1 << -poll), - xstrdup("-z"), xstrdup(uds_path), -+ xstrdup("-t"), xstrdup(message_tag), - xstrdup("-n"), string_newf("%d", domain), - xstrdup("-E"), xstrdup("ntpshm"), - xstrdup("-M"), string_newf("%d", shm_segment), NULL); -@@ -671,7 +673,7 @@ static int add_ptp_source(struct ptp_domain *source, - struct script *script) - { - struct config_file *config_file; -- char **command, *uds_path, **interfaces; -+ char **command, *uds_path, **interfaces, *message_tag; - int i, j, num_interfaces, *phc, *phcs, hw_ts; - struct sk_ts_info ts_info; - -@@ -749,6 +751,12 @@ static int add_ptp_source(struct ptp_domain *source, - uds_path = string_newf("%s/ptp4l.%d.socket", - config->rundir, *shm_segment); - -+ message_tag = string_newf("[%d", source->domain); -+ for (j = 0; interfaces[j]; j++) -+ string_appendf(&message_tag, "%s%s", j ? "+" : ":", -+ interfaces[j]); -+ string_appendf(&message_tag, "]"); -+ - config_file = xmalloc(sizeof(*config_file)); - config_file->path = string_newf("%s/ptp4l.%d.conf", - config->rundir, *shm_segment); -@@ -760,8 +768,9 @@ static int add_ptp_source(struct ptp_domain *source, - string_appendf(&config_file->content, - "slaveOnly 1\n" - "domainNumber %d\n" -- "uds_address %s\n", -- source->domain, uds_path); -+ "uds_address %s\n" -+ "message_tag %s\n", -+ source->domain, uds_path, message_tag); - - if (phcs[i] >= 0) { - /* HW time stamping */ -@@ -772,7 +781,8 @@ static int add_ptp_source(struct ptp_domain *source, - command = get_phc2sys_command(&config->phc2sys, - source->domain, - source->phc2sys_poll, -- *shm_segment, uds_path); -+ *shm_segment, uds_path, -+ message_tag); - parray_append((void ***)&script->commands, command); - } else { - /* SW time stamping */ -@@ -793,6 +803,7 @@ static int add_ptp_source(struct ptp_domain *source, - - (*shm_segment)++; - -+ free(message_tag); - free(uds_path); - free(interfaces); - } diff --git a/SOURCES/linuxptp-mgttlv.patch b/SOURCES/linuxptp-mgttlv.patch deleted file mode 100644 index 646bf43..0000000 --- a/SOURCES/linuxptp-mgttlv.patch +++ /dev/null @@ -1,50 +0,0 @@ -commit 43b2f5d1207a010f1df67e101b129b09502371e2 -Author: Hangbin Liu -Date: Fri May 12 15:36:45 2017 +0800 - - msg: use last_tlv if there is not enough room for another tlv - - If the len is not enought for another tlv process. e.g. one more bytes - padding at the end of message. And we set extra to NULL instead of - msg->last_tlv in tlv_post_recv(). Then the msg->last_tlv will not be - initialised. And program will crash if we read msg->last_tlv. e.g. in - function pmc_show(). - - Signed-off-by: Hangbin Liu - -diff --git a/msg.c b/msg.c -index a38b815..4b3d926 100644 ---- a/msg.c -+++ b/msg.c -@@ -140,7 +140,7 @@ static int suffix_post_recv(uint8_t *ptr, int len, struct tlv_extra *last) - } - len -= tlv->length; - ptr += tlv->length; -- err = tlv_post_recv(tlv, len ? NULL : last); -+ err = tlv_post_recv(tlv, len > sizeof(struct TLV) ? NULL : last); - if (err) - return err; - } -commit 95b5a13cb2787b6a436ad395bb4931d1661e59a7 -Author: Hangbin Liu -Date: Tue May 23 14:49:55 2017 +0800 - - pmc: goto out when get unknown management tlv - - If handle unknown management tlv. The management message id and format are - also unknown, thus we may crash due to access unknown area. - - Signed-off-by: Hangbin Liu - -diff --git a/pmc.c b/pmc.c -index cefa771..af9cc63 100644 ---- a/pmc.c -+++ b/pmc.c -@@ -217,6 +217,7 @@ static void pmc_show(struct ptp_message *msg, FILE *fp) - goto out; - } else { - fprintf(fp, "unknown-tlv "); -+ goto out; - } - mgt = (struct management_tlv *) msg->management.suffix; - if (mgt->length == 2 && mgt->id != TLV_NULL_MANAGEMENT) { diff --git a/SOURCES/linuxptp-msgput.patch b/SOURCES/linuxptp-msgput.patch new file mode 100644 index 0000000..0fab821 --- /dev/null +++ b/SOURCES/linuxptp-msgput.patch @@ -0,0 +1,20 @@ +commit 86723cfc6a7ac1d9b1bff5e90b7f4696d6460a0e +Author: Miroslav Lichvar +Date: Thu Mar 21 17:12:03 2019 +0100 + + pmc: Don't leak memory when msg_tlv_append() fails. + + Signed-off-by: Miroslav Lichvar + +diff --git a/pmc_common.c b/pmc_common.c +index 4a160f6..4d48e3a 100644 +--- a/pmc_common.c ++++ b/pmc_common.c +@@ -546,6 +546,7 @@ int pmc_send_set_action(struct pmc *pmc, int id, void *data, int datasize) + } + extra = msg_tlv_append(msg, sizeof(*mgt) + datasize); + if (!extra) { ++ msg_put(msg); + return -ENOMEM; + } + mgt = (struct management_tlv *) extra->tlv; diff --git a/SOURCES/linuxptp-multiport.patch b/SOURCES/linuxptp-multiport.patch deleted file mode 100644 index 8f9568c..0000000 --- a/SOURCES/linuxptp-multiport.patch +++ /dev/null @@ -1,77 +0,0 @@ -commit ac92a711614c413b75a4963eab95cd1aa2de8293 -Author: Miroslav Lichvar -Date: Mon Mar 27 17:43:06 2017 +0200 - - phc2sys: don't synchronize clock to itself. - - When ptp4l is using multiple interfaces sharing the same clock, phc2sys - in the automatic mode should not try to synchronize them to each other. - - Signed-off-by: Miroslav Lichvar - Reported-by: Stefan Lange - -diff --git a/phc2sys.c b/phc2sys.c -index aa4186b..4c8b552 100644 ---- a/phc2sys.c -+++ b/phc2sys.c -@@ -72,6 +72,7 @@ - struct clock { - LIST_ENTRY(clock) list; - clockid_t clkid; -+ int phc_index; - int sysoff_supported; - int is_utc; - int dest_only; -@@ -127,7 +128,7 @@ static int clock_handle_leap(struct node *node, struct clock *clock, - static int run_pmc_get_utc_offset(struct node *node, int timeout); - static void run_pmc_events(struct node *node); - --static clockid_t clock_open(char *device) -+static clockid_t clock_open(char *device, int *phc_index) - { - struct sk_ts_info ts_info; - char phc_device[16]; -@@ -157,6 +158,7 @@ static clockid_t clock_open(char *device) - clkid = phc_open(phc_device); - if (clkid == CLOCK_INVALID) - fprintf(stderr, "cannot open %s: %m\n", device); -+ *phc_index = ts_info.phc_index; - return clkid; - } - -@@ -164,11 +166,11 @@ static struct clock *clock_add(struct node *node, char *device) - { - struct clock *c; - clockid_t clkid = CLOCK_INVALID; -- int max_ppb; -+ int max_ppb, phc_index = -1; - double ppb; - - if (device) { -- clkid = clock_open(device); -+ clkid = clock_open(device, &phc_index); - if (clkid == CLOCK_INVALID) - return NULL; - } -@@ -179,6 +181,7 @@ static struct clock *clock_add(struct node *node, char *device) - return NULL; - } - c->clkid = clkid; -+ c->phc_index = phc_index; - c->servo_state = SERVO_UNLOCKED; - c->device = strdup(device); - -@@ -638,6 +641,13 @@ static int do_loop(struct node *node, int subscriptions) - if (!update_needed(clock)) - continue; - -+ /* don't try to synchronize the clock to itself */ -+ if (clock->clkid == node->master->clkid || -+ (clock->phc_index >= 0 && -+ clock->phc_index == node->master->phc_index) || -+ !strcmp(clock->device, node->master->device)) -+ continue; -+ - if (clock->clkid == CLOCK_REALTIME && - node->master->sysoff_supported) { - /* use sysoff */ diff --git a/SOURCES/linuxptp-portdispatch.patch b/SOURCES/linuxptp-portdispatch.patch deleted file mode 100644 index 2bb09c1..0000000 --- a/SOURCES/linuxptp-portdispatch.patch +++ /dev/null @@ -1,434 +0,0 @@ -commit 10d4e7f8b0525bbf72981e3e5fcf0c10833a7631 -Author: Richard Cochran -Date: Tue Jan 3 20:55:18 2017 +0100 - - port: Make the finite state machine into a function variable. - - This allows adding new FSM flavors in the future. - - Signed-off-by: Richard Cochran - -diff --git a/port.c b/port.c -index a1ad6f6..afe0057 100644 ---- a/port.c -+++ b/port.c -@@ -94,6 +94,8 @@ struct port { - unsigned int pdr_missing; - unsigned int multiple_seq_pdr_count; - unsigned int multiple_pdr_detected; -+ enum port_state (*state_machine)(enum port_state state, -+ enum fsm_event event, int mdiff); - /* portDS */ - struct PortIdentity portIdentity; - enum port_state state; /*portState*/ -@@ -2142,10 +2144,8 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff) - if (event == EV_RS_MASTER || event == EV_RS_GRAND_MASTER) { - port_slave_priority_warning(p); - } -- next = ptp_slave_fsm(p->state, event, mdiff); -- } else { -- next = ptp_fsm(p->state, event, mdiff); - } -+ next = p->state_machine(p->state, event, mdiff); - - if (!fault_interval(p, last_fault_type(p), &i) && - ((i.val == FRI_ASAP && i.type == FTMO_LOG2_SECONDS) || -@@ -2555,6 +2555,7 @@ struct port *port_open(int phc_index, - - memset(p, 0, sizeof(*p)); - -+ p->state_machine = clock_slave_only(clock) ? ptp_slave_fsm : ptp_fsm; - p->phc_index = phc_index; - p->jbod = config_get_int(cfg, interface->name, "boundary_clock_jbod"); - transport = config_get_int(cfg, interface->name, "network_transport"); - -commit 80a28a9dc322f28b991effc44ec1c5362a598281 -Author: Richard Cochran -Date: Tue Jan 3 20:55:33 2017 +0100 - - Change a misleading fault handling function signature. - - Looking at the fault logic in port_dispatch(), you might think that - the function, fault_interval(), checks whether a fault is active, but - you would be wrong, since that function always returns zero. - - This patch removes the superfluous input error checking inside of - fault_interval() and changes the return type to void, making the - actual behavior explicit. Dropping the input check is safe because - that function has exactly two callers, both of whom always provide - valid inputs. - - Signed-off-by: Richard Cochran - -diff --git a/port.c b/port.c -index afe0057..6c9aa72 100644 ---- a/port.c -+++ b/port.c -@@ -205,16 +205,11 @@ enum fault_type last_fault_type(struct port *port) - return port->last_fault_type; - } - --int fault_interval(struct port *port, enum fault_type ft, -- struct fault_interval *i) -+void fault_interval(struct port *port, enum fault_type ft, -+ struct fault_interval *i) - { -- if (!port || !i) -- return -EINVAL; -- if (ft < 0 || ft >= FT_CNT) -- return -EINVAL; - i->type = port->flt_interval_pertype[ft].type; - i->val = port->flt_interval_pertype[ft].val; -- return 0; - } - - int port_fault_fd(struct port *port) -@@ -2147,9 +2142,9 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff) - } - next = p->state_machine(p->state, event, mdiff); - -- if (!fault_interval(p, last_fault_type(p), &i) && -- ((i.val == FRI_ASAP && i.type == FTMO_LOG2_SECONDS) || -- (i.val == 0 && i.type == FTMO_LINEAR_SECONDS))) -+ fault_interval(p, last_fault_type(p), &i); -+ if ((i.val == FRI_ASAP && i.type == FTMO_LOG2_SECONDS) || -+ (i.val == 0 && i.type == FTMO_LINEAR_SECONDS)) - fri_asap = 1; - if (PS_INITIALIZING == next || (PS_FAULTY == next && fri_asap)) { - /* -diff --git a/port.h b/port.h -index 19dec4a..d2e0865 100644 ---- a/port.h -+++ b/port.h -@@ -318,9 +318,8 @@ enum fault_type last_fault_type(struct port *port); - * @param port A port instance. - * @param ft Fault type. - * @param i Pointer to the struct which will be filled in. -- * @return Zero on success, non-zero otherwise. - */ --int fault_interval(struct port *port, enum fault_type ft, -- struct fault_interval *i); -+void fault_interval(struct port *port, enum fault_type ft, -+ struct fault_interval *i); - - #endif - -commit 1f66948d3853c8b08c7f52c9c8daecb361164a43 -Author: Richard Cochran -Date: Tue Jan 3 20:55:42 2017 +0100 - - Make the fault handling code more readable. - - The code that decides whether a fault qualifies for ASAP treatment is - a tangle of logical operators. This patch replaces the open coded - logic with a helper function whose name makes the intent clear. This - is a cosmetic change only. - - Signed-off-by: Richard Cochran - -diff --git a/port.c b/port.c -index 6c9aa72..02dbabb 100644 ---- a/port.c -+++ b/port.c -@@ -161,6 +161,19 @@ static void announce_to_dataset(struct ptp_message *m, struct port *p, - out->receiver = p->portIdentity; - } - -+static int clear_fault_asap(struct fault_interval *faint) -+{ -+ switch (faint->type) { -+ case FTMO_LINEAR_SECONDS: -+ return faint->val == 0 ? 1 : 0; -+ case FTMO_LOG2_SECONDS: -+ return faint->val == FRI_ASAP ? 1 : 0; -+ case FTMO_CNT: -+ return 0; -+ } -+ return 0; -+} -+ - static int msg_current(struct ptp_message *m, struct timespec now) - { - int64_t t1, t2, tmo; -@@ -2143,9 +2156,9 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff) - next = p->state_machine(p->state, event, mdiff); - - fault_interval(p, last_fault_type(p), &i); -- if ((i.val == FRI_ASAP && i.type == FTMO_LOG2_SECONDS) || -- (i.val == 0 && i.type == FTMO_LINEAR_SECONDS)) -+ if (clear_fault_asap(&i)) { - fri_asap = 1; -+ } - if (PS_INITIALIZING == next || (PS_FAULTY == next && fri_asap)) { - /* - * This is a special case. Since we initialize the - -commit 01ee947457813078f63d606c310818d6dedb4ca3 -Author: Richard Cochran -Date: Tue Jan 3 20:55:50 2017 +0100 - - Disentangle initialization from fault clearing. - - Although leaving the INITIALIZING state and clearing the FAULTY state - ASAP both result in a port entering the LISTENING state, still there - is no benefit from conflating the two. In the FAULTY case, the - current code actually skips the INITIALIZING state altogether. - - This patch separates the two cases resulting in two benefits. First, - the check for ASAP fault status is only made when a fault is actually - present, unlike the present unconditional check. Second, this change - will allow us to cleanly support alternative state machines later on. - - Signed-off-by: Richard Cochran - -diff --git a/port.c b/port.c -index 02dbabb..ebe7342 100644 ---- a/port.c -+++ b/port.c -@@ -2145,8 +2145,6 @@ static void port_p2p_transition(struct port *p, enum port_state next) - int port_dispatch(struct port *p, enum fsm_event event, int mdiff) - { - enum port_state next; -- struct fault_interval i; -- int fri_asap = 0; - - if (clock_slave_only(p->clock)) { - if (event == EV_RS_MASTER || event == EV_RS_GRAND_MASTER) { -@@ -2155,11 +2153,15 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff) - } - next = p->state_machine(p->state, event, mdiff); - -- fault_interval(p, last_fault_type(p), &i); -- if (clear_fault_asap(&i)) { -- fri_asap = 1; -+ if (PS_FAULTY == next) { -+ struct fault_interval i; -+ fault_interval(p, last_fault_type(p), &i); -+ if (clear_fault_asap(&i)) { -+ pr_notice("port %hu: clearing fault immediately", portnum(p)); -+ next = PS_INITIALIZING; -+ } - } -- if (PS_INITIALIZING == next || (PS_FAULTY == next && fri_asap)) { -+ if (PS_INITIALIZING == next) { - /* - * This is a special case. Since we initialize the - * port immediately, we can skip right to listening - -commit b738afb6044a8c59310fc13f646c8f5c4dcf2963 -Author: Richard Cochran -Date: Thu Oct 27 15:20:36 2016 +0200 - - fsm: Make the transition out of INITIALIZING part of the FSM code. - - The state machines in 1588 do not specify an event that causes a transition - out of the initializing state. This was left as a local issue. For this - transition, the current code assigns the next state outside of the FSM. But - doing so prevents an alternative FSM to handle this transition differently. - - By introducing a new event, this patch places this transition where it - belongs, namely under the control of the FSM code, - - Signed-off-by: Richard Cochran - -diff --git a/fsm.c b/fsm.c -index d1423e7..ce6efad 100644 ---- a/fsm.c -+++ b/fsm.c -@@ -27,7 +27,16 @@ enum port_state ptp_fsm(enum port_state state, enum fsm_event event, int mdiff) - - switch (state) { - case PS_INITIALIZING: -- next = PS_LISTENING; -+ switch (event) { -+ case EV_FAULT_DETECTED: -+ next = PS_FAULTY; -+ break; -+ case EV_INIT_COMPLETE: -+ next = PS_LISTENING; -+ break; -+ default: -+ break; -+ } - break; - - case PS_FAULTY: -@@ -220,7 +229,16 @@ enum port_state ptp_slave_fsm(enum port_state state, enum fsm_event event, - - switch (state) { - case PS_INITIALIZING: -- next = PS_LISTENING; -+ switch (event) { -+ case EV_FAULT_DETECTED: -+ next = PS_FAULTY; -+ break; -+ case EV_INIT_COMPLETE: -+ next = PS_LISTENING; -+ break; -+ default: -+ break; -+ } - break; - - case PS_FAULTY: -diff --git a/fsm.h b/fsm.h -index 5d4ae91..0616daa 100644 ---- a/fsm.h -+++ b/fsm.h -@@ -48,6 +48,7 @@ enum fsm_event { - EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES, - EV_SYNCHRONIZATION_FAULT, - EV_MASTER_CLOCK_SELECTED, -+ EV_INIT_COMPLETE, - EV_RS_MASTER, - EV_RS_GRAND_MASTER, - EV_RS_SLAVE, -diff --git a/port.c b/port.c -index ebe7342..5f1646b 100644 ---- a/port.c -+++ b/port.c -@@ -2120,6 +2120,7 @@ static void port_p2p_transition(struct port *p, enum port_state next) - break; - case PS_LISTENING: - port_set_announce_tmo(p); -+ port_set_delay_tmo(p); - break; - case PS_PRE_MASTER: - port_set_qualification_tmo(p); -@@ -2158,7 +2159,7 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff) - fault_interval(p, last_fault_type(p), &i); - if (clear_fault_asap(&i)) { - pr_notice("port %hu: clearing fault immediately", portnum(p)); -- next = PS_INITIALIZING; -+ next = p->state_machine(next, EV_FAULT_CLEARED, 0); - } - } - if (PS_INITIALIZING == next) { -@@ -2170,14 +2171,12 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff) - if (port_is_enabled(p)) { - port_disable(p); - } -- next = port_initialize(p) ? PS_FAULTY : PS_LISTENING; -- port_show_transition(p, next, event); -- p->state = next; -- if (next == PS_LISTENING && p->delayMechanism == DM_P2P) { -- port_set_delay_tmo(p); -+ if (port_initialize(p)) { -+ event = EV_FAULT_DETECTED; -+ } else { -+ event = EV_INIT_COMPLETE; - } -- port_notify_event(p, NOTIFY_PORT_STATE); -- return 1; -+ next = p->state_machine(next, event, 0); - } - - if (next == p->state) -diff --git a/util.c b/util.c -index 594b49f..2b880ff 100644 ---- a/util.c -+++ b/util.c -@@ -61,6 +61,7 @@ const char *ev_str[] = { - "ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES", - "SYNCHRONIZATION_FAULT", - "MASTER_CLOCK_SELECTED", -+ "INIT_COMPLETE", - "RS_MASTER", - "RS_GRAND_MASTER", - "RS_SLAVE", - -commit 6b471d45edfdfa835a9115ce4be96d92f100e2ac -Author: Richard Cochran -Date: Sun Feb 5 18:25:18 2017 +0100 - - port: Change port_dispatch() into a void function. - - This global function used to return an error code, but now it always - returns zero. This patch converts the function signature to return void - and simplifies the main clock loop by removing the useless test. - - Signed-off-by: Richard Cochran - -diff --git a/clock.c b/clock.c -index a6a1a1a..f027305 100644 ---- a/clock.c -+++ b/clock.c -@@ -1463,7 +1463,7 @@ struct PortIdentity clock_parent_identity(struct clock *c) - - int clock_poll(struct clock *c) - { -- int cnt, err, i, sde = 0; -+ int cnt, i, sde = 0; - enum fsm_event event; - struct pollfd *cur; - struct port *p; -@@ -1490,14 +1490,14 @@ int clock_poll(struct clock *c) - cur++; - LIST_FOREACH(p, &c->ports, list) { - /* Let the ports handle their events. */ -- for (i = err = 0; i < N_POLLFD && !err; i++) { -+ for (i = 0; i < N_POLLFD; i++) { - if (cur[i].revents & (POLLIN|POLLPRI)) { - event = port_event(p, i); - if (EV_STATE_DECISION_EVENT == event) - sde = 1; - if (EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES == event) - sde = 1; -- err = port_dispatch(p, event, 0); -+ port_dispatch(p, event, 0); - /* Clear any fault after a little while. */ - if (PS_FAULTY == port_state(p)) { - clock_fault_timeout(p, 1); -diff --git a/port.c b/port.c -index 5f1646b..0f99b1b 100644 ---- a/port.c -+++ b/port.c -@@ -2143,7 +2143,7 @@ static void port_p2p_transition(struct port *p, enum port_state next) - }; - } - --int port_dispatch(struct port *p, enum fsm_event event, int mdiff) -+void port_dispatch(struct port *p, enum fsm_event event, int mdiff) - { - enum port_state next; - -@@ -2180,7 +2180,7 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff) - } - - if (next == p->state) -- return 0; -+ return; - - port_show_transition(p, next, event); - -@@ -2196,12 +2196,11 @@ int port_dispatch(struct port *p, enum fsm_event event, int mdiff) - if (p->jbod && next == PS_UNCALIBRATED) { - if (clock_switch_phc(p->clock, p->phc_index)) { - p->last_fault_type = FT_SWITCH_PHC; -- return port_dispatch(p, EV_FAULT_DETECTED, 0); -+ port_dispatch(p, EV_FAULT_DETECTED, 0); -+ return; - } - clock_sync_interval(p->clock, p->log_sync_interval); - } -- -- return 0; - } - - enum fsm_event port_event(struct port *p, int fd_index) -diff --git a/port.h b/port.h -index d2e0865..b00bc64 100644 ---- a/port.h -+++ b/port.h -@@ -69,10 +69,8 @@ struct foreign_clock *port_compute_best(struct port *port); - * @param port A pointer previously obtained via port_open(). - * @param event One of the @a fsm_event codes. - * @param mdiff Whether a new master has been selected. -- * @return Zero if the port's file descriptor array is still valid, -- * and non-zero if it has become invalid. - */ --int port_dispatch(struct port *p, enum fsm_event event, int mdiff); -+void port_dispatch(struct port *p, enum fsm_event event, int mdiff); - - /** - * Generates state machine events based on activity on a port's file diff --git a/SOURCES/linuxptp-statechange.patch b/SOURCES/linuxptp-statechange.patch deleted file mode 100644 index 26c0ad9..0000000 --- a/SOURCES/linuxptp-statechange.patch +++ /dev/null @@ -1,30 +0,0 @@ -commit 17c9787b1d6891636b5be9e4e5a08278b44e9a7a -Author: Miroslav Lichvar -Date: Fri Sep 01 11:42:26 2017 +0100 - - phc2sys: fix handling of multiple state changes. - - When the master clock changed its state and then changed it back to the - original state before phc2sys could process the first change, e.g. SLAVE - -> UNCALIBRATED -> SLAVE after a clockcheck failure, the second change - was ignored because the new value was the same as the original state, - which wasn't updated for the first change yet. This caused phc2sys to be - stuck with a wrong state. - - Fix phc2sys to check both the state and new_state variables of the clock. - - Signed-off-by: Miroslav Lichvar - -diff --git a/phc2sys.c b/phc2sys.c -index b6f6719..e2b5c47 100644 ---- a/phc2sys.c -+++ b/phc2sys.c -@@ -786,7 +786,7 @@ static int recv_subscribed(struct node *node, struct ptp_message *msg, - port->state = state; - clock = port->clock; - state = clock_compute_state(node, clock); -- if (clock->state != state) { -+ if (clock->state != state || clock->new_state) { - clock->new_state = state; - node->state_changed = 1; - } diff --git a/SOURCES/linuxptp-swtscheck.patch b/SOURCES/linuxptp-swtscheck.patch deleted file mode 100644 index e448dbd..0000000 --- a/SOURCES/linuxptp-swtscheck.patch +++ /dev/null @@ -1,50 +0,0 @@ -commit 117ed5c2d0f865894dd930d877f0ec28bc23d951 -Author: Miroslav Lichvar -Date: Tue Jan 17 14:17:41 2017 +0100 - - timemaster: check support for SW time stamping. - - When an interface doesn't support HW time stamping, before falling back - to SW time stamping, check if it's actually supported and exit with an - error message if not. - - Signed-off-by: Miroslav Lichvar - -diff --git a/timemaster.c b/timemaster.c -index 880b2ab..cda2d90 100644 ---- a/timemaster.c -+++ b/timemaster.c -@@ -674,13 +674,15 @@ static int add_ptp_source(struct ptp_domain *source, - { - struct config_file *config_file; - char **command, *uds_path, **interfaces, *message_tag; -- int i, j, num_interfaces, *phc, *phcs, hw_ts; -+ int i, j, num_interfaces, *phc, *phcs, hw_ts, sw_ts; - struct sk_ts_info ts_info; - - pr_debug("adding PTP domain %d", source->domain); - - hw_ts = SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | - SOF_TIMESTAMPING_RAW_HARDWARE; -+ sw_ts = SOF_TIMESTAMPING_TX_SOFTWARE | SOF_TIMESTAMPING_RX_SOFTWARE | -+ SOF_TIMESTAMPING_SOFTWARE; - - for (num_interfaces = 0; - source->interfaces[num_interfaces]; num_interfaces++) -@@ -702,9 +704,14 @@ static int add_ptp_source(struct ptp_domain *source, - return 1; - } - -- if (!ts_info.valid || -- ((ts_info.so_timestamping & hw_ts) != hw_ts)) { -+ if (((ts_info.so_timestamping & hw_ts) != hw_ts)) { - pr_debug("interface %s: no PHC", source->interfaces[i]); -+ if ((ts_info.so_timestamping & sw_ts) != sw_ts) { -+ pr_err("time stamping not supported on %s", -+ source->interfaces[i]); -+ free(phcs); -+ return 1; -+ } - continue; - } - diff --git a/SOURCES/linuxptp-sysoff.patch b/SOURCES/linuxptp-sysoff.patch new file mode 100644 index 0000000..9f84f80 --- /dev/null +++ b/SOURCES/linuxptp-sysoff.patch @@ -0,0 +1,403 @@ +commit c0e49c708814ec783726fe92202371847703c5ed +Author: Miroslav Lichvar +Date: Mon Nov 12 17:27:58 2018 +0100 + + sysoff: Initialize data for ioctl(PTP_SYS_OFFSET). + + This fixes valgrind errors. + + Signed-off-by: Miroslav Lichvar + +diff --git a/sysoff.c b/sysoff.c +index f7b6240..407a01c 100644 +--- a/sysoff.c ++++ b/sysoff.c +@@ -18,6 +18,7 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + #include ++#include + #include + #include + +@@ -76,6 +77,7 @@ int sysoff_measure(int fd, int n_samples, + int64_t *result, uint64_t *ts, int64_t *delay) + { + struct ptp_sys_offset pso; ++ memset(&pso, 0, sizeof(pso)); + pso.n_samples = n_samples; + if (ioctl(fd, PTP_SYS_OFFSET, &pso)) { + perror("ioctl PTP_SYS_OFFSET"); + +commit 93baf34adb81046a5e1c3b9a3e685029f2046993 +Author: Miroslav Lichvar +Date: Mon Nov 12 17:27:59 2018 +0100 + + sysoff: Extend API for different sysoff methods. + + The kernel supports different PTP_SYS_OFFSET* ioctls. Use the sysoff + enum to allow selecting between them in sysoff_measure(). + + Signed-off-by: Miroslav Lichvar + +diff --git a/phc2sys.c b/phc2sys.c +index 15f8d75..2cd477a 100644 +--- a/phc2sys.c ++++ b/phc2sys.c +@@ -74,7 +74,7 @@ struct clock { + LIST_ENTRY(clock) dst_list; + clockid_t clkid; + int phc_index; +- int sysoff_supported; ++ int sysoff_method; + int is_utc; + int dest_only; + int state; +@@ -255,9 +255,8 @@ static struct clock *clock_add(struct node *node, char *device) + c->servo = servo_add(node, c); + + if (clkid != CLOCK_INVALID && clkid != CLOCK_REALTIME) +- c->sysoff_supported = (SYSOFF_SUPPORTED == +- sysoff_probe(CLOCKID_TO_FD(clkid), +- node->phc_readings)); ++ c->sysoff_method = sysoff_probe(CLOCKID_TO_FD(clkid), ++ node->phc_readings); + + LIST_INSERT_HEAD(&node->clocks, c, list); + return c; +@@ -784,11 +783,12 @@ static int do_loop(struct node *node, int subscriptions) + continue; + + if (clock->clkid == CLOCK_REALTIME && +- node->master->sysoff_supported) { ++ node->master->sysoff_method >= 0) { + /* use sysoff */ + if (sysoff_measure(CLOCKID_TO_FD(node->master->clkid), ++ node->master->sysoff_method, + node->phc_readings, +- &offset, &ts, &delay)) ++ &offset, &ts, &delay) < 0) + return -1; + } else { + /* use phc */ +diff --git a/phc_ctl.c b/phc_ctl.c +index 4a78a19..b9a9cf4 100644 +--- a/phc_ctl.c ++++ b/phc_ctl.c +@@ -367,10 +367,12 @@ static int do_cmp(clockid_t clkid, int cmdc, char *cmdv[]) + struct timespec ts, rta, rtb; + int64_t sys_offset, delay = 0, offset; + uint64_t sys_ts; ++ int method; + +- if (SYSOFF_SUPPORTED == +- sysoff_measure(CLOCKID_TO_FD(clkid), +- 9, &sys_offset, &sys_ts, &delay)) { ++ method = sysoff_probe(CLOCKID_TO_FD(clkid), 9); ++ ++ if (method >= 0 && sysoff_measure(CLOCKID_TO_FD(clkid), method, 9, ++ &sys_offset, &sys_ts, &delay) >= 0) { + pr_notice( "offset from CLOCK_REALTIME is %"PRId64"ns\n", + sys_offset); + return 0; +diff --git a/sysoff.c b/sysoff.c +index 407a01c..f709a9b 100644 +--- a/sysoff.c ++++ b/sysoff.c +@@ -73,8 +73,8 @@ static int64_t sysoff_estimate(struct ptp_clock_time *pct, int n_samples, + return samples[0].offset; + } + +-int sysoff_measure(int fd, int n_samples, +- int64_t *result, uint64_t *ts, int64_t *delay) ++static int sysoff_basic(int fd, int n_samples, ++ int64_t *result, uint64_t *ts, int64_t *delay) + { + struct ptp_sys_offset pso; + memset(&pso, 0, sizeof(pso)); +@@ -84,13 +84,24 @@ int sysoff_measure(int fd, int n_samples, + return SYSOFF_RUN_TIME_MISSING; + } + *result = sysoff_estimate(pso.ts, n_samples, ts, delay); +- return SYSOFF_SUPPORTED; ++ return SYSOFF_BASIC; ++} ++ ++int sysoff_measure(int fd, int method, int n_samples, ++ int64_t *result, uint64_t *ts, int64_t *delay) ++{ ++ switch (method) { ++ case SYSOFF_BASIC: ++ return sysoff_basic(fd, n_samples, result, ts, delay); ++ } ++ return SYSOFF_COMPILE_TIME_MISSING; + } + + int sysoff_probe(int fd, int n_samples) + { + int64_t junk, delay; + uint64_t ts; ++ int i; + + if (n_samples > PTP_MAX_SAMPLES) { + fprintf(stderr, "warning: %d exceeds kernel max readings %d\n", +@@ -99,7 +110,13 @@ int sysoff_probe(int fd, int n_samples) + return SYSOFF_RUN_TIME_MISSING; + } + +- return sysoff_measure(fd, n_samples, &junk, &ts, &delay); ++ for (i = 0; i < SYSOFF_LAST; i++) { ++ if (sysoff_measure(fd, i, n_samples, &junk, &ts, &delay) < 0) ++ continue; ++ return i; ++ } ++ ++ return SYSOFF_RUN_TIME_MISSING; + } + + #else /* !PTP_SYS_OFFSET */ +diff --git a/sysoff.h b/sysoff.h +index cb70265..02ecdfa 100644 +--- a/sysoff.h ++++ b/sysoff.h +@@ -21,13 +21,14 @@ + #include + + enum { +- SYSOFF_SUPPORTED, +- SYSOFF_COMPILE_TIME_MISSING, +- SYSOFF_RUN_TIME_MISSING, ++ SYSOFF_COMPILE_TIME_MISSING = -2, ++ SYSOFF_RUN_TIME_MISSING = -1, ++ SYSOFF_BASIC, ++ SYSOFF_LAST, + }; + + /** +- * Check to see if the PTP_SYS_OFFSET ioctl is supported. ++ * Check to see if a PTP_SYS_OFFSET ioctl is supported. + * @param fd An open file descriptor to a PHC device. + * @return One of the SYSOFF_ enumeration values. + */ +@@ -36,11 +37,12 @@ int sysoff_probe(int fd, int n_samples); + /** + * Measure the offset between a PHC and the system time. + * @param fd An open file descriptor to a PHC device. ++ * @param method A non-negative SYSOFF_ value returned by sysoff_probe(). + * @param n_samples The number of consecutive readings to make. + * @param result The estimated offset in nanoseconds. + * @param ts The system time corresponding to the 'result'. + * @param delay The delay in reading of the clock in nanoseconds. + * @return One of the SYSOFF_ enumeration values. + */ +-int sysoff_measure(int fd, int n_samples, ++int sysoff_measure(int fd, int method, int n_samples, + int64_t *result, uint64_t *ts, int64_t *delay); + +commit 192b8e315c4585489d7aa7f59683035998805e40 +Author: Miroslav Lichvar +Date: Mon Nov 12 17:28:00 2018 +0100 + + sysoff: Add support for PTP_SYS_OFFSET_PRECISE ioctl. + + This ioctl uses cross timestamping for a more accurate measurement of + the offset. It is supported on some onboard Intel NICs using the e1000e + driver and a virtual PHC with the ptp_kvm driver. + + Signed-off-by: Miroslav Lichvar + +diff --git a/sysoff.c b/sysoff.c +index f709a9b..9f65d95 100644 +--- a/sysoff.c ++++ b/sysoff.c +@@ -22,6 +22,7 @@ + #include + #include + ++#include "print.h" + #include "sysoff.h" + + #define NS_PER_SEC 1000000000LL +@@ -39,6 +40,23 @@ static struct { + uint64_t timestamp; + } samples[PTP_MAX_SAMPLES]; + ++static int sysoff_precise(int fd, int64_t *result, uint64_t *ts) ++{ ++#ifdef PTP_SYS_OFFSET_PRECISE ++ struct ptp_sys_offset_precise pso; ++ memset(&pso, 0, sizeof(pso)); ++ if (ioctl(fd, PTP_SYS_OFFSET_PRECISE, &pso)) { ++ pr_debug("ioctl PTP_SYS_OFFSET_PRECISE: %m"); ++ return SYSOFF_RUN_TIME_MISSING; ++ } ++ *result = pctns(&pso.sys_realtime) - pctns(&pso.device); ++ *ts = pctns(&pso.sys_realtime); ++ return SYSOFF_PRECISE; ++#else ++ return SYSOFF_COMPILE_TIME_MISSING; ++#endif ++} ++ + static void insertion_sort(int length, int64_t interval, int64_t offset, uint64_t ts) + { + int i = length - 1; +@@ -91,6 +109,9 @@ int sysoff_measure(int fd, int method, int n_samples, + int64_t *result, uint64_t *ts, int64_t *delay) + { + switch (method) { ++ case SYSOFF_PRECISE: ++ *delay = 0; ++ return sysoff_precise(fd, result, ts); + case SYSOFF_BASIC: + return sysoff_basic(fd, n_samples, result, ts, delay); + } +diff --git a/sysoff.h b/sysoff.h +index 02ecdfa..37f7353 100644 +--- a/sysoff.h ++++ b/sysoff.h +@@ -23,6 +23,7 @@ + enum { + SYSOFF_COMPILE_TIME_MISSING = -2, + SYSOFF_RUN_TIME_MISSING = -1, ++ SYSOFF_PRECISE, + SYSOFF_BASIC, + SYSOFF_LAST, + }; + +commit 68a9011c9d7d859920da339ba59c14dc1d617a45 +Author: Miroslav Lichvar +Date: Mon Nov 12 17:28:01 2018 +0100 + + sysoff: Add support for PTP_SYS_OFFSET_EXTENDED ioctl. + + This is a more accurate variant of the the PTP_SYS_OFFSET ioctl, which + will probably be supported in future kernel versions. + + Signed-off-by: Miroslav Lichvar + +diff --git a/sysoff.c b/sysoff.c +index 9f65d95..b993ee9 100644 +--- a/sysoff.c ++++ b/sysoff.c +@@ -71,17 +71,23 @@ static void insertion_sort(int length, int64_t interval, int64_t offset, uint64_ + samples[i+1].timestamp = ts; + } + +-static int64_t sysoff_estimate(struct ptp_clock_time *pct, int n_samples, +- uint64_t *ts, int64_t *delay) ++static int64_t sysoff_estimate(struct ptp_clock_time *pct, int extended, ++ int n_samples, uint64_t *ts, int64_t *delay) + { + int64_t t1, t2, tp; + int64_t interval, offset; + int i; + + for (i = 0; i < n_samples; i++) { +- t1 = pctns(&pct[2*i]); +- tp = pctns(&pct[2*i+1]); +- t2 = pctns(&pct[2*i+2]); ++ if (extended) { ++ t1 = pctns(&pct[3*i]); ++ tp = pctns(&pct[3*i+1]); ++ t2 = pctns(&pct[3*i+2]); ++ } else { ++ t1 = pctns(&pct[2*i]); ++ tp = pctns(&pct[2*i+1]); ++ t2 = pctns(&pct[2*i+2]); ++ } + interval = t2 - t1; + offset = (t2 + t1) / 2 - tp; + insertion_sort(i, interval, offset, (t2 + t1) / 2); +@@ -91,6 +97,24 @@ static int64_t sysoff_estimate(struct ptp_clock_time *pct, int n_samples, + return samples[0].offset; + } + ++static int sysoff_extended(int fd, int n_samples, ++ int64_t *result, uint64_t *ts, int64_t *delay) ++{ ++#ifdef PTP_SYS_OFFSET_EXTENDED ++ struct ptp_sys_offset_extended pso; ++ memset(&pso, 0, sizeof(pso)); ++ pso.n_samples = n_samples; ++ if (ioctl(fd, PTP_SYS_OFFSET_EXTENDED, &pso)) { ++ pr_debug("ioctl PTP_SYS_OFFSET_EXTENDED: %m"); ++ return SYSOFF_RUN_TIME_MISSING; ++ } ++ *result = sysoff_estimate(&pso.ts[0][0], 1, n_samples, ts, delay); ++ return SYSOFF_EXTENDED; ++#else ++ return SYSOFF_COMPILE_TIME_MISSING; ++#endif ++} ++ + static int sysoff_basic(int fd, int n_samples, + int64_t *result, uint64_t *ts, int64_t *delay) + { +@@ -101,7 +125,7 @@ static int sysoff_basic(int fd, int n_samples, + perror("ioctl PTP_SYS_OFFSET"); + return SYSOFF_RUN_TIME_MISSING; + } +- *result = sysoff_estimate(pso.ts, n_samples, ts, delay); ++ *result = sysoff_estimate(pso.ts, 0, n_samples, ts, delay); + return SYSOFF_BASIC; + } + +@@ -112,6 +136,8 @@ int sysoff_measure(int fd, int method, int n_samples, + case SYSOFF_PRECISE: + *delay = 0; + return sysoff_precise(fd, result, ts); ++ case SYSOFF_EXTENDED: ++ return sysoff_extended(fd, n_samples, result, ts, delay); + case SYSOFF_BASIC: + return sysoff_basic(fd, n_samples, result, ts, delay); + } +diff --git a/sysoff.h b/sysoff.h +index 37f7353..79d2290 100644 +--- a/sysoff.h ++++ b/sysoff.h +@@ -24,6 +24,7 @@ enum { + SYSOFF_COMPILE_TIME_MISSING = -2, + SYSOFF_RUN_TIME_MISSING = -1, + SYSOFF_PRECISE, ++ SYSOFF_EXTENDED, + SYSOFF_BASIC, + SYSOFF_LAST, + }; + +commit 8142da41b61fb5b9ee4ad8f5ab56adb0447cd37b +Author: Miroslav Lichvar +Date: Mon Nov 12 17:28:02 2018 +0100 + + phc2sys: Use reversed sysoff when synchronizing to system clock. + + If synchronizing a PHC to the system clock, use one of the + PTP_SYS_OFFSET ioctls (if supported) to measure the offset between the + two clocks. Negate the offset and switch the timestamp before passing + them to the servo. + + This makes the synchronization between PHC and system clock symmetric. + + Signed-off-by: Miroslav Lichvar + +diff --git a/phc2sys.c b/phc2sys.c +index 2cd477a..b8f1ea0 100644 +--- a/phc2sys.c ++++ b/phc2sys.c +@@ -790,6 +790,16 @@ static int do_loop(struct node *node, int subscriptions) + node->phc_readings, + &offset, &ts, &delay) < 0) + return -1; ++ } else if (node->master->clkid == CLOCK_REALTIME && ++ clock->sysoff_method >= 0) { ++ /* use reversed sysoff */ ++ if (sysoff_measure(CLOCKID_TO_FD(clock->clkid), ++ clock->sysoff_method, ++ node->phc_readings, ++ &offset, &ts, &delay) < 0) ++ return -1; ++ ts += offset; ++ offset = -offset; + } else { + /* use phc */ + if (!read_phc(node->master->clkid, clock->clkid, diff --git a/SOURCES/linuxptp-team.patch b/SOURCES/linuxptp-team.patch new file mode 100644 index 0000000..bb4b9c9 --- /dev/null +++ b/SOURCES/linuxptp-team.patch @@ -0,0 +1,459 @@ +commit 8ca81014a352a125aab38fce2b1302d92c0f5ef2 +Author: Hangbin Liu +Date: Fri Mar 1 15:08:48 2019 +0800 + + rtnl: add team activebackup support + + This patch add team interface activebackup mode support. As linux team use + genl netlink message, when we get a rtnl link change notify, we have to setup + a new genl socket and request the current active port. + + v2: check nlmsg_len before copy rta_data + v3: a) Do not make rtnl_buf global as it may be freed by calling rtnl_close() + while we are using it in rtnl_link_status() + b) Reorder declarations of variables as reversed Christmas tree for + function rtnl_link_status() + c) remove rtnl_len + v4: Remove the first !rtnl_buf check in rtnl_link_status as it's alway true + v5: a) Re-order {nl, rtnl}_open and add function nl_close() + b) revert the v3_{a,c}, v4 changes, use nl_close to close genl fd + c) do not use len in get_team_active_iface() as it may mislead reader + + Signed-off-by: Hangbin Liu + +diff --git a/missing.h b/missing.h +index 2f7adb9..8f92079 100644 +--- a/missing.h ++++ b/missing.h +@@ -118,6 +118,22 @@ enum { + #define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1) + #endif /*IFLA_BOND_MAX*/ + ++#ifndef NLA_TYPE_MAX ++enum { ++ NLA_UNSPEC, ++ NLA_U8, ++ NLA_U16, ++ NLA_U32, ++ NLA_U64, ++ NLA_STRING, ++ NLA_FLAG, ++ NLA_MSECS, ++ NLA_NESTED, ++ __NLA_TYPE_MAX, ++}; ++#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1) ++#endif /*NLA_TYPE_MAX*/ ++ + #ifdef __UCLIBC__ + + #if (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L) && \ +diff --git a/phc2sys.8 b/phc2sys.8 +index 45cb0e3..b3a3de3 100644 +--- a/phc2sys.8 ++++ b/phc2sys.8 +@@ -108,9 +108,9 @@ together with the + option, the master clock is used only to correct the offset by whole number of + seconds, which cannot be fixed with PPS alone. Not compatible with the + .B \-a +-option. This option does not support bonded interface (e.g. bond0). If ++option. This option does not support bonded interface (e.g. bond0, team0). If + .B ptp4l +-has a port on an active-backup bond interface, the ++has a port on an active-backup bond or team interface, the + .B \-a + option can be used to track the active interface. + .TP +diff --git a/rtnl.c b/rtnl.c +index f9a572b..e3758b3 100644 +--- a/rtnl.c ++++ b/rtnl.c +@@ -20,6 +20,8 @@ + #include /* Must come before linux/netlink.h on some systems. */ + #include + #include ++#include ++#include + #include + #include + #include +@@ -30,8 +32,39 @@ + #include "print.h" + #include "rtnl.h" + ++#define BUF_SIZE 4096 ++#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN)) ++ + static int rtnl_len; + static char *rtnl_buf; ++static int get_team_active_iface(int master_index); ++ ++static int nl_close(int fd) ++{ ++ return close(fd); ++} ++ ++static int nl_open(int family) ++{ ++ int fd; ++ struct sockaddr_nl sa; ++ ++ memset(&sa, 0, sizeof(sa)); ++ sa.nl_family = AF_NETLINK; ++ sa.nl_groups = RTNLGRP_LINK; ++ ++ fd = socket(AF_NETLINK, SOCK_RAW, family); ++ if (fd < 0) { ++ pr_err("failed to open netlink socket: %m"); ++ return -1; ++ } ++ if (bind(fd, (struct sockaddr *) &sa, sizeof(sa))) { ++ pr_err("failed to bind netlink socket: %m"); ++ close(fd); ++ return -1; ++ } ++ return fd; ++} + + int rtnl_close(int fd) + { +@@ -40,7 +73,12 @@ int rtnl_close(int fd) + rtnl_buf = NULL; + rtnl_len = 0; + } +- return close(fd); ++ return nl_close(fd); ++} ++ ++int rtnl_open(void) ++{ ++ return nl_open(NETLINK_ROUTE); + } + + static void rtnl_get_ts_device_callback(void *ctx, int linkup, int ts_index) +@@ -116,14 +154,24 @@ int rtnl_link_query(int fd, char *device) + return 0; + } + +-static inline __u32 rta_getattr_u32(const struct rtattr *rta) ++static inline __u8 rta_getattr_u8(struct rtattr *rta) ++{ ++ return *(__u8 *)RTA_DATA(rta); ++} ++ ++static inline __u16 rta_getattr_u16(struct rtattr *rta) ++{ ++ return *(__u16 *)RTA_DATA(rta); ++} ++ ++static inline __u32 rta_getattr_u32(struct rtattr *rta) + { + return *(__u32 *)RTA_DATA(rta); + } + +-static inline const char *rta_getattr_str(const struct rtattr *rta) ++static inline char *rta_getattr_str(struct rtattr *rta) + { +- return (const char *)RTA_DATA(rta); ++ return (char *)RTA_DATA(rta); + } + + static int rtnl_rtattr_parse(struct rtattr *tb[], int max, struct rtattr *rta, int len) +@@ -150,12 +198,12 @@ static inline int rtnl_nested_rtattr_parse(struct rtattr *tb[], int max, struct + return rtnl_rtattr_parse(tb, max, RTA_DATA(rta), RTA_PAYLOAD(rta)); + } + +-static int rtnl_linkinfo_parse(struct rtattr *rta) ++static int rtnl_linkinfo_parse(int master_index, struct rtattr *rta) + { +- int index = -1; +- const char *kind; + struct rtattr *linkinfo[IFLA_INFO_MAX]; + struct rtattr *bond[IFLA_BOND_MAX]; ++ int index = -1; ++ char *kind; + + if (rtnl_nested_rtattr_parse(linkinfo, IFLA_INFO_MAX, rta) < 0) + return -1; +@@ -172,6 +220,8 @@ static int rtnl_linkinfo_parse(struct rtattr *rta) + if (bond[IFLA_BOND_ACTIVE_SLAVE]) { + index = rta_getattr_u32(bond[IFLA_BOND_ACTIVE_SLAVE]); + } ++ } else if (kind && !strncmp(kind, "team", 4)) { ++ index = get_team_active_iface(master_index); + } + } + return index; +@@ -179,18 +229,18 @@ static int rtnl_linkinfo_parse(struct rtattr *rta) + + int rtnl_link_status(int fd, char *device, rtnl_callback cb, void *ctx) + { ++ struct rtattr *tb[IFLA_MAX+1]; ++ struct ifinfomsg *info = NULL; + int index, len, link_up; +- int slave_index = -1; +- struct iovec iov; + struct sockaddr_nl sa; +- struct msghdr msg; ++ int slave_index = -1; + struct nlmsghdr *nh; +- struct ifinfomsg *info = NULL; +- struct rtattr *tb[IFLA_MAX+1]; ++ struct msghdr msg; ++ struct iovec iov; + + index = if_nametoindex(device); + if (!rtnl_buf) { +- rtnl_len = 4096; ++ rtnl_len = BUF_SIZE; + rtnl_buf = malloc(rtnl_len); + if (!rtnl_buf) { + pr_err("rtnl: low memory"); +@@ -246,7 +296,7 @@ int rtnl_link_status(int fd, char *device, rtnl_callback cb, void *ctx) + IFLA_PAYLOAD(nh)); + + if (tb[IFLA_LINKINFO]) +- slave_index = rtnl_linkinfo_parse(tb[IFLA_LINKINFO]); ++ slave_index = rtnl_linkinfo_parse(index, tb[IFLA_LINKINFO]); + + if (cb) + cb(ctx, link_up, slave_index); +@@ -255,24 +305,164 @@ int rtnl_link_status(int fd, char *device, rtnl_callback cb, void *ctx) + return 0; + } + +-int rtnl_open(void) ++static int genl_send_msg(int fd, int family_id, int genl_cmd, int genl_version, ++ int rta_type, void *rta_data, int rta_len) + { +- int fd; +- struct sockaddr_nl sa; ++ struct sockaddr_nl daddr; ++ struct genlmsghdr *gnlh; ++ struct nlmsghdr *nlh; ++ struct rtattr *attr; ++ char msg[BUF_SIZE]; + +- memset(&sa, 0, sizeof(sa)); +- sa.nl_family = AF_NETLINK; +- sa.nl_groups = RTNLGRP_LINK; ++ memset(&daddr, 0, sizeof(daddr)); ++ daddr.nl_family = AF_NETLINK; + +- fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); +- if (fd < 0) { +- pr_err("failed to open netlink socket: %m"); ++ memset(&msg, 0, sizeof(msg)); ++ nlh = (struct nlmsghdr *) msg; ++ nlh->nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); ++ nlh->nlmsg_type = family_id; ++ nlh->nlmsg_flags = NLM_F_REQUEST; ++ ++ gnlh = (struct genlmsghdr *) NLMSG_DATA(nlh); ++ gnlh->cmd = genl_cmd; ++ gnlh->version = genl_version; ++ ++ if (rta_data && rta_len > 0) { ++ attr = (struct rtattr *) GENLMSG_DATA(msg); ++ attr->rta_type = rta_type; ++ attr->rta_len = RTA_LENGTH(rta_len); ++ nlh->nlmsg_len += NLMSG_ALIGN(attr->rta_len); ++ if (nlh->nlmsg_len < sizeof(msg)) ++ memcpy(RTA_DATA(attr), rta_data, rta_len); ++ else ++ return -1; ++ } ++ ++ return sendto(fd, &msg, nlh->nlmsg_len, 0, ++ (struct sockaddr *)&daddr, sizeof(daddr)); ++} ++ ++static int genl_get_family_id(int fd, void *family_name) ++{ ++ struct rtattr *tb[CTRL_ATTR_MAX+1]; ++ struct nlmsghdr *nlh; ++ struct rtattr *attr; ++ char msg[BUF_SIZE]; ++ int len, gf_id; ++ ++ len = genl_send_msg(fd, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 1, ++ CTRL_ATTR_FAMILY_NAME, family_name, ++ strlen(family_name) + 1); ++ if (len < 0) ++ return len; ++ ++ len = recv(fd, &msg, sizeof(msg), 0); ++ if (len < 0) ++ return len; ++ ++ nlh = (struct nlmsghdr *) msg; ++ if (nlh->nlmsg_type == NLMSG_ERROR || !NLMSG_OK(nlh, len)) + return -1; ++ ++ attr = (struct rtattr *) GENLMSG_DATA(msg); ++ rtnl_rtattr_parse(tb, CTRL_ATTR_MAX, attr, NLMSG_PAYLOAD(nlh, GENL_HDRLEN)); ++ ++ if (tb[CTRL_ATTR_FAMILY_ID]) ++ gf_id = rta_getattr_u16(tb[CTRL_ATTR_FAMILY_ID]); ++ else ++ gf_id = -1; ++ ++ return gf_id; ++} ++ ++static int parase_team_list_option(struct rtattr *attr) ++{ ++ struct rtattr *tb[TEAM_ATTR_OPTION_MAX+1]; ++ int len = RTA_PAYLOAD(attr); ++ const char *optname = ""; ++ const char *mode = ""; ++ int active_index = -1; ++ ++ for (attr = RTA_DATA(attr); RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) { ++ rtnl_nested_rtattr_parse(tb, TEAM_ATTR_OPTION_MAX, attr); ++ ++ if (tb[TEAM_ATTR_OPTION_NAME]) ++ optname = rta_getattr_str(tb[TEAM_ATTR_OPTION_NAME]); ++ ++ if (!strcmp(optname, "mode") && tb[TEAM_ATTR_OPTION_TYPE] && ++ rta_getattr_u8(tb[TEAM_ATTR_OPTION_TYPE]) == NLA_STRING) ++ mode = rta_getattr_str(tb[TEAM_ATTR_OPTION_DATA]); ++ ++ if (!strcmp(optname, "activeport") && tb[TEAM_ATTR_OPTION_TYPE] && ++ rta_getattr_u8(tb[TEAM_ATTR_OPTION_TYPE]) == NLA_U32) ++ active_index = rta_getattr_u32(tb[TEAM_ATTR_OPTION_DATA]); + } +- if (bind(fd, (struct sockaddr *) &sa, sizeof(sa))) { +- pr_err("failed to bind netlink socket: %m"); +- close(fd); ++ ++ if (strcmp(mode, "activebackup")) { ++ pr_err("team supported only in activebackup mode"); + return -1; ++ } else { ++ return active_index; + } +- return fd; ++} ++ ++static int get_team_active_iface(int master_index) ++{ ++ struct rtattr *tb[TEAM_ATTR_MAX+1]; ++ struct genlmsghdr *gnlh; ++ struct nlmsghdr *nlh; ++ char msg[BUF_SIZE]; ++ int fd, gf_id, len; ++ int index = -1; ++ ++ fd = nl_open(NETLINK_GENERIC); ++ if (fd < 0) ++ return fd; ++ ++ gf_id = genl_get_family_id(fd, TEAM_GENL_NAME); ++ if (gf_id < 0) { ++ pr_err("get genl family failed"); ++ goto no_info; ++ } ++ ++ len = genl_send_msg(fd, gf_id, TEAM_CMD_OPTIONS_GET, ++ TEAM_GENL_VERSION, TEAM_ATTR_TEAM_IFINDEX, ++ &master_index, sizeof(master_index)); ++ if (len < 0) { ++ pr_err("send team info request failed: %m"); ++ goto no_info; ++ } ++ ++ len = recv(fd, msg, sizeof(msg), 0); ++ if (len < 0) { ++ pr_err("recv team info failed: %m"); ++ goto no_info; ++ } ++ ++ nlh = (struct nlmsghdr *) msg; ++ for ( ; NLMSG_OK(nlh, len); nlh = NLMSG_NEXT(nlh, len)) { ++ if (nlh->nlmsg_type != gf_id) ++ continue; ++ ++ gnlh = (struct genlmsghdr *) NLMSG_DATA(nlh); ++ if (gnlh->cmd != TEAM_CMD_OPTIONS_GET) ++ continue; ++ ++ rtnl_rtattr_parse(tb, TEAM_ATTR_MAX, (struct rtattr *)GENLMSG_DATA(msg), ++ NLMSG_PAYLOAD(nlh, GENL_HDRLEN)); ++ ++ if (tb[TEAM_ATTR_TEAM_IFINDEX] && ++ master_index != rta_getattr_u32(tb[TEAM_ATTR_TEAM_IFINDEX])) ++ continue; ++ ++ if (tb[TEAM_ATTR_LIST_OPTION]) { ++ index = parase_team_list_option(tb[TEAM_ATTR_LIST_OPTION]); ++ break; ++ } ++ } ++ ++ return index; ++no_info: ++ nl_close(fd); ++ return -1; + } +commit d8eafa6a39a609597e6c1ce44d616ba6f33c27f8 +Author: Hangbin Liu +Date: Wed Mar 20 14:44:13 2019 +0800 + + port: should check the new phc_index before switching + + In logic, when we want to switch phc, we should check if the new phc + index is valid instead of checking the previous one. + + In reality, if we use linux team interface with activebackup mode. As + teamd is a userspace tool, it sets the new slave as active port after + receiving link change message. If we set current active port down and + another slave up. There is a race that we receive the new slave's link + up message while active port(ts_index) is still the old one. This means + we may use a link down interface as ts_index and get phc_index with -1. + + If we update the p->phc_index to -1, there will be no possibility to + change it back to other value as we swith phc only when p->phc_index >= 0. + + With this fix, we will not switch phc_index until receiving the real + active port(p->iface->ts_info.phc_index >= 0) update message. + + Reported-by: Miroslav Lichvar + Fixes: 536a71031d5c ("ptp4l: use ts label to get ts info") + Signed-off-by: Hangbin Liu + +diff --git a/port.c b/port.c +index ad9554f..49c6f76 100644 +--- a/port.c ++++ b/port.c +@@ -2442,7 +2442,7 @@ void port_link_status(void *ctx, int linkup, int ts_index) + sk_get_ts_info(p->iface->ts_label, &p->iface->ts_info); + + /* Only switch phc with HW time stamping mode */ +- if (p->phc_index >= 0 && p->iface->ts_info.valid) { ++ if (p->iface->ts_info.valid && p->iface->ts_info.phc_index >= 0) { + required_modes = clock_required_modes(p->clock); + if ((p->iface->ts_info.so_timestamping & required_modes) != required_modes) { + pr_err("interface '%s' does not support requested " +commit ecfbea2dac2312cb61aa5d2fe1646ee4c6b18643 +Author: Miroslav Lichvar +Date: Thu Mar 21 15:44:32 2019 +0100 + + rtnl: close file descriptor in get_team_active_iface() + + Signed-off-by: Miroslav Lichvar + +diff --git a/rtnl.c b/rtnl.c +index e3758b3..59ed0ec 100644 +--- a/rtnl.c ++++ b/rtnl.c +@@ -461,8 +461,7 @@ static int get_team_active_iface(int master_index) + } + } + +- return index; + no_info: + nl_close(fd); +- return -1; ++ return index; + } diff --git a/SOURCES/linuxptp-timeout.patch b/SOURCES/linuxptp-timeout.patch new file mode 100644 index 0000000..b104787 --- /dev/null +++ b/SOURCES/linuxptp-timeout.patch @@ -0,0 +1,24 @@ +commit 241d8a064efa535029e28b87a8995add3cca8c0c +Author: Miroslav Lichvar +Date: Tue Sep 25 18:16:19 2018 +0200 + + unicast: Process timeouts equal to current time. + + Don't postpone processing of a timeout if it is equal to the current + time. This prevents an infinite loop with a simulated clock. + + Signed-off-by: Miroslav Lichvar + +diff --git a/unicast_service.c b/unicast_service.c +index ad0e06a..9c9b95b 100644 +--- a/unicast_service.c ++++ b/unicast_service.c +@@ -502,7 +502,7 @@ int unicast_service_timer(struct port *p) + pr_debug("peek i={2^%d} tmo={%ld,%ld}", interval->log_period, + interval->tmo.tv_sec, interval->tmo.tv_nsec); + +- if (timespec_compare(&now, &interval->tmo) >= 0) { ++ if (timespec_compare(&now, &interval->tmo) > 0) { + break; + } + interval = pqueue_extract(p->unicast_service->queue); diff --git a/SOURCES/linuxptp-tmasterrestart.patch b/SOURCES/linuxptp-tmasterrestart.patch deleted file mode 100644 index dc8f7eb..0000000 --- a/SOURCES/linuxptp-tmasterrestart.patch +++ /dev/null @@ -1,388 +0,0 @@ -commit e79e5040a0e7efd622ecdd572bee40c90e59c3bd -Author: Miroslav Lichvar -Date: Fri Apr 13 17:11:58 2018 +0200 - - timemaster: restart terminated processes. - - If a ptp4l or phc2sys process is terminated (e.g. due to a crash) and - timemaster was running for at least one second (i.e. it's not an error - in ptp4l/phc2sys configuration), start the process again. Restart all - processes corresponding to the same time source at the same time to - ensure phc2sys is always connected to the currently running ptp4l. - - Add a new option to disable the restarting. - - Signed-off-by: Miroslav Lichvar - -diff --git a/timemaster.8 b/timemaster.8 -index e0e22eb..7288972 100644 ---- a/timemaster.8 -+++ b/timemaster.8 -@@ -87,6 +87,16 @@ Specify the first number in a sequence of SHM segments that will be used by - can be useful to avoid conflicts with time sources that are not started by - \fBtimemaster\fR, e.g. \fBgpsd\fR using segments number 0 and 1. - -+.TP -+.B restart_processes -+Enable or disable restarting of processes started by \fBtimemaster\fR. If the -+option is set to a non-zero value, all processes except \fBchronyd\fR and -+\fBntpd\fR will be automatically restarted when terminated and \fBtimemaster\fR -+is running for at least one second (i.e. the process did not terminate due to a -+configuration error). If a process was terminated and is not started again, -+\fBtimemaster\fR will kill the other processes and exit with a non-zero status. -+The default value is 1 (enabled). -+ - .SS [ntp_server address] - - The \fBntp_server\fR section specifies an NTP server that should be used as a -@@ -318,6 +328,7 @@ ptp4l_option delay_mechanism P2P - ntp_program chronyd - rundir /var/run/timemaster - first_shm_segment 1 -+restart_processes 0 - - [chronyd] - path /usr/sbin/chronyd -diff --git a/timemaster.c b/timemaster.c -index fc3ba31..4ba921e 100644 ---- a/timemaster.c -+++ b/timemaster.c -@@ -44,6 +44,7 @@ - #define DEFAULT_RUNDIR "/var/run/timemaster" - - #define DEFAULT_FIRST_SHM_SEGMENT 0 -+#define DEFAULT_RESTART_PROCESSES 1 - - #define DEFAULT_NTP_PROGRAM CHRONYD - #define DEFAULT_NTP_MINPOLL 6 -@@ -108,6 +109,7 @@ struct timemaster_config { - enum ntp_program ntp_program; - char *rundir; - int first_shm_segment; -+ int restart_processes; - struct program_config chronyd; - struct program_config ntpd; - struct program_config phc2sys; -@@ -122,6 +124,9 @@ struct config_file { - struct script { - struct config_file **configs; - char ***commands; -+ int **command_groups; -+ int restart_groups; -+ int no_restart_group; - }; - - static void free_parray(void **a) -@@ -385,6 +390,8 @@ static int parse_timemaster_settings(char **settings, - replace_string(value, &config->rundir); - } else if (!strcasecmp(name, "first_shm_segment")) { - r = parse_int(value, &config->first_shm_segment); -+ } else if (!strcasecmp(name, "restart_processes")) { -+ r = parse_int(value, &config->restart_processes); - } else { - pr_err("unknown timemaster setting %s", name); - return 1; -@@ -508,6 +515,7 @@ static struct timemaster_config *config_parse(char *path) - config->ntp_program = DEFAULT_NTP_PROGRAM; - config->rundir = xstrdup(DEFAULT_RUNDIR); - config->first_shm_segment = DEFAULT_FIRST_SHM_SEGMENT; -+ config->restart_processes = DEFAULT_RESTART_PROCESSES; - - init_program_config(&config->chronyd, "chronyd", - NULL, DEFAULT_CHRONYD_SETTINGS, NULL); -@@ -632,6 +640,18 @@ static char *get_refid(char *prefix, unsigned int number) - return NULL; - }; - -+static void add_command(char **command, int command_group, -+ struct script *script) -+{ -+ int *group; -+ -+ parray_append((void ***)&script->commands, command); -+ -+ group = xmalloc(sizeof(int)); -+ *group = command_group; -+ parray_append((void ***)&script->command_groups, group); -+} -+ - static void add_shm_source(int shm_segment, int poll, int dpoll, double delay, - char *ntp_options, char *prefix, - struct timemaster_config *config, char **ntp_config) -@@ -671,8 +691,8 @@ static int add_ntp_source(struct ntp_server *source, char **ntp_config) - - static int add_ptp_source(struct ptp_domain *source, - struct timemaster_config *config, int *shm_segment, -- int ***allocated_phcs, char **ntp_config, -- struct script *script) -+ int *command_group, int ***allocated_phcs, -+ char **ntp_config, struct script *script) - { - struct config_file *config_file; - char **command, *uds_path, **interfaces, *message_tag; -@@ -798,19 +818,19 @@ static int add_ptp_source(struct ptp_domain *source, - /* HW time stamping */ - command = get_ptp4l_command(&config->ptp4l, config_file, - interfaces, 1); -- parray_append((void ***)&script->commands, command); -+ add_command(command, *command_group, script); - - command = get_phc2sys_command(&config->phc2sys, - source->domain, - source->phc2sys_poll, - *shm_segment, uds_path, - message_tag); -- parray_append((void ***)&script->commands, command); -+ add_command(command, (*command_group)++, script); - } else { - /* SW time stamping */ - command = get_ptp4l_command(&config->ptp4l, config_file, - interfaces, 0); -- parray_append((void ***)&script->commands, command); -+ add_command(command, (*command_group)++, script); - - string_appendf(&config_file->content, - "clock_servo ntpshm\n" -@@ -862,7 +882,8 @@ static char **get_ntpd_command(struct program_config *config, - } - - static struct config_file *add_ntp_program(struct timemaster_config *config, -- struct script *script) -+ struct script *script, -+ int command_group) - { - struct config_file *ntp_config = xmalloc(sizeof(*ntp_config)); - char **command = NULL; -@@ -886,7 +907,7 @@ static struct config_file *add_ntp_program(struct timemaster_config *config, - } - - parray_append((void ***)&script->configs, ntp_config); -- parray_append((void ***)&script->commands, command); -+ add_command(command, command_group, script); - - return ntp_config; - } -@@ -894,6 +915,7 @@ static struct config_file *add_ntp_program(struct timemaster_config *config, - static void script_destroy(struct script *script) - { - char ***commands, **command; -+ int **groups; - struct config_file *config, **configs; - - for (configs = script->configs; *configs; configs++) { -@@ -911,6 +933,10 @@ static void script_destroy(struct script *script) - } - free(script->commands); - -+ for (groups = script->command_groups; *groups; groups++) -+ free(*groups); -+ free(script->command_groups); -+ - free(script); - } - -@@ -920,12 +946,15 @@ static struct script *script_create(struct timemaster_config *config) - struct source *source, **sources; - struct config_file *ntp_config = NULL; - int **allocated_phcs = (int **)parray_new(); -- int ret = 0, shm_segment; -+ int ret = 0, shm_segment, command_group = 0; - - script->configs = (struct config_file **)parray_new(); - script->commands = (char ***)parray_new(); -+ script->command_groups = (int **)parray_new(); -+ script->no_restart_group = command_group; -+ script->restart_groups = config->restart_processes; - -- ntp_config = add_ntp_program(config, script); -+ ntp_config = add_ntp_program(config, script, command_group++); - shm_segment = config->first_shm_segment; - - for (sources = config->sources; (source = *sources); sources++) { -@@ -936,7 +965,7 @@ static struct script *script_create(struct timemaster_config *config) - break; - case PTP_DOMAIN: - if (add_ptp_source(&source->ptp, config, &shm_segment, -- &allocated_phcs, -+ &command_group, &allocated_phcs, - &ntp_config->content, script)) - ret = 1; - break; -@@ -1063,10 +1092,11 @@ static int remove_config_files(struct config_file **configs) - - static int script_run(struct script *script) - { -+ struct timespec ts_start, ts_now; - sigset_t mask, old_mask; - siginfo_t info; - pid_t pid, *pids; -- int i, num_commands, status, ret = 0; -+ int i, group, num_commands, status, quit = 0, ret = 0; - - for (num_commands = 0; script->commands[num_commands]; num_commands++) - ; -@@ -1101,7 +1131,9 @@ static int script_run(struct script *script) - } - } - -- /* wait for one of the blocked signals */ -+ clock_gettime(CLOCK_MONOTONIC, &ts_start); -+ -+ /* process the blocked signals */ - while (1) { - if (sigwaitinfo(&mask, &info) < 0) { - if (errno == EINTR) -@@ -1110,36 +1142,111 @@ static int script_run(struct script *script) - break; - } - -- /* -- * assume only the first process (i.e. chronyd or ntpd) is -- * essential and continue if other processes terminate -- */ -- if (info.si_signo == SIGCHLD && info.si_pid != pids[0]) { -- pr_info("process %d terminated (ignored)", info.si_pid); -+ clock_gettime(CLOCK_MONOTONIC, &ts_now); -+ -+ if (info.si_signo != SIGCHLD) { -+ if (quit) -+ continue; -+ -+ quit = 1; -+ pr_debug("exiting on signal %d", info.si_signo); -+ -+ /* terminate remaining processes */ -+ for (i = 0; i < num_commands; i++) { -+ if (pids[i] > 0) { -+ pr_debug("killing process %d", pids[i]); -+ kill(pids[i], SIGTERM); -+ } -+ } -+ - continue; - } - -- pr_info("received signal %d", info.si_signo); -- break; -- } -+ /* wait for all terminated processes */ -+ while (1) { -+ pid = waitpid(-1, &status, WNOHANG); -+ if (pid <= 0) -+ break; - -- /* kill all started processes */ -- for (i = 0; i < num_commands; i++) { -- if (pids[i] > 0) { -- pr_debug("killing process %d", pids[i]); -- kill(pids[i], SIGTERM); -+ if (!WIFEXITED(status)) { -+ pr_info("process %d terminated abnormally", -+ pid); -+ } else { -+ pr_info("process %d terminated with status %d", -+ pid, WEXITSTATUS(status)); -+ } -+ -+ for (i = 0; i < num_commands; i++) { -+ if (pids[i] == pid) -+ pids[i] = 0; -+ } - } -- } - -- while ((pid = wait(&status)) >= 0) { -- if (!WIFEXITED(status)) { -- pr_info("process %d terminated abnormally", pid); -- ret = 1; -- } else { -- if (WEXITSTATUS(status)) -+ /* wait for all processes to terminate when exiting */ -+ if (quit) { -+ for (i = 0; i < num_commands; i++) { -+ if (pids[i]) -+ break; -+ } -+ if (i == num_commands) -+ break; -+ -+ pr_debug("waiting for other processes to terminate"); -+ continue; -+ } -+ -+ /* -+ * terminate (and then restart if allowed) all processes in -+ * groups that have a terminated process -+ */ -+ for (group = 0; group < num_commands; group++) { -+ int terminated = 0, running = 0; -+ -+ for (i = 0; i < num_commands; i++) { -+ if (*(script->command_groups[i]) != group) -+ continue; -+ if (pids[i]) -+ running++; -+ else -+ terminated++; -+ } -+ -+ if (!terminated) -+ continue; -+ -+ /* -+ * exit with a non-zero status if the group should not -+ * be restarted (i.e. chronyd/ntpd), timemaster is -+ * running only for a short time (and it is likely a -+ * configuration error), or restarting is disabled -+ * completely -+ */ -+ if (group == script->no_restart_group || -+ ts_now.tv_sec - ts_start.tv_sec <= 1 || -+ !script->restart_groups) { -+ kill(getpid(), SIGTERM); - ret = 1; -- pr_info("process %d terminated with status %d", pid, -- WEXITSTATUS(status)); -+ break; -+ } -+ -+ for (i = 0; i < num_commands; i++) { -+ if (*(script->command_groups[i]) != group) -+ continue; -+ -+ /* terminate all processes in the group first */ -+ if (running && pids[i]) { -+ pr_debug("killing process %d", pids[i]); -+ kill(pids[i], SIGTERM); -+ } else if (!running && !pids[i]) { -+ pids[i] = start_program(script->commands[i], -+ &old_mask); -+ if (!pids[i]) -+ kill(getpid(), SIGTERM); -+ -+ /* limit restarting rate */ -+ sleep(1); -+ } -+ } - } - } - -@@ -1154,6 +1261,7 @@ static int script_run(struct script *script) - static void script_print(struct script *script) - { - char ***commands, **command; -+ int **groups; - struct config_file *config, **configs; - - for (configs = script->configs; *configs; configs++) { -@@ -1162,7 +1270,9 @@ static void script_print(struct script *script) - } - - fprintf(stderr, "commands:\n\n"); -- for (commands = script->commands; *commands; commands++) { -+ for (commands = script->commands, groups = script->command_groups; -+ *commands; commands++, groups++) { -+ fprintf(stderr, "[%d] ", **groups); - for (command = *commands; *command; command++) - fprintf(stderr, "%s ", *command); - fprintf(stderr, "\n"); diff --git a/SOURCES/linuxptp-ucastrate.patch b/SOURCES/linuxptp-ucastrate.patch new file mode 100644 index 0000000..77fad5c --- /dev/null +++ b/SOURCES/linuxptp-ucastrate.patch @@ -0,0 +1,45 @@ +commit a36602f1e65cd6bace6ed9405b0ce359de4a27d1 +Author: Miroslav Lichvar +Date: Thu Jan 3 15:23:54 2019 +0100 + + unicast: limit message rate and grant duration + + Deny service requests with logInterMessagePeriod smaller than -7 (128 + packets per second) or larger than 16. This limits the network and CPU + consumption per address and prevents undefined shifts in the calculation + of the interval. + + Also, limit the maximum grant duration to one hour. + + Signed-off-by: Miroslav Lichvar + +diff --git a/unicast_service.c b/unicast_service.c +index 9c9b95b..c6c17c6 100644 +--- a/unicast_service.c ++++ b/unicast_service.c +@@ -31,6 +31,9 @@ + #include "unicast_service.h" + #include "util.h" + ++#define MIN_LOG_INTER_MESSAGE_PERIOD -7 ++#define MAX_LOG_INTER_MESSAGE_PERIOD 16 ++#define MAX_DURATION 3600 + #define QUEUE_LEN 16 + + struct unicast_client_address { +@@ -289,6 +292,15 @@ int unicast_service_add(struct port *p, struct ptp_message *m, + return SERVICE_DENIED; + } + ++ if (req->logInterMessagePeriod < MIN_LOG_INTER_MESSAGE_PERIOD || ++ req->logInterMessagePeriod > MAX_LOG_INTER_MESSAGE_PERIOD) { ++ return SERVICE_DENIED; ++ } ++ ++ if (req->durationField > MAX_DURATION) { ++ req->durationField = MAX_DURATION; ++ } ++ + LIST_FOREACH(itmp, &p->unicast_service->intervals, list) { + /* + * Remember the interval of interest. diff --git a/SOURCES/linuxptp-udsmgt.patch b/SOURCES/linuxptp-udsmgt.patch deleted file mode 100644 index c42ca74..0000000 --- a/SOURCES/linuxptp-udsmgt.patch +++ /dev/null @@ -1,37 +0,0 @@ -commit 303b08cbf55096aba55bd08a314e0701e5c33482 -Author: Miroslav Lichvar -Date: Mon Dec 11 14:21:25 2017 +0100 - - clock: Don't forward management requests to UDS port. - - The UDS port is not expected to be used by PTP clocks and forwarding of - management messages to the port can be limited to responses. - - This prevents ptp4l from printing error messages when a management - request is received from a non-UDS port and the last client which used - the UDS port is no longer listening. - - Signed-off-by: Miroslav Lichvar - -diff --git a/clock.c b/clock.c -index 41c8f81..6dbc45e 100644 ---- a/clock.c -+++ b/clock.c -@@ -1243,6 +1243,17 @@ static int clock_do_forward_mgmt(struct clock *c, - { - if (in == out || !forwarding(c, out)) - return 0; -+ -+ /* Don't forward any requests to the UDS port. */ -+ if (out == c->uds_port) { -+ switch (management_action(msg)) { -+ case GET: -+ case SET: -+ case COMMAND: -+ return 0; -+ } -+ } -+ - if (!*pre_sent) { - /* delay calling msg_pre_send until - * actually forwarding */ diff --git a/SOURCES/linuxptp-utcoffset.patch b/SOURCES/linuxptp-utcoffset.patch deleted file mode 100644 index b54f800..0000000 --- a/SOURCES/linuxptp-utcoffset.patch +++ /dev/null @@ -1,130 +0,0 @@ -commit 0309a880fb4389e869ae0ba431d3d17b1ec5a272 -Author: Miroslav Lichvar -Date: Thu Jan 5 10:15:53 2017 +0100 - - Update TAI-UTC offset - - A leap second was applied to UTC on 2016-12-31 and the offset between - TAI and UTC is now 37 seconds. - - Signed-off-by: Miroslav Lichvar - -diff --git a/ds.h b/ds.h -index b36862d..0e48d05 100644 ---- a/ds.h -+++ b/ds.h -@@ -84,7 +84,7 @@ struct parent_ds { - unsigned int path_length; - }; - --#define CURRENT_UTC_OFFSET 36 /* 1 Jul 2015 */ -+#define CURRENT_UTC_OFFSET 37 /* 1 Jan 2017 */ - #define INTERNAL_OSCILLATOR 0xA0 - - struct timePropertiesDS { -commit 33e62f992542ac5ce6bdbb8ae6c34dec7011b543 -Author: Viliam Lejcik -Date: Tue Jan 17 18:25:26 2017 +0100 - - ptp4l: Make UTC offset configurable. - - Currently UTC offset is defined as a constant - CURRENT_UTC_OFFSET, and if - a leap second is added, that constant is no longer valid. Ptp4l was - updated to read the UTC offset from configuration instead. - - Signed-off-by: Viliam Lejcik - -diff --git a/clock.c b/clock.c -index c716f01..a6a1a1a 100644 ---- a/clock.c -+++ b/clock.c -@@ -105,6 +105,7 @@ struct clock { - int leap_set; - int kernel_leap; - int utc_offset; /* grand master role */ -+ int current_utc_offset; /* UTC offset fallback */ - int time_flags; /* grand master role */ - int time_source; /* grand master role */ - enum servo_state servo_state; -@@ -681,7 +682,7 @@ static void clock_update_slave(struct clock *c) - if (!(c->tds.flags & PTP_TIMESCALE)) { - pr_warning("foreign master not using PTP timescale"); - } -- if (c->tds.currentUtcOffset < CURRENT_UTC_OFFSET) { -+ if (c->tds.currentUtcOffset < c->current_utc_offset) { - pr_warning("running in a temporal vortex"); - } - } -@@ -697,10 +698,10 @@ static int clock_utc_correct(struct clock *c, tmv_t ingress) - - if (c->tds.flags & UTC_OFF_VALID && c->tds.flags & TIME_TRACEABLE) { - utc_offset = c->tds.currentUtcOffset; -- } else if (c->tds.currentUtcOffset > CURRENT_UTC_OFFSET) { -+ } else if (c->tds.currentUtcOffset > c->current_utc_offset) { - utc_offset = c->tds.currentUtcOffset; - } else { -- utc_offset = CURRENT_UTC_OFFSET; -+ utc_offset = c->current_utc_offset; - } - - if (c->tds.flags & LEAP_61) { -@@ -1035,7 +1036,7 @@ struct clock *clock_create(enum clock_type type, struct config *config, - c->freq_est_interval = config_get_int(config, NULL, "freq_est_interval"); - c->grand_master_capable = config_get_int(config, NULL, "gmCapable"); - c->kernel_leap = config_get_int(config, NULL, "kernel_leap"); -- c->utc_offset = CURRENT_UTC_OFFSET; -+ c->utc_offset = c->current_utc_offset = config_get_int(config, NULL, "utc_offset"); - c->time_source = config_get_int(config, NULL, "timeSource"); - - if (c->free_running) { -diff --git a/config.c b/config.c -index b19f3ad..7bb949d 100644 ---- a/config.c -+++ b/config.c -@@ -237,6 +237,7 @@ struct config_item config_tab[] = { - GLOB_ITEM_STR("uds_address", "/var/run/ptp4l"), - GLOB_ITEM_INT("use_syslog", 1, 0, 1), - GLOB_ITEM_STR("userDescription", ""), -+ GLOB_ITEM_INT("utc_offset", CURRENT_UTC_OFFSET, 0, INT_MAX), - GLOB_ITEM_INT("verbose", 0, 0, 1), - }; - -diff --git a/default.cfg b/default.cfg -index 12542c0..ebb263a 100644 ---- a/default.cfg -+++ b/default.cfg -@@ -7,6 +7,7 @@ slaveOnly 0 - priority1 128 - priority2 128 - domainNumber 0 -+#utc_offset 37 - clockClass 248 - clockAccuracy 0xFE - offsetScaledLogVariance 0xFFFF -diff --git a/gPTP.cfg b/gPTP.cfg -index 75e996c..142996a 100644 ---- a/gPTP.cfg -+++ b/gPTP.cfg -@@ -7,6 +7,7 @@ gmCapable 1 - priority1 248 - priority2 248 - domainNumber 0 -+#utc_offset 37 - clockClass 248 - clockAccuracy 0xFE - offsetScaledLogVariance 0xFFFF -diff --git a/ptp4l.8 b/ptp4l.8 -index f53fc6e..53d5f28 100644 ---- a/ptp4l.8 -+++ b/ptp4l.8 -@@ -327,6 +327,10 @@ The default is 0xFFFF. - The domain attribute of the local clock. - The default is 0. - .TP -+.B utc_offset -+The current offset between TAI and UTC. -+The default is 37. -+.TP - .B free_running - Don't adjust the local clock if enabled. - The default is 0 (disabled). diff --git a/SPECS/linuxptp.spec b/SPECS/linuxptp.spec index e03e295..3f91582 100644 --- a/SPECS/linuxptp.spec +++ b/SPECS/linuxptp.spec @@ -1,9 +1,9 @@ %global _hardened_build 1 -%global testsuite_ver 502e82 -%global clknetsim_ver ce89a1 +%global testsuite_ver a7f6e1 +%global clknetsim_ver 8b4842 Name: linuxptp -Version: 1.8 -Release: 6%{?dist} +Version: 2.0 +Release: 2%{?dist} Summary: PTP implementation for Linux Group: System Environment/Base @@ -20,33 +20,22 @@ Source10: https://github.com/mlichvar/linuxptp-testsuite/archive/%{testsuite_ver # simulator for test suite Source11: https://github.com/mlichvar/clknetsim/archive/%{clknetsim_ver}/clknetsim-%{clknetsim_ver}.tar.gz -# update default TAI-UTC offset and make it configurable -Patch1: linuxptp-utcoffset.patch -# add options to tag ptp4l/phc2sys log messages and use them in timemaster -Patch2: linuxptp-messagetag.patch -# check support for SW timestamping in timemaster -Patch3: linuxptp-swtscheck.patch -# fix leaks of sockets in error handling -Patch4: linuxptp-closesocket.patch -# update port dispatch code (needed by other patches) -Patch5: linuxptp-portdispatch.patch -# Fix phc2sys to check both the state and new_state variables of the clock -Patch6: linuxptp-statechange.patch -# fix handling of unknown/invalid management TLVs in pmc -Patch7: linuxptp-mgttlv.patch -# add support for IP over InfiniBand -Patch8: linuxptp-ipoib.patch -# force BMC election when link goes down -Patch9: linuxptp-linkdown.patch -# fix phc2sys to not synchronize clock to itself -Patch10: linuxptp-multiport.patch -# add support for active-backup bonding -Patch11: linuxptp-bonding.patch -# don't forward management requests to UDS port -Patch12: linuxptp-udsmgt.patch -# improve timemaster to restart terminated processes -Patch13: linuxptp-tmasterrestart.patch - +# fix building with new kernel headers +Patch1: linuxptp-headers.patch +# fix timeout handling to work with simulated clock +Patch2: linuxptp-timeout.patch +# add support for more accurate synchronization to phc2sys +Patch3: linuxptp-sysoff.patch +# limit unicast message rate per address and grant duration +Patch4: linuxptp-ucastrate.patch +# add support for active-backup team interface +Patch5: linuxptp-team.patch +# fix comparing of unicast addresses +Patch6: linuxptp-addreq.patch +# don't leak memory when allocation fails +Patch7: linuxptp-msgput.patch + +BuildRequires: kernel-headers > 3.10.0-1002 BuildRequires: systemd-units Requires(post): systemd-units @@ -62,19 +51,13 @@ Supporting legacy APIs and other platforms is not a goal. %prep %setup -q -a 10 -a 11 -%patch1 -p1 -b .utcoffset -%patch2 -p1 -b .messagetag -%patch3 -p1 -b .swtscheck -%patch4 -p1 -b .closesocket -%patch5 -p1 -b .portdispatch -%patch6 -p1 -b .statechange -%patch7 -p1 -b .mgttlv -%patch8 -p1 -b .ipoib -%patch9 -p1 -b .linkdown -%patch10 -p1 -b .multiport -%patch11 -p1 -b .bonding -%patch12 -p1 -b .udsmgt -%patch13 -p1 -b .tmasterrestart +%patch1 -p1 -b .headers +%patch2 -p1 -b .timeout +%patch3 -p1 -b .sysoff +%patch4 -p1 -b .ucastrate +%patch5 -p1 -b .team +%patch6 -p1 -b .addreq +%patch7 -p1 -b .msgput mv linuxptp-testsuite-%{testsuite_ver}* testsuite mv clknetsim-%{clknetsim_ver}* testsuite/clknetsim @@ -87,7 +70,7 @@ make %{?_smp_mflags} \ %makeinstall mkdir -p $RPM_BUILD_ROOT{%{_sysconfdir}/sysconfig,%{_unitdir},%{_mandir}/man5} -install -m 644 -p default.cfg $RPM_BUILD_ROOT%{_sysconfdir}/ptp4l.conf +install -m 644 -p configs/default.cfg $RPM_BUILD_ROOT%{_sysconfdir}/ptp4l.conf install -m 644 -p %{SOURCE1} %{SOURCE2} %{SOURCE3} $RPM_BUILD_ROOT%{_unitdir} install -m 644 -p %{SOURCE4} $RPM_BUILD_ROOT%{_sysconfdir} @@ -115,7 +98,7 @@ PATH=..:$PATH ./run %systemd_postun_with_restart phc2sys.service ptp4l.service timemaster.service %files -%doc COPYING README.org default.cfg gPTP.cfg +%doc COPYING README.org configs %config(noreplace) %{_sysconfdir}/ptp4l.conf %config(noreplace) %{_sysconfdir}/sysconfig/phc2sys %config(noreplace) %{_sysconfdir}/sysconfig/ptp4l @@ -124,6 +107,7 @@ PATH=..:$PATH ./run %{_unitdir}/ptp4l.service %{_unitdir}/timemaster.service %{_sbindir}/hwstamp_ctl +%{_sbindir}/nsm %{_sbindir}/phc2sys %{_sbindir}/phc_ctl %{_sbindir}/pmc @@ -133,6 +117,16 @@ PATH=..:$PATH ./run %{_mandir}/man8/*.8* %changelog +* Tue Mar 26 2019 Miroslav Lichvar 2.0-2 +- fix comparing of unicast addresses +- don't leak memory when allocation fails + +* Thu Mar 21 2019 Miroslav Lichvar 2.0-1 +- update to 2.0 (#1623919) +- add support for more accurate synchronization to phc2sys (#1643977) +- add support for active-backup team interface (#1650672) +- limit unicast message rate per address and grant duration + * Wed May 30 2018 Miroslav Lichvar 1.8-6 - add support for bonding to timemaster (#1549015) - improve timemaster to restart terminated processes (#1527170)