Commit 04f722fe authored by Jean-Claude BAU's avatar Jean-Claude BAU

Clock degradation

- New mechanism for clock degradation (degrade clock class, clock
accuracy, clock variance, timeSource, ptpTimeScale, frequencyTraceable,
timeTraceable)
- timeSource can be configured now
- If clock accuracy, clock variance and timeSource are not set in
ppsi.conf, default values are used depending of the clock class.
parent 12c52105
/*
* Copyright (C) 2019 CERN (www.cern.ch)
* Author: Jean-Claude BAU
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#ifndef USERSPACE_PPSI_INCLUDE_PPSI_BMC_H_
#define USERSPACE_PPSI_INCLUDE_PPSI_BMC_H_
typedef enum {
PP_TIMING_MODE_STATE_UNLOCKED=0,
PP_TIMING_MODE_STATE_HOLDOVER,
PP_TIMING_MODE_STATE_LOCKED,
}pp_timing_mode_state_t;
/**
* These structure is used to describe the behavior to degrade a clock class
* or its attributes.
*/
typedef struct {
ClockQuality clockQuality;
UInteger8 timeSource;
Boolean ptpTimeScale;
Boolean frequencyTraceable;
Boolean timeTraceable;
char *msg;
}deviceAttributesDegradation_t;
typedef struct {
int clockClass;
pp_timing_mode_state_t lastTimingModeState;
int enable_timing_output;
deviceAttributesDegradation_t holdover;
deviceAttributesDegradation_t unlocked;
}clockDegradation_t;
/* Used to define all default PTP device attributes for a given clock class */
typedef struct {
int clockClass;
UInteger8 clock_quality_clockAccuracy;
UInteger8 timeSource;
UInteger16 clock_quality_offsetScaledLogVariance;
Boolean ptpTimeScale;
Boolean frequencyTraceable;
Boolean timeTraceable;
}defaultDeviceAttributes_t;
/* These structures can be patched to change the default behavior */
extern deviceAttributesDegradation_t deviceAttributesDegradation[];
extern defaultDeviceAttributes_t defaultDeviceAttributes[];
extern void bmc_set_default_device_attributes (struct pp_globals *ppg);
extern void bmc_update_clock_quality(struct pp_globals *ppg);
extern void bmc_apply_configured_device_attributes(struct pp_globals *ppg);
#endif /* USERSPACE_PPSI_INCLUDE_PPSI_BMC_H_ */
......@@ -87,25 +87,46 @@
#define PP_ARB_CLASS_GM_UNLOCKED_A 58 /* Path A */
#define PP_ARB_CLASS_GM_UNLOCKED_B 193 /* Path B */
#define PP_MIN_CLOCK_ACCURACY 0
#define PP_MAX_CLOCK_ACCURACY 255
#define PP_ACCURACY_DEFAULT 0xFE
#define PP_PTP_ACCURACY_GM_LOCKED 0x21
#define PP_PTP_ACCURACY_GM_HOLDOVER 0x21
#define PP_PTP_ACCURACY_GM_UNLOCKED 0xFE
#define PP_ARB_ACCURACY_GM_LOCKED 0x20
#define PP_ARB_ACCURACY_GM_HOLDOVER 0x20
#define PP_ARB_ACCURACY_GM_UNLOCKED 0xFE
#define PP_MIN_CLOCK_ACCURACY CLOCK_ACCURACY_MIN_VALUE
#define PP_MAX_CLOCK_ACCURACY CLOCK_ACCURACY_MAX_VALUE
#define PP_ACCURACY_DEFAULT CLOCK_ACCURACY_UNKNOWN
#define PP_PTP_ACCURACY_GM_LOCKED CLOCK_ACCURACY_100_NS
#define PP_PTP_ACCURACY_GM_HOLDOVER CLOCK_ACCURACY_100_NS
#define PP_PTP_ACCURACY_GM_UNLOCKED_A CLOCK_ACCURACY_UNKNOWN
#define PP_PTP_ACCURACY_GM_UNLOCKED_B CLOCK_ACCURACY_UNKNOWN
#define PP_ARB_ACCURACY_GM_LOCKED CLOCK_ACCURACY_25_NS
#define PP_ARB_ACCURACY_GM_HOLDOVER CLOCK_ACCURACY_25_NS
#define PP_ARB_ACCURACY_GM_UNLOCKED_A CLOCK_ACCURACY_25_NS
#define PP_ARB_ACCURACY_GM_UNLOCKED_B CLOCK_ACCURACY_25_NS
#define PP_MIN_CLOCK_VARIANCE 0
#define PP_MAX_CLOCK_VARIANCE 65535
#define PP_VARIANCE_DEFAULT 0xC71D
#define PP_PTP_VARIANCE_GM_LOCKED 0xB900
#define PP_PTP_VARIANCE_GM_HOLDOVER 0xC71D
#define PP_PTP_VARIANCE_GM_UNLOCKED 0xC71D
#define PP_PTP_VARIANCE_GM_UNLOCKED_A 0xC71D
#define PP_PTP_VARIANCE_GM_UNLOCKED_B 0xC71D
#define PP_ARB_VARIANCE_GM_LOCKED 0xB900
#define PP_ARB_VARIANCE_GM_HOLDOVER 0xC71D
#define PP_ARB_VARIANCE_GM_UNLOCKED 0xC71D
#define PP_ARB_VARIANCE_GM_UNLOCKED_A 0xC71D
#define PP_ARB_VARIANCE_GM_UNLOCKED_B 0xC71D
#define PP_MIN_TIME_SOURCE TIME_SRC_MIN_VALUE
#define PP_MAX_TIME_SOURCE TIME_SRC_MAX_VALUE
#define PP_TIME_SOURCE_DEFAULT TIME_SRC_INTERNAL_OSCILLATOR
#define PP_PTP_TIME_SOURCE_GM_LOCKED TIME_SRC_GNSS
#define PP_PTP_TIME_SOURCE_GM_HOLDOVER TIME_SRC_INTERNAL_OSCILLATOR
#define PP_PTP_TIME_SOURCE_GM_UNLOCKED_A TIME_SRC_INTERNAL_OSCILLATOR
#define PP_PTP_TIME_SOURCE_GM_UNLOCKED_B TIME_SRC_INTERNAL_OSCILLATOR
#define PP_ARB_TIME_SOURCE_GM_LOCKED TIME_SRC_ATOMIC_CLOCK
#define PP_ARB_TIME_SOURCE_GM_HOLDOVER TIME_SRC_INTERNAL_OSCILLATOR
#define PP_ARB_TIME_SOURCE_GM_UNLOCKED_A TIME_SRC_INTERNAL_OSCILLATOR
#define PP_ARB_TIME_SOURCE_GM_UNLOCKED_B TIME_SRC_INTERNAL_OSCILLATOR
/* Free running master */
#define PP_FRUNNING_CLOCK_CLASS PP_ARB_CLASS_GM_UNLOCKED_B
#define PP_FRUNNING_CLOCK_VARIANCE PP_ARB_VARIANCE_GM_UNLOCKED
#define PP_FRUNNING_CLOCK_ACCURACY PP_ARB_ACCURACY_GM_UNLOCKED
#define PP_NR_FOREIGN_RECORDS CONFIG_NR_FOREIGN_RECORDS /* Clause 9.3.2.4.5 */
#define PP_FOREIGN_MASTER_TIME_WINDOW 4
......
......@@ -406,14 +406,17 @@ enum ENNetworkProtocol {
/* Enumeration Time Source (table 7, page 57) */
enum ENTimeSource {
ATOMIC_CLOCK = 0x10,
GPS = 0x20,
TERRESTRIAL_RADIO = 0x30,
PTP = 0x40,
NTP = 0x50,
HAND_SET = 0x60,
OTHER = 0x90,
INTERNAL_OSCILLATOR = 0xA0
TIME_SRC_MIN_VALUE = 0x10,
TIME_SRC_ATOMIC_CLOCK = 0x10,
TIME_SRC_GNSS = 0x20,
TIME_SRC_TERRESTRIAL_RADIO = 0x30,
TIME_SRC_SERIAL_TIME_CODE = 0x39,
TIME_SRC_PTP = 0x40,
TIME_SRC_NTP = 0x50,
TIME_SRC_HAND_SET = 0x60,
TIME_SRC_OTHER = 0x90,
TIME_SRC_INTERNAL_OSCILLATOR= 0xA0,
TIME_SRC_MAX_VALUE = 0xFF
};
/* Enumeration Delay mechanism (table 21, page 126) */
......@@ -425,4 +428,38 @@ enum ENDelayMechanism {
NO_MECHANISM = 0xFE
};
/* clockAccuracy enumeration (table 5) */
enum ENClockAccuracy {
CLOCK_ACCURACY_MIN_VALUE=0,
CLOCK_ACCURACY_1PS = 0x17,
CLOCK_ACCURACY_2_5_PS,
CLOCK_ACCURACY_10_PS,
CLOCK_ACCURACY_25_PS,
CLOCK_ACCURACY_100_PS,
CLOCK_ACCURACY_250_PS,
CLOCK_ACCURACY_1_NS,
CLOCK_ACCURACY_2_5_NS,
CLOCK_ACCURACY_10_NS,
CLOCK_ACCURACY_25_NS,
CLOCK_ACCURACY_100_NS,
CLOCK_ACCURACY_250_NS,
CLOCK_ACCURACY_1_US,
CLOCK_ACCURACY_2_5_US,
CLOCK_ACCURACY_10_US,
CLOCK_ACCURACY_25_US,
CLOCK_ACCURACY_100_US,
CLOCK_ACCURACY_250_US,
CLOCK_ACCURACY_1_MS,
CLOCK_ACCURACY_2_5_MS,
CLOCK_ACCURACY_10_MS,
CLOCK_ACCURACY_25_MS,
CLOCK_ACCURACY_100_MS,
CLOCK_ACCURACY_250_MS,
CLOCK_ACCURACY_1_S,
CLOCK_ACCURACY_10_S,
CLOCK_ACCURACY_GREATER_10_S,
CLOCK_ACCURACY_UNKNOWN = 0xFE,
CLOCK_ACCURACY_MAX_VALUE
};
#endif /* __PPSI_IEEE_1588_TYPES_H__ */
......@@ -19,6 +19,10 @@ struct pp_runtime_opts {
int clock_quality_clockClass; // ClockQuality.clockClass
int clock_quality_clockAccuracy; // ClockQuality.clockAccuracy
int clock_quality_offsetScaledLogVariance; // ClockQuality.offsetScaledLogVariance
int timeSource; // timePropertiesDS_t.timeSource
Boolean ptpTimeScale; // timePropertiesDS_t.timeSource
Boolean frequencyTraceable; // timePropertiesDS_t.frequencyTraceable
Boolean timeTraceable; // timePropertiesDS_t.timeTraceable
Integer32 ttl;
int flags; /* see below */
Integer16 ap, ai;
......
......@@ -21,6 +21,7 @@
#include <ppsi/timeout_def.h>
#include <ppsi/pp-instance.h>
#include <ppsi/diag-macros.h>
#include <ppsi/bmc.h>
#include <arch/arch.h> /* ntohs and so on -- and wr-api.h for wr archs */
......@@ -144,6 +145,11 @@ static inline timePropertiesDS_t *DSPRO(struct pp_instance *ppi)
return GLBS(ppi)->timePropertiesDS;
}
static inline timePropertiesDS_t *GDSPRO(struct pp_globals *ppg)
{
return ppg->timePropertiesDS;
}
static inline struct pp_time_operations *TOPS(struct pp_instance *ppi) {
return ppi->t_ops;
}
......@@ -244,12 +250,6 @@ extern struct pp_network_operations DEFAULT_NET_OPS;
/* These can be liked and used as fallback by a different timing engine */
extern struct pp_network_operations unix_net_ops;
typedef enum {
PP_TIMING_MODE_STATE_UNLOCKED=0,
PP_TIMING_MODE_STATE_HOLDOVER,
PP_TIMING_MODE_STATE_LOCKED,
}pp_timing_mode_state_t;
/*
* Time operations, like network operations above, are encapsulated.
* They may live in their own time-<name> subdirectory.
......
......@@ -370,6 +370,8 @@ static struct pp_argline pp_global_arglines[] = {
PP_MIN_CLOCK_ACCURACY,PP_MAX_CLOCK_ACCURACY),
RT_OPTION_INT_RANGE("clock-allan-variance", ARG_INT, NULL,clock_quality_offsetScaledLogVariance,
PP_MIN_CLOCK_VARIANCE,PP_MAX_CLOCK_VARIANCE),
RT_OPTION_INT_RANGE("time-source", ARG_INT, NULL, timeSource,
PP_MIN_TIME_SOURCE,PP_MAX_TIME_SOURCE),
RT_OPTION_INT_RANGE("domain-number", ARG_INT, NULL, domainNumber,
PP_MIN_DOMAIN_NUMBER,PP_MAX_DOMAIN_NUMBER),
RT_OPTION_INT_RANGE("priority1", ARG_INT, NULL, priority1,
......
......@@ -14,6 +14,7 @@ OBJ-y += $D/fsm-table.o \
$D/state-slave.o \
$D/common-fun.o \
$D/common-fun-p2p.o \
$D/bmc_clock_quality.o \
$D/bmc.o \
$D/msg.o \
$D/msg-p2p.o \
......
......@@ -27,7 +27,6 @@ void bmc_m1(struct pp_instance *ppi)
parentDS_t *parent = DSPAR(ppi);
defaultDS_t *defds = DSDEF(ppi);
timePropertiesDS_t *prop = DSPRO(ppi);
UInteger8 clockClass;
int ret = 0;
int offset, leap59, leap61;
......@@ -49,31 +48,6 @@ void bmc_m1(struct pp_instance *ppi)
parent->grandmasterPriority1 = defds->priority1;
parent->grandmasterPriority2 = defds->priority2;
/**
* This table describes how the time properties are set :
*
* field\clockClass | GM_LOCKED | GM_HOLDOVER | GM_UNLOCKED_A| DEFAULT
* ---------------------------------------------------------------------------
* ptpTimescale | TRUE | TRUE | TRUE | FALSE
* timeSource | GPS | INTERNAL_OSC | INTERNAL_OSC | INTERNAL_OSC
* frequencyTraceable | TRUE | TRUE | FALSE | FALSE
* timeTraceable | TRUE | TRUE | FALSE | FALSE
*/
clockClass=defds->clockQuality.clockClass;
prop->timeSource= clockClass==PP_PTP_CLASS_GM_LOCKED ?
GPS : INTERNAL_OSCILLATOR;
prop->ptpTimescale=
((clockClass== PP_PTP_CLASS_GM_LOCKED) ||
(clockClass== PP_PTP_CLASS_GM_HOLDOVER) ||
(clockClass== PP_PTP_CLASS_GM_UNLOCKED_A))
? TRUE : FALSE;
prop->frequencyTraceable=
prop->timeTraceable=
((clockClass== PP_PTP_CLASS_GM_LOCKED) ||
(clockClass== PP_PTP_CLASS_GM_HOLDOVER))
? TRUE : FALSE;
/* Set currentUtcOffset and currentUtcOffsetValid
* If they cannot be set properly, frequencyTraceable & timeTraceable are cleared
*/
......@@ -95,11 +69,9 @@ void bmc_m1(struct pp_instance *ppi)
if (ret)
{
prop->frequencyTraceable=
prop->timeTraceable = FALSE; /* Clear them if they were set */
prop->currentUtcOffsetValid = FALSE;
prop->leap59 = FALSE;
prop->leap61 = FALSE;
prop->currentUtcOffsetValid =
prop->leap59 =
prop->leap61 = FALSE;
}
else
{
......@@ -111,9 +83,9 @@ void bmc_m1(struct pp_instance *ppi)
/* 9.4 for ARB just take the value when built */
prop->currentUtcOffset = PP_DEFAULT_UTC_OFFSET;
/* always false */
prop->currentUtcOffsetValid = FALSE;
prop->leap59 = FALSE;
prop->leap61 = FALSE;
prop->currentUtcOffsetValid =
prop->leap59 =
prop->leap61 = FALSE;
}
}
......@@ -345,7 +317,7 @@ static void bmc_setup_local_frgn_master(struct pp_instance *ppi,
memcpy(&frgn_master->grandmasterIdentity,
&DSDEF(ppi)->clockIdentity, sizeof(ClockIdentity));
frgn_master->stepsRemoved = 0;
frgn_master->timeSource = INTERNAL_OSCILLATOR; //TODO get this from somewhere
frgn_master->timeSource = TIME_SRC_INTERNAL_OSCILLATOR; //TODO get this from somewhere
frgn_master->ext_specific = 0;
}
......@@ -1316,150 +1288,6 @@ static void bmc_update_ebest(struct pp_globals *ppg)
}
void bmc_update_clock_quality(struct pp_globals *ppg)
{
char *pp_diag_msg;
struct pp_runtime_opts *rt_opts = ppg->rt_opts;
int rt_opts_clock_quality_clockClass=rt_opts->clock_quality_clockClass;
int defaultDS_clock_quality_clockClass=ppg->defaultDS->clockQuality.clockClass;
pp_timing_mode_state_t timing_mode_state;
static struct oper_t {
pp_timing_mode_state_t timing_mode_state;
int reqClockQuality;
ClockQuality clockQuality;
char *msg;
int enable_timing_output;
} oper[]= {
{
.timing_mode_state=PP_TIMING_MODE_STATE_LOCKED,
.reqClockQuality=PP_PTP_CLASS_GM_LOCKED,
.clockQuality={
.clockClass=PP_PTP_CLASS_GM_LOCKED,
.clockAccuracy=PP_PTP_ACCURACY_GM_LOCKED,
.offsetScaledLogVariance=PP_PTP_VARIANCE_GM_LOCKED,
},
.msg="locked",
.enable_timing_output=1
},
{
.timing_mode_state=PP_TIMING_MODE_STATE_LOCKED,
.reqClockQuality=PP_ARB_CLASS_GM_LOCKED,
.clockQuality={
.clockClass=PP_ARB_CLASS_GM_LOCKED,
.clockAccuracy=PP_ARB_ACCURACY_GM_LOCKED,
.offsetScaledLogVariance=PP_ARB_VARIANCE_GM_LOCKED,
},
.msg="locked",
},
{
.timing_mode_state=PP_TIMING_MODE_STATE_HOLDOVER,
.reqClockQuality=PP_PTP_CLASS_GM_LOCKED,
.clockQuality={
.clockClass=PP_PTP_CLASS_GM_HOLDOVER,
.clockAccuracy=PP_PTP_ACCURACY_GM_HOLDOVER,
.offsetScaledLogVariance=PP_PTP_VARIANCE_GM_HOLDOVER,
},
.msg="holdover",
},
{
.timing_mode_state=PP_TIMING_MODE_STATE_HOLDOVER,
.reqClockQuality=PP_ARB_CLASS_GM_LOCKED,
.clockQuality={
.clockClass=PP_ARB_CLASS_GM_HOLDOVER,
.clockAccuracy=PP_ARB_ACCURACY_GM_HOLDOVER,
.offsetScaledLogVariance=PP_ARB_VARIANCE_GM_HOLDOVER,
},
.msg="holdover",
},
{
.timing_mode_state=PP_TIMING_MODE_STATE_UNLOCKED,
.reqClockQuality=PP_PTP_CLASS_GM_LOCKED,
.clockQuality={
.clockClass=PP_PTP_CLASS_GM_UNLOCKED_B,
.clockAccuracy=PP_PTP_ACCURACY_GM_UNLOCKED,
.offsetScaledLogVariance=PP_PTP_VARIANCE_GM_UNLOCKED,
},
.msg="unlocked",
},
{
.timing_mode_state=PP_TIMING_MODE_STATE_UNLOCKED,
.reqClockQuality=PP_ARB_CLASS_GM_LOCKED,
.clockQuality={
.clockClass=PP_ARB_CLASS_GM_UNLOCKED_B,
.clockAccuracy=PP_ARB_ACCURACY_GM_UNLOCKED,
.offsetScaledLogVariance=PP_ARB_VARIANCE_GM_UNLOCKED,
},
.msg="unlocked",
}
};
/* We are only interested on configured clock class PP_PTP_CLASS_GM_LOCKED and PP_ARB_CLASS_GM_LOCKED */
if ( rt_opts_clock_quality_clockClass > PP_MAX_VALUE_GM )
return ; /* Exclude also PP_PTP_CLASS_GM_UNLOCKED_B and PP_ARB_CLASS_GM_UNLOCKED_B */
switch (rt_opts_clock_quality_clockClass ) {
case PP_PTP_CLASS_GM_LOCKED :
case PP_ARB_CLASS_GM_LOCKED :
pp_diag(NULL, bmc, 2,
"GM locked class configured, checking PLL locking\n");
break;
case PP_PTP_CLASS_GM_UNLOCKED_A :
case PP_ARB_CLASS_GM_UNLOCKED_A :
pp_diag(NULL, bmc, 2,
"GM unlocked class configured, skipping checking PLL locking\n");
return;
default :
pp_diag(NULL, bmc, 2,
"GM unknown clock class configured, skipping checking PLL locking\n");
return;
}
/* Get the clock status ( locked, holdover, unlocked ) */
if (TOPS(INST(ppg,0))->get_GM_lock_state(ppg,&timing_mode_state) ) {
pp_diag(NULL, bmc, 1,
"Could not get GM locking state, taking old clock class: %i\n",
ppg->defaultDS->clockQuality.clockClass);
return;
}
pp_diag_clear_msg(pp_diag_msg);
{
struct oper_t *p=oper;
int i;
for (i=0; i<ARRAY_SIZE(oper); i++ ) {
if ( p->timing_mode_state==timing_mode_state &&
rt_opts_clock_quality_clockClass==p->reqClockQuality &&
defaultDS_clock_quality_clockClass!=p->clockQuality.clockClass) {
ppg->defaultDS->clockQuality=p->clockQuality;
pp_diag_set_msg(pp_diag_msg,p->msg);
if ( p->enable_timing_output)
TOPS(INST(ppg,0))->enable_timing_output(ppg,1); /* Enable PPS generation */
break;
}
p++;
}
if ( i > ARRAY_SIZE(oper) )
pp_diag(NULL, bmc, 2,
"Unknown timing mode state, taking old clock class: %i\n",
defaultDS_clock_quality_clockClass);
}
if ( pp_diag_is_msg_set(pp_diag_msg) ) {
pp_diag(NULL, bmc, 1,
"Timing mode: %s, "
"new clock class: %i, "
"new clock accuracy: %i, "
"new clock variance: %04x\n",
pp_diag_get_msg(pp_diag_msg),
ppg->defaultDS->clockQuality.clockClass,
ppg->defaultDS->clockQuality.clockAccuracy,
ppg->defaultDS->clockQuality.offsetScaledLogVariance);
}
}
void bmc_calculate_ebest(struct pp_globals *ppg)
{
int i;
......
This diff is collapsed.
......@@ -13,8 +13,12 @@
*/
struct pp_runtime_opts __pp_default_rt_opts = {
.clock_quality_clockClass = PP_CLASS_DEFAULT,
.clock_quality_clockAccuracy = PP_ACCURACY_DEFAULT,
.clock_quality_offsetScaledLogVariance = PP_VARIANCE_DEFAULT,
.clock_quality_clockAccuracy = -1, // Not defined
.clock_quality_offsetScaledLogVariance = -1, // Not defined
.timeSource = -1, // Not defined
.ptpTimeScale=-1, // Not defined
.frequencyTraceable=-1, // Not defined
.timeTraceable=-1, // Not defined
.flags = PP_DEFAULT_FLAGS,
.ap = PP_DEFAULT_AP,
.ai = PP_DEFAULT_AI,
......@@ -88,10 +92,10 @@ int pp_init_globals(struct pp_globals *ppg, struct pp_runtime_opts *pp_rt_opts)
rt_opts = ppg->rt_opts;
// Copy clock quality
def->clockQuality.clockClass=rt_opts->clock_quality_clockClass;
def->clockQuality.clockAccuracy=rt_opts->clock_quality_clockAccuracy;
def->clockQuality.offsetScaledLogVariance=rt_opts->clock_quality_offsetScaledLogVariance;
// Update the default attributes depending on the clock class in the configuration structure
bmc_set_default_device_attributes(ppg);
// Update defaultDS & timePropertiesDS with configured setting (clockClass,...)
bmc_apply_configured_device_attributes(ppg);
/* Clause 17.6.5.3 : Clause 9.2.2 shall not be in effect. If implemented, defaultDS.slaveOnly should be FALSE, and
* portDS.masterOnly should be FALSE on all PTP Ports of the PTP Instance.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment