This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git

commit 269bdf04408cc831ec647145d0d5195661329456
Author: Daniel P. Carvalho <[email protected]>
AuthorDate: Thu Sep 24 10:33:26 2026 -0300

    netutils/ptpd: query timestamping capabilities via ETHTOOL_GET_TS_INFO
    
    Query interface hardware timestamping capabilities with the SIOCETHTOOL
    ETHTOOL_GET_TS_INFO ioctl during initialization, the same way
    linuxptp/ptp4l does on Linux, instead of detecting support through
    runtime trial and error. If the query itself fails, refuse to start.
    
    Remove the consecutive failure counter (hwts_tx_failures,
    PTP_HWTS_TX_MAX_FAILURES, hwts_tx_disabled). When hardware TX
    timestamping is supported and requested, report genuine runtime timeouts
    as errors (ptperr) instead of silently downgrading to software
    timestamping. Invalidate clock_source_valid in ptpd status while a
    hardware TX timestamp failure persists.
    
    Assisted-by: Gemini:gemini-3.8-pro
    Assisted-by: Claude:claude-sonnet-5
    Signed-off-by: Daniel P. Carvalho <[email protected]>
---
 netutils/ptpd/ptpd.c | 72 ++++++++++++++++++++++++++++++++++------------------
 1 file changed, 47 insertions(+), 25 deletions(-)

diff --git a/netutils/ptpd/ptpd.c b/netutils/ptpd/ptpd.c
index f10606bf5..2c0687f01 100644
--- a/netutils/ptpd/ptpd.c
+++ b/netutils/ptpd/ptpd.c
@@ -59,6 +59,7 @@
 #include <sys/poll.h>
 #include <sys/stat.h>
 #include <nuttx/clock.h>
+#include <nuttx/ethtool.h>
 #include <nuttx/net/netconfig.h>
 #include <netutils/ptpd.h>
 
@@ -69,12 +70,6 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
-/* Number of consecutive missing hardware TX timestamps after which the
- * driver is assumed not to provide them and software timestamps are used.
- */
-
-#define PTP_HWTS_TX_MAX_FAILURES 3
-
 #if CONFIG_NETUTILS_PTPD_OUTLIER_THRESHOLD_NS > 0
 /* Outlier rejection of the measured phase error: number of recent samples
  * the median is taken over, the least number of samples needed before
@@ -122,12 +117,10 @@ struct ptp_state_s
 
   int tx_socket;
 
-  /* Hardware TX timestamp retrieval: consecutive failures, and whether it
-   * was given up on because the driver does not provide the timestamps.
-   */
+  /* Hardware TX timestamp support and health tracking */
 
-  unsigned int hwts_tx_failures;
-  bool hwts_tx_disabled;
+  bool hwts_tx;
+  bool hwts_tx_failed;
 
   /* Sockets for PTP event and information ports */
 
@@ -766,6 +759,41 @@ static int ptp_initialize_state(FAR struct ptp_state_s 
*state)
         }
     }
 
+  /* Query timestamping capabilities */
+
+  state->hwts_tx = false;
+  state->hwts_tx_failed = false;
+#ifdef CONFIG_NET_TIMESTAMP
+  if (state->config->hardware_ts)
+    {
+      struct ethtool_ts_info info;
+
+      memset(&info, 0, sizeof(info));
+      info.cmd = ETHTOOL_GET_TS_INFO;
+
+      memset(&req, 0, sizeof(req));
+      strlcpy(req.ifr_name, state->config->interface, sizeof(req.ifr_name));
+      req.ifr_data = &info;
+
+      ret = ioctl(state->event_socket, SIOCETHTOOL, (unsigned long)&req);
+      if (ret < 0)
+        {
+          ptperr("ETHTOOL_GET_TS_INFO failed for %s: %d\n",
+                 state->config->interface, errno);
+          return ERROR;
+        }
+      else if ((info.so_timestamping & SOF_TIMESTAMPING_TX_HARDWARE) == 0)
+        {
+          ptpwarn("Interface %s does not support hardware TX timestamping\n",
+                  state->config->interface);
+        }
+      else
+        {
+          state->hwts_tx = true;
+        }
+    }
+#endif
+
   /* Get address information of the specified interface for binding socket
    * Only supports IPv4 currently.
    */
@@ -1006,8 +1034,7 @@ static int ptp_sendmsg(FAR struct ptp_state_s *state, FAR 
const void *buf,
   int ret;
   struct timespec sw_ts;
 #ifdef CONFIG_NET_TIMESTAMP
-  bool do_hwts = (sendts != NULL && state->config->hardware_ts &&
-                  !state->hwts_tx_disabled &&
+  bool do_hwts = (sendts != NULL && state->hwts_tx &&
                   state->config->af == AF_PACKET);
 #endif
 
@@ -1127,7 +1154,7 @@ static int ptp_sendmsg(FAR struct ptp_state_s *state, FAR 
const void *buf,
 
           if (ptp_get_tx_timestamp(state, sendts) == OK)
             {
-              state->hwts_tx_failures = 0;
+              state->hwts_tx_failed = false;
 
               /* The frame reaches the wire later than the MAC latches the
                * timestamp: compensate the egress latency.
@@ -1137,17 +1164,11 @@ static int ptp_sendmsg(FAR struct ptp_state_s *state, 
FAR const void *buf,
             }
           else
             {
-              ptpwarn("PTP TX HWTS timeout, fallback to SW ts: "
-                      "%jd.%09ld s\n",
-                      (intmax_t)sw_ts.tv_sec, sw_ts.tv_nsec);
+              state->hwts_tx_failed = true;
+              ptperr("ERROR: PTP TX HWTS timeout, fallback to SW ts: "
+                     "%jd.%09ld s\n",
+                     (intmax_t)sw_ts.tv_sec, sw_ts.tv_nsec);
               *sendts = sw_ts;
-
-              if (++state->hwts_tx_failures >= PTP_HWTS_TX_MAX_FAILURES)
-                {
-                  state->hwts_tx_disabled = true;
-                  ptpwarn("Hardware TX timestamps unavailable, "
-                          "using software timestamps\n");
-                }
             }
 
           setsockopt(state->tx_socket, SOL_SOCKET, SO_TIMESTAMPING,
@@ -2321,7 +2342,8 @@ static void ptp_populate_status(FAR struct ptp_state_s 
*state,
                                 FAR struct ptpd_status_s *status)
 {
   memset(status, 0, sizeof(*status));
-  status->clock_source_valid = state->selected_source_valid;
+  status->clock_source_valid = state->selected_source_valid &&
+                               !state->hwts_tx_failed;
 
   if (status->clock_source_valid)
     {

Reply via email to