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 free_running;
|
||||
int freq_est_interval;
|
||||
int local_sync_uncertain;
|
||||
int write_phase_mode;
|
||||
int grand_master_capable; /* for 802.1AS only */
|
||||
int utc_timescale;
|
||||
|
@ -137,6 +138,7 @@ struct clock the_clock;
|
|||
static void handle_state_decision_event(struct clock *c);
|
||||
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_stats_display(struct clock_stats *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);
|
||||
datalen = sizeof(*sen);
|
||||
break;
|
||||
case TLV_SYNCHRONIZATION_UNCERTAIN_NP:
|
||||
mtd = (struct management_tlv_datum *) tlv->data;
|
||||
mtd->val = c->local_sync_uncertain;
|
||||
datalen = sizeof(*mtd);
|
||||
break;
|
||||
default:
|
||||
/* The caller should *not* respond to this message. */
|
||||
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);
|
||||
respond = 1;
|
||||
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))
|
||||
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,
|
||||
double offset, double freq)
|
||||
{
|
||||
struct stats_result offset_stats, freq_stats, delay_stats;
|
||||
|
||||
stats_add_value(s->offset, offset);
|
||||
stats_add_value(s->freq, freq);
|
||||
|
||||
if (stats_get_num_values(s->offset) < s->max_count)
|
||||
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->freq, &freq_stats);
|
||||
|
||||
|
@ -1030,6 +1057,7 @@ struct clock *clock_create(enum clock_type type, struct config *config,
|
|||
c->config = config;
|
||||
c->free_running = config_get_int(config, NULL, "free_running");
|
||||
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->grand_master_capable = config_get_int(config, NULL, "gmCapable");
|
||||
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_GRANDMASTER_SETTINGS_NP:
|
||||
case TLV_SUBSCRIBE_EVENTS_NP:
|
||||
case TLV_SYNCHRONIZATION_UNCERTAIN_NP:
|
||||
clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
|
||||
break;
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
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.
|
||||
* @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.
|
||||
|
|
1
msg.h
1
msg.h
|
@ -56,6 +56,7 @@
|
|||
#define PTP_TIMESCALE (1<<3)
|
||||
#define TIME_TRACEABLE (1<<4)
|
||||
#define FREQ_TRACEABLE (1<<5)
|
||||
#define SYNC_UNCERTAIN (1<<6)
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
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 currentDS *cds = clock_current_dataset(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->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));
|
||||
|
||||
return 0;
|
||||
|
@ -1407,7 +1407,7 @@ out:
|
|||
|
||||
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 ptp_message *msg;
|
||||
int err;
|
||||
|
@ -1434,19 +1434,19 @@ int port_tx_announce(struct port *p, struct address *dst)
|
|||
msg->header.control = CTL_OTHER;
|
||||
msg->header.logMessageInterval = p->logAnnounceInterval;
|
||||
|
||||
msg->header.flagField[1] = tp->flags;
|
||||
msg->header.flagField[1] = tp.flags;
|
||||
|
||||
if (dst) {
|
||||
msg->address = *dst;
|
||||
msg->header.flagField[0] |= UNICAST;
|
||||
}
|
||||
msg->announce.currentUtcOffset = tp->currentUtcOffset;
|
||||
msg->announce.currentUtcOffset = tp.currentUtcOffset;
|
||||
msg->announce.grandmasterPriority1 = dad->pds.grandmasterPriority1;
|
||||
msg->announce.grandmasterClockQuality = dad->pds.grandmasterClockQuality;
|
||||
msg->announce.grandmasterPriority2 = dad->pds.grandmasterPriority2;
|
||||
msg->announce.grandmasterIdentity = dad->pds.grandmasterIdentity;
|
||||
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)) {
|
||||
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_GRANDMASTER_SETTINGS_NP 0xC001
|
||||
#define TLV_SUBSCRIBE_EVENTS_NP 0xC003
|
||||
#define TLV_SYNCHRONIZATION_UNCERTAIN_NP 0xC006
|
||||
|
||||
/* Port management ID values */
|
||||
#define TLV_NULL_MANAGEMENT 0x0000
|
||||
|
@ -116,6 +117,11 @@ enum management_action {
|
|||
#define TLV_NOT_SUPPORTED 0x0006
|
||||
#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_GRANT (1 << 1)
|
||||
#define GRANT_UNICAST_RENEWAL_INVITED (1 << 0)
|
||||
|
|
Loading…
Reference in New Issue