Commit a45008ca authored by Jean-Claude BAU's avatar Jean-Claude BAU Committed by Adam Wujek

High Accuracy - Second implementation

This implementation does not include yet the possibility to declare 2
exclusive instances on a same port (WR & HA)
- Some structures are renamed with the suffix _t to make it more
readable.
- Some variables are renamed  to be more clear
- Implementation of masterOnly, slaveOnly and externalPortConfiguration
- All extension specific includes (XX-api.h) is now automatically
included in ppsi.h and do not need to be included in other files.
parent e0b61c86
......@@ -88,10 +88,10 @@ struct sim_ppi_arch_data {
/* Runtime options */
struct pp_runtime_opts *rt_opts;
/* Data sets */
DSDefault *defaultDS;
DSCurrent *currentDS;
DSParent *parentDS;
DSTimeProperties *timePropertiesDS;
defaultDS_t *defaultDS;
currentDS_t *currentDS;
[parentDS_t *parentDS;
timePropertiesDS_t *timePropertiesDS;
/* other pp_instance, used in net ops */
struct pp_instance *other_ppi;
};
......
......@@ -20,11 +20,11 @@ static struct pp_runtime_opts sim_master_rt_opts = {
.ap = PP_DEFAULT_AP,
.ai = PP_DEFAULT_AI,
.s = PP_DEFAULT_DELAY_S,
.announce_intvl = PP_DEFAULT_ANNOUNCE_INTERVAL,
.sync_intvl = PP_DEFAULT_SYNC_INTERVAL,
.prio1 = PP_DEFAULT_PRIORITY1,
.prio2 = PP_DEFAULT_PRIORITY2,
.domain_number = PP_DEFAULT_DOMAIN_NUMBER,
.logAnnounceInterval = PP_DEFAULT_ANNOUNCE_INTERVAL,
.logSyncInterval = PP_DEFAULT_SYNC_INTERVAL,
.priority1 = PP_DEFAULT_PRIORITY1,
.priority2 = PP_DEFAULT_PRIORITY2,
.domainNumber = PP_DEFAULT_DOMAIN_NUMBER,
.ttl = PP_DEFAULT_TTL,
};
......@@ -142,7 +142,7 @@ int main(int argc, char **argv)
sim_set_global_DS(ppi);
ppi->iface_name = ppi->cfg.iface_name;
ppi->port_name = ppi->cfg.port_name;
ppi->mech = ppi->cfg.mech;
ppi->delayMechanism = ppi->cfg.delayMechanism;
if (ppi->proto == PPSI_PROTO_RAW)
pp_printf("Warning: simulator doesn't support raw "
"ethernet. Using UDP\n");
......
......@@ -25,10 +25,10 @@
/* ppg and fields */
static struct pp_globals ppg_static;
static DSDefault defaultDS;
static DSCurrent currentDS;
static DSParent parentDS;
static DSTimeProperties timePropertiesDS;
static defaultDS_t defaultDS;
static currentDS_t currentDS;
static [parentDS_t parentDS;
static timePropertiesDS_t timePropertiesDS;
static struct pp_servo servo;
extern struct pp_ext_hooks pp_hooks;
......
......@@ -24,7 +24,8 @@ OBJ-y += \
$A/wrc_ptp_ppsi.o \
lib/dump-funcs.o \
lib/drop.o \
lib/div64.o
lib/div64.o \
lib/time-arith.o
OBJ-$(CONFIG_WRPC_FAULTS) += $A/faults.o
......
......@@ -48,10 +48,10 @@ struct wrh_operations wrh_oper = {
};
/*ppi fields*/
static DSDefault defaultDS;
static DSCurrent currentDS;
static DSParent parentDS;
static DSTimeProperties timePropertiesDS;
static defaultDS_t defaultDS;
static currentDS_t currentDS;
static [parentDS_t parentDS;
static timePropertiesDS_t timePropertiesDS;
static struct pp_servo servo;
......@@ -65,7 +65,7 @@ static struct wr_data wr_ext_data; /* WR extension data */
static struct wr_dsport wr_dsport;
#endif
static DSPort portDS ;
static portDS_t portDS ;
static int delay_ms = PP_DEFAULT_NEXT_DELAY_MS;
static int start_tics = 0;
......@@ -117,7 +117,6 @@ int wrc_ptp_init()
ppi->ext_hooks = &wr_ext_hooks;
ppi->ext_data = &wr_ext_data;
wr_ext_data->servo_state.servo_head.extension=PPSI_EXT_WR;
GBLS(ppi)->global_ext_data=&wr_ext_data.servo_state; /* Updated for the WR monitor tools */
portDS.ext_dsport = &wr_dsport;
}
......
......@@ -73,7 +73,7 @@ int wrpc_calibrating_poll(struct pp_instance *ppi, int txrx, uint32_t *delta)
/* FIXME: why delta was 64bit whereas ep_get_deltas accepts 32bit? */
wrpc_read_calibration_data(ppi, &delta_tx, &delta_rx, NULL, NULL);
if (txrx == WR_HW_CALIB_TX)
if (txrx == WRH_HW_CALIB_TX)
*delta = delta_tx;
else
*delta = delta_rx;
......
......@@ -11,6 +11,8 @@
#include <softpll_ng.h>
#include "../proto-ext-whiterabbit/wr-constants.h"
#include <rxts_calibrator.h>
#include "../include/hw-specific/wrh.h"
#include "wrpc.h"
extern uint32_t cal_phase_transition;
......@@ -20,7 +22,7 @@ int wrpc_spll_locking_enable(struct pp_instance *ppi)
spll_init(SPLL_MODE_SLAVE, 0, 1);
spll_enable_ptracker(0, 1);
rxts_calibration_start();
return WR_SPLL_OK;
return WRH_SPLL_OK;
}
int wrpc_spll_locking_poll(struct pp_instance *ppi, int grandmaster)
......@@ -31,7 +33,7 @@ int wrpc_spll_locking_poll(struct pp_instance *ppi, int grandmaster)
locked = spll_check_lock(0); /* both slave and gm mode */
if (grandmaster)
return locked ? WR_SPLL_READY : WR_SPLL_ERROR;
return locked ? WRH_SPLL_READY : WRH_SPLL_ERROR;
/* Else, slave: ensure calibration is done */
if(!locked) {
......@@ -40,30 +42,30 @@ int wrpc_spll_locking_poll(struct pp_instance *ppi, int grandmaster)
else if(locked && !t24p_calibrated) {
/*run t24p calibration if needed*/
if (calib_t24p(WRC_MODE_SLAVE, &cal_phase_transition) < 0)
return WR_SPLL_CALIB_NOT_READY;
return WRH_SPLL_CALIB_NOT_READY;
t24p_calibrated = 1;
}
return locked ? WR_SPLL_READY : WR_SPLL_ERROR;
return locked ? WRH_SPLL_READY : WRH_SPLL_ERROR;
}
int wrpc_spll_locking_reset(struct pp_instance *ppi)
{
//TODO?
return WR_SPLL_OK;
return WRH_SPLL_OK;
}
int wrpc_spll_locking_disable(struct pp_instance *ppi)
{
/* softpll_disable(); */
return WR_SPLL_OK;
return WRH_SPLL_OK;
}
int wrpc_spll_enable_ptracker(struct pp_instance *ppi)
{
spll_enable_ptracker(0, 1);
return WR_SPLL_OK;
return WRH_SPLL_OK;
}
int wrpc_enable_timing_output(struct pp_instance *ppi, int enable)
......@@ -73,7 +75,7 @@ int wrpc_enable_timing_output(struct pp_instance *ppi, int enable)
WR_DSPOR(ppi)->ppsOutputOn = enable;
shw_pps_gen_enable_output(enable);
return WR_SPLL_OK;
return WRH_SPLL_OK;
}
int wrpc_adjust_in_progress(void)
......@@ -93,6 +95,6 @@ int wrpc_adjust_counters(int64_t adjust_sec, int32_t adjust_nsec)
int wrpc_adjust_phase(int32_t phase_ps)
{
spll_set_phase_shift(SPLL_ALL_CHANNELS, phase_ps);
return WR_SPLL_OK;
return WRH_SPLL_OK;
}
......@@ -51,7 +51,7 @@ int wrpc_spll_enable_ptracker(struct pp_instance *ppi);
int wrpc_adjust_in_progress(void);
int wrpc_adjust_counters(int64_t adjust_sec, int32_t adjust_nsec);
int wrpc_adjust_phase(int32_t phase_ps);
int wrpc_enable_timing_output(struct pp_instance *ppi, int enable);
int wrpc_enable_timing_output(struct pp_instance *ppi, int *ppsOutputOn, int enable);
/* wrpc-calibration.c */
int wrpc_read_calibration_data(struct pp_instance *ppi,
......
......@@ -74,9 +74,6 @@ struct hal_port_state {
int fd;
int hw_addr_auto;
/* port timing mode (HEXP_PORT_MODE_xxxx) */
int mode;
/* port FSM state (HAL_PORT_STATE_xxxx) */
int state;
......
......@@ -13,6 +13,9 @@
#include <libwr/shmem.h>
#include <libwr/hal_shmem.h>
#define WRS_NUMBER_PHYSICAL_PORTS 18 /* Number of physical ports on a WR switch */
extern struct minipc_ch *hal_ch;
extern struct minipc_ch *ppsi_ch;
extern struct hal_port_state *hal_ports;
......
......@@ -16,7 +16,6 @@
#include <ppsi/ppsi.h>
#include <ppsi-wrs.h>
#include <wr-api.h>
#include <hal_exports.h>
#include <common-fun.h>
......
......@@ -8,7 +8,6 @@
#include <ppsi/ppsi.h>
#include <ppsi-wrs.h>
#include <hal_exports.h>
#include <wr-api.h>
/* minipc Encoding of the supported commands */
......
......@@ -28,9 +28,6 @@
#include <ppsi-wrs.h>
#include <libwr/shmem.h>
#include "../proto-ext-whiterabbit/wr-api.h"
#include "../proto-ext-l1sync/l1e-api.h"
# define WRSW_HAL_RETRIES 1000
#define WRSW_HAL_TIMEOUT 2000000 /* us */
......@@ -217,14 +214,14 @@ int main(int argc, char **argv)
char s[128];
int i;
for (i = 0; i < 18; i++) {
for (i = 0; i < WRS_NUMBER_PHYSICAL_PORTS; i++) {
Boolean configured=FALSE;
#if CONFIG_EXT_L1SYNC == 1
#if CONFIG_PROFILE_HA == 1
sprintf(s, "port %i; iface wri%i; proto raw;"
"profile ha; role auto", i + 1, i + 1);
configured=TRUE;
#endif
#if CONFIG_EXT_WR == 1
#if CONFIG_PROFILE_WR == 1
if ( ! configured )
sprintf(s, "port %i; iface wri%i; proto raw;"
"profile wr; role auto", i + 1, i + 1);
......@@ -243,9 +240,10 @@ int main(int argc, char **argv)
ppi->port_name = ppi->cfg.port_name;
ppi->delayMechanism = ppi->cfg.delayMechanism;
ppi->portDS = alloc_fn(ppsi_head, sizeof(*ppi->portDS));
ppi->servo = alloc_fn(ppsi_head, sizeof(*ppi->servo));
ppi->ext_hooks=&pp_hooks; /* Default value. Can be overwritten by an extension */
if (ppi->portDS) {
#if CONFIG_EXT_WR == 1
#if CONFIG_PROFILE_WR == 1
if ( ppi->cfg.profile==PPSI_PROFILE_WR ) {
ppi->protocol_extension=PPSI_EXT_WR;
/* Add WR extension portDS */
......@@ -262,7 +260,7 @@ int main(int argc, char **argv)
ppi->ext_hooks=&wr_ext_hooks;
}
#endif
#if CONFIG_EXT_L1SYNC == 1
#if CONFIG_PROFILE_HA == 1
if ( ppi->cfg.profile==PPSI_PROFILE_HA ) {
ppi->protocol_extension=PPSI_EXT_L1S;
/* Add L1E extension portDS */
......@@ -281,13 +279,20 @@ int main(int argc, char **argv)
ppi->asymmetryCorrectionPortDS.constantAsymmetry=picos_to_interval(ppi->cfg.constantAsymmetry_ps);
ppi->asymmetryCorrectionPortDS.scaledDelayCoefficient=
(RelativeDifference)(ppi->cfg.delayCoefficient * (double)pow(2.0, REL_DIFF_FRACBITS_AS_FLOAT));
/* Set L1SYNC portDS */
L1E_DSPOR_BS(ppi)->logL1SyncInterval=ppi->cfg.l1sync_interval;
L1E_DSPOR_BS(ppi)->L1SyncReceiptTimeout=ppi->cfg.l1sync_receipt_timeout;
/* Set L1SYNC extension hooks */
ppi->ext_hooks=&l1e_ext_hooks;
/* Set default profile parameters */
ppg->defaultDS->externalPortConfigurationEnabled = 1;
ppi->portDS->masterOnly = 0;
}
#endif
ppi->portDS->masterOnly= ppi->cfg.masterOnly; /* can be overridden in pp_init_globals() */
ppi->portDS->logAnnounceInterval=ppi->cfg.announce_interval;
ppi->portDS->announceReceiptTimeout=ppi->cfg.announce_receipt_timeout;
ppi->portDS->logSyncInterval=ppi->cfg.sync_interval;
ppi->portDS->logMinDelayReqInterval=ppi->cfg.min_delay_req_interval;
ppi->portDS->logMinPdelayReqInterval=ppi->cfg.min_pdelay_req_interval;
} else {
goto exit_out_of_memory;
}
......
......@@ -164,7 +164,7 @@ static int pp_packet_prefilter(struct pp_instance *ppi)
sizeof(ClockIdentity))) {
if (DSDEF(ppi)->numberPorts > 1) {
/* Announces are handled by the BMC, since otherwise the state
* also the PASSIVE states in this case is overwritten */
* also the PASSIVE states in this case is overwritten */
if (hdr->messageType != PPM_ANNOUNCE) {
/* ignore messages, except announce coming from its own clock */
return -1;
......@@ -225,7 +225,7 @@ int pp_state_machine(struct pp_instance *ppi, void *buf, int len)
"RECV %02d bytes at %9d.%09d.%03d (type %x, %s)\n",
len, (int)t->secs, (int)(t->scaled_nsecs >> 16),
((int)(t->scaled_nsecs & 0xffff) * 1000) >> 16,
msgtype, pp_msgtype_info[msgtype].name);
msgtype, pp_msgtype_name[msgtype]);
}
/*
......@@ -298,12 +298,12 @@ int pp_state_machine(struct pp_instance *ppi, void *buf, int len)
return pp_leave_current_state(ppi);
}
pp_diag_fsm(ppi, ip->name, STATE_LOOP, 0);
/* check if the BMC timeout is the next to run */
if (pp_next_delay_1(ppi, PP_TO_BMC) < ppi->next_delay)
ppi->next_delay = pp_next_delay_1(ppi, PP_TO_BMC);
pp_diag_fsm(ppi, ip->name, STATE_LOOP, 0);
/* Run the extension state machine. The extension can provide its own time-out */
if ( ppi->ext_hooks->run_ext_state_machine) {
int delay = ppi->ext_hooks->run_ext_state_machine(ppi);
......
......@@ -13,7 +13,7 @@
#include <ppsi/lib.h>
/* Please increment WRS_PPSI_SHMEM_VERSION if you change any exported data structure */
#define WRS_PPSI_SHMEM_VERSION 31 /* changed wrs_shm_head */
#define WRS_PPSI_SHMEM_VERSION 32 /* added HAL_PORT_STATE_RESET to hal */
/* White Rabbit softpll status values */
#define WRH_SPLL_OK 0
......
......@@ -187,7 +187,7 @@ typedef struct MsgPDelayRespFollowUp {
PortIdentity requestingPortIdentity;
} MsgPDelayRespFollowUp;
/* Signaling Message (table 33, page 133) */
/* Signaling Message (Table 51 : Signaling message fields) */
typedef struct MsgSignaling {
PortIdentity targetPortIdentity;
char *tlv;
......@@ -218,7 +218,7 @@ typedef struct { /* page 65 */
/** Optional (IEEE1588-2018) */
Timestamp currentTime; /*draft P1588_v_29: page 85*/
Boolean instanceEnable; /*draft P1588_v_29: page 86*/
Enumeration8 externalPortConfigurationEnabled; /*draft P1588_v_29: page 86*/
Boolean externalPortConfigurationEnabled; /*draft P1588_v_29: page 86*/
Enumeration8 maxStepsRemoved; /*draft P1588_v_29: page 86 (bug)*/
Enumeration8 SdoId; /*draft P1588_v_29: page 86 (bug)*/
Enumeration8 instanceType; /*draft P1588_v_29: page 86 */
......@@ -332,6 +332,10 @@ typedef struct { /*draft P1588_v_29: page129*/
RelativeDifference scaledDelayCoefficient;
} asymmetryCorrectionPortDS_t;
typedef struct {/*draft P1588_v_29: Clause 17.6.3 */
Enumeration8 desiredState; /* draft P1588_v_29: Clause 17.6.3.2 */
}externalPortConfigurationPortDS_t;
/** ************************************************************************/
/* Enumeration States (table 8, page 73) */
enum pp_std_states {
......
......@@ -24,6 +24,7 @@ struct pp_runtime_opts {
int priority1;
int priority2;
int domainNumber;
Boolean externalPortConfigurationEnabled;
void *arch_opts;
};
......@@ -204,11 +205,11 @@ struct pp_instance {
portDS_t *portDS; /* page 72 */
struct pp_servo *servo; /* Servo moved from globals because we may have more than one servo : redundancy */
/** (IEEE1588-2018) */
/** (IEEE1588-2019) */
asymmetryCorrectionPortDS_t asymmetryCorrectionPortDS; /*draft P1588_v_29: page 99*/
timestampCorrectionPortDS_t timestampCorrectionPortDS; /*draft P1588_v_29: page 99*/
/** *********************** */
externalPortConfigurationPortDS_t externalPortConfigurationPortDS; /*draft P1588: Clause 17.6.3*/
/************************* */
unsigned long timeouts[__PP_TO_ARRAY_SIZE];
UInteger16 recv_sync_sequence_id;
......
......@@ -23,6 +23,14 @@
#include <arch/arch.h> /* ntohs and so on -- and wr-api.h for wr archs */
#if CONFIG_EXT_WR==1
#include "../proto-ext-whiterabbit/wr-api.h"
#endif
#if CONFIG_EXT_L1SYNC==1
#include "../proto-ext-l1sync/l1e-api.h"
#endif
/* At this point in time, we need ARRAY_SIZE to conditionally build vlan code */
#undef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
......
......@@ -23,11 +23,11 @@ void ppsi_clear_bss(void)
}
/* ppg fields */
static DSDefault defaultDS;
static DSCurrent currentDS;
static DSParent parentDS;
static DSPort portDS;
static DSTimeProperties timePropertiesDS;
static defaultDS_t defaultDS;
static currentDS_t currentDS;
static [parentDS_t parentDS;
static portDS_t portDS;
static timePropertiesDS_t timePropertiesDS;
static struct pp_servo servo;
static struct pp_globals ppg_static; /* forward declaration */
......@@ -43,7 +43,7 @@ static struct pp_instance ppi_static = {
.port_name = "eth0",
.vlans_array_len = CONFIG_VLAN_ARRAY_SIZE,
.proto = PP_DEFAULT_PROTO,
.mech = CONFIG_HAS_P2P ? PP_P2P_MECH : PP_E2E_MECH,
.delayMechanism = CONFIG_HAS_P2P ? P2P : E2E,
.__tx_buffer = __tx_buffer,
.__rx_buffer = __rx_buffer,
};
......
......@@ -119,7 +119,7 @@ void pp_time_hardwarize(struct pp_time *time, int clock_period_ps,
ps = time->scaled_nsecs & 0xffff; /* fractional nano */
ps = (ps * 1000) >> TIME_INTERVAL_FRACBITS; /* now picoseconds 0..999 -- positive*/
ns = time->scaled_nsecs >> TIME_INTERVAL_FRACBITS;
if (ns > 0) {
if (ns > 0 && clock_ns) {
ps += (ns % clock_ns) * 1000;
ns -= (ns % clock_ns);
}
......
......@@ -26,7 +26,12 @@
#define L1E_TIMEOUT_TX_SYNC PP_TO_EXT_0
#define L1E_TIMEOUT_RX_SYNC PP_TO_EXT_1
#define L1E_DEFAULT_L1SYNCRECEIPTTIMEOUT 5 /* was 3: need more for pll lock */
#define L1E_DEFAULT_L1SYNC_INTERVAL 0
#define L1E_MIN_L1SYNC_INTERVAL -4
#define L1E_MAX_L1SYNC_INTERVAL 4
#define L1E_DEFAULT_L1SYNC_RECEIPT_TIMEOUT 3
#define L1E_MIN_L1SYNC_RECEIPT_TIMEOUT 2
#define L1E_MAX_L1SYNC_RECEIPT_TIMEOUT 10
/*
* We don't have ha_dsport, but rather rely on wr_dsport with our fields added.
......
......@@ -8,7 +8,6 @@
#include <inttypes.h>
#include <ppsi/ppsi.h>
#include <common-fun.h>
#include "l1e-api.h"
#include "l1e-constants.h"
#include <math.h>
......@@ -86,7 +85,7 @@ static int l1e_init(struct pp_instance *ppi, void *buf, int len)
bds->congruentIsRequired = TRUE;
bds->optParamsEnabled = FALSE;
bds->logL1SyncInterval = 0;
bds->L1SyncReceiptTimeout = L1E_DEFAULT_L1SYNCRECEIPTTIMEOUT;
bds->L1SyncReceiptTimeout = L1E_DEFAULT_L1SYNC_RECEIPT_TIMEOUT;
// init dynamic data set members with zeros/defaults
bds->L1SyncLinkAlive = FALSE;
bds->isTxCoherent = FALSE;
......@@ -234,6 +233,20 @@ static int l1e_ready_for_slave(struct pp_instance *ppi)
}
static void l1e_state_change(struct pp_instance *ppi) {
switch (ppi->next_state) {
case PPS_DISABLED :
/* In PPSI we go to DISABLE state when the link is down */
/* For the time being, it should be done like this because fsm is not called when the link is down */
l1e_run_state_machine(ppi); /* First call to choose the next state */
l1e_run_state_machine(ppi); /* Second call to apply next state */
break;
case PPS_INITIALIZING :
L1E_DSPOR(ppi)->basic.L1SyncState=L1E_DSPOR(ppi)->basic.next_state=L1SYNC_DISABLED;
break;
}
}
/* The global structure used by ppsi */
struct pp_ext_hooks l1e_ext_hooks = {
.open = l1e_open,
......@@ -246,5 +259,6 @@ struct pp_ext_hooks l1e_ext_hooks = {
#if CONFIG_HAS_P2P
.handle_presp = l1e_handle_presp,
#endif
.state_change = l1e_state_change,
};
......@@ -6,7 +6,6 @@
*/
#include <ppsi/ppsi.h>
#include "l1e-api.h"
#define MSG_OFFSET_HEADER 0
#define MSG_OFFSET_HEADER_MESSAGE_LENGTH (MSG_OFFSET_HEADER+2)
......@@ -26,10 +25,6 @@
#define MSG_TYPE_SIGNALING 0xC
#define MSG_HEADER_CONTROL_FIELD_ALL_OTHERS 5
#define MSG_TYPE_
#define MSG_GET_16(buf,off) (*(UInteger16 *)(buf+off))
#define MSG_GET_8(buf,off ) *(UInteger8 *)(buf+off)
......@@ -41,13 +36,7 @@
#define MSG_GET_TLV_L1SYNC_PEER_ACTIVE(buf) MSG_GET_8(buf,MSG_OFFSET_TLV_L1SYNC_PEER_ACTIVE)
#define MSG_SET_HEADER_TYPE(buf,val) MSG_GET_8(buf,MSG_OFFSET_HEADER_TYPE) = \
(MSG_GET_8(buf,MSG_OFFSET_HEADER_TYPE) & 0xF0) | val
#define MSG_SET_HEADER_MESSAGE_LENGTH(buf,val) MSG_GET_16(buf,MSG_OFFSET_HEADER_MESSAGE_LENGTH) = htons(val)
#define MSG_SET_HEADER_CONTROL_FIELD(buf, val) MSG_GET_8(buf,MSG_OFFSET_HEADER_CONTROL_FIELD) = val
#define MSG_SET_TARGET_PORT_IDENTITY(buf,clock,port) *(ClockIdentity *)(buf+MSG_OFFSET_TARGET_PORT_IDENTITY) = clock;\
MSG_GET_16(buf,MSG_OFFSET_TARGET_PORT_IDENTITY_PORT_NUMBER) = htons(port);
#define MSG_SET_TLV_TYPE(buf,val) MSG_GET_16(buf,MSG_OFFSET_TLV_TYPE)=htons(val)
#define MSG_SET_TLV_LENGTH_FIELD(buf,val) MSG_GET_16(buf,MSG_OFFSET_TLV_LENGTH_FIELD)=htons(val)
#define MSG_SET_TLV_L1SYNC_PEER_CONF(buf,val) MSG_GET_8(buf,MSG_OFFSET_TLV_L1SYNC_PEER_CONF)= val
#define MSG_SET_TLV_L1SYNC_PEER_ACTIVE(buf,val) MSG_GET_8(buf,MSG_OFFSET_TLV_L1SYNC_PEER_ACTIVE)=val
......@@ -58,27 +47,16 @@
int l1e_pack_signal(struct pp_instance *ppi)
{
void *buf;
void *buf=ppi->tx_ptp;
PortIdentity targetPortIdentity;
uint8_t local_config, local_active;
L1SyncBasicPortDS_t * bds=L1E_DSPOR_BS(ppi);
buf = ppi->tx_ptp;
/* Changes in header */
MSG_SET_HEADER_TYPE(buf,MSG_TYPE_SIGNALING);
MSG_SET_HEADER_CONTROL_FIELD(buf,MSG_HEADER_CONTROL_FIELD_ALL_OTHERS);
memset(&targetPortIdentity,-1,sizeof(targetPortIdentity)); /* cloclk identity and port set all 1's */
/* Generic pack of a signaling message */
msg_pack_signaling_no_fowardable(ppi,&targetPortIdentity,TLV_TYPE_L1_SYNC,2);
/* target portIdentity */
MSG_SET_TARGET_PORT_IDENTITY(buf,
DSPAR(ppi)->parentPortIdentity.clockIdentity,
DSPAR(ppi)->parentPortIdentity.portNumber);
/* L1SyncTLV */
MSG_SET_TLV_TYPE(buf,TLV_TYPE_L1_SYNC);
MSG_SET_TLV_LENGTH_FIELD(buf,2);
/* O.6.4 */
/* Clause O.6.4 */
local_config = l1e_creat_L1Sync_bitmask(bds->txCoherentIsRequired,
bds->rxCoherentIsRequired,
bds->congruentIsRequired);
......@@ -104,10 +82,6 @@ int l1e_unpack_signal(struct pp_instance *ppi, void *buf, int plen)
L1SyncBasicPortDS_t * basicDS=L1E_DSPOR_BS(ppi);
int l1sync_peer_conf, l1sync_peer_acti;
if ( MSG_GET_HEADER_TYPE(buf) != MSG_TYPE_SIGNALING) {
pp_diag(ppi, ext, 1, "Not a signaling message, ignore\n");
return -1;
}
if (MSG_GET_TLV_TYPE(buf) != TLV_TYPE_L1_SYNC) {
pp_diag(ppi, ext, 1, "Not L1Sync TLV, ignore\n");
return -1;
......
......@@ -6,7 +6,6 @@
*/
#include <ppsi/ppsi.h>
#include "l1e-api.h"
#include "l1e-constants.h"
#include <libwr/shmem.h>
......
......@@ -7,7 +7,6 @@
#include <ppsi/ppsi.h>
#include <common-fun.h>
#include "l1e-api.h"
#include "l1e-constants.h"
#include <math.h>
......@@ -167,8 +166,7 @@ static void l1e_send_sync_msg(struct pp_instance *ppi, Boolean immediatSend) {
pp_diag(ppi, ext, 1, "Sending L1SYNC_TLV signaling msg\n");
len = l1e_pack_signal(ppi);
/* FIXME: check the destination MAC address */
__send_and_log(ppi, len, PP_NP_GEN);
__send_and_log(ppi, len, PP_NP_GEN,PPM_SIGNALING_NO_FWD_FMT);
/* Calculate when the next message should be sent */
__pp_timeout_set(ppi, L1E_TIMEOUT_TX_SYNC,
......
......@@ -5,7 +5,6 @@
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#include <ppsi/ppsi.h>
#include "wr-api.h"
/* We are entering WR handshake, as either master or slave */
void wr_handshake_init(struct pp_instance *ppi, int mode_or_retry)
......
......@@ -6,7 +6,6 @@
*/
#include <ppsi/ppsi.h>
#include "wr-api.h"
/*
* This is the WR state machine table.
......
#include <ppsi/ppsi.h>
#include "wr-api.h"
/* ext-whiterabbit must offer its own hooks */
......@@ -8,6 +7,7 @@ static int wr_init(struct pp_instance *ppi, void *buf, int len)
struct wr_dsport *wrp = WR_DSPOR(ppi);
pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
wrp->wrStateTimeout = WR_DEFAULT_STATE_TIMEOUT_MS;
wrp->calPeriod = WR_DEFAULT_CAL_PERIOD;
wrp->head.extModeOn = 0;
......@@ -39,15 +39,15 @@ static int wr_open(struct pp_instance *ppi, struct pp_runtime_opts *rt_opts)
pp_diag(NULL, ext, 2, "hook: %s\n", __func__);
if (ppi->protocol_extension == PPSI_EXT_WR) {
switch (ppi->role) {
case PPSI_ROLE_MASTER:
if ( DSDEF(ppi)->slaveOnly ) {
WR_DSPOR(ppi)->wrConfig = WR_S_ONLY;
} else {
if ( ppi->portDS->masterOnly ) {
WR_DSPOR(ppi)->wrConfig = WR_M_ONLY;
break;
case PPSI_ROLE_SLAVE:
WR_DSPOR(ppi)->wrConfig = WR_S_ONLY;
break;
default:
} else {
WR_DSPOR(ppi)->wrConfig = WR_M_AND_S;
}
}
return 0;
}
......
#include <ppsi/ppsi.h>
#include "common-fun.h"
#include "wr-api.h"
/*
* This is similar to master state, but it only sends sync, that
......
......@@ -7,7 +7,6 @@
*/
#include <ppsi/ppsi.h>
#include "wr-api.h"
/*
* We enter here from WRS_CALIBRATION. If master we wait for
......
......@@ -7,7 +7,6 @@
*/
#include <ppsi/ppsi.h>
#include "wr-api.h"
/*
* We enter this state from WRS_M_LOCK or WRS_RESP_CALIB_REQ.
......
......@@ -7,7 +7,6 @@
*/
#include <ppsi/ppsi.h>
#include "wr-api.h"
/*
* This is the last WR state: ack the other party and go master or slave.
......
......@@ -7,7 +7,6 @@
*/
#include <ppsi/ppsi.h>
#include "wr-api.h"
/*
* WR slave: got here from WRS_S_LOCK: send LOCKED, wait for CALIBRATE.
......
......@@ -7,7 +7,6 @@
*/
#include <ppsi/ppsi.h>
#include "wr-api.h"
/*
* This the entry point for a WR master: send "LOCK" and wait
......
......@@ -7,7 +7,6 @@
*/
#include <ppsi/ppsi.h>
#include "wr-api.h"
/*
* WRS_PRESENT is the entry point for a WR slave
......
......@@ -7,7 +7,6 @@
*/
#include <ppsi/ppsi.h>
#include "wr-api.h"
int wr_resp_calib_req(struct pp_instance *ppi, void *buf, int len)
{
......
......@@ -7,7 +7,6 @@
*/
#include <ppsi/ppsi.h>
#include "wr-api.h"
int wr_s_lock(struct pp_instance *ppi, void *buf, int len)
{
......
......@@ -8,7 +8,6 @@
*/
#include <ppsi/ppsi.h>
#include "wr-api.h"
#include "../proto-standard/common-fun.h"
/*
......@@ -303,5 +302,5 @@ int msg_issue_wrsig(struct pp_instance *ppi, Enumeration16 wr_msg_id)
{
int len = msg_pack_wrsig(ppi, wr_msg_id);
return __send_and_log(ppi, len, PP_NP_GEN);
return __send_and_log(ppi, len, PP_NP_GEN,PPM_SIGNALING_FMT);
}
#include <ppsi/ppsi.h>
#include <ppsi/assert.h>
#include "wr-api.h"
#include <libwr/shmem.h>
/* prototypes */
......@@ -405,9 +404,9 @@ int wr_servo_update(struct pp_instance *ppi)
pp_time_hardwarize(&offset, s->clock_period_ps,
&offset_ticks, &offset_ps);
pp_diag(ppi, servo, 2, "offset_hw: %li.%09li (+%li)\n",
pp_diag(ppi, servo, 2, "offset_hw= %li.%09li (+%li), clock_period= %dps\n",
(long)offset.secs, (long)offset_ticks,
(long)offset_ps);
(long)offset_ps,s->clock_period_ps);
locking_poll_ret = WRH_OPER()->locking_poll(ppi, 0);
if (locking_poll_ret != WRH_SPLL_READY
......
......@@ -459,24 +459,23 @@ static int bmc_topology_cmp(struct pp_instance *ppi,
qualifieda += ca[i];
qualifiedb += cb[i];
}
qualifieda=qualifieda >= PP_FOREIGN_MASTER_THRESHOLD;
qualifiedb=qualifiedb >= PP_FOREIGN_MASTER_THRESHOLD;
/* if B is not qualified 9.3.2.5 c) & 9.3.2.3 a) & b)*/
if ((qualifieda >= PP_FOREIGN_MASTER_THRESHOLD)
&& (qualifiedb < PP_FOREIGN_MASTER_THRESHOLD)) {
if ( qualifieda && !qualifiedb ) {
pp_diag(ppi, bmc, 2, "Dataset B not qualified\n");
return -1;
}
/* if A is not qualified 9.3.2.5 c) & 9.3.2.3 a) & b) */
if ((qualifiedb >= PP_FOREIGN_MASTER_THRESHOLD)
&& (qualifieda < PP_FOREIGN_MASTER_THRESHOLD)) {
if (qualifiedb && !qualifieda) {
pp_diag(ppi, bmc, 2, "Dataset A not qualified\n");
return 1;
}
/* if both are not qualified 9.3.2.5 c) & 9.3.2.3 a) & b) */
if ((qualifieda < PP_FOREIGN_MASTER_THRESHOLD)
&& (qualifiedb < PP_FOREIGN_MASTER_THRESHOLD)) {
if ( !qualifieda && !qualifiedb ) {
pp_diag(ppi, bmc, 2, "Dataset A & B not qualified\n");
return 0;
}
......@@ -580,7 +579,7 @@ static int bmc_state_decision(struct pp_instance *ppi)
struct pp_instance *ppi_best;
struct pp_frgn_master *erbest = &ppi->frgn_master[ppi->frgn_rec_best];
struct pp_frgn_master *ebest;
int qualified = 0;
int foreign_master_qualified = 0;
/* bmc_state_decision is called several times, so report only at
* level 2 */
......@@ -589,33 +588,46 @@ static int bmc_state_decision(struct pp_instance *ppi)
/* check if the erbest is qualified */
if (ppi->frgn_rec_num) {
for (i = 0; i < PP_FOREIGN_MASTER_TIME_WINDOW; i++)
qualified += erbest->foreignMasterAnnounceMessages[i];
foreign_master_qualified += erbest->foreignMasterAnnounceMessages[i];
foreign_master_qualified= foreign_master_qualified >= PP_FOREIGN_MASTER_THRESHOLD; /* True means qualified */
}
if (ppi->role == PPSI_ROLE_SLAVE) {
if ((!ppi->frgn_rec_num) || (qualified < PP_FOREIGN_MASTER_THRESHOLD))
return PPS_LISTENING;
else {
/* if this is the slave port of the whole system then go to slave otherwise stay in listening*/
if (ppi->port_idx == ppg->ebest_idx) {
/* if on this conigured port is ebest it will be taken as
* parent */
ebest = erbest;
goto slave_s1;
} else
return PPS_LISTENING;
/* Clause 17.6.5.3: The state machines of Figure 30 or Figure 31 shall not be used */
if ( DSDEF(ppi)->externalPortConfigurationEnabled) {
/* Qualification of the foreign master is not checked */
int dstate=ppi->externalPortConfigurationPortDS.desiredState;
/* Update the data set for a PTP port in SLAVE or UNCALIBRATED states: Table 137 */
if ( (dstate==PPS_SLAVE || dstate==PPS_UNCALIBRATED ) &&
(ppi->port_idx == ppg->ebest_idx)) {
/* if on this configured port is ebest it will be taken as parent */
bmc_s1(ppi, erbest);
}
return dstate;
}
if (DSDEF(ppi)->slaveOnly) {
if ( !foreign_master_qualified )
return PPS_LISTENING;
/* if this is the slave port of the whole system then go to slave otherwise stay in listening*/
if (ppi->port_idx == ppg->ebest_idx) {
/* if on this configured port is ebest it will be taken as
* parent */
ebest = erbest;
goto slave_s1;
} else
return PPS_LISTENING;
}
if (((!ppi->frgn_rec_num) || (qualified < PP_FOREIGN_MASTER_THRESHOLD)) && (ppi->state == PPS_LISTENING))
if ( !foreign_master_qualified && (ppi->state == PPS_LISTENING))
return PPS_LISTENING;
/* copy local information to a foreign_master structure */
bmc_setup_local_frgn_master(ppi, &d0);
if (ppi->role == PPSI_ROLE_MASTER) {
if ( ppi->portDS->masterOnly ) {
/* if there is a better master show these values */
if (ppg->ebest_idx >= 0) {
/* don't update parent dataset */
......@@ -792,7 +804,7 @@ slave_s1:
* on that port */
cmpres = 0;
}
/* if we are not comming from the slave state we go to uncalibrated
/* if we are not coming from the slave state we go to uncalibrated
* first */
if ((ppi->state != PPS_SLAVE) &&
(ppi->state != PPS_UNCALIBRATED)) {
......@@ -812,7 +824,7 @@ slave_s1:
/* 9.2.6.11 c) reset ANNOUNCE RECEIPT timeout when entering*/
if (ppi->state != PPS_SLAVE)
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
/* the decision to go from UNCALIBRATED to SLAVEW is
/* the decision to go from UNCALIBRATED to SLAVE is
* done outside the BMC, so just return the current state */
return ppi->state;
}
......@@ -872,10 +884,6 @@ void bmc_add_frgn_master(struct pp_instance *ppi, void *buf,
pp_diag(ppi, bmc, 2, "%s\n", __func__);
/* if we are a configured master don't add*/
if (ppi->role == PPSI_ROLE_MASTER)
return;
/* if in DISABLED, INITIALIZING or FAULTY ignore announce */
if ((ppi->state == PPS_DISABLED) ||
(ppi->state == PPS_FAULTY) ||
......@@ -942,6 +950,13 @@ void bmc_add_frgn_master(struct pp_instance *ppi, void *buf,
return;
}
/* External Port Configuration */
if ( DSDEF(ppi)->externalPortConfigurationEnabled) {
/* Clear all other foreign masters. The last foreign master is always the one to be used */
/* If externalPortConfigurationEnabled is set, foreign master qualification will be not checked */
ppi->frgn_rec_num=0;
}
/* Check if foreign master is already known */
i=0;
#if CODEOPT_ONE_FMASTER()==0
......@@ -1425,7 +1440,7 @@ int bmc(struct pp_instance *ppi)
if (pp_timeout(ppi, PP_TO_BMC)) {
bmc_age_frgn_master(ppi);
/* restart timer, shall occur at
least once per annnounce interval 9.2.6.8
least once per announce interval 9.2.6.8
*/
pp_timeout_set(ppi, PP_TO_BMC);
}
......@@ -1447,6 +1462,11 @@ int bmc(struct pp_instance *ppi)
/* Calulate Ebest Figure 25 */
bmc_update_ebest(ppg);
/* Clause 17.6.5.3: The state machines of Figure 30 or Figure 31 shall not be used */
if ( DSDEF(ppi)->externalPortConfigurationEnabled) {
return bmc_state_decision(ppi);
}
if (!ppi->link_up) {
/* Set it back to initializing */
next_state = PPS_INITIALIZING;
......
......@@ -80,30 +80,46 @@ static int presp_call_servo(struct pp_instance *ppi)
return ret;
}
static int is_grand_master(struct pp_instance *ppi) {
int has_slave= 0;
int has_master=0;
int i=0;
#if CODEOPT_ONE_PORT()
{
#else
for (; i < DSDEF(ppi)->numberPorts; i++) {
#endif
switch (INST(GLBS(ppi), i)->state) {
case PPS_UNCALIBRATED:
case PPS_SLAVE:
has_slave=1;
break;
case PPS_MASTER:
case PPS_PRE_MASTER:
case PPS_PASSIVE:
has_master=1;
}
}
return has_master && !has_slave;
}
int st_com_check_announce_receive_timeout(struct pp_instance *ppi)
{
struct pp_globals *ppg = GLBS(ppi);
int is_gm = 1;
int i;
if (pp_timeout(ppi, PP_TO_ANN_RECEIPT)) {
/* 9.2.6.11 b) reset timeout when an announce timeout happended */
/* 9.2.6.11 b) reset timeout when an announce timeout happened */
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
if (DSDEF(ppi)->clockQuality.clockClass != PP_CLASS_SLAVE_ONLY
&& (ppi->role != PPSI_ROLE_SLAVE)) {
if (!CODEOPT_ONE_PORT() && DSDEF(ppi)->numberPorts > 1) {
for (i = 0; i < ppg->defaultDS->numberPorts; i++) {
if ((INST(ppg, i)->state == PPS_UNCALIBRATED) ||
(INST(ppg, i)->state == PPS_SLAVE))
is_gm = 0;
}
if (is_gm)
bmc_m1(ppi);
else
bmc_m3(ppi);
} else
bmc_m1(ppi);
if ( !DSDEF(ppi)->slaveOnly ) {
if ( is_grand_master(ppi) ) {
bmc_m1(ppi);
} else {
bmc_m3(ppi);
}
if ( DSDEF(ppi)->externalPortConfigurationEnabled ) {
/* Clause 17.6.5.3 : The announce receipt timeout mechanism shall not be active */
return 0;
}
ppi->next_state = PPS_MASTER;
} else {
ppi->next_state = PPS_LISTENING;
......@@ -213,8 +229,13 @@ int st_com_peer_handle_preq(struct pp_instance *ppi, void *buf,
int st_com_handle_announce(struct pp_instance *ppi, void *buf, int len)
{
bmc_add_frgn_master(ppi, buf, len);
/* Clause 9.2.2.2 MasterOnly PTP ports :
* Announce messages received on a masterOnly PTP Port shall not be considered
* in the operation of the best master clock algorithm or in the update of data sets.
*/
if ( ! DSPOR(ppi)->masterOnly ) {
bmc_add_frgn_master(ppi, buf, len);
}
if (ppi->ext_hooks->handle_announce)
return ppi->ext_hooks->handle_announce(ppi);
return 0;
......@@ -228,19 +249,18 @@ int st_com_handle_signaling(struct pp_instance *ppi, void *buf, int len)
}
int __send_and_log(struct pp_instance *ppi, int msglen, int chtype)
int __send_and_log(struct pp_instance *ppi, int msglen, int chtype,enum pp_msg_format msg_fmt)
{
int msgtype = ((char *)ppi->tx_ptp)[0] & 0xf;
struct pp_msgtype_info *mf = pp_msgtype_info + msg_fmt;
struct pp_time *t = &ppi->last_snt_time;
int ret;
ret = ppi->n_ops->send(ppi, ppi->tx_frame, msglen + ppi->tx_offset,
msgtype);
ret = ppi->n_ops->send(ppi, ppi->tx_frame, msglen + ppi->tx_offset,msg_fmt);
if (ret == PP_SEND_DROP)
return 0; /* don't report as error, nor count nor log as sent */
if (ret < msglen) {
pp_diag(ppi, frames, 1, "%s(%d) Message can't be sent\n",
pp_msgtype_info[msgtype].name, msgtype);
pp_msgtype_name[mf->msg_type], mf->msg_type);
return PP_SEND_ERROR;
}
/* The send method updates ppi->last_snt_time with the Tx timestamp. */
......@@ -251,7 +271,7 @@ int __send_and_log(struct pp_instance *ppi, int msglen, int chtype)
pp_diag(ppi, frames, 1, "SENT %02d bytes at %d.%09d.%03d (%s)\n",
msglen, (int)t->secs, (int)(t->scaled_nsecs >> 16),
((int)(t->scaled_nsecs & 0xffff) * 1000) >> 16,
pp_msgtype_info[msgtype].name);
pp_msgtype_name[mf->msg_type]);
if (chtype == PP_NP_EVT && is_incorrect(&ppi->last_snt_time))
return PP_SEND_NO_STAMP;
......
......@@ -19,7 +19,7 @@ int st_com_peer_handle_pres_followup(struct pp_instance *ppi, void *buf, int len
int st_com_handle_announce(struct pp_instance *ppi, void *buf, int len);
int st_com_handle_signaling(struct pp_instance *ppi, void *buf, int len);
int __send_and_log(struct pp_instance *ppi, int msglen, int chtype);
int __send_and_log(struct pp_instance *ppi, int msglen, int chtype,enum pp_msg_format msg_fmt);
/* Count successfully received PTP packets */
static inline int __recv_and_count(struct pp_instance *ppi, void *buf, int len,
......
......@@ -54,7 +54,7 @@ int msg_unpack_header(struct pp_instance *ppi, void *buf, int len)
void msg_init_header(struct pp_instance *ppi, void *buf)
{
memset(buf, 0, 34);
*(char *)(buf + 1) = DSPOR(ppi)->versionNumber;
*(char *)(buf + 1) = DSPOR(ppi)->minorVersionNumber<<4 | (DSPOR(ppi)->versionNumber & 0xF);
*(char *)(buf + 4) = DSDEF(ppi)->domainNumber;
memcpy((buf + 20), &DSPOR(ppi)->portIdentity.clockIdentity,
......@@ -63,26 +63,28 @@ void msg_init_header(struct pp_instance *ppi, void *buf)
htons(DSPOR(ppi)->portIdentity.portNumber);
}
/* set the sequence id in the buffer and update the stored one */
static void __msg_set_seq_id(struct pp_instance *ppi, struct pp_msgtype_info *mf) {
void *buf = ppi->tx_ptp;
ppi->sent_seq[mf->msg_type]++;
*(UInteger16 *) (buf + 30) = htons(ppi->sent_seq[mf->msg_type]); /* SequenceId */
}
/* Helper used by all "msg_pack" below */
static int __msg_pack_header(struct pp_instance *ppi, unsigned msgtype)
static int __msg_pack_header(struct pp_instance *ppi, struct pp_msgtype_info *msg_fmt)
{
struct pp_msgtype_info *i = pp_msgtype_info + msgtype;
void *buf = ppi->tx_ptp;
int len, log;
uint16_t *flags16 = buf + 6;
signed char *logp = buf + 33;
if (msgtype > 15)
return 0;
len = i->msglen;
log = i->logMessageInterval;
*(char *)(buf + 0) = msgtype;
len = msg_fmt->msglen;
log = msg_fmt->logMessageInterval;
*(char *)(buf + 0) = msg_fmt->msg_type;
*(UInteger16 *) (buf + 2) = htons(len);
memset((buf + 8), 0, 8); /* correctionField: default is cleared */
*flags16 = 0; /* most message types wont 0 here */
*(UInteger8 *)(buf + 32) = i->controlField;
*(UInteger8 *)(buf + 32) = msg_fmt->controlField;
switch(log) {
case PP_LOG_ANNOUNCE:
*logp = DSPOR(ppi)->logAnnounceInterval; break;
......@@ -96,17 +98,59 @@ static int __msg_pack_header(struct pp_instance *ppi, unsigned msgtype)
return len;
}
/* Pack Signaling message into out buffer of ppi */
static int __msg_pack_signaling(struct pp_instance *ppi,enum pp_msg_format msg_fmt, PortIdentity *target_port_identity,
UInteger16 tlv_type,UInteger16 tlv_length_field)
{
void *buf = ppi->tx_ptp;
int len;
struct pp_msgtype_info *mf = pp_msgtype_info + msg_fmt;
if (msg_fmt >=PPM_MSG_FMT_MAX)
return 0;
len = __msg_pack_header(ppi, mf);
__msg_set_seq_id(ppi,mf);
/* Set target port identity */
*(ClockIdentity *) (buf + 34) = target_port_identity->clockIdentity;
*(UInteger16 *) (buf + 42) = target_port_identity->portNumber;
*(UInteger16 *) (buf + 44) = htons(tlv_type); /* TLV type*/
*(UInteger16 *)(buf + 46) = htons(tlv_length_field); /* TLV length field */
return len;
}
/* Pack Signaling message into out buffer of ppi */
int msg_pack_signaling(struct pp_instance *ppi,PortIdentity *target_port_identity,
UInteger16 tlv_type,UInteger16 tlv_length_field) {
return __msg_pack_signaling(ppi,PPM_SIGNALING_FMT,target_port_identity,tlv_type,tlv_length_field);
}
/* Pack Signaling message into out buffer of ppi */
int msg_pack_signaling_no_fowardable(struct pp_instance *ppi,PortIdentity *target_port_identity,
UInteger16 tlv_type,UInteger16 tlv_length_field) {
return __msg_pack_signaling(ppi,PPM_SIGNALING_NO_FWD_FMT,target_port_identity,tlv_type,tlv_length_field);
}
/* Unpack signaling message from in buffer */
void msg_unpack_signaling(void *buf, MsgSignaling *signaling)
{
signaling->targetPortIdentity.clockIdentity= *(ClockIdentity *) (buf + 34);
signaling->targetPortIdentity.portNumber= *(UInteger16 *) (buf + 42);
signaling->tlv=buf + 44;
}
/* Pack Sync message into out buffer of ppi */
int msg_pack_sync(struct pp_instance *ppi, struct pp_time *orig_tstamp)
{
void *buf = ppi->tx_ptp;
UInteger8 *flags8 = buf + 6;;
int len = __msg_pack_header(ppi, PPM_SYNC);
UInteger8 *flags8 = buf + 6;
struct pp_msgtype_info *mf = pp_msgtype_info + PPM_SYNC_FMT;
int len= __msg_pack_header(ppi, mf);
ppi->sent_seq[PPM_SYNC]++;
/* Header */
flags8[0] = PP_TWO_STEP_FLAG; /* Table 20 */
*(UInteger16 *) (buf + 30) = htons(ppi->sent_seq[PPM_SYNC]);
__msg_set_seq_id(ppi,mf);
/* Sync message */
memset((buf + 34), 0, 10);
......@@ -164,12 +208,12 @@ static int msg_pack_announce(struct pp_instance *ppi)
{
void *buf = ppi->tx_ptp;
UInteger8 *flags8 = buf + 6;;
int len = __msg_pack_header(ppi, PPM_ANNOUNCE);
struct pp_msgtype_info *mf = pp_msgtype_info + PPM_ANNOUNCE_FMT;
int len= __msg_pack_header(ppi, mf);
ppi->sent_seq[PPM_ANNOUNCE]++;
/* Header */
__msg_set_seq_id(ppi,mf);
msg_set_announce_flags(ppi, flags8);
*(UInteger16 *) (buf + 30) = htons(ppi->sent_seq[PPM_ANNOUNCE]);
/* Announce message */
memset((buf + 34), 0, 30);
......@@ -229,9 +273,13 @@ static int msg_pack_follow_up(struct pp_instance *ppi,
struct pp_time *prec_orig_tstamp)
{
void *buf = ppi->tx_ptp;
int len = __msg_pack_header(ppi, PPM_FOLLOW_UP);
struct pp_msgtype_info *mf = pp_msgtype_info + PPM_FOLLOW_UP_FMT;
int len= __msg_pack_header(ppi, mf);
/* Header */
/* Clause 9.5.10: The value of the sequenceId field of the Follow_Up message
* shall be the value of the sequenceId field of the associated Sync message.
*/
*(UInteger16 *) (buf + 30) = htons(ppi->sent_seq[PPM_SYNC]);
/* Follow Up message */
......@@ -251,7 +299,10 @@ static int msg_pack_pdelay_resp_follow_up(struct pp_instance *ppi,
struct pp_time *prec_orig_tstamp)
{
void *buf = ppi->tx_ptp;
int len = __msg_pack_header(ppi, PPM_PDELAY_R_FUP);
int len;
struct pp_msgtype_info *mf = pp_msgtype_info + PPM_PDELAY_R_FUP_FMT;
len= __msg_pack_header(ppi, mf);
/* Header */
*(UInteger8 *) (buf + 4) = hdr->domainNumber; /* FIXME: why? */
......@@ -319,11 +370,11 @@ static int msg_pack_delay_req(struct pp_instance *ppi,
struct pp_time *now)
{
void *buf = ppi->tx_ptp;
int len = __msg_pack_header(ppi, PPM_DELAY_REQ);
struct pp_msgtype_info *mf = pp_msgtype_info + PPM_DELAY_REQ_FMT;
int len= __msg_pack_header(ppi, mf);
ppi->sent_seq[PPM_DELAY_REQ]++;
/* Header */
*(UInteger16 *) (buf + 30) = htons(ppi->sent_seq[PPM_DELAY_REQ]);
__msg_set_seq_id(ppi,mf);
/* Delay_req message - we may send zero instead */
memset((buf + 34), 0, 10);
......@@ -338,11 +389,11 @@ static int msg_pack_pdelay_req(struct pp_instance *ppi,
struct pp_time *now)
{
void *buf = ppi->tx_ptp;
int len = __msg_pack_header(ppi, PPM_PDELAY_REQ);
struct pp_msgtype_info *mf = pp_msgtype_info + PPM_PDELAY_REQ_FMT;
int len= __msg_pack_header(ppi, mf);
ppi->sent_seq[PPM_PDELAY_REQ]++;
/* Header */
*(UInteger16 *) (buf + 30) = htons(ppi->sent_seq[PPM_PDELAY_REQ]);
__msg_set_seq_id(ppi,mf);
/* PDelay_req message - we may send zero instead */
memset((buf + 34), 0, 20);
......@@ -358,7 +409,8 @@ static int msg_pack_pdelay_resp(struct pp_instance *ppi,
{
void *buf = ppi->tx_ptp;
UInteger8 *flags8 = buf + 6;;
int len = __msg_pack_header(ppi, PPM_PDELAY_RESP);
struct pp_msgtype_info *mf = pp_msgtype_info + PPM_PDELAY_RESP_FMT;
int len= __msg_pack_header(ppi, mf);
/* Header */
flags8[0] = PP_TWO_STEP_FLAG; /* Table 20) */
......@@ -386,7 +438,8 @@ static int msg_pack_delay_resp(struct pp_instance *ppi,
MsgHeader *hdr, struct pp_time *rcv_tstamp)
{
void *buf = ppi->tx_ptp;
int len = __msg_pack_header(ppi, PPM_DELAY_RESP);
struct pp_msgtype_info *mf = pp_msgtype_info + PPM_DELAY_RESP_FMT;
int len= __msg_pack_header(ppi, mf);
/* Header */
/*
......@@ -483,7 +536,7 @@ int msg_issue_announce(struct pp_instance *ppi)
{
int len = msg_pack_announce(ppi);
return __send_and_log(ppi, len, PP_NP_GEN);
return __send_and_log(ppi, len, PP_NP_GEN,PPM_ANNOUNCE_FMT);
}
/* Pack and send on event multicast ip adress a Sync message */
......@@ -495,12 +548,12 @@ int msg_issue_sync_followup(struct pp_instance *ppi)
/* Send sync on the event channel with the "current" timestamp */
ppi->t_ops->get(ppi, &now);
len = msg_pack_sync(ppi, &now);
e = __send_and_log(ppi, len, PP_NP_EVT);
e = __send_and_log(ppi, len, PP_NP_EVT,PPM_SYNC_FMT);
if (e) return e;
/* Send followup on general channel with sent-stamp of sync */
len = msg_pack_follow_up(ppi, &ppi->last_snt_time);
return __send_and_log(ppi, len, PP_NP_GEN);
return __send_and_log(ppi, len, PP_NP_GEN,PPM_FOLLOW_UP_FMT);
}
/* Pack and send on general multicast ip address a FollowUp message */
......@@ -509,7 +562,7 @@ int msg_issue_pdelay_resp_followup(struct pp_instance *ppi, struct pp_time *t)
int len;
len = msg_pack_pdelay_resp_follow_up(ppi, &ppi->received_ptp_header, t);
return __send_and_log(ppi, len, PP_NP_GEN);
return __send_and_log(ppi, len, PP_NP_GEN,PPM_PDELAY_R_FUP_FMT);
}
/* Pack and send on event multicast ip adress a DelayReq message */
......@@ -521,7 +574,7 @@ static int msg_issue_delay_req(struct pp_instance *ppi)
ppi->t_ops->get(ppi, &now);
len = msg_pack_delay_req(ppi, &now);
return __send_and_log(ppi, len, PP_NP_EVT);
return __send_and_log(ppi, len, PP_NP_EVT,PPM_DELAY_REQ_FMT);
}
/* Pack and send on event multicast ip adress a PDelayReq message */
......@@ -533,7 +586,7 @@ static int msg_issue_pdelay_req(struct pp_instance *ppi)
mark_incorrect(&ppi->t4); /* see commit message */
ppi->t_ops->get(ppi, &now);
len = msg_pack_pdelay_req(ppi, &now);
return __send_and_log(ppi, len, PP_NP_EVT);
return __send_and_log(ppi, len, PP_NP_EVT,PPM_PDELAY_REQ_FMT);
}
int msg_issue_request(struct pp_instance *ppi)
......@@ -549,7 +602,7 @@ int msg_issue_delay_resp(struct pp_instance *ppi, struct pp_time *t)
int len;
len = msg_pack_delay_resp(ppi, &ppi->received_ptp_header, t);
return __send_and_log(ppi, len, PP_NP_GEN);
return __send_and_log(ppi, len, PP_NP_GEN,PPM_DELAY_RESP_FMT);
}
/* Pack and send on event multicast ip adress a DelayResp message */
......@@ -558,5 +611,5 @@ int msg_issue_pdelay_resp(struct pp_instance *ppi, struct pp_time *t)
int len;
len = msg_pack_pdelay_resp(ppi, &ppi->received_ptp_header, t);
return __send_and_log(ppi, len, PP_NP_EVT);
return __send_and_log(ppi, len, PP_NP_EVT,PPM_PDELAY_RESP_FMT);
}
......@@ -78,11 +78,35 @@ int pp_init_globals(struct pp_globals *ppg, struct pp_runtime_opts *pp_rt_opts)
memcpy(&def->clockQuality, &rt_opts->clock_quality,
sizeof(ClockQuality));
if (def->numberPorts == 1)
def->slaveOnly = (INST(ppg, 0)->role == PPSI_ROLE_SLAVE);
else
def->slaveOnly = 1; /* the for cycle below will set it to 0 if not
* ports are not all slave_only */
if ( def->slaveOnly ) {
if ( def->numberPorts > 1 ) {
/* Check if slaveOnly is allowed
* Only one ppsi instance must exist however n instances on the same physical port
* and using the same protocol must be considered as one. We do this because these
* instances are exclusive and will be never enabled at the same time
*/
struct pp_instance *ppi = INST(ppg, 0);
for (i = 1; i < def->numberPorts; i++) {
struct pp_instance *ppi_cmp = INST(ppg, i);
if ( ppi->proto != ppi_cmp->proto /* different protocol used */
|| strcmp(ppi->cfg.iface_name,ppi_cmp->cfg.iface_name)!=0 /* Not the same interface */
) {
/* remove slaveOnly */
def->slaveOnly = 0;
pp_printf("ppsi: SlaveOnly cannot be applied. It is not a ordinary clock\n");
break; /* No reason to continue */
}
}
}
if ( def->slaveOnly ) {
def->clockQuality.clockClass = PP_CLASS_SLAVE_ONLY;
pp_printf("Slave Only, clock class set to %d\n", def->clockQuality.clockClass);
}
}
if ( def->numberPorts > 1) {
/* slaveOnly can be applied only on a ordinary clock */
}
def->priority1 = rt_opts->priority1;
def->priority2 = rt_opts->priority2;
......@@ -91,19 +115,34 @@ int pp_init_globals(struct pp_globals *ppg, struct pp_runtime_opts *pp_rt_opts)
for (i = 0; i < def->numberPorts; i++) {
struct pp_instance *ppi = INST(ppg, i);
if (def->slaveOnly && ppi->role != PPSI_ROLE_SLAVE)
def->slaveOnly = 0;
ppi->state = PPS_INITIALIZING;
ppi->current_state_item = NULL;
ppi->port_idx = i;
ppi->frgn_rec_best = -1;
}
if (def->slaveOnly) {
def->clockQuality.clockClass = PP_CLASS_SLAVE_ONLY;
pp_printf("Slave Only, clock class set to %d\n",
def->clockQuality.clockClass);
/* Clause 17.6.2 : On an Ordinary Clock that is slaveOnly by configuration or by-design, an attempt
* to set the defaultDS.externalPortConfigurationEnabled to TRUE should result in a management error,
* and the value of defaultDS.externalPortConfigurationEnabled shall remain FALSE
*/
def->externalPortConfigurationEnabled=pp_rt_opts->externalPortConfigurationEnabled;
if ( def->slaveOnly && def->externalPortConfigurationEnabled ) {
pp_printf("ppsi: Incompatible configuration: SlaveOnly and externalPortConfigurationEnabled\n");
def->externalPortConfigurationEnabled=FALSE;
}
if ( ppg->defaultDS->externalPortConfigurationEnabled ) {
for (i = 0; i < def->numberPorts; i++) {
struct pp_instance *ppi = INST(ppg, i);
/* Clause 17.6.5.3 : - Clause 9.2.2 shall not be in effect */
if ( ppi->portDS->masterOnly ) {
/* priority given to externalPortConfigurationEnabled */
ppi->portDS->masterOnly=FALSE;
pp_printf("ppsi: Wrong configuration: externalPortConfigurationEnabled=materOnly=TRUE. externalPortConfigurationEnabled set to FALSE\n");
}
ppi->externalPortConfigurationPortDS.desiredState =ppi->cfg.desiredState ;
}
}
for (i = 0; i < def->numberPorts; i++) {
......
......@@ -37,6 +37,8 @@ void pp_servo_init(struct pp_instance *ppi)
static void _pp_servo_init(struct pp_instance *ppi)
{
int d;
SRV(ppi)->state=0;
SRV(ppi)->servo_state_name[0]=0;
SRV(ppi)->mpd_fltr.s_exp = 0; /* clears meanDelay filter */
if (ppi->t_ops->init_servo) {
......
......@@ -41,7 +41,6 @@ int pp_initializing(struct pp_instance *ppi, void *buf, int len)
unsigned char *mac;
unsigned char mac_port1[6];
portDS_t *port = DSPOR(ppi);
struct pp_runtime_opts *opt = OPTS(ppi);
struct pp_globals *ppg = GLBS(ppi);
int ret = 0;
int i;
......@@ -98,13 +97,11 @@ int pp_initializing(struct pp_instance *ppi, void *buf, int len)
&DSDEF(ppi)->clockIdentity, PP_CLOCK_IDENTITY_LENGTH);
/* 1-based port number = index of this ppi in the global array */
port->portIdentity.portNumber = 1 + ppi - ppi->glbs->pp_instances;
port->logMinDelayReqInterval = PP_DEFAULT_DELAYREQ_INTERVAL;
port->logAnnounceInterval = opt->logAnnounceInterval;
port->announceReceiptTimeout = PP_DEFAULT_ANNOUNCE_RECEIPT_TIMEOUT;
port->logSyncInterval = opt->logSyncInterval;
port->versionNumber = PP_VERSION_PTP;
port->minorVersionNumber = PP_MINOR_VERSION_PTP;
pp_timeout_init(ppi);
pp_timeout_setall(ppi);
pp_timeout_setall(ppi);/* PP_TO_BMC is not set by default */
pp_timeout_set(ppi, PP_TO_BMC);
if (ppi->ext_hooks->init)
ret = ppi->ext_hooks->init(ppi, buf, len);
......@@ -120,10 +117,17 @@ int pp_initializing(struct pp_instance *ppi, void *buf, int len)
msg_init_header(ppi, ppi->tx_ptp); /* This is used for all tx */
if (ppi->role != PPSI_ROLE_MASTER)
ppi->next_state = PPS_LISTENING;
if (DSDEF(ppi)->externalPortConfigurationEnabled) {
/* Clause 17.6.5.2 : the member portDS.portState shall be set to
* the value of the member externalPortConfigurationPortDS.desiredState
*/
if ( ppi->externalPortConfigurationPortDS.desiredState==PPS_SLAVE)
ppi->next_state=PPS_UNCALIBRATED;
else
ppi->next_state = ppi->externalPortConfigurationPortDS.desiredState;
}
else
ppi->next_state = PPS_MASTER;
ppi->next_state = PPS_LISTENING;
#ifdef CONFIG_ABSCAL
/* absolute calibration only exists in arch-wrpc, so far */
......
......@@ -105,8 +105,7 @@ out:
switch(e) {
case PP_SEND_OK: /* 0 */
/* Why should we switch to slave? Remove this code? */
if (DSDEF(ppi)->clockQuality.clockClass == PP_CLASS_SLAVE_ONLY
|| (ppi->role == PPSI_ROLE_SLAVE))
if (DSDEF(ppi)->slaveOnly)
ppi->next_state = PPS_LISTENING;
break;
case PP_SEND_ERROR:
......
......@@ -126,13 +126,11 @@ static int slave_handle_response(struct pp_instance *ppi, void *buf,
if ((bmc_idcmp(&DSPOR(ppi)->portIdentity.clockIdentity,
&resp.requestingPortIdentity.clockIdentity) != 0) ||
((ppi->sent_seq[PPM_DELAY_REQ]) !=
hdr->sequenceId) ||
(DSPOR(ppi)->portIdentity.portNumber !=
resp.requestingPortIdentity.portNumber) ||
(ppi->sent_seq[PPM_DELAY_REQ] != hdr->sequenceId) ||
(DSPOR(ppi)->portIdentity.portNumber != resp.requestingPortIdentity.portNumber) ||
(!msg_from_current_master(ppi))) {
pp_diag(ppi, frames, 1, "pp_slave : "
"Delay Resp doesn't match Delay Req (f %x)\n",
pp_diag(ppi, frames, 1, "%s : "
"Delay Resp doesn't match Delay Req (f %x)\n",__func__,
ppi->flags);
return 0;
}
......@@ -214,10 +212,10 @@ int pp_slave(struct pp_instance *ppi, void *buf, int len)
ppi->next_state = PPS_SLAVE;
}
} else {
/* TODO add implementation specific SYNCHRONIZATION FAULT
* event */
if (pp_timeout(ppi, PP_TO_FAULT))
ppi->next_state = PPS_UNCALIBRATED;
/* TODO add implementation specific SYNCHRONIZATION event */
if (! DSDEF(ppi)->externalPortConfigurationEnabled )
if (pp_timeout(ppi, PP_TO_FAULT))
ppi->next_state = PPS_UNCALIBRATED;
}
/* when entering uncalibrated init servo */
......@@ -232,7 +230,7 @@ int pp_slave(struct pp_instance *ppi, void *buf, int len)
goto out;
}
/* do a delay mesurement either in p2p or e2e delay mode */
/* do a delay measurement either in p2p or e2e delay mode */
pp_lib_may_issue_request(ppi);
/*
......
......@@ -32,7 +32,6 @@
#include <ppsi-wrs.h>
#include <hal_exports.h>
#include "../proto-ext-whiterabbit/wr-api.h"
#define ETHER_MTU 1518
#define DMTD_UPDATE_INTERVAL 500
......
......@@ -37,8 +37,8 @@ void pp_timeout_init(struct pp_instance *ppi)
{
portDS_t *port = ppi->portDS;
to_configs[PP_TO_REQUEST].value =
port->logMinDelayReqInterval;
to_configs[PP_TO_REQUEST].value = (CONFIG_HAS_P2P && ppi->delayMechanism == P2P) ?
port->logMinPdelayReqInterval : port->logMinDelayReqInterval;
/* fault timeout is 4 avg request intervals, not randomized */
to_configs[PP_TO_FAULT].value =
1 << (port->logMinDelayReqInterval + 12); /* 0 -> 4096ms */
......@@ -54,7 +54,7 @@ void pp_timeout_init(struct pp_instance *ppi)
void __pp_timeout_set(struct pp_instance *ppi, int index, int millisec)
{
ppi->timeouts[index] = ppi->t_ops->calc_timeout(ppi, millisec);
pp_diag(ppi, time, 3, "new timeout for %s : %i / %lu\n",
pp_diag(ppi, time, 3, "Set timeout for %s : %i / %lu\n",
to_configs[index].name, millisec, ppi->timeouts[index]);
}
......@@ -66,48 +66,53 @@ void pp_timeout_clear(struct pp_instance *ppi, int index)
void pp_timeout_set(struct pp_instance *ppi, int index)
{
static uint32_t seed;
uint32_t rval;
int millisec;
int logval = to_configs[index].value;
if (!seed) {
uint32_t *p;
/* use the least 32 bits of the mac address as seed */
p = (void *)(&DSDEF(ppi)->clockIdentity)
+ sizeof(ClockIdentity) - 4;
seed = *p;
}
/* From uclibc: they make 11 + 10 + 10 bits, we stop at 21 */
seed *= 1103515245;
seed += 12345;
rval = (unsigned int) (seed / 65536) % 2048;
seed *= 1103515245;
seed += 12345;
rval <<= 10;
rval ^= (unsigned int) (seed / 65536) % 1024;
/*
* logval is signed. Let's imagine it's no less than -4.
* Here below, 0 gets to 16 * 25 = 400ms, 40% of the nominal value
*/
millisec = (1 << (logval + 4)) * 25;
switch(to_configs[index].which_rand) {
case RAND_70_130:
struct timeout_config * to_config=&to_configs[index];
if (to_config->which_rand==RAND_NONE ) {
millisec = to_config->value; /* Just a constant */
} else {
uint32_t rval;
int logval = to_config->value;
if (!seed) {
uint32_t *p;
/* use the least 32 bits of the mac address as seed */
p = (void *)(&DSDEF(ppi)->clockIdentity)
+ sizeof(ClockIdentity) - 4;
seed = *p;
}
/* From uclibc: they make 11 + 10 + 10 bits, we stop at 21 */
seed *= 1103515245;
seed += 12345;
rval = (unsigned int) (seed / 65536) % 2048;
seed *= 1103515245;
seed += 12345;
rval <<= 10;
rval ^= (unsigned int) (seed / 65536) % 1024;
/*
* We are required to fit between 70% and 130%
* of the value for 90% of the time, at least.
* So randomize between 80% and 120%: constant
* part is 80% and variable is 40%.
* logval is signed. Let's imagine it's no less than -4.
* Here below, 0 gets to 16 * 25 = 400ms, 40% of the nominal value
*/
millisec = (millisec * 2) + rval % millisec;
break;
case RAND_0_200:
millisec = rval % (millisec * 5);
break;
case RAND_NONE:
millisec = logval; /* not a log, just a constant */
millisec = (1 << (logval + 4)) * 25;
switch(to_config->which_rand) {
case RAND_70_130:
/*
* We are required to fit between 70% and 130%
* of the value for 90% of the time, at least.
* So randomize between 80% and 120%: constant
* part is 80% and variable is 40%.
*/
millisec = (millisec * 2) + rval % millisec;
break;
case RAND_0_200:
millisec = rval % (millisec * 5);
break;
/* RAND_NONE already treated */
}
}
__pp_timeout_set(ppi, index, millisec);
}
......@@ -121,8 +126,9 @@ void pp_timeout_setall(struct pp_instance *ppi)
int i;
for (i = 0; i < __PP_TO_ARRAY_SIZE; i++) {
/* keep BMC timeout */
if (i != PP_TO_BMC)
if (i!=PP_TO_BMC) {
pp_timeout_set(ppi, i);
}
}
/* but announce_send must be send soon */
__pp_timeout_set(ppi, PP_TO_ANN_SEND, 20);
......
......@@ -278,7 +278,7 @@ static int wr_dump_tlv(char *prefix, struct ptp_tlv *tlv, int totallen)
static int l1sync_dump_tlv(char *prefix, struct l1sync_tlv *tlv, int totallen)
{
/* the field includes 6 bytes of the header, ecludes 4 of them. Bah! */
/* the field includes 6 bytes of the header, excludes 4 of them. Bah! */
int explen = ntohs(tlv->len) + 4;
printf("TLV: type %04x len %i conf %02x act %02x ",
......@@ -293,7 +293,7 @@ static int l1sync_dump_tlv(char *prefix, struct l1sync_tlv *tlv, int totallen)
/* later: if (memcmp(tlv->oui, "\x08\x00\x30", 3)) ... */
/* Now dump non-wr tlv in binary, count only payload */
/* Now dump non-l1sync tlv in binary, count only payload */
dumpstruct(prefix, "TLV: ", "tlv-content", tlv->data,
explen - sizeof(*tlv));
return explen;
......
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