From b53c25fa7c6253ae54b52e987fb512cc51559409 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Wed, 28 May 2025 10:51:05 +0200 Subject: [PATCH] fix unicast server to recover after port fault (RHEL-93497) Resolves: RHEL-93497 --- linuxptp-unirecover.patch | 104 ++++++++++++++++++++++++++++++++++++++ linuxptp.spec | 2 + 2 files changed, 106 insertions(+) create mode 100644 linuxptp-unirecover.patch diff --git a/linuxptp-unirecover.patch b/linuxptp-unirecover.patch new file mode 100644 index 0000000..f3f2bf7 --- /dev/null +++ b/linuxptp-unirecover.patch @@ -0,0 +1,104 @@ +commit 71241f3fdcff59b35ad5de0b8b37cb07a4b677bd +Author: Vincent Cheng +Date: Tue Sep 17 15:23:54 2024 -0400 + + port: Fix unicast negotiation doesn't recover after FAULT_DETECTED + + _Problem_ + After a port link down/up or a tx_timestamp timeout issue, a port acting + as unicast master does not issue ANNC messages after granting unicast + request for ANNC. + + _Analysis_ + When a port FAULT occurs, the port transitions to FAULTY on FAULT_DETECTED + and subsequently port_disable(p) and port_initialize(p) are called on port recovery. + + A port acting as a unicast master, stores clients in p->unicast_service->queue. + + When a port receives a unicast request, unicast_service_add() is called. + + In unicast_service_add(), if the request does not match an entry in + p->unicast_service->queue, FD_UNICAST_SRV_TIMER is started via + unicast_service_rearm_timer(). + + If the unicast request matches an existing p->unicast_service->queue entry + the request is considered an extension and FD_UNICAST_SRV_TIMER must + already be running. + + port_disable() clears FD_UNICAST_SRV_TIMER, ie. stops FD_UNICAST_SRV_TIMER. + However, port_disable() does not clear p->unicast_service->queue. + When the port is restarted, the port retains the previous client data. + + After port recovery, when the client attempts to restart the unicast + service, the request matches an existing entry in p->unicast_service->queue, + and so FD_UNICAST_SRV_TIMER is not started because the port expected + that the FD_UNICAST_SRV_TIMER is already running. + + _Fix_ + This patch clears the unicast client data in port_disable() so + that upon recovery, the initial unicast request will be considered + a new request and trigger the start of the FD_UNICAST_SRV_TIMER. + + v2: + - Add missing sign-off + - Send to develop-request instead of users list + + Signed-off-by: Vincent Cheng + +diff --git a/port.c b/port.c +index 1bb407c..90b0860 100644 +--- a/port.c ++++ b/port.c +@@ -1999,6 +1999,7 @@ void port_disable(struct port *p) + flush_peer_delay(p); + + p->best = NULL; ++ unicast_service_clear_clients(p); + free_foreign_masters(p); + transport_close(p->trp, &p->fda); + +diff --git a/unicast_service.c b/unicast_service.c +index 2fc2fbe..cee6691 100644 +--- a/unicast_service.c ++++ b/unicast_service.c +@@ -583,3 +583,24 @@ int unicast_service_timer(struct port *p) + } + return err; + } ++ ++void unicast_service_clear_clients(struct port *p) ++{ ++ struct unicast_client_address *client, *temp; ++ struct unicast_service_interval *interval; ++ ++ if (!p->unicast_service) { ++ return; ++ } ++ ++ while ((interval = pqueue_extract(p->unicast_service->queue)) != NULL) { ++ ++ LIST_REMOVE(interval, list); ++ ++ LIST_FOREACH_SAFE(client, &interval->clients, list, temp) { ++ LIST_REMOVE(client, list); ++ free(client); ++ } ++ free(interval); ++ } ++} +\ No newline at end of file +diff --git a/unicast_service.h b/unicast_service.h +index f0d6487..8ea1a59 100644 +--- a/unicast_service.h ++++ b/unicast_service.h +@@ -87,4 +87,10 @@ void unicast_service_remove(struct port *p, struct ptp_message *m, + */ + int unicast_service_timer(struct port *p); + ++/** ++ * Clears unicast clients on a given port. ++ * @param p The port in question. ++ */ ++void unicast_service_clear_clients(struct port *p); ++ + #endif diff --git a/linuxptp.spec b/linuxptp.spec index 02e817f..3ebf7d2 100644 --- a/linuxptp.spec +++ b/linuxptp.spec @@ -41,6 +41,8 @@ Patch8: linuxptp-externalpps.patch Patch9: linuxptp-externalgm.patch # refresh link status on faults Patch10: linuxptp-rtnlinit.patch +# fix unicast server to recover after port fault +Patch11: linuxptp-unirecover.patch BuildRequires: gcc gcc-c++ gnutls-devel make systemd