Implement the synchronization uncertain flag.
IEEE 1588 v2.1 and ITU G.8275.1/2 call for an optional "synchronization uncertain" flag passed in Announce messages along with the other flags from the time properties data set. The value of the flag depends is a logical OR function of the inputs from the remote master and the local process. This patch adds background support for handling the flag. Signed-off-by: Richard Cochran <richardcochran@gmail.com>master
parent
7df88afab9
commit
b8194a177a
50
clock.c
50
clock.c
|
@ -103,6 +103,7 @@ struct clock {
|
||||||
int sde;
|
int sde;
|
||||||
int free_running;
|
int free_running;
|
||||||
int freq_est_interval;
|
int freq_est_interval;
|
||||||
|
int local_sync_uncertain;
|
||||||
int write_phase_mode;
|
int write_phase_mode;
|
||||||
int grand_master_capable; /* for 802.1AS only */
|
int grand_master_capable; /* for 802.1AS only */
|
||||||
int utc_timescale;
|
int utc_timescale;
|
||||||
|
@ -137,6 +138,7 @@ struct clock the_clock;
|
||||||
static void handle_state_decision_event(struct clock *c);
|
static void handle_state_decision_event(struct clock *c);
|
||||||
static int clock_resize_pollfd(struct clock *c, int new_nports);
|
static int clock_resize_pollfd(struct clock *c, int new_nports);
|
||||||
static void clock_remove_port(struct clock *c, struct port *p);
|
static void clock_remove_port(struct clock *c, struct port *p);
|
||||||
|
static void clock_stats_display(struct clock_stats *s);
|
||||||
|
|
||||||
static void remove_subscriber(struct clock_subscriber *s)
|
static void remove_subscriber(struct clock_subscriber *s)
|
||||||
{
|
{
|
||||||
|
@ -446,6 +448,11 @@ static int clock_management_fill_response(struct clock *c, struct port *p,
|
||||||
clock_get_subscription(c, req, sen->bitmask, &sen->duration);
|
clock_get_subscription(c, req, sen->bitmask, &sen->duration);
|
||||||
datalen = sizeof(*sen);
|
datalen = sizeof(*sen);
|
||||||
break;
|
break;
|
||||||
|
case TLV_SYNCHRONIZATION_UNCERTAIN_NP:
|
||||||
|
mtd = (struct management_tlv_datum *) tlv->data;
|
||||||
|
mtd->val = c->local_sync_uncertain;
|
||||||
|
datalen = sizeof(*mtd);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* The caller should *not* respond to this message. */
|
/* The caller should *not* respond to this message. */
|
||||||
tlv_extra_recycle(extra);
|
tlv_extra_recycle(extra);
|
||||||
|
@ -519,6 +526,21 @@ static int clock_management_set(struct clock *c, struct port *p,
|
||||||
clock_update_subscription(c, req, sen->bitmask, sen->duration);
|
clock_update_subscription(c, req, sen->bitmask, sen->duration);
|
||||||
respond = 1;
|
respond = 1;
|
||||||
break;
|
break;
|
||||||
|
case TLV_SYNCHRONIZATION_UNCERTAIN_NP:
|
||||||
|
mtd = (struct management_tlv_datum *) tlv->data;
|
||||||
|
switch (mtd->val) {
|
||||||
|
case SYNC_UNCERTAIN_DONTCARE:
|
||||||
|
case SYNC_UNCERTAIN_FALSE:
|
||||||
|
case SYNC_UNCERTAIN_TRUE:
|
||||||
|
/* Display stats on change of local_sync_uncertain */
|
||||||
|
if (c->local_sync_uncertain != mtd->val
|
||||||
|
&& stats_get_num_values(c->stats.offset))
|
||||||
|
clock_stats_display(&c->stats);
|
||||||
|
c->local_sync_uncertain = mtd->val;
|
||||||
|
respond = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (respond && !clock_management_get_response(c, p, id, req))
|
if (respond && !clock_management_get_response(c, p, id, req))
|
||||||
pr_err("failed to send management set response");
|
pr_err("failed to send management set response");
|
||||||
|
@ -528,14 +550,19 @@ static int clock_management_set(struct clock *c, struct port *p,
|
||||||
static void clock_stats_update(struct clock_stats *s,
|
static void clock_stats_update(struct clock_stats *s,
|
||||||
double offset, double freq)
|
double offset, double freq)
|
||||||
{
|
{
|
||||||
struct stats_result offset_stats, freq_stats, delay_stats;
|
|
||||||
|
|
||||||
stats_add_value(s->offset, offset);
|
stats_add_value(s->offset, offset);
|
||||||
stats_add_value(s->freq, freq);
|
stats_add_value(s->freq, freq);
|
||||||
|
|
||||||
if (stats_get_num_values(s->offset) < s->max_count)
|
if (stats_get_num_values(s->offset) < s->max_count)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
clock_stats_display(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clock_stats_display(struct clock_stats *s)
|
||||||
|
{
|
||||||
|
struct stats_result offset_stats, freq_stats, delay_stats;
|
||||||
|
|
||||||
stats_get_result(s->offset, &offset_stats);
|
stats_get_result(s->offset, &offset_stats);
|
||||||
stats_get_result(s->freq, &freq_stats);
|
stats_get_result(s->freq, &freq_stats);
|
||||||
|
|
||||||
|
@ -1030,6 +1057,7 @@ struct clock *clock_create(enum clock_type type, struct config *config,
|
||||||
c->config = config;
|
c->config = config;
|
||||||
c->free_running = config_get_int(config, NULL, "free_running");
|
c->free_running = config_get_int(config, NULL, "free_running");
|
||||||
c->freq_est_interval = config_get_int(config, NULL, "freq_est_interval");
|
c->freq_est_interval = config_get_int(config, NULL, "freq_est_interval");
|
||||||
|
c->local_sync_uncertain = SYNC_UNCERTAIN_DONTCARE;
|
||||||
c->write_phase_mode = config_get_int(config, NULL, "write_phase_mode");
|
c->write_phase_mode = config_get_int(config, NULL, "write_phase_mode");
|
||||||
c->grand_master_capable = config_get_int(config, NULL, "gmCapable");
|
c->grand_master_capable = config_get_int(config, NULL, "gmCapable");
|
||||||
c->kernel_leap = config_get_int(config, NULL, "kernel_leap");
|
c->kernel_leap = config_get_int(config, NULL, "kernel_leap");
|
||||||
|
@ -1429,6 +1457,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg)
|
||||||
case TLV_TIME_STATUS_NP:
|
case TLV_TIME_STATUS_NP:
|
||||||
case TLV_GRANDMASTER_SETTINGS_NP:
|
case TLV_GRANDMASTER_SETTINGS_NP:
|
||||||
case TLV_SUBSCRIBE_EVENTS_NP:
|
case TLV_SUBSCRIBE_EVENTS_NP:
|
||||||
|
case TLV_SYNCHRONIZATION_UNCERTAIN_NP:
|
||||||
clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
|
clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1751,9 +1780,22 @@ void clock_sync_interval(struct clock *c, int n)
|
||||||
servo_sync_interval(c->servo, n < 0 ? 1.0 / (1 << -n) : 1 << n);
|
servo_sync_interval(c->servo, n < 0 ? 1.0 / (1 << -n) : 1 << n);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct timePropertiesDS *clock_time_properties(struct clock *c)
|
struct timePropertiesDS clock_time_properties(struct clock *c)
|
||||||
{
|
{
|
||||||
return &c->tds;
|
struct timePropertiesDS tds = c->tds;
|
||||||
|
|
||||||
|
switch (c->local_sync_uncertain) {
|
||||||
|
case SYNC_UNCERTAIN_DONTCARE:
|
||||||
|
tds.flags &= ~SYNC_UNCERTAIN;
|
||||||
|
break;
|
||||||
|
case SYNC_UNCERTAIN_FALSE:
|
||||||
|
/* Pass the upstream value, if any. */
|
||||||
|
break;
|
||||||
|
case SYNC_UNCERTAIN_TRUE:
|
||||||
|
tds.flags |= SYNC_UNCERTAIN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return tds;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clock_update_time_properties(struct clock *c, struct timePropertiesDS tds)
|
void clock_update_time_properties(struct clock *c, struct timePropertiesDS tds)
|
||||||
|
|
4
clock.h
4
clock.h
|
@ -320,9 +320,9 @@ void clock_sync_interval(struct clock *c, int n);
|
||||||
/**
|
/**
|
||||||
* Obtain a clock's time properties data set.
|
* Obtain a clock's time properties data set.
|
||||||
* @param c The clock instance.
|
* @param c The clock instance.
|
||||||
* @return A pointer to the time properties data set of the clock.
|
* @return A copy of the clock's time properties data set.
|
||||||
*/
|
*/
|
||||||
struct timePropertiesDS *clock_time_properties(struct clock *c);
|
struct timePropertiesDS clock_time_properties(struct clock *c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a clock's time properties data set.
|
* Update a clock's time properties data set.
|
||||||
|
|
1
msg.h
1
msg.h
|
@ -56,6 +56,7 @@
|
||||||
#define PTP_TIMESCALE (1<<3)
|
#define PTP_TIMESCALE (1<<3)
|
||||||
#define TIME_TRACEABLE (1<<4)
|
#define TIME_TRACEABLE (1<<4)
|
||||||
#define FREQ_TRACEABLE (1<<5)
|
#define FREQ_TRACEABLE (1<<5)
|
||||||
|
#define SYNC_UNCERTAIN (1<<6)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Signaling interval special values. For more info look at 802.1AS table 10-11
|
* Signaling interval special values. For more info look at 802.1AS table 10-11
|
||||||
|
|
12
port.c
12
port.c
|
@ -412,7 +412,7 @@ static int follow_up_info_append(struct ptp_message *m)
|
||||||
|
|
||||||
static int net_sync_resp_append(struct port *p, struct ptp_message *m)
|
static int net_sync_resp_append(struct port *p, struct ptp_message *m)
|
||||||
{
|
{
|
||||||
struct timePropertiesDS *tp = clock_time_properties(p->clock);
|
struct timePropertiesDS tp = clock_time_properties(p->clock);
|
||||||
struct ClockIdentity cid = clock_identity(p->clock), pid;
|
struct ClockIdentity cid = clock_identity(p->clock), pid;
|
||||||
struct currentDS *cds = clock_current_dataset(p->clock);
|
struct currentDS *cds = clock_current_dataset(p->clock);
|
||||||
struct parent_ds *dad = clock_parent_ds(p->clock);
|
struct parent_ds *dad = clock_parent_ds(p->clock);
|
||||||
|
@ -468,7 +468,7 @@ static int net_sync_resp_append(struct port *p, struct ptp_message *m)
|
||||||
|
|
||||||
memcpy(&extra->foot->parent, &dad->pds, sizeof(extra->foot->parent));
|
memcpy(&extra->foot->parent, &dad->pds, sizeof(extra->foot->parent));
|
||||||
memcpy(&extra->foot->current, cds, sizeof(extra->foot->current));
|
memcpy(&extra->foot->current, cds, sizeof(extra->foot->current));
|
||||||
memcpy(&extra->foot->timeprop, tp, sizeof(extra->foot->timeprop));
|
memcpy(&extra->foot->timeprop, &tp, sizeof(extra->foot->timeprop));
|
||||||
memcpy(&extra->foot->lastsync, &last_sync, sizeof(extra->foot->lastsync));
|
memcpy(&extra->foot->lastsync, &last_sync, sizeof(extra->foot->lastsync));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1407,7 +1407,7 @@ out:
|
||||||
|
|
||||||
int port_tx_announce(struct port *p, struct address *dst)
|
int port_tx_announce(struct port *p, struct address *dst)
|
||||||
{
|
{
|
||||||
struct timePropertiesDS *tp = clock_time_properties(p->clock);
|
struct timePropertiesDS tp = clock_time_properties(p->clock);
|
||||||
struct parent_ds *dad = clock_parent_ds(p->clock);
|
struct parent_ds *dad = clock_parent_ds(p->clock);
|
||||||
struct ptp_message *msg;
|
struct ptp_message *msg;
|
||||||
int err;
|
int err;
|
||||||
|
@ -1434,19 +1434,19 @@ int port_tx_announce(struct port *p, struct address *dst)
|
||||||
msg->header.control = CTL_OTHER;
|
msg->header.control = CTL_OTHER;
|
||||||
msg->header.logMessageInterval = p->logAnnounceInterval;
|
msg->header.logMessageInterval = p->logAnnounceInterval;
|
||||||
|
|
||||||
msg->header.flagField[1] = tp->flags;
|
msg->header.flagField[1] = tp.flags;
|
||||||
|
|
||||||
if (dst) {
|
if (dst) {
|
||||||
msg->address = *dst;
|
msg->address = *dst;
|
||||||
msg->header.flagField[0] |= UNICAST;
|
msg->header.flagField[0] |= UNICAST;
|
||||||
}
|
}
|
||||||
msg->announce.currentUtcOffset = tp->currentUtcOffset;
|
msg->announce.currentUtcOffset = tp.currentUtcOffset;
|
||||||
msg->announce.grandmasterPriority1 = dad->pds.grandmasterPriority1;
|
msg->announce.grandmasterPriority1 = dad->pds.grandmasterPriority1;
|
||||||
msg->announce.grandmasterClockQuality = dad->pds.grandmasterClockQuality;
|
msg->announce.grandmasterClockQuality = dad->pds.grandmasterClockQuality;
|
||||||
msg->announce.grandmasterPriority2 = dad->pds.grandmasterPriority2;
|
msg->announce.grandmasterPriority2 = dad->pds.grandmasterPriority2;
|
||||||
msg->announce.grandmasterIdentity = dad->pds.grandmasterIdentity;
|
msg->announce.grandmasterIdentity = dad->pds.grandmasterIdentity;
|
||||||
msg->announce.stepsRemoved = clock_steps_removed(p->clock);
|
msg->announce.stepsRemoved = clock_steps_removed(p->clock);
|
||||||
msg->announce.timeSource = tp->timeSource;
|
msg->announce.timeSource = tp.timeSource;
|
||||||
|
|
||||||
if (p->path_trace_enabled && path_trace_append(p, msg, dad)) {
|
if (p->path_trace_enabled && path_trace_append(p, msg, dad)) {
|
||||||
pr_err("port %hu: append path trace failed", portnum(p));
|
pr_err("port %hu: append path trace failed", portnum(p));
|
||||||
|
|
6
tlv.h
6
tlv.h
|
@ -84,6 +84,7 @@ enum management_action {
|
||||||
#define TLV_TIME_STATUS_NP 0xC000
|
#define TLV_TIME_STATUS_NP 0xC000
|
||||||
#define TLV_GRANDMASTER_SETTINGS_NP 0xC001
|
#define TLV_GRANDMASTER_SETTINGS_NP 0xC001
|
||||||
#define TLV_SUBSCRIBE_EVENTS_NP 0xC003
|
#define TLV_SUBSCRIBE_EVENTS_NP 0xC003
|
||||||
|
#define TLV_SYNCHRONIZATION_UNCERTAIN_NP 0xC006
|
||||||
|
|
||||||
/* Port management ID values */
|
/* Port management ID values */
|
||||||
#define TLV_NULL_MANAGEMENT 0x0000
|
#define TLV_NULL_MANAGEMENT 0x0000
|
||||||
|
@ -116,6 +117,11 @@ enum management_action {
|
||||||
#define TLV_NOT_SUPPORTED 0x0006
|
#define TLV_NOT_SUPPORTED 0x0006
|
||||||
#define TLV_GENERAL_ERROR 0xFFFE
|
#define TLV_GENERAL_ERROR 0xFFFE
|
||||||
|
|
||||||
|
/* Values for the SYNCHRONIZATION_UNCERTAIN_NP management TLV */
|
||||||
|
#define SYNC_UNCERTAIN_DONTCARE 0xff
|
||||||
|
#define SYNC_UNCERTAIN_FALSE 0
|
||||||
|
#define SYNC_UNCERTAIN_TRUE 1
|
||||||
|
|
||||||
#define CANCEL_UNICAST_MAINTAIN_REQUEST (1 << 0)
|
#define CANCEL_UNICAST_MAINTAIN_REQUEST (1 << 0)
|
||||||
#define CANCEL_UNICAST_MAINTAIN_GRANT (1 << 1)
|
#define CANCEL_UNICAST_MAINTAIN_GRANT (1 << 1)
|
||||||
#define GRANT_UNICAST_RENEWAL_INVITED (1 << 0)
|
#define GRANT_UNICAST_RENEWAL_INVITED (1 << 0)
|
||||||
|
|
Loading…
Reference in New Issue