linuxptp/linuxptp-rtnlinit.patch
2026-07-02 08:50:29 +02:00

109 lines
3.7 KiB
Diff

commit 01de33e91f9717d0cbae5af6eee2beb45deee219
Author: Miroslav Lichvar <mlichvar@redhat.com>
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 <mlichvar@redhat.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
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);
}
}
commit 84c2d7f4ef7c0ff9353909194ae03e5a09aa0a12
Author: Miroslav Lichvar (via linuxptp-devel Mailing List) <linuxptp-devel@lists.nwtime.org>
Date: Mon May 4 15:32:46 2026 +0200
port: Don't request sde on repeated link down event.
When the link goes down, request a state decision event only when the
link status actually changed (the same status can be received multiple
times due to unrelated events or refresh).
This fixes an infinite loop when the link is down and BMCA is set to
"noop" due to bmc_state_decision() copying the FAULTY state and
causing port_dispatch() to be called with EV_FAULT_DETECTED, which
triggers an rntl_link_status() call. The netlink response (with no
change in the link status) no longer forces a new state decision event.
Fixes: a1eae149f519 ("port: Refresh link status on faults.")
Reported-by: Martin Pecka <peckama2@fel.cvut.cz>
Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
diff --git a/port.c b/port.c
index 90b0860..05aabea 100644
--- a/port.c
+++ b/port.c
@@ -3042,7 +3042,7 @@ void port_link_status(void *ctx, int linkup, int ts_index)
* A port going down can affect the BMCA result.
* Force a state decision event.
*/
- if (p->link_status & LINK_DOWN)
+ if (p->link_status & LINK_STATE_CHANGED && p->link_status & LINK_DOWN)
clock_set_sde(p->clock, 1);
}