mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 09:10:36 +00:00
ptp: Downgrade clocks that don't send FOLLOW_UPs / DELAY_RESPs
This allows to select a different clock if there is one that is for the same grandmaster clock and has fewer timeouts. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5520>
This commit is contained in:
parent
ea7861a757
commit
c7421c0f16
1 changed files with 119 additions and 11 deletions
|
@ -289,6 +289,19 @@ static PtpClockIdentity ptp_clock_id = { GST_PTP_CLOCK_ID_NONE, 0 };
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
PtpClockIdentity master_clock_identity;
|
||||||
|
guint8 iface_idx;
|
||||||
|
|
||||||
|
GstClockTime announce_interval; /* last interval we received */
|
||||||
|
GQueue announce_messages;
|
||||||
|
guint64 timed_out_sync; /* how often did this sender continously time out a FOLLOW_UP */
|
||||||
|
guint64 timed_out_delay_resp; /* how often did this sender continously time out a DELAY_RESP */
|
||||||
|
} PtpAnnounceSender;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PtpAnnounceSender *sender;
|
||||||
|
|
||||||
GstClockTime receive_time;
|
GstClockTime receive_time;
|
||||||
|
|
||||||
PtpClockIdentity master_clock_identity;
|
PtpClockIdentity master_clock_identity;
|
||||||
|
@ -304,19 +317,9 @@ typedef struct
|
||||||
guint16 sequence_id;
|
guint16 sequence_id;
|
||||||
} PtpAnnounceMessage;
|
} PtpAnnounceMessage;
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
PtpClockIdentity master_clock_identity;
|
|
||||||
guint8 iface_idx;
|
|
||||||
|
|
||||||
GstClockTime announce_interval; /* last interval we received */
|
|
||||||
GQueue announce_messages;
|
|
||||||
} PtpAnnounceSender;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
guint domain;
|
guint domain;
|
||||||
PtpClockIdentity master_clock_identity;
|
|
||||||
|
|
||||||
guint16 sync_seqnum;
|
guint16 sync_seqnum;
|
||||||
GstClockTime sync_recv_time_local; /* t2 */
|
GstClockTime sync_recv_time_local; /* t2 */
|
||||||
|
@ -363,11 +366,13 @@ typedef struct
|
||||||
|
|
||||||
/* Last SYNC or FOLLOW_UP timestamp we received */
|
/* Last SYNC or FOLLOW_UP timestamp we received */
|
||||||
GstClockTime last_ptp_sync_time;
|
GstClockTime last_ptp_sync_time;
|
||||||
|
GstClockTime last_ptp_sync_time_local;
|
||||||
GstClockTime sync_interval;
|
GstClockTime sync_interval;
|
||||||
|
|
||||||
GstClockTime mean_path_delay;
|
GstClockTime mean_path_delay;
|
||||||
GstClockTime last_delay_req, min_delay_req_interval;
|
GstClockTime last_delay_req, min_delay_req_interval;
|
||||||
guint16 last_delay_req_seqnum;
|
guint16 last_delay_req_seqnum;
|
||||||
|
GstClockTime last_ptp_delay_resp_time_local;
|
||||||
|
|
||||||
GstClockTime last_path_delays[MEDIAN_PRE_FILTERING_WINDOW];
|
GstClockTime last_path_delays[MEDIAN_PRE_FILTERING_WINDOW];
|
||||||
gint last_path_delays_missing;
|
gint last_path_delays_missing;
|
||||||
|
@ -700,11 +705,29 @@ compare_announce_message (const PtpAnnounceMessage * a,
|
||||||
{
|
{
|
||||||
/* IEEE 1588 Figure 27 */
|
/* IEEE 1588 Figure 27 */
|
||||||
if (a->grandmaster_identity == b->grandmaster_identity) {
|
if (a->grandmaster_identity == b->grandmaster_identity) {
|
||||||
|
// Random threshold of 4 timeouts to completely ignore all steps removed
|
||||||
|
if (a->sender->timed_out_delay_resp + a->sender->timed_out_sync + 4 <
|
||||||
|
b->sender->timed_out_delay_resp + b->sender->timed_out_sync)
|
||||||
|
return -1;
|
||||||
|
if (a->sender->timed_out_delay_resp + a->sender->timed_out_sync >
|
||||||
|
b->sender->timed_out_delay_resp + b->sender->timed_out_sync + 4)
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (a->steps_removed < b->steps_removed)
|
if (a->steps_removed < b->steps_removed)
|
||||||
return -1;
|
return -1;
|
||||||
else if (a->steps_removed > b->steps_removed)
|
else if (a->steps_removed > b->steps_removed)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
// If both are the same number of steps removed, prefer the clock with
|
||||||
|
// fewer timeouts before going to the tie breakers based on clock
|
||||||
|
// identities and interface indices
|
||||||
|
if (a->sender->timed_out_delay_resp + a->sender->timed_out_sync <
|
||||||
|
b->sender->timed_out_delay_resp + b->sender->timed_out_sync)
|
||||||
|
return -1;
|
||||||
|
if (a->sender->timed_out_delay_resp + a->sender->timed_out_sync >
|
||||||
|
b->sender->timed_out_delay_resp + b->sender->timed_out_sync)
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (skip_tiebreakers)
|
if (skip_tiebreakers)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -895,9 +918,11 @@ select_best_master_clock (PtpDomainData * domain, GstClockTime now)
|
||||||
domain->mean_path_delay = 0;
|
domain->mean_path_delay = 0;
|
||||||
domain->last_delay_req = 0;
|
domain->last_delay_req = 0;
|
||||||
domain->last_path_delays_missing = 9;
|
domain->last_path_delays_missing = 9;
|
||||||
|
domain->last_ptp_delay_resp_time_local = 0;
|
||||||
domain->min_delay_req_interval = 0;
|
domain->min_delay_req_interval = 0;
|
||||||
domain->sync_interval = 0;
|
domain->sync_interval = 0;
|
||||||
domain->last_ptp_sync_time = 0;
|
domain->last_ptp_sync_time = 0;
|
||||||
|
domain->last_ptp_sync_time_local = 0;
|
||||||
domain->skipped_updates = 0;
|
domain->skipped_updates = 0;
|
||||||
g_queue_foreach (&domain->pending_syncs, (GFunc) ptp_pending_sync_free,
|
g_queue_foreach (&domain->pending_syncs, (GFunc) ptp_pending_sync_free,
|
||||||
NULL);
|
NULL);
|
||||||
|
@ -1022,6 +1047,7 @@ handle_announce_message (PtpMessage * msg, guint8 iface_idx,
|
||||||
}
|
}
|
||||||
|
|
||||||
announce = g_new0 (PtpAnnounceMessage, 1);
|
announce = g_new0 (PtpAnnounceMessage, 1);
|
||||||
|
announce->sender = sender;
|
||||||
announce->receive_time = receive_time;
|
announce->receive_time = receive_time;
|
||||||
announce->sequence_id = msg->sequence_id;
|
announce->sequence_id = msg->sequence_id;
|
||||||
memcpy (&announce->master_clock_identity, &msg->source_port_identity,
|
memcpy (&announce->master_clock_identity, &msg->source_port_identity,
|
||||||
|
@ -1665,6 +1691,20 @@ handle_sync_message (PtpMessage * msg, guint8 iface_idx,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
domain->last_ptp_sync_time = sync->sync_send_time_remote;
|
domain->last_ptp_sync_time = sync->sync_send_time_remote;
|
||||||
|
domain->last_ptp_sync_time_local = receive_time;
|
||||||
|
|
||||||
|
for (l = domain->announce_senders; l; l = l->next) {
|
||||||
|
PtpAnnounceSender *sender = l->data;
|
||||||
|
|
||||||
|
if (compare_clock_identity (&domain->master_clock_identity,
|
||||||
|
&sender->master_clock_identity) == 0
|
||||||
|
&& domain->iface_idx == sender->iface_idx) {
|
||||||
|
|
||||||
|
sender->timed_out_sync = 0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (send_delay_req (domain, sync)) {
|
if (send_delay_req (domain, sync)) {
|
||||||
/* Sent delay request */
|
/* Sent delay request */
|
||||||
|
@ -1766,6 +1806,20 @@ handle_follow_up_message (PtpMessage * msg, guint8 iface_idx,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
domain->last_ptp_sync_time = sync->sync_send_time_remote;
|
domain->last_ptp_sync_time = sync->sync_send_time_remote;
|
||||||
|
domain->last_ptp_sync_time_local = receive_time;
|
||||||
|
|
||||||
|
for (l = domain->announce_senders; l; l = l->next) {
|
||||||
|
PtpAnnounceSender *sender = l->data;
|
||||||
|
|
||||||
|
if (compare_clock_identity (&domain->master_clock_identity,
|
||||||
|
&sender->master_clock_identity) == 0
|
||||||
|
&& domain->iface_idx == sender->iface_idx) {
|
||||||
|
|
||||||
|
sender->timed_out_sync = 0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (send_delay_req (domain, sync)) {
|
if (send_delay_req (domain, sync)) {
|
||||||
/* Sent delay request */
|
/* Sent delay request */
|
||||||
|
@ -1875,6 +1929,21 @@ handle_delay_resp_message (PtpMessage * msg, guint8 iface_idx,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
domain->last_ptp_delay_resp_time_local = receive_time;
|
||||||
|
|
||||||
|
for (l = domain->announce_senders; l; l = l->next) {
|
||||||
|
PtpAnnounceSender *sender = l->data;
|
||||||
|
|
||||||
|
if (compare_clock_identity (&domain->master_clock_identity,
|
||||||
|
&sender->master_clock_identity) == 0
|
||||||
|
&& domain->iface_idx == sender->iface_idx) {
|
||||||
|
|
||||||
|
sender->timed_out_delay_resp = 0;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (update_mean_path_delay (domain, sync))
|
if (update_mean_path_delay (domain, sync))
|
||||||
update_ptp_time (domain, sync);
|
update_ptp_time (domain, sync);
|
||||||
g_queue_remove (&domain->pending_syncs, sync);
|
g_queue_remove (&domain->pending_syncs, sync);
|
||||||
|
@ -2306,12 +2375,13 @@ cleanup_cb (gpointer data)
|
||||||
n = n->next;
|
n = n->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
select_best_master_clock (domain, now);
|
|
||||||
|
|
||||||
/* Clean up any pending syncs */
|
/* Clean up any pending syncs */
|
||||||
for (n = domain->pending_syncs.head; n;) {
|
for (n = domain->pending_syncs.head; n;) {
|
||||||
PtpPendingSync *sync = n->data;
|
PtpPendingSync *sync = n->data;
|
||||||
gboolean timed_out = FALSE;
|
gboolean timed_out = FALSE;
|
||||||
|
gboolean clock_timed_out_sync = FALSE;
|
||||||
|
gboolean clock_timed_out_delay_resp = FALSE;
|
||||||
|
|
||||||
/* Time out pending syncs after 4 sync intervals or 10 seconds,
|
/* Time out pending syncs after 4 sync intervals or 10 seconds,
|
||||||
* and pending delay reqs after 4 delay req intervals or 10 seconds
|
* and pending delay reqs after 4 delay req intervals or 10 seconds
|
||||||
|
@ -2322,10 +2392,46 @@ cleanup_cb (gpointer data)
|
||||||
4 * domain->min_delay_req_interval < now)
|
4 * domain->min_delay_req_interval < now)
|
||||||
|| (sync->delay_req_send_time_local + 10 * GST_SECOND < now))) {
|
|| (sync->delay_req_send_time_local + 10 * GST_SECOND < now))) {
|
||||||
timed_out = TRUE;
|
timed_out = TRUE;
|
||||||
|
|
||||||
|
// If no newer delay resp received in the meantime, downgrade the
|
||||||
|
// selected clock
|
||||||
|
if (domain->last_ptp_delay_resp_time_local <
|
||||||
|
sync->delay_req_send_time_local) {
|
||||||
|
clock_timed_out_delay_resp = TRUE;
|
||||||
|
}
|
||||||
} else if ((domain->sync_interval != 0
|
} else if ((domain->sync_interval != 0
|
||||||
&& sync->sync_recv_time_local + 4 * domain->sync_interval < now)
|
&& sync->sync_recv_time_local + 4 * domain->sync_interval < now)
|
||||||
|| (sync->sync_recv_time_local + 10 * GST_SECOND < now)) {
|
|| (sync->sync_recv_time_local + 10 * GST_SECOND < now)) {
|
||||||
timed_out = TRUE;
|
timed_out = TRUE;
|
||||||
|
|
||||||
|
// If no newer sync/follow-up received in the meantime, downgrade the
|
||||||
|
// selected clock
|
||||||
|
if (domain->last_ptp_sync_time_local < sync->sync_recv_time_local) {
|
||||||
|
clock_timed_out_sync = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the clock is timed out then downgrade it now in case there is a
|
||||||
|
// better clock for the domain that can be selected below.
|
||||||
|
if (domain->have_master_clock && (clock_timed_out_sync
|
||||||
|
|| clock_timed_out_delay_resp)) {
|
||||||
|
GST_DEBUG ("Currently selected clock timed out, downgrading");
|
||||||
|
|
||||||
|
for (m = domain->announce_senders; m; m = m->next) {
|
||||||
|
PtpAnnounceSender *sender = m->data;
|
||||||
|
|
||||||
|
if (compare_clock_identity (&domain->master_clock_identity,
|
||||||
|
&sender->master_clock_identity) == 0
|
||||||
|
&& domain->iface_idx == sender->iface_idx) {
|
||||||
|
|
||||||
|
if (clock_timed_out_sync)
|
||||||
|
sender->timed_out_sync++;
|
||||||
|
if (clock_timed_out_delay_resp)
|
||||||
|
sender->timed_out_delay_resp++;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timed_out) {
|
if (timed_out) {
|
||||||
|
@ -2337,6 +2443,8 @@ cleanup_cb (gpointer data)
|
||||||
n = n->next;
|
n = n->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
select_best_master_clock (domain, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
return G_SOURCE_CONTINUE;
|
return G_SOURCE_CONTINUE;
|
||||||
|
|
Loading…
Reference in a new issue