From c5d125c9d015bf07ec7c579aa27ef724999c0b35 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Tue, 6 May 2025 10:16:30 +0200 Subject: [PATCH] refresh link status on faults (RHEL-89811) Resolves: RHEL-89811 --- linuxptp-rtnlinit.patch | 75 +++++++++++++++++++++++++++++++++++++++++ linuxptp.spec | 2 ++ 2 files changed, 77 insertions(+) create mode 100644 linuxptp-rtnlinit.patch diff --git a/linuxptp-rtnlinit.patch b/linuxptp-rtnlinit.patch new file mode 100644 index 0000000..60e011d --- /dev/null +++ b/linuxptp-rtnlinit.patch @@ -0,0 +1,75 @@ +commit 01de33e91f9717d0cbae5af6eee2beb45deee219 +Author: Miroslav Lichvar +Date: Tue Mar 4 15:53:37 2025 +0100 + + port: Refresh link status on faults. + + ptp4l gets the ENOBUFS error on the netlink socket when the kernel has + to drop messages due to full socket buffer. If ptp4l has a port in the + faulty state waiting for the link to go up and that event corresponds + to one of the dropped netlink messages, the port will be stuck in the + faulty state until the link goes down and up again. + + To prevent the port from getting stuck, request the current link status + when dispatching the EV_FAULT_DETECTED event. Also, reopen the socket to + get rid of the buffered messages when handling the fault and again when + reinitializing the port. + + Signed-off-by: Miroslav Lichvar + Reviewed-by: Jacob Keller + +diff --git a/port.c b/port.c +index 7f945ac..1bb407c 100644 +--- a/port.c ++++ b/port.c +@@ -1975,6 +1975,20 @@ static int port_cmlds_initialize(struct port *p) + return port_cmlds_renew(p, now.tv_sec); + } + ++static void port_rtnl_initialize(struct port *p) ++{ ++ /* Reopen the socket to get rid of buffered messages */ ++ if (p->fda.fd[FD_RTNL] >= 0) { ++ rtnl_close(p->fda.fd[FD_RTNL]); ++ } ++ p->fda.fd[FD_RTNL] = rtnl_open(); ++ if (p->fda.fd[FD_RTNL] >= 0) { ++ rtnl_link_query(p->fda.fd[FD_RTNL], interface_name(p->iface)); ++ } ++ ++ clock_fda_changed(p->clock); ++} ++ + void port_disable(struct port *p) + { + int i; +@@ -2087,13 +2101,8 @@ int port_initialize(struct port *p) + if (p->bmca == BMCA_NOOP) { + port_set_delay_tmo(p); + } +- if (p->fda.fd[FD_RTNL] == -1) { +- p->fda.fd[FD_RTNL] = rtnl_open(); +- } +- if (p->fda.fd[FD_RTNL] >= 0) { +- const char *ifname = interface_name(p->iface); +- rtnl_link_query(p->fda.fd[FD_RTNL], ifname); +- } ++ ++ port_rtnl_initialize(p); + } + + port_nrate_initialize(p); +@@ -3768,6 +3777,13 @@ int port_state_update(struct port *p, enum fsm_event event, int mdiff) + if (port_link_status_get(p) && clear_fault_asap(&i)) { + pr_notice("%s: clearing fault immediately", p->log_name); + next = p->state_machine(next, EV_FAULT_CLEARED, 0); ++ } else if (event == EV_FAULT_DETECTED) { ++ /* ++ * Reopen the netlink socket and refresh the link ++ * status in case the fault was triggered by a missed ++ * netlink message (ENOBUFS). ++ */ ++ port_rtnl_initialize(p); + } + } + diff --git a/linuxptp.spec b/linuxptp.spec index 9968d6f..c6f22ec 100644 --- a/linuxptp.spec +++ b/linuxptp.spec @@ -39,6 +39,8 @@ Patch4: linuxptp-nowait.patch Patch8: linuxptp-externalpps.patch # add command to set external grandmaster properties Patch9: linuxptp-externalgm.patch +# refresh link status on faults +Patch10: linuxptp-rtnlinit.patch BuildRequires: gcc gcc-c++ gnutls-devel make systemd