ptpd: Re-join multicast group after timeout
If multicast PTP packets are not being received, rejoin the multicast group. This automatically recovers from situations such as rebooting a network switch.
This commit is contained in:
parent
ae59177279
commit
8dbf26016a
@ -162,6 +162,15 @@ config NETUTILS_PTPD_SETTIME_THRESHOLD_MS
|
|||||||
time is reset with settimeofday() instead of changing the rate with
|
time is reset with settimeofday() instead of changing the rate with
|
||||||
adjtime().
|
adjtime().
|
||||||
|
|
||||||
|
config NETUTILS_PTPD_MULTICAST_TIMEOUT_MS
|
||||||
|
int "PTP client timeout to rejoin multicast group (ms)"
|
||||||
|
default 30000
|
||||||
|
---help---
|
||||||
|
If no PTP multicast packets are being received, attempt to rejoin the
|
||||||
|
multicast group. This can be necessary if network topology changes, or
|
||||||
|
depending on hardware, after some error recovery events.
|
||||||
|
Set to 0 to disable.
|
||||||
|
|
||||||
endif # NETUTILS_PTPD_CLIENT
|
endif # NETUTILS_PTPD_CLIENT
|
||||||
|
|
||||||
endif # NETUTILS_PTPD
|
endif # NETUTILS_PTPD
|
||||||
|
@ -93,6 +93,7 @@ struct ptp_state_s
|
|||||||
|
|
||||||
struct ptp_announce_s selected_source;
|
struct ptp_announce_s selected_source;
|
||||||
struct timespec last_received_sync;
|
struct timespec last_received_sync;
|
||||||
|
struct timespec last_received_multicast;
|
||||||
|
|
||||||
/* Last transmitted sync & announcement packets */
|
/* Last transmitted sync & announcement packets */
|
||||||
|
|
||||||
@ -399,6 +400,8 @@ static int ptp_initialize_state(struct ptp_state_s *state,
|
|||||||
bind_addr.sin_family = AF_INET;
|
bind_addr.sin_family = AF_INET;
|
||||||
bind_addr.sin_addr.s_addr = HTONL(PTP_MULTICAST_ADDR);
|
bind_addr.sin_addr.s_addr = HTONL(PTP_MULTICAST_ADDR);
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &state->last_received_multicast);
|
||||||
|
|
||||||
ret = ipmsfilter(&state->interface_addr.sin_addr,
|
ret = ipmsfilter(&state->interface_addr.sin_addr,
|
||||||
&bind_addr.sin_addr,
|
&bind_addr.sin_addr,
|
||||||
MCAST_INCLUDE);
|
MCAST_INCLUDE);
|
||||||
@ -476,6 +479,45 @@ static int ptp_destroy_state(struct ptp_state_s *state)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Re-subscribe multicast address.
|
||||||
|
* This can become necessary if Ethernet interface gets reset or if external
|
||||||
|
* IGMP-compliant Ethernet switch gets plugged in.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int ptp_check_multicast_status(struct ptp_state_s *state)
|
||||||
|
{
|
||||||
|
#if CONFIG_NETUTILS_PTPD_MULTICAST_TIMEOUT_MS > 0
|
||||||
|
struct in_addr mcast_addr;
|
||||||
|
struct timespec time_now;
|
||||||
|
struct timespec delta;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &time_now);
|
||||||
|
clock_timespec_subtract(&time_now, &state->last_received_multicast,
|
||||||
|
&delta);
|
||||||
|
|
||||||
|
if (timespec_to_ms(&delta) > CONFIG_NETUTILS_PTPD_MULTICAST_TIMEOUT_MS)
|
||||||
|
{
|
||||||
|
/* Remove and re-add the multicast group */
|
||||||
|
|
||||||
|
state->last_received_multicast = time_now;
|
||||||
|
|
||||||
|
mcast_addr.s_addr = HTONL(PTP_MULTICAST_ADDR);
|
||||||
|
ipmsfilter(&state->interface_addr.sin_addr,
|
||||||
|
&mcast_addr,
|
||||||
|
MCAST_EXCLUDE);
|
||||||
|
|
||||||
|
return ipmsfilter(&state->interface_addr.sin_addr,
|
||||||
|
&mcast_addr,
|
||||||
|
MCAST_INCLUDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
UNUSED(state);
|
||||||
|
#endif /* CONFIG_NETUTILS_PTPD_MULTICAST_TIMEOUT_MS */
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Send PTP server announcement packet */
|
/* Send PTP server announcement packet */
|
||||||
|
|
||||||
static int ptp_send_announce(struct ptp_state_s *state)
|
static int ptp_send_announce(struct ptp_state_s *state)
|
||||||
@ -779,6 +821,8 @@ static int ptp_process_rx_packet(struct ptp_state_s *state, ssize_t length)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &state->last_received_multicast);
|
||||||
|
|
||||||
switch (state->rxbuf.header.messagetype & PTP_MSGTYPE_MASK)
|
switch (state->rxbuf.header.messagetype & PTP_MSGTYPE_MASK)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_NETUTILS_PTPD_CLIENT
|
#ifdef CONFIG_NETUTILS_PTPD_CLIENT
|
||||||
@ -877,6 +921,13 @@ static int ptp_daemon(int argc, FAR char** argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pollfds[0].revents == 0 && pollfds[1].revents == 0)
|
||||||
|
{
|
||||||
|
/* No packets received, check for multicast timeout */
|
||||||
|
|
||||||
|
ptp_check_multicast_status(state);
|
||||||
|
}
|
||||||
|
|
||||||
ptp_periodic_send(state);
|
ptp_periodic_send(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user