clock, port: Fix BMCA oscillation and duplicate Sync in HSR/PRP mode

Three independent bugs cause a redundant OC slave to fail to sync when
connected to an HSR ring:

1. BMCA flip-flop between ring paths (clock.c):

   The master has two GM ports (portNumber 1 and 2).  HSR frame
   duplication causes every slave port to receive Announce messages from
   both master ports via both the direct path (stepsRemoved=0) and the
   ring path (stepsRemoved=1).  Whichever copy happens to arrive last is
   stored as the active dataset, so stepsRemoved oscillates cycle-by-cycle.
   dscmp2() uses stepsRemoved as a tiebreaker, so the globally-best
   foreign_clock pointer alternates between eth1 and eth2 every Announce
   period, firing "selected best master clock" twice per second and keeping
   the application in perpetual UNCALIBRATED.

   Fix: in handle_state_decision_event(), track whether c->best is still
   returned by any port's port_compute_best() call (current_best_alive).
   If the same grandmaster is still reachable and the current best FC is
   still alive, keep it to prevent stepsRemoved-driven flip-flopping.

2. Rogue PDelayResp causing port FAULTY (port.c):

   HSR duplicates all frames onto both ring legs.  When eth1 completes a
   PDelayReq/PDelayResp exchange, the PDelayResp is also forwarded to
   eth2.  Because eth2 has no pending peer_delay_req for that exchange,
   ptp4l treats the message as a rogue peer delay response and raises a
   FAULT_DETECTED event, forcing eth2 into FAULTY state.

   Fix: in process_pdelay_resp(), when the port is one half of a redundant
   pair (p->paired_port != NULL), silently discard PDelayResp messages
   whose requestingPortIdentity does not match the receiving port's own
   identity.

3. Duplicate Sync updates driving servo instability (port.c):

   HSR duplicates Sync frames onto both ring legs.  The same Sync message
   (same sequenceId) arrives twice on the active slave port with slightly
   different hardware RX timestamps.  Each copy triggers clock_synchronize()
   independently, so the servo runs twice per interval with conflicting t2
   values, producing large oscillating offsets (hundreds of microseconds).

   Fix: in process_sync(), when p->paired_port is set, track the last
   processed Sync sequenceId (last_sync_seqid in port_private.h).  Discard
   any Sync with the same sequenceId as the last accepted one, ensuring
   clock_synchronize() is called exactly once per Sync interval.

Signed-off-by: MD Danish Anwar <danishanwar@ti.com>
3 files changed
tree: 7f4aa40cca0bfe2449c5f1248380af9d2c26ffe6
  1. configs/
  2. .gitignore
  3. address.h
  4. as_capable.h
  5. bmc.c
  6. bmc.h
  7. clock.c
  8. clock.h
  9. clockadj.c
  10. clockadj.h
  11. clockcheck.c
  12. clockcheck.h
  13. CODING_STYLE.org
  14. config.c
  15. config.h
  16. contain.h
  17. COPYING
  18. ddt.h
  19. designated_fsm.c
  20. designated_fsm.h
  21. dm.h
  22. ds.h
  23. e2e_tc.c
  24. ether.h
  25. fault.c
  26. fault.h
  27. fd.h
  28. filter.c
  29. filter.h
  30. filter_private.h
  31. foreign.h
  32. fsm.c
  33. fsm.h
  34. hash.c
  35. hash.h
  36. hwstamp_ctl.8
  37. hwstamp_ctl.c
  38. incdefs.sh
  39. interface.c
  40. interface.h
  41. linreg.c
  42. linreg.h
  43. lstab.c
  44. lstab.h
  45. makefile
  46. mave.c
  47. mave.h
  48. missing.h
  49. mmedian.c
  50. mmedian.h
  51. monitor.c
  52. monitor.h
  53. msg.c
  54. msg.h
  55. mtab.h
  56. nmea.c
  57. nmea.h
  58. notification.h
  59. nsm.8
  60. nsm.c
  61. ntpshm.c
  62. ntpshm.h
  63. nullf.c
  64. nullf.h
  65. p2p_hc.c
  66. p2p_tc.c
  67. pdt.h
  68. phc.c
  69. phc.h
  70. phc2sys.8
  71. phc2sys.c
  72. phc_ctl.8
  73. phc_ctl.c
  74. pi.c
  75. pi.h
  76. pmc.8
  77. pmc.c
  78. pmc_agent.c
  79. pmc_agent.h
  80. pmc_common.c
  81. pmc_common.h
  82. port.c
  83. port.h
  84. port_private.h
  85. port_signaling.c
  86. power_profile.h
  87. pqueue.c
  88. pqueue.h
  89. print.c
  90. print.h
  91. ptp4l.8
  92. ptp4l.c
  93. raw.c
  94. raw.h
  95. README.org
  96. refclock_sock.c
  97. refclock_sock.h
  98. rtnl.c
  99. rtnl.h
  100. sad.c
  101. sad.h
  102. sad_gnupg.c
  103. sad_gnutls.c
  104. sad_nettle.c
  105. sad_openssl.c
  106. sad_private.h
  107. serial.c
  108. serial.h
  109. servo.c
  110. servo.h
  111. servo_private.h
  112. sk.c
  113. sk.h
  114. sock.c
  115. sock.h
  116. stats.c
  117. stats.h
  118. sysoff.c
  119. sysoff.h
  120. tc.c
  121. tc.h
  122. telecom.c
  123. timemaster.8
  124. timemaster.c
  125. tlv.c
  126. tlv.h
  127. tmv.h
  128. transport.c
  129. transport.h
  130. transport_private.h
  131. ts2phc.8
  132. ts2phc.c
  133. ts2phc.h
  134. ts2phc_generic_pps_source.c
  135. ts2phc_generic_pps_source.h
  136. ts2phc_nmea_pps_source.c
  137. ts2phc_nmea_pps_source.h
  138. ts2phc_phc_pps_source.c
  139. ts2phc_phc_pps_source.h
  140. ts2phc_pps_sink.c
  141. ts2phc_pps_sink.h
  142. ts2phc_pps_source.c
  143. ts2phc_pps_source.h
  144. ts2phc_pps_source_private.h
  145. tsproc.c
  146. tsproc.h
  147. tz.h
  148. tz2alt.8
  149. tz2alt.c
  150. udp.c
  151. udp.h
  152. udp6.c
  153. udp6.h
  154. uds.c
  155. uds.h
  156. unicast_client.c
  157. unicast_client.h
  158. unicast_fsm.c
  159. unicast_fsm.h
  160. unicast_service.c
  161. unicast_service.h
  162. util.c
  163. util.h
  164. version.c
  165. version.h
  166. version.sh