mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-10-01 19:36:36 +00:00
netutils/ptpd: Fix Delay_Resp consumption by sendmsg.
ptp_sendmsg() called a blocking recvmsg(state->tx_socket, ...) right after sending a Delay_Req whenever hardware_ts was set, assuming a Linux-style MSG_ERRQUEUE/loopback semantics NuttX does not have. Since tx_socket and event_socket share the same underlying connection, this call instead blocked on and consumed whatever PTP packet arrived next on the wire — almost always the Delay_Resp, which typically arrives within milliseconds of the request. Its payload was read into a local buffer that went out of scope on return, so the packet never reached ptp_process_rx_packet() and path_delay_ns stayed at 0 in -H mode. t3 is now captured locally via ptp_gettime(), the same way -S mode already did, until hardware TX timestamping is supported. Also replaces the path delay heuristic in ptp_process_delay_resp() (which derived an approximation of (t2-t1) from path_delay_ns and last_delta_ns, only valid once the clock had already converged) with the canonical IEEE 1588-2008 §11.3 formula: store (t2-t1) directly from Sync/Follow_Up as sync_diff_ns, then average it with (t4-t3) from the Delay_Req/Delay_Resp exchange. Relaxes the path delay ceiling to 10ms unconditionally, since Delay_Req's t3 is software- timestamped in both modes until hardware TX timestamping is supported. Assisted-by: Claude:claude-sonnet-5 Assisted-by: Gemini:gemini-3.8-flash-medium Signed-off-by: Daniel P. Carvalho <danieloak@gmail.com>
This commit is contained in:
parent
46e148db09
commit
7c4ea1dbff
1 changed files with 49 additions and 50 deletions
|
|
@ -139,6 +139,8 @@ struct ptp_state_s
|
|||
int path_delay_avgcount;
|
||||
long path_delay_ns;
|
||||
long delayreq_interval;
|
||||
int64_t sync_diff_ns;
|
||||
bool sync_diff_valid;
|
||||
|
||||
/* Latest received packet and its timestamp (CLOCK_REALTIME) */
|
||||
|
||||
|
|
@ -788,26 +790,13 @@ static int ptp_sendmsg(FAR struct ptp_state_s *state, FAR const void *buf,
|
|||
{
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (state->config->hardware_ts && sendts != NULL)
|
||||
{
|
||||
uint8_t rxcmsg[CMSG_LEN(sizeof(struct timespec))];
|
||||
|
||||
msg.msg_control = &rxcmsg;
|
||||
msg.msg_controllen = CMSG_LEN(sizeof(struct timespec));
|
||||
ret = recvmsg(state->tx_socket, &msg, 0);
|
||||
if (ret >= 0)
|
||||
{
|
||||
ptp_getrxtime(state, &msg, sendts);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = sendto(state->tx_socket, buf, buflen, 0, addr, addrlen);
|
||||
}
|
||||
|
||||
if (!state->config->hardware_ts && sendts != NULL)
|
||||
if (sendts != NULL)
|
||||
{
|
||||
ptp_gettime(state, sendts);
|
||||
}
|
||||
|
|
@ -1206,6 +1195,31 @@ static int ptp_update_local_clock(FAR struct ptp_state_s *state,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void ptp_add_correction_time(FAR const uint8_t *correction,
|
||||
FAR struct timespec *ts)
|
||||
{
|
||||
uint64_t correction_time = (((uint64_t)correction[0]) << 40)
|
||||
| (((uint64_t)correction[1]) << 32)
|
||||
| (((uint64_t)correction[2]) << 24)
|
||||
| (((uint64_t)correction[3]) << 16)
|
||||
| (((uint64_t)correction[4]) << 8)
|
||||
| (((uint64_t)correction[5]) << 0);
|
||||
|
||||
ptpinfo("correction before: %jd.%09ld\n", (intmax_t)ts->tv_sec,
|
||||
ts->tv_nsec);
|
||||
|
||||
ts->tv_sec += correction_time / NSEC_PER_SEC;
|
||||
ts->tv_nsec += correction_time % NSEC_PER_SEC;
|
||||
if (ts->tv_nsec >= NSEC_PER_SEC)
|
||||
{
|
||||
ts->tv_nsec -= NSEC_PER_SEC;
|
||||
ts->tv_sec += 1;
|
||||
}
|
||||
|
||||
ptpinfo("correction after: %jd.%09ld\n", (intmax_t)ts->tv_sec,
|
||||
ts->tv_nsec);
|
||||
}
|
||||
|
||||
/* Process received PTP sync packet */
|
||||
|
||||
static int ptp_process_sync(FAR struct ptp_state_s *state,
|
||||
|
|
@ -1240,34 +1254,12 @@ static int ptp_process_sync(FAR struct ptp_state_s *state,
|
|||
/* Update local clock */
|
||||
|
||||
ptp_format_to_timespec(msg->origintimestamp, &remote_time);
|
||||
ptp_add_correction_time(msg->header.correction, &remote_time);
|
||||
state->sync_diff_ns = timespec_delta_ns(&state->rxtime, &remote_time);
|
||||
state->sync_diff_valid = true;
|
||||
return ptp_update_local_clock(state, &remote_time, &state->rxtime);
|
||||
}
|
||||
|
||||
static void ptp_add_correction_time(FAR const uint8_t *correction,
|
||||
FAR struct timespec *ts)
|
||||
{
|
||||
uint64_t correction_time = (((uint64_t)correction[0]) << 40)
|
||||
| (((uint64_t)correction[1]) << 32)
|
||||
| (((uint64_t)correction[2]) << 24)
|
||||
| (((uint64_t)correction[3]) << 16)
|
||||
| (((uint64_t)correction[4]) << 8)
|
||||
| (((uint64_t)correction[5]) << 0);
|
||||
|
||||
ptpinfo("correction before: %jd.%09ld\n", (intmax_t)ts->tv_sec,
|
||||
ts->tv_nsec);
|
||||
|
||||
ts->tv_sec += correction_time / NSEC_PER_SEC;
|
||||
ts->tv_nsec += correction_time % NSEC_PER_SEC;
|
||||
if (ts->tv_nsec >= NSEC_PER_SEC)
|
||||
{
|
||||
ts->tv_nsec -= NSEC_PER_SEC;
|
||||
ts->tv_sec += 1;
|
||||
}
|
||||
|
||||
ptpinfo("correction after: %jd.%09ld\n", (intmax_t)ts->tv_sec,
|
||||
ts->tv_nsec);
|
||||
}
|
||||
|
||||
static int ptp_process_followup(FAR struct ptp_state_s *state,
|
||||
FAR struct ptp_follow_up_s *msg)
|
||||
{
|
||||
|
|
@ -1301,6 +1293,12 @@ static int ptp_process_followup(FAR struct ptp_state_s *state,
|
|||
|
||||
ptp_add_correction_time(msg->header.correction, &remote_time);
|
||||
|
||||
/* Store (t2 - t1) for canonical IEEE 1588-2008 §11.3 path delay */
|
||||
|
||||
state->sync_diff_ns = timespec_delta_ns(&state->twostep_rxtime,
|
||||
&remote_time);
|
||||
state->sync_diff_valid = true;
|
||||
|
||||
/* done */
|
||||
|
||||
return ptp_update_local_clock(state, &remote_time, &state->twostep_rxtime);
|
||||
|
|
@ -1356,7 +1354,6 @@ static int ptp_process_delay_resp(FAR struct ptp_state_s *state,
|
|||
FAR struct ptp_delay_resp_s *msg)
|
||||
{
|
||||
int64_t path_delay;
|
||||
int64_t sync_delay;
|
||||
struct timespec remote_rxtime;
|
||||
uint16_t sequence;
|
||||
int interval;
|
||||
|
|
@ -1371,10 +1368,13 @@ static int ptp_process_delay_resp(FAR struct ptp_state_s *state,
|
|||
state->own_identity.header.sourceidentity,
|
||||
sizeof(msg->reqidentity)) == 0;
|
||||
|
||||
if (!state->selected_source_valid || !source_match || !request_match)
|
||||
if (!state->selected_source_valid || !state->sync_diff_valid ||
|
||||
!source_match || !request_match)
|
||||
{
|
||||
ptpwarn("Delay_Resp ignored: valid=%d, src_match=%d, req_match=%d\n",
|
||||
state->selected_source_valid, source_match, request_match);
|
||||
ptpwarn("Delay_Resp ignored: valid=%d, sync_valid=%d, src_match=%d, "
|
||||
"req_match=%d\n",
|
||||
state->selected_source_valid, state->sync_diff_valid,
|
||||
source_match, request_match);
|
||||
return OK; /* This packet wasn't for us */
|
||||
}
|
||||
|
||||
|
|
@ -1388,22 +1388,21 @@ static int ptp_process_delay_resp(FAR struct ptp_state_s *state,
|
|||
}
|
||||
|
||||
/* Path delay is calculated as the average between delta for sync
|
||||
* message and delta for delay req message.
|
||||
* message (t2 - t1) and delta for delay req message (t4 - t3).
|
||||
* (IEEE-1588 section 11.3: Delay request-response mechanism)
|
||||
*/
|
||||
|
||||
ptp_format_to_timespec(msg->receivetimestamp, &remote_rxtime);
|
||||
path_delay = timespec_delta_ns(&remote_rxtime, &state->delayreq_time);
|
||||
sync_delay = state->path_delay_ns - state->last_delta_ns;
|
||||
path_delay = (path_delay + sync_delay) / 2;
|
||||
path_delay = (state->sync_diff_ns + path_delay) / 2;
|
||||
|
||||
max_path_delay = CONFIG_NETUTILS_PTPD_MAX_PATH_DELAY_NS;
|
||||
|
||||
if (!state->config->hardware_ts &&
|
||||
max_path_delay < 10 * (int64_t)NSEC_PER_MSEC)
|
||||
if (max_path_delay < 10 * (int64_t)NSEC_PER_MSEC)
|
||||
{
|
||||
/* Software timestamping includes network stack and OS latency,
|
||||
* allow up to 10 ms.
|
||||
/* Software TX latency on Delay_Req 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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue