xiaoxiang781216 commented on code in PR #3782:
URL: https://github.com/apache/nuttx-apps/pull/3782#discussion_r4017567122


##########
netutils/ptpd/ptpd.c:
##########
@@ -1349,14 +1474,53 @@ static int ptp_process_delay_req(FAR struct ptp_state_s 
*state,
   return ret;
 }
 
+/* Record and filter measured path delay (used by both E2E and P2P) */
+
+static void ptp_record_path_delay(FAR struct ptp_state_s *state,
+                                  int64_t path_delay)
+{
+  int64_t max_path_delay;
+
+  max_path_delay = CONFIG_NETUTILS_PTPD_MAX_PATH_DELAY_NS;

Review Comment:
   merge with line 1482



##########
netutils/ptpd/ptpd.c:
##########
@@ -861,7 +861,25 @@ static int ptp_sendmsg(FAR struct ptp_state_s *state, FAR 
const void *buf,
 
   if (sendts != NULL)
     {
+#ifdef SIOCG_TX_HW_TIMESTAMP
+      struct ifreq req;
+      int ret_ts;
+
+      memset(&req, 0, sizeof(req));
+      strlcpy(req.ifr_name, state->config->interface, sizeof(req.ifr_name));
+      req.ifr_data = sendts;
+
+      ret_ts = ioctl(state->tx_socket, SIOCG_TX_HW_TIMESTAMP,
+                     (unsigned long)&req);
+      if (ret_ts < 0)

Review Comment:
   `if (ioct(...) < 0)` and remove line 866



##########
netutils/ptpd/ptpd.c:
##########
@@ -1349,14 +1474,53 @@ static int ptp_process_delay_req(FAR struct ptp_state_s 
*state,
   return ret;
 }
 
+/* Record and filter measured path delay (used by both E2E and P2P) */
+
+static void ptp_record_path_delay(FAR struct ptp_state_s *state,
+                                  int64_t path_delay)
+{
+  int64_t max_path_delay;
+
+  max_path_delay = CONFIG_NETUTILS_PTPD_MAX_PATH_DELAY_NS;
+
+  if (max_path_delay < 10 * (int64_t)NSEC_PER_MSEC)
+    {
+      /* Software TX latency on delay measurement transmission can add up
+       * to several milliseconds. Allow up to 10 ms until hardware TX
+       * timestamping is available.
+       */
+
+      max_path_delay = 10 * (int64_t)NSEC_PER_MSEC;
+    }
+
+  if (path_delay >= 0 && path_delay < max_path_delay)
+    {
+      if (state->path_delay_avgcount <
+          CONFIG_NETUTILS_PTPD_DELAYREQ_AVGCOUNT)
+        {
+          state->path_delay_avgcount++;
+        }
+
+      state->path_delay_ns += (path_delay - state->path_delay_ns)
+                              / state->path_delay_avgcount;
+
+      ptpinfo("Path delay: %ld ns (avg: %ld ns)\n",
+              (long)path_delay, (long)state->path_delay_ns);

Review Comment:
   remove all cast



##########
netutils/ptpd/ptpd.c:
##########
@@ -1349,14 +1474,53 @@ static int ptp_process_delay_req(FAR struct ptp_state_s 
*state,
   return ret;
 }
 
+/* Record and filter measured path delay (used by both E2E and P2P) */
+
+static void ptp_record_path_delay(FAR struct ptp_state_s *state,
+                                  int64_t path_delay)
+{
+  int64_t max_path_delay;
+
+  max_path_delay = CONFIG_NETUTILS_PTPD_MAX_PATH_DELAY_NS;
+
+  if (max_path_delay < 10 * (int64_t)NSEC_PER_MSEC)
+    {
+      /* Software TX latency on delay measurement transmission can add up
+       * to several milliseconds. Allow up to 10 ms until hardware TX
+       * timestamping is available.
+       */
+
+      max_path_delay = 10 * (int64_t)NSEC_PER_MSEC;
+    }
+
+  if (path_delay >= 0 && path_delay < max_path_delay)
+    {
+      if (state->path_delay_avgcount <
+          CONFIG_NETUTILS_PTPD_DELAYREQ_AVGCOUNT)
+        {
+          state->path_delay_avgcount++;
+        }
+
+      state->path_delay_ns += (path_delay - state->path_delay_ns)
+                              / state->path_delay_avgcount;
+
+      ptpinfo("Path delay: %ld ns (avg: %ld ns)\n",
+              (long)path_delay, (long)state->path_delay_ns);
+    }
+  else
+    {
+      ptpwarn("Path delay out of range: %lld ns\n",
+              (long long)path_delay);

Review Comment:
   remove too



##########
netutils/ptpd/ptpd.c:
##########
@@ -1349,14 +1474,53 @@ static int ptp_process_delay_req(FAR struct ptp_state_s 
*state,
   return ret;
 }
 
+/* Record and filter measured path delay (used by both E2E and P2P) */
+
+static void ptp_record_path_delay(FAR struct ptp_state_s *state,
+                                  int64_t path_delay)
+{
+  int64_t max_path_delay;
+
+  max_path_delay = CONFIG_NETUTILS_PTPD_MAX_PATH_DELAY_NS;
+
+  if (max_path_delay < 10 * (int64_t)NSEC_PER_MSEC)
+    {
+      /* Software TX latency on delay measurement transmission can add up
+       * to several milliseconds. Allow up to 10 ms until hardware TX
+       * timestamping is available.
+       */
+
+      max_path_delay = 10 * (int64_t)NSEC_PER_MSEC;
+    }
+
+  if (path_delay >= 0 && path_delay < max_path_delay)
+    {
+      if (state->path_delay_avgcount <
+          CONFIG_NETUTILS_PTPD_DELAYREQ_AVGCOUNT)

Review Comment:
   merge into one line



##########
netutils/ptpd/ptpd.c:
##########
@@ -1395,52 +1559,218 @@ static int ptp_process_delay_resp(FAR struct 
ptp_state_s *state,
   path_delay = timespec_delta_ns(&remote_rxtime, &state->delayreq_time);
   path_delay = (state->sync_diff_ns + path_delay) / 2;
 
-  max_path_delay = CONFIG_NETUTILS_PTPD_MAX_PATH_DELAY_NS;
+  ptp_record_path_delay(state, path_delay);
 
-  if (max_path_delay < 10 * (int64_t)NSEC_PER_MSEC)
+  /* Calculate interval until next packet */
+
+  if (msg->header.logmessageinterval <= 12)
     {
-      /* Software TX latency on Delay_Req transmission can add up to
-       * several milliseconds. Allow up to 10 ms until hardware TX
-       * timestamping is available.
-       */
+      interval = (1 << msg->header.logmessageinterval);
+    }
+  else
+    {
+      interval = 4096; /* Refuse to obey excessively long intervals */
+    }
 
-      max_path_delay = 10 * (int64_t)NSEC_PER_MSEC;
+  /* Randomize up to 2x nominal delay) */
+
+  state->delayreq_interval = interval + (random() % interval);
+
+  return OK;
+}
+
+/* Process received peer delay request (responder role) */
+
+static int ptp_process_pdelay_req(FAR struct ptp_state_s *state,
+                                  FAR struct ptp_pdelay_req_s *msg)
+{
+  struct ptp_pdelay_resp_s resp;
+  struct ptp_pdelay_resp_follow_up_s fup;
+  struct sockaddr_in addr;
+  struct timespec t3;
+  int ret;
+
+  if (state->config->delay_mechanism != PTP_DELAY_P2P)
+    {
+      return OK;
     }
 
-  if (path_delay >= 0 && path_delay < max_path_delay)
+  addr.sin_family      = AF_INET;
+  addr.sin_addr.s_addr = HTONL(PTP_PDELAY_MULTICAST_ADDR);
+  addr.sin_port        = HTONS(PTP_UDP_PORT_EVENT);
+
+  memset(&resp, 0, sizeof(resp));
+  resp.header = state->own_identity.header;
+  resp.header.messagetype = PTP_MSGTYPE_PDELAY_RESP;
+  resp.header.messagelength[1] = sizeof(resp);
+  resp.header.flags[0] = PTP_FLAGS0_TWOSTEP;
+  memcpy(resp.header.sequenceid, msg->header.sequenceid,
+         sizeof(resp.header.sequenceid));
+  resp.header.logmessageinterval = 0x7f;
+
+  timespec_to_ptp_format(&state->rxtime, resp.requestreceipttimestamp);
+  memcpy(resp.reqidentity, msg->header.sourceidentity,
+         sizeof(resp.reqidentity));
+  memcpy(resp.reqportindex, msg->header.sourceportindex,
+         sizeof(resp.reqportindex));
+
+  ret = ptp_sendmsg(state, &resp, sizeof(resp), &addr, sizeof(addr), &t3);
+  if (ret < 0)
     {
-      if (state->path_delay_avgcount <
-          CONFIG_NETUTILS_PTPD_DELAYREQ_AVGCOUNT)
-        {
-          state->path_delay_avgcount++;
-        }
+      ptperr("ptp sendmsg failed for Pdelay_Resp: %d\n", errno);
+      return ret;
+    }
 
-      state->path_delay_ns += (path_delay - state->path_delay_ns)
-                              / state->path_delay_avgcount;
+  clock_gettime(CLOCK_MONOTONIC, &state->last_transmitted_delayresp);
+  ptpinfo("Sent Pdelay_Resp, seq %d\n",
+          ptp_get_sequence(&resp.header));
 
-      ptpinfo("Path delay: %ld ns (avg: %ld ns)\n",
-        (long)path_delay, (long)state->path_delay_ns);
+  /* Send Pdelay_Resp_Follow_Up with transmit timestamp t3 */
+
+  addr.sin_port = HTONS(PTP_UDP_PORT_INFO);
+
+  memset(&fup, 0, sizeof(fup));
+  fup.header = state->own_identity.header;
+  fup.header.messagetype = PTP_MSGTYPE_PDELAY_RESP_FOLLOW_UP;
+  fup.header.messagelength[1] = sizeof(fup);
+  memcpy(fup.header.sequenceid, msg->header.sequenceid,
+         sizeof(fup.header.sequenceid));
+  fup.header.logmessageinterval = 0x7f;
+
+  timespec_to_ptp_format(&t3, fup.responseorigintimestamp);
+  memcpy(fup.reqidentity, msg->header.sourceidentity,
+         sizeof(fup.reqidentity));
+  memcpy(fup.reqportindex, msg->header.sourceportindex,
+         sizeof(fup.reqportindex));
+
+  ret = ptp_sendmsg(state, &fup, sizeof(fup), &addr, sizeof(addr), NULL);
+  if (ret < 0)
+    {
+      ptperr("ptp sendmsg failed for Pdelay_Resp_Follow_Up: %d\n", errno);
+      return ret;
     }
-  else
+
+  ptpinfo("Sent Pdelay_Resp_Follow_Up, seq %d\n",
+          ptp_get_sequence(&fup.header));
+
+  return OK;
+}
+
+/* Process received peer delay response (requester role) */
+
+static int ptp_process_pdelay_resp(FAR struct ptp_state_s *state,
+                                   FAR struct ptp_pdelay_resp_s *msg)
+{
+  uint16_t sequence;
+
+  if (state->config->delay_mechanism != PTP_DELAY_P2P)
     {
-      ptpwarn("Path delay out of range: %lld ns\n",
-              (long long)path_delay);
+      return OK;
     }
 
-  /* Calculate interval until next packet */
+  if (memcmp(msg->reqidentity, state->own_identity.header.sourceidentity,
+             sizeof(msg->reqidentity)) != 0)
+    {
+      return OK; /* Not for us */
+    }
 
-  if (msg->header.logmessageinterval <= 12)
+  sequence = ptp_get_sequence(&msg->header);
+  if (sequence != state->pdelay_req_seq)
     {
-      interval = (1 << msg->header.logmessageinterval);
+      ptpwarn("Ignoring out-of-sequence Pdelay_Resp (%d vs. expected %d)\n",
+              (int)sequence, (int)state->pdelay_req_seq);

Review Comment:
   remove the cast



##########
netutils/ptpd/ptpd.c:
##########
@@ -1395,52 +1559,218 @@ static int ptp_process_delay_resp(FAR struct 
ptp_state_s *state,
   path_delay = timespec_delta_ns(&remote_rxtime, &state->delayreq_time);
   path_delay = (state->sync_diff_ns + path_delay) / 2;
 
-  max_path_delay = CONFIG_NETUTILS_PTPD_MAX_PATH_DELAY_NS;
+  ptp_record_path_delay(state, path_delay);
 
-  if (max_path_delay < 10 * (int64_t)NSEC_PER_MSEC)
+  /* Calculate interval until next packet */
+
+  if (msg->header.logmessageinterval <= 12)
     {
-      /* Software TX latency on Delay_Req transmission can add up to
-       * several milliseconds. Allow up to 10 ms until hardware TX
-       * timestamping is available.
-       */
+      interval = (1 << msg->header.logmessageinterval);
+    }
+  else
+    {
+      interval = 4096; /* Refuse to obey excessively long intervals */
+    }
 
-      max_path_delay = 10 * (int64_t)NSEC_PER_MSEC;
+  /* Randomize up to 2x nominal delay) */
+
+  state->delayreq_interval = interval + (random() % interval);
+
+  return OK;
+}
+
+/* Process received peer delay request (responder role) */
+
+static int ptp_process_pdelay_req(FAR struct ptp_state_s *state,
+                                  FAR struct ptp_pdelay_req_s *msg)
+{
+  struct ptp_pdelay_resp_s resp;
+  struct ptp_pdelay_resp_follow_up_s fup;
+  struct sockaddr_in addr;
+  struct timespec t3;
+  int ret;
+
+  if (state->config->delay_mechanism != PTP_DELAY_P2P)
+    {
+      return OK;
     }
 
-  if (path_delay >= 0 && path_delay < max_path_delay)
+  addr.sin_family      = AF_INET;
+  addr.sin_addr.s_addr = HTONL(PTP_PDELAY_MULTICAST_ADDR);
+  addr.sin_port        = HTONS(PTP_UDP_PORT_EVENT);
+
+  memset(&resp, 0, sizeof(resp));
+  resp.header = state->own_identity.header;
+  resp.header.messagetype = PTP_MSGTYPE_PDELAY_RESP;
+  resp.header.messagelength[1] = sizeof(resp);
+  resp.header.flags[0] = PTP_FLAGS0_TWOSTEP;
+  memcpy(resp.header.sequenceid, msg->header.sequenceid,
+         sizeof(resp.header.sequenceid));
+  resp.header.logmessageinterval = 0x7f;
+
+  timespec_to_ptp_format(&state->rxtime, resp.requestreceipttimestamp);
+  memcpy(resp.reqidentity, msg->header.sourceidentity,
+         sizeof(resp.reqidentity));
+  memcpy(resp.reqportindex, msg->header.sourceportindex,
+         sizeof(resp.reqportindex));
+
+  ret = ptp_sendmsg(state, &resp, sizeof(resp), &addr, sizeof(addr), &t3);
+  if (ret < 0)
     {
-      if (state->path_delay_avgcount <
-          CONFIG_NETUTILS_PTPD_DELAYREQ_AVGCOUNT)
-        {
-          state->path_delay_avgcount++;
-        }
+      ptperr("ptp sendmsg failed for Pdelay_Resp: %d\n", errno);
+      return ret;
+    }
 
-      state->path_delay_ns += (path_delay - state->path_delay_ns)
-                              / state->path_delay_avgcount;
+  clock_gettime(CLOCK_MONOTONIC, &state->last_transmitted_delayresp);
+  ptpinfo("Sent Pdelay_Resp, seq %d\n",
+          ptp_get_sequence(&resp.header));
 
-      ptpinfo("Path delay: %ld ns (avg: %ld ns)\n",
-        (long)path_delay, (long)state->path_delay_ns);
+  /* Send Pdelay_Resp_Follow_Up with transmit timestamp t3 */
+
+  addr.sin_port = HTONS(PTP_UDP_PORT_INFO);
+
+  memset(&fup, 0, sizeof(fup));
+  fup.header = state->own_identity.header;
+  fup.header.messagetype = PTP_MSGTYPE_PDELAY_RESP_FOLLOW_UP;
+  fup.header.messagelength[1] = sizeof(fup);
+  memcpy(fup.header.sequenceid, msg->header.sequenceid,
+         sizeof(fup.header.sequenceid));
+  fup.header.logmessageinterval = 0x7f;
+
+  timespec_to_ptp_format(&t3, fup.responseorigintimestamp);
+  memcpy(fup.reqidentity, msg->header.sourceidentity,
+         sizeof(fup.reqidentity));
+  memcpy(fup.reqportindex, msg->header.sourceportindex,
+         sizeof(fup.reqportindex));
+
+  ret = ptp_sendmsg(state, &fup, sizeof(fup), &addr, sizeof(addr), NULL);
+  if (ret < 0)
+    {
+      ptperr("ptp sendmsg failed for Pdelay_Resp_Follow_Up: %d\n", errno);
+      return ret;
     }
-  else
+
+  ptpinfo("Sent Pdelay_Resp_Follow_Up, seq %d\n",
+          ptp_get_sequence(&fup.header));
+
+  return OK;
+}
+
+/* Process received peer delay response (requester role) */
+
+static int ptp_process_pdelay_resp(FAR struct ptp_state_s *state,
+                                   FAR struct ptp_pdelay_resp_s *msg)
+{
+  uint16_t sequence;
+
+  if (state->config->delay_mechanism != PTP_DELAY_P2P)
     {
-      ptpwarn("Path delay out of range: %lld ns\n",
-              (long long)path_delay);
+      return OK;
     }
 
-  /* Calculate interval until next packet */
+  if (memcmp(msg->reqidentity, state->own_identity.header.sourceidentity,
+             sizeof(msg->reqidentity)) != 0)
+    {
+      return OK; /* Not for us */
+    }
 
-  if (msg->header.logmessageinterval <= 12)
+  sequence = ptp_get_sequence(&msg->header);
+  if (sequence != state->pdelay_req_seq)
     {
-      interval = (1 << msg->header.logmessageinterval);
+      ptpwarn("Ignoring out-of-sequence Pdelay_Resp (%d vs. expected %d)\n",
+              (int)sequence, (int)state->pdelay_req_seq);
+      return OK;
+    }
+
+  /* Store t4 (local receive timestamp) and t2 (receipt timestamp
+   * from peer).
+   */
+
+  state->pdelayresp_rx_time = state->rxtime;
+  ptp_format_to_timespec(msg->requestreceipttimestamp,
+                         &state->pdelayreq_rx_time);
+  ptp_add_correction_time(msg->header.correction,
+                          &state->pdelayreq_rx_time);
+
+  if (msg->header.flags[0] & PTP_FLAGS0_TWOSTEP)
+    {
+      state->pdelay_waiting_followup = true;
+      ptpinfo("Waiting for Pdelay_Resp_Follow_Up, seq %d\n",
+              (int)sequence);
     }
   else
     {
-      interval = 4096; /* Refuse to obey excessively long intervals */
+      /* One-step: turnaround time (t3 - t2) is carried in correctionField */
+
+      int64_t t4_t1_ns;
+      int64_t t3_t2_ns;
+      int64_t path_delay;
+      uint64_t correction_time;
+
+      correction_time = (((uint64_t)msg->header.correction[0]) << 40)
+                      | (((uint64_t)msg->header.correction[1]) << 32)
+                      | (((uint64_t)msg->header.correction[2]) << 24)
+                      | (((uint64_t)msg->header.correction[3]) << 16)
+                      | (((uint64_t)msg->header.correction[4]) <<  8)
+                      | (((uint64_t)msg->header.correction[5]) <<  0);
+
+      t4_t1_ns = timespec_delta_ns(&state->pdelayresp_rx_time,
+                                   &state->pdelayreq_tx_time);
+      t3_t2_ns = (int64_t)correction_time;
+      path_delay = (t4_t1_ns - t3_t2_ns) / 2;
+
+      ptp_record_path_delay(state, path_delay);
     }
 
-  /* Randomize up to 2x nominal delay) */
+  return OK;
+}
 
-  state->delayreq_interval = interval + (random() % interval);
+/* Process received peer delay response follow-up (requester role) */
+
+static int ptp_process_pdelay_resp_followup(
+             FAR struct ptp_state_s *state,
+             FAR struct ptp_pdelay_resp_follow_up_s *msg)
+{
+  struct timespec t3;
+  int64_t t4_t1_ns;
+  int64_t t3_t2_ns;
+  int64_t path_delay;
+  uint16_t sequence;
+
+  if (state->config->delay_mechanism != PTP_DELAY_P2P ||
+      !state->pdelay_waiting_followup)
+    {
+      return OK;
+    }
+
+  if (memcmp(msg->reqidentity, state->own_identity.header.sourceidentity,
+             sizeof(msg->reqidentity)) != 0)
+    {
+      return OK;
+    }
+
+  sequence = ptp_get_sequence(&msg->header);
+  if (sequence != state->pdelay_req_seq)
+    {
+      ptpwarn("Ignoring out-of-sequence Pdelay_Resp_Follow_Up "
+              "(%d vs. expected %d)\n",
+              (int)sequence, (int)state->pdelay_req_seq);

Review Comment:
   remove too



##########
netutils/ptpd/ptpd.c:
##########
@@ -1395,52 +1559,218 @@ static int ptp_process_delay_resp(FAR struct 
ptp_state_s *state,
   path_delay = timespec_delta_ns(&remote_rxtime, &state->delayreq_time);
   path_delay = (state->sync_diff_ns + path_delay) / 2;
 
-  max_path_delay = CONFIG_NETUTILS_PTPD_MAX_PATH_DELAY_NS;
+  ptp_record_path_delay(state, path_delay);
 
-  if (max_path_delay < 10 * (int64_t)NSEC_PER_MSEC)
+  /* Calculate interval until next packet */
+
+  if (msg->header.logmessageinterval <= 12)
     {
-      /* Software TX latency on Delay_Req transmission can add up to
-       * several milliseconds. Allow up to 10 ms until hardware TX
-       * timestamping is available.
-       */
+      interval = (1 << msg->header.logmessageinterval);
+    }
+  else
+    {
+      interval = 4096; /* Refuse to obey excessively long intervals */
+    }
 
-      max_path_delay = 10 * (int64_t)NSEC_PER_MSEC;
+  /* Randomize up to 2x nominal delay) */
+
+  state->delayreq_interval = interval + (random() % interval);
+
+  return OK;
+}
+
+/* Process received peer delay request (responder role) */
+
+static int ptp_process_pdelay_req(FAR struct ptp_state_s *state,
+                                  FAR struct ptp_pdelay_req_s *msg)
+{
+  struct ptp_pdelay_resp_s resp;
+  struct ptp_pdelay_resp_follow_up_s fup;
+  struct sockaddr_in addr;
+  struct timespec t3;
+  int ret;
+
+  if (state->config->delay_mechanism != PTP_DELAY_P2P)
+    {
+      return OK;
     }
 
-  if (path_delay >= 0 && path_delay < max_path_delay)
+  addr.sin_family      = AF_INET;
+  addr.sin_addr.s_addr = HTONL(PTP_PDELAY_MULTICAST_ADDR);
+  addr.sin_port        = HTONS(PTP_UDP_PORT_EVENT);
+
+  memset(&resp, 0, sizeof(resp));
+  resp.header = state->own_identity.header;
+  resp.header.messagetype = PTP_MSGTYPE_PDELAY_RESP;
+  resp.header.messagelength[1] = sizeof(resp);
+  resp.header.flags[0] = PTP_FLAGS0_TWOSTEP;
+  memcpy(resp.header.sequenceid, msg->header.sequenceid,
+         sizeof(resp.header.sequenceid));
+  resp.header.logmessageinterval = 0x7f;
+
+  timespec_to_ptp_format(&state->rxtime, resp.requestreceipttimestamp);
+  memcpy(resp.reqidentity, msg->header.sourceidentity,
+         sizeof(resp.reqidentity));
+  memcpy(resp.reqportindex, msg->header.sourceportindex,
+         sizeof(resp.reqportindex));
+
+  ret = ptp_sendmsg(state, &resp, sizeof(resp), &addr, sizeof(addr), &t3);
+  if (ret < 0)
     {
-      if (state->path_delay_avgcount <
-          CONFIG_NETUTILS_PTPD_DELAYREQ_AVGCOUNT)
-        {
-          state->path_delay_avgcount++;
-        }
+      ptperr("ptp sendmsg failed for Pdelay_Resp: %d\n", errno);
+      return ret;
+    }
 
-      state->path_delay_ns += (path_delay - state->path_delay_ns)
-                              / state->path_delay_avgcount;
+  clock_gettime(CLOCK_MONOTONIC, &state->last_transmitted_delayresp);
+  ptpinfo("Sent Pdelay_Resp, seq %d\n",
+          ptp_get_sequence(&resp.header));
 
-      ptpinfo("Path delay: %ld ns (avg: %ld ns)\n",
-        (long)path_delay, (long)state->path_delay_ns);
+  /* Send Pdelay_Resp_Follow_Up with transmit timestamp t3 */
+
+  addr.sin_port = HTONS(PTP_UDP_PORT_INFO);
+
+  memset(&fup, 0, sizeof(fup));
+  fup.header = state->own_identity.header;
+  fup.header.messagetype = PTP_MSGTYPE_PDELAY_RESP_FOLLOW_UP;
+  fup.header.messagelength[1] = sizeof(fup);
+  memcpy(fup.header.sequenceid, msg->header.sequenceid,
+         sizeof(fup.header.sequenceid));
+  fup.header.logmessageinterval = 0x7f;
+
+  timespec_to_ptp_format(&t3, fup.responseorigintimestamp);
+  memcpy(fup.reqidentity, msg->header.sourceidentity,
+         sizeof(fup.reqidentity));
+  memcpy(fup.reqportindex, msg->header.sourceportindex,
+         sizeof(fup.reqportindex));
+
+  ret = ptp_sendmsg(state, &fup, sizeof(fup), &addr, sizeof(addr), NULL);
+  if (ret < 0)
+    {
+      ptperr("ptp sendmsg failed for Pdelay_Resp_Follow_Up: %d\n", errno);
+      return ret;
     }
-  else
+
+  ptpinfo("Sent Pdelay_Resp_Follow_Up, seq %d\n",
+          ptp_get_sequence(&fup.header));
+
+  return OK;
+}
+
+/* Process received peer delay response (requester role) */
+
+static int ptp_process_pdelay_resp(FAR struct ptp_state_s *state,
+                                   FAR struct ptp_pdelay_resp_s *msg)
+{
+  uint16_t sequence;
+
+  if (state->config->delay_mechanism != PTP_DELAY_P2P)
     {
-      ptpwarn("Path delay out of range: %lld ns\n",
-              (long long)path_delay);
+      return OK;
     }
 
-  /* Calculate interval until next packet */
+  if (memcmp(msg->reqidentity, state->own_identity.header.sourceidentity,
+             sizeof(msg->reqidentity)) != 0)
+    {
+      return OK; /* Not for us */
+    }
 
-  if (msg->header.logmessageinterval <= 12)
+  sequence = ptp_get_sequence(&msg->header);
+  if (sequence != state->pdelay_req_seq)
     {
-      interval = (1 << msg->header.logmessageinterval);
+      ptpwarn("Ignoring out-of-sequence Pdelay_Resp (%d vs. expected %d)\n",
+              (int)sequence, (int)state->pdelay_req_seq);
+      return OK;
+    }
+
+  /* Store t4 (local receive timestamp) and t2 (receipt timestamp
+   * from peer).
+   */
+
+  state->pdelayresp_rx_time = state->rxtime;
+  ptp_format_to_timespec(msg->requestreceipttimestamp,
+                         &state->pdelayreq_rx_time);
+  ptp_add_correction_time(msg->header.correction,
+                          &state->pdelayreq_rx_time);
+
+  if (msg->header.flags[0] & PTP_FLAGS0_TWOSTEP)
+    {
+      state->pdelay_waiting_followup = true;
+      ptpinfo("Waiting for Pdelay_Resp_Follow_Up, seq %d\n",
+              (int)sequence);

Review Comment:
   ditto



##########
netutils/ptpd/ptpd.c:
##########
@@ -1395,52 +1559,218 @@ static int ptp_process_delay_resp(FAR struct 
ptp_state_s *state,
   path_delay = timespec_delta_ns(&remote_rxtime, &state->delayreq_time);
   path_delay = (state->sync_diff_ns + path_delay) / 2;
 
-  max_path_delay = CONFIG_NETUTILS_PTPD_MAX_PATH_DELAY_NS;
+  ptp_record_path_delay(state, path_delay);
 
-  if (max_path_delay < 10 * (int64_t)NSEC_PER_MSEC)
+  /* Calculate interval until next packet */
+
+  if (msg->header.logmessageinterval <= 12)
     {
-      /* Software TX latency on Delay_Req transmission can add up to
-       * several milliseconds. Allow up to 10 ms until hardware TX
-       * timestamping is available.
-       */
+      interval = (1 << msg->header.logmessageinterval);
+    }
+  else
+    {
+      interval = 4096; /* Refuse to obey excessively long intervals */
+    }
 
-      max_path_delay = 10 * (int64_t)NSEC_PER_MSEC;
+  /* Randomize up to 2x nominal delay) */
+
+  state->delayreq_interval = interval + (random() % interval);
+
+  return OK;
+}
+
+/* Process received peer delay request (responder role) */
+
+static int ptp_process_pdelay_req(FAR struct ptp_state_s *state,
+                                  FAR struct ptp_pdelay_req_s *msg)
+{
+  struct ptp_pdelay_resp_s resp;
+  struct ptp_pdelay_resp_follow_up_s fup;
+  struct sockaddr_in addr;
+  struct timespec t3;
+  int ret;
+
+  if (state->config->delay_mechanism != PTP_DELAY_P2P)
+    {
+      return OK;
     }
 
-  if (path_delay >= 0 && path_delay < max_path_delay)
+  addr.sin_family      = AF_INET;
+  addr.sin_addr.s_addr = HTONL(PTP_PDELAY_MULTICAST_ADDR);
+  addr.sin_port        = HTONS(PTP_UDP_PORT_EVENT);
+
+  memset(&resp, 0, sizeof(resp));
+  resp.header = state->own_identity.header;
+  resp.header.messagetype = PTP_MSGTYPE_PDELAY_RESP;
+  resp.header.messagelength[1] = sizeof(resp);
+  resp.header.flags[0] = PTP_FLAGS0_TWOSTEP;
+  memcpy(resp.header.sequenceid, msg->header.sequenceid,
+         sizeof(resp.header.sequenceid));
+  resp.header.logmessageinterval = 0x7f;
+
+  timespec_to_ptp_format(&state->rxtime, resp.requestreceipttimestamp);
+  memcpy(resp.reqidentity, msg->header.sourceidentity,
+         sizeof(resp.reqidentity));
+  memcpy(resp.reqportindex, msg->header.sourceportindex,
+         sizeof(resp.reqportindex));
+
+  ret = ptp_sendmsg(state, &resp, sizeof(resp), &addr, sizeof(addr), &t3);
+  if (ret < 0)
     {
-      if (state->path_delay_avgcount <
-          CONFIG_NETUTILS_PTPD_DELAYREQ_AVGCOUNT)
-        {
-          state->path_delay_avgcount++;
-        }
+      ptperr("ptp sendmsg failed for Pdelay_Resp: %d\n", errno);
+      return ret;
+    }
 
-      state->path_delay_ns += (path_delay - state->path_delay_ns)
-                              / state->path_delay_avgcount;
+  clock_gettime(CLOCK_MONOTONIC, &state->last_transmitted_delayresp);
+  ptpinfo("Sent Pdelay_Resp, seq %d\n",
+          ptp_get_sequence(&resp.header));
 
-      ptpinfo("Path delay: %ld ns (avg: %ld ns)\n",
-        (long)path_delay, (long)state->path_delay_ns);
+  /* Send Pdelay_Resp_Follow_Up with transmit timestamp t3 */
+
+  addr.sin_port = HTONS(PTP_UDP_PORT_INFO);
+
+  memset(&fup, 0, sizeof(fup));
+  fup.header = state->own_identity.header;
+  fup.header.messagetype = PTP_MSGTYPE_PDELAY_RESP_FOLLOW_UP;
+  fup.header.messagelength[1] = sizeof(fup);
+  memcpy(fup.header.sequenceid, msg->header.sequenceid,
+         sizeof(fup.header.sequenceid));
+  fup.header.logmessageinterval = 0x7f;
+
+  timespec_to_ptp_format(&t3, fup.responseorigintimestamp);
+  memcpy(fup.reqidentity, msg->header.sourceidentity,
+         sizeof(fup.reqidentity));
+  memcpy(fup.reqportindex, msg->header.sourceportindex,
+         sizeof(fup.reqportindex));
+
+  ret = ptp_sendmsg(state, &fup, sizeof(fup), &addr, sizeof(addr), NULL);
+  if (ret < 0)
+    {
+      ptperr("ptp sendmsg failed for Pdelay_Resp_Follow_Up: %d\n", errno);
+      return ret;
     }
-  else
+
+  ptpinfo("Sent Pdelay_Resp_Follow_Up, seq %d\n",
+          ptp_get_sequence(&fup.header));
+
+  return OK;
+}
+
+/* Process received peer delay response (requester role) */
+
+static int ptp_process_pdelay_resp(FAR struct ptp_state_s *state,
+                                   FAR struct ptp_pdelay_resp_s *msg)
+{
+  uint16_t sequence;
+
+  if (state->config->delay_mechanism != PTP_DELAY_P2P)
     {
-      ptpwarn("Path delay out of range: %lld ns\n",
-              (long long)path_delay);
+      return OK;
     }
 
-  /* Calculate interval until next packet */
+  if (memcmp(msg->reqidentity, state->own_identity.header.sourceidentity,
+             sizeof(msg->reqidentity)) != 0)
+    {
+      return OK; /* Not for us */
+    }
 
-  if (msg->header.logmessageinterval <= 12)
+  sequence = ptp_get_sequence(&msg->header);
+  if (sequence != state->pdelay_req_seq)
     {
-      interval = (1 << msg->header.logmessageinterval);
+      ptpwarn("Ignoring out-of-sequence Pdelay_Resp (%d vs. expected %d)\n",
+              (int)sequence, (int)state->pdelay_req_seq);
+      return OK;
+    }
+
+  /* Store t4 (local receive timestamp) and t2 (receipt timestamp
+   * from peer).
+   */
+
+  state->pdelayresp_rx_time = state->rxtime;
+  ptp_format_to_timespec(msg->requestreceipttimestamp,
+                         &state->pdelayreq_rx_time);
+  ptp_add_correction_time(msg->header.correction,
+                          &state->pdelayreq_rx_time);
+
+  if (msg->header.flags[0] & PTP_FLAGS0_TWOSTEP)
+    {
+      state->pdelay_waiting_followup = true;
+      ptpinfo("Waiting for Pdelay_Resp_Follow_Up, seq %d\n",
+              (int)sequence);
     }
   else
     {
-      interval = 4096; /* Refuse to obey excessively long intervals */
+      /* One-step: turnaround time (t3 - t2) is carried in correctionField */
+
+      int64_t t4_t1_ns;
+      int64_t t3_t2_ns;
+      int64_t path_delay;
+      uint64_t correction_time;
+
+      correction_time = (((uint64_t)msg->header.correction[0]) << 40)
+                      | (((uint64_t)msg->header.correction[1]) << 32)
+                      | (((uint64_t)msg->header.correction[2]) << 24)
+                      | (((uint64_t)msg->header.correction[3]) << 16)
+                      | (((uint64_t)msg->header.correction[4]) <<  8)
+                      | (((uint64_t)msg->header.correction[5]) <<  0);
+
+      t4_t1_ns = timespec_delta_ns(&state->pdelayresp_rx_time,
+                                   &state->pdelayreq_tx_time);
+      t3_t2_ns = (int64_t)correction_time;

Review Comment:
   remove the cast



##########
netutils/ptpd/ptpd.c:
##########
@@ -1076,119 +1079,118 @@ static int ptp_update_local_clock(FAR struct 
ptp_state_s *state,
        * the adjustment that was made previously.
        */
 
-      int64_t drift_ppb;
+      int64_t drift_ppb = 0;
       struct timespec interval;
-      int interval_ms;
+      int interval_ms = 0;
       int max_avg_period_ms;
       int64_t adjustment_ns;
+      const int64_t max_adjust_ns =
+        (int64_t)CONFIG_CLOCK_ADJTIME_SLEWLIMIT_PPM *
+        CONFIG_CLOCK_ADJTIME_PERIOD_MS;
+      const int64_t slew_limit_ppb =
+        (int64_t)CONFIG_CLOCK_ADJTIME_SLEWLIMIT_PPM * 1000;
 
-      clock_timespec_subtract(local_timestamp,
-                              &state->last_delta_timestamp,
-                              &interval);
-      interval_ms = timespec_to_ms(&interval);
-
-      if (interval_ms > 0 && interval_ms < CONFIG_NETUTILS_PTPD_TIMEOUT_MS)
+      if (!state->has_last_delta)
         {
-          drift_ppb = (delta_ns - state->last_delta_ns) * MSEC_PER_SEC
-                      / interval_ms;
+          /* First measurement after jump or startup: no previous
+           * delta available to compute frequency drift rate.
+           */
+
+          adjustment_ns = delta_ns;
         }
       else
         {
-          ptpwarn("Measurement interval out of range: %d ms\n", interval_ms);
-          drift_ppb = 0;
-          interval_ms = 1;
-        }
+          clock_timespec_subtract(local_timestamp,
+                                  &state->last_delta_timestamp,
+                                  &interval);
+          interval_ms = timespec_to_ms(&interval);
 
-      /* Account for the adjustment previously made */
+          if (interval_ms > 0 &&
+              interval_ms < CONFIG_NETUTILS_PTPD_TIMEOUT_MS)
+            {
+              /* Natural change in delta over the interval, accounting for
+               * the adjustment applied during that same interval.
+               */
 
-      drift_ppb += state->last_adjtime_ns * MSEC_PER_SEC
-                  / CONFIG_CLOCK_ADJTIME_PERIOD_MS;
+              drift_ppb = (delta_ns - state->last_delta_ns +
+                           state->last_adjtime_ns) * MSEC_PER_SEC
+                          / interval_ms;
+            }
+          else
+            {
+              ptpwarn("Measurement interval out of range: %d ms\n",
+                      interval_ms);
+              drift_ppb = state->drift_ppb;
+              interval_ms = 1;
+            }
 
-      if (drift_ppb > CONFIG_CLOCK_ADJTIME_SLEWLIMIT_PPM * 1000 ||
-          drift_ppb < -CONFIG_CLOCK_ADJTIME_SLEWLIMIT_PPM * 1000)
-        {
-          ptpwarn("Drift estimate out of range: %lld\n",
-                  (long long)drift_ppb);
-          drift_ppb = state->drift_ppb;
-        }
+          if (drift_ppb > slew_limit_ppb || drift_ppb < -slew_limit_ppb)
+            {
+              ptpwarn("Drift estimate out of range: %lld\n",
+                      (long long)drift_ppb);

Review Comment:
   remove the cast



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to