Commit fbce8f05 authored by Alessandro Rubini's avatar Alessandro Rubini

Merge branch 'pdelay'

parents cc3e8ce2 fe029501
......@@ -72,8 +72,23 @@ config ARCH
default "wrs" if ARCH_WRS
default "sim" if ARCH_SIMULATOR
menu "PTP Protocol Options"
choice
prompt "PTP Synchronization Mechanism"
config E2E
boolean "Delay-Request-Respond"
help
Delay-Request-Response uses 4 timestamps
for calculating the link delay and synchronizing.
config P2P
boolean "Peer Delay"
help
Peer Delay uses 4 timestamps for calculating
the link delay and another 2 for synchronizing.
endchoice
endmenu
# This is not a choice any more: it is mandated by the architecture
config EXT_WR
bool
default y if ARCH_WRS || ARCH_WRPC
......
......@@ -98,6 +98,7 @@ int main(int argc, char **argv)
ppg->max_links = 2; // master and slave, nothing else
ppg->arch_data = calloc(1, sizeof(struct sim_ppg_arch_data));
ppg->pp_instances = calloc(ppg->max_links, sizeof(struct pp_instance));
ppg->delay_mech = HAS_P2P ? PP_P2P_MECH : PP_E2E_MECH;
if ((!ppg->arch_data) || (!ppg->pp_instances))
return -1;
......
......@@ -51,6 +51,11 @@ int main(int argc, char **argv)
ppg->servo = &servo;
ppg->rt_opts = &__pp_default_rt_opts;
if (HAS_P2P) /* FIXME: turn this to a configuration opion */
ppg->delay_mech = PP_P2P_MECH;
else
ppg->delay_mech = PP_E2E_MECH;
/* We are hosted, so we can allocate */
ppg->max_links = PP_MAX_LINKS;
ppg->arch_data = calloc(1, sizeof(struct unix_arch_data));
......
......@@ -26,7 +26,6 @@
extern int32_t cal_phase_transition;
int ptp_mode = WRC_MODE_UNKNOWN;
int ptp_sync_mech = WRC_E2E;
static int ptp_enabled = 0;
static struct wr_operations wrpc_wr_operations = {
......@@ -95,7 +94,7 @@ static struct pp_globals ppg_static = {
.parentDS = &parentDS,
.timePropertiesDS = &timePropertiesDS,
.global_ext_data = &servo_state,
.delay_mech = WRC_E2E,
.delay_mech = HAS_P2P ? PP_P2P_MECH : PP_E2E_MECH,
};
int wrc_ptp_init()
......@@ -196,14 +195,14 @@ void wrc_ptp_set_sync_mech(int mech)
struct pp_globals *ppg = ppi->glbs;
wrc_ptp_stop();
ppg->delay_mech = mech;
ptp_sync_mech = mech;
}
int wrc_ptp_get_sync_mech()
{
return ptp_sync_mech;
struct pp_instance *ppi = &ppi_static;
struct pp_globals *ppg = ppi->glbs;
return ppg->delay_mech;
}
int wrc_ptp_start()
......
......@@ -18,13 +18,8 @@
#define WRC_MODE_GM 1
#define WRC_MODE_MASTER 2
#define WRC_MODE_SLAVE 3
#define WRC_MODE_PCLOCK 4
#define WRC_E2E 0
#define WRC_P2P 1
extern int ptp_mode;
extern int ptp_sync_mech;
int wrc_ptp_init(void);
int wrc_ptp_set_mode(int mode);
......
......@@ -153,6 +153,11 @@ int main(int argc, char **argv)
ppg->servo = alloc_fn(ppsi_head, sizeof(*ppg->servo));
ppg->rt_opts = &__pp_default_rt_opts;
if (HAS_P2P) /* FIXME: turn this to a configuration opion */
ppg->delay_mech = PP_P2P_MECH;
else
ppg->delay_mech = PP_E2E_MECH;
ppg->max_links = PP_MAX_LINKS;
ppg->global_ext_data = alloc_fn(ppsi_head,
sizeof(struct wr_servo_state));
......
......@@ -6,10 +6,17 @@ CONFIG_ARCH_BARE_I386=y
# CONFIG_ARCH_BARE_X86_64 is not set
# CONFIG_ARCH_WRPC is not set
# CONFIG_ARCH_WRS is not set
# CONFIG_ARCH_SIMULATOR is not set
CONFIG_ARCH="bare-i386"
# CONFIG_EXT_WR is not set
#
# PTP Protocol Options
#
CONFIG_E2E=y
# CONFIG_P2P is not set
CONFIG_EXT_NONE=y
CONFIG_EXTENSION=""
CONFIG_CROSS_COMPILE=""
CONFIG_ARCH_CFLAGS="-m32"
CONFIG_ARCH_LDFLAGS="-m elf_i386"
CONFIG_VLAN_ARRAY_SIZE=0
......@@ -6,10 +6,17 @@
CONFIG_ARCH_BARE_X86_64=y
# CONFIG_ARCH_WRPC is not set
# CONFIG_ARCH_WRS is not set
# CONFIG_ARCH_SIMULATOR is not set
CONFIG_ARCH="bare-x86-64"
# CONFIG_EXT_WR is not set
#
# PTP Protocol Options
#
CONFIG_E2E=y
# CONFIG_P2P is not set
CONFIG_EXT_NONE=y
CONFIG_EXTENSION=""
CONFIG_CROSS_COMPILE=""
CONFIG_ARCH_CFLAGS="-m64"
CONFIG_ARCH_LDFLAGS="-m elf_x86_64"
CONFIG_VLAN_ARRAY_SIZE=0
......@@ -8,9 +8,15 @@
# CONFIG_ARCH_WRS is not set
CONFIG_ARCH_SIMULATOR=y
CONFIG_ARCH="sim"
# CONFIG_EXT_WR is not set
#
# PTP Protocol Options
#
CONFIG_E2E=y
# CONFIG_P2P is not set
CONFIG_EXT_NONE=y
CONFIG_EXTENSION=""
CONFIG_CROSS_COMPILE=""
CONFIG_ARCH_CFLAGS=""
CONFIG_ARCH_LDFLAGS=""
CONFIG_VLAN_ARRAY_SIZE=0
......@@ -6,10 +6,21 @@ CONFIG_ARCH_UNIX=y
# CONFIG_ARCH_BARE_X86_64 is not set
# CONFIG_ARCH_WRPC is not set
# CONFIG_ARCH_WRS is not set
# CONFIG_ARCH_SIMULATOR is not set
CONFIG_ARCH="unix"
# CONFIG_EXT_WR is not set
#
# PTP Protocol Options
#
CONFIG_E2E=y
# CONFIG_P2P is not set
CONFIG_EXT_NONE=y
CONFIG_EXTENSION=""
CONFIG_CROSS_COMPILE=""
CONFIG_ARCH_CFLAGS=""
CONFIG_ARCH_LDFLAGS=""
CONFIG_HAS_VLAN=y
CONFIG_HAS_MULTIPLE_VLAN=y
CONFIG_VLAN=y
CONFIG_MAX_VLANS_PER_PORT=32
CONFIG_VLAN_ARRAY_SIZE=32
#
# Automatically generated make config: don't edit
#
CONFIG_ARCH_UNIX=y
# CONFIG_ARCH_BARE_I386 is not set
# CONFIG_ARCH_BARE_X86_64 is not set
# CONFIG_ARCH_WRPC is not set
# CONFIG_ARCH_WRS is not set
# CONFIG_ARCH_SIMULATOR is not set
CONFIG_ARCH="unix"
#
# PTP Protocol Options
#
# CONFIG_E2E is not set
CONFIG_P2P=y
CONFIG_EXT_NONE=y
CONFIG_EXTENSION=""
CONFIG_CROSS_COMPILE=""
CONFIG_ARCH_CFLAGS=""
CONFIG_ARCH_LDFLAGS=""
CONFIG_HAS_VLAN=y
CONFIG_HAS_MULTIPLE_VLAN=y
CONFIG_VLAN=y
CONFIG_MAX_VLANS_PER_PORT=32
CONFIG_VLAN_ARRAY_SIZE=32
......@@ -6,10 +6,21 @@
# CONFIG_ARCH_BARE_X86_64 is not set
CONFIG_ARCH_WRPC=y
# CONFIG_ARCH_WRS is not set
# CONFIG_ARCH_SIMULATOR is not set
CONFIG_ARCH="wrpc"
#
# PTP Protocol Options
#
CONFIG_E2E=y
# CONFIG_P2P is not set
CONFIG_EXT_WR=y
# CONFIG_EXT_NONE is not set
CONFIG_EXTENSION="whiterabbit"
CONFIG_CROSS_COMPILE="/opt/gcc-lm32/bin/lm32-elf-"
CONFIG_ARCH_CFLAGS=""
CONFIG_ARCH_LDFLAGS=""
CONFIG_WRPCSW_ROOT="../wrpc-sw"
CONFIG_HAS_VLAN=y
CONFIG_VLAN=y
CONFIG_VLAN_ARRAY_SIZE=1
#
# Automatically generated make config: don't edit
#
# CONFIG_ARCH_UNIX is not set
# CONFIG_ARCH_BARE_I386 is not set
# CONFIG_ARCH_BARE_X86_64 is not set
CONFIG_ARCH_WRPC=y
# CONFIG_ARCH_WRS is not set
# CONFIG_ARCH_SIMULATOR is not set
CONFIG_ARCH="wrpc"
#
# PTP Protocol Options
#
# CONFIG_E2E is not set
CONFIG_P2P=y
CONFIG_EXT_WR=y
# CONFIG_EXT_NONE is not set
CONFIG_EXTENSION="whiterabbit"
CONFIG_CROSS_COMPILE="/opt/gcc-lm32/bin/lm32-elf-"
CONFIG_ARCH_CFLAGS=""
CONFIG_ARCH_LDFLAGS=""
CONFIG_WRPCSW_ROOT="../wrpc-sw"
CONFIG_HAS_VLAN=y
CONFIG_VLAN=y
CONFIG_VLAN_ARRAY_SIZE=1
......@@ -6,10 +6,22 @@
# CONFIG_ARCH_BARE_X86_64 is not set
# CONFIG_ARCH_WRPC is not set
CONFIG_ARCH_WRS=y
# CONFIG_ARCH_SIMULATOR is not set
CONFIG_ARCH="wrs"
#
# PTP Protocol Options
#
CONFIG_E2E=y
# CONFIG_P2P is not set
CONFIG_EXT_WR=y
# CONFIG_EXT_NONE is not set
CONFIG_EXTENSION="whiterabbit"
CONFIG_CROSS_COMPILE="/opt/arm-wrswitch/bin/arm-linux-"
CONFIG_ARCH_CFLAGS=""
CONFIG_ARCH_LDFLAGS=""
CONFIG_HAS_VLAN=y
CONFIG_HAS_MULTIPLE_VLAN=y
CONFIG_VLAN=y
CONFIG_MAX_VLANS_PER_PORT=32
CONFIG_VLAN_ARRAY_SIZE=32
#
# Automatically generated make config: don't edit
#
# CONFIG_ARCH_UNIX is not set
# CONFIG_ARCH_BARE_I386 is not set
# CONFIG_ARCH_BARE_X86_64 is not set
# CONFIG_ARCH_WRPC is not set
CONFIG_ARCH_WRS=y
# CONFIG_ARCH_SIMULATOR is not set
CONFIG_ARCH="wrs"
#
# PTP Protocol Options
#
# CONFIG_E2E is not set
CONFIG_P2P=y
CONFIG_EXT_WR=y
# CONFIG_EXT_NONE is not set
CONFIG_EXTENSION="whiterabbit"
CONFIG_CROSS_COMPILE="/opt/arm-wrswitch/bin/arm-linux-"
CONFIG_ARCH_CFLAGS=""
CONFIG_ARCH_LDFLAGS=""
CONFIG_HAS_VLAN=y
CONFIG_HAS_MULTIPLE_VLAN=y
CONFIG_VLAN=y
CONFIG_MAX_VLANS_PER_PORT=32
CONFIG_VLAN_ARRAY_SIZE=32
......@@ -52,15 +52,14 @@
/* We use an array of timeouts, with these indexes */
enum pp_timeouts {
PP_TO_DELAYREQ = 0,
PP_TO_REQUEST = 0,
PP_TO_SYNC,
PP_TO_ANN_RECEIPT,
PP_TO_ANN_INTERVAL,
PP_TO_FAULTY,
/* A few timeouts for the protocol extension */
/* Two timeouts for the protocol extension */
PP_TO_EXT_0,
PP_TO_EXT_1,
PP_TO_EXT_2,
__PP_TO_ARRAY_SIZE,
};
......@@ -99,6 +98,9 @@ enum pp_timeouts {
#define PP_MCAST_MACADDRESS "\x01\x1B\x19\x00\x00\x00"
#define PP_PDELAY_MACADDRESS "\x01\x80\xC2\x00\x00\x0E"
#define PP_E2E_MECH 0
#define PP_P2P_MECH 1
#include <arch/constants.h> /* architectures may override the defaults */
#endif /* __PPSI_CONSTANTS_H__ */
......@@ -178,23 +178,22 @@ typedef struct MsgDelayResp {
PortIdentity requestingPortIdentity;
} MsgDelayResp;
/* PdelayReq Message (table 29, page 131) -- not used in ppsi */
struct MsgPDelayReq {
/* PdelayReq Message (table 29, page 131) */
typedef struct MsgPDelayReq {
Timestamp originTimestamp;
} MsgPDelayReq;
};
/* PdelayResp Message (table 30, page 131) -- not used in ppsi */
struct MsgPDelayResp {
/* PdelayResp Message (table 30, page 131) */
typedef struct MsgPDelayResp {
Timestamp requestReceiptTimestamp;
PortIdentity requestingPortIdentity;
};
} MsgPDelayResp;
/* PdelayRespFollowUp Message (table 31, page 132) -- not used in ppsi */
struct MsgPDelayRespFollowUp {
/* PdelayRespFollowUp Message (table 31, page 132) */
typedef struct MsgPDelayRespFollowUp {
Timestamp responseOriginTimestamp;
PortIdentity requestingPortIdentity;
};
} MsgPDelayRespFollowUp;
/* Signaling Message (table 33, page 133) */
typedef struct MsgSignaling {
......@@ -256,7 +255,7 @@ typedef struct DSPort { /* page 72 */
PortIdentity portIdentity;
/* Dynamic */
/* Enumeration8 portState; -- not used */
Integer8 logMinDelayReqInterval; /* note: never changed */
Integer8 logMinDelayReqInterval; /* -- same as pdelay one */
/* TimeInternal peerMeanPathDelay; -- not used */
/* Configurable */
Integer8 logAnnounceInterval;
......
......@@ -115,7 +115,6 @@ struct pp_instance_cfg {
char port_name[16];
char iface_name[16];
int ext; /* 0: none, 1: whiterabbit */ /* FIXME extension enumeration */
int delay_mech; /* E2E: 0, P2P: 1 */
};
/*
......@@ -155,6 +154,7 @@ struct pp_instance {
/* Times, for the various offset computations */
TimeInternal t1, t2, t3, t4, t5, t6; /* *the* stamps */
Integer32 t4_cf, t6_cf; /* peer delay */
TimeInternal cField; /* transp. clocks */
TimeInternal last_rcv_time, last_snt_time; /* two temporaries */
......@@ -174,6 +174,7 @@ struct pp_instance {
UInteger16 sent_seq[__PP_NR_MESSAGES_TYPES]; /* last sent this type */
MsgHeader received_ptp_header;
char *iface_name; /* for direct actions on hardware */
char *port_name; /* for diagnostics, mainly */
int port_idx;
......@@ -188,7 +189,8 @@ struct pp_instance {
/* The following things used to be bit fields. Other flags are now enums */
#define PPI_FLAG_FROM_CURRENT_PARENT 0x01
#define PPI_FLAG_WAITING_FOR_F_UP 0x02
#define PPI_FLAG_WAITING_FOR_RF_UP 0x04
#define PPI_FLAGS_WAITING 0x06 /* both of the above */
struct pp_globals_cfg {
int cfg_items; /* Remember how many we parsed */
......@@ -213,7 +215,7 @@ struct pp_globals {
DSTimeProperties *timePropertiesDS; /* page 70 */
/* Sync Mechanism */
int delay_mech; /* E2E : 0 , P2P : 1 */
int delay_mech; /* PP_E2E_MECH, PP_P2P_MECH */
/* Index of the pp_instance receiving the "Ebest" clock */
int ebest_idx;
......
......@@ -9,6 +9,18 @@
#define __PPSI_PPSI_H__
#include <generated/autoconf.h>
#ifdef CONFIG_E2E
# define HAS_E2E 1
#else
# define HAS_E2E 0
#endif
#ifdef CONFIG_P2P
# define HAS_P2P 1
#else
# define HAS_P2P 0
#endif
#include <stdint.h>
#include <stdarg.h>
#include <stddef.h>
......@@ -136,6 +148,8 @@ struct pp_ext_hooks {
void (*handle_announce)(struct pp_instance *ppi);
int (*handle_followup)(struct pp_instance *ppi, TimeInternal *orig,
TimeInternal *correction_field);
int (*handle_preq) (struct pp_instance * ppi);
int (*handle_presp) (struct pp_instance * ppi);
int (*pack_announce)(struct pp_instance *ppi);
void (*unpack_announce)(void *buf, MsgAnnounce *ann);
};
......@@ -377,7 +391,8 @@ extern int f_simple_int(struct pp_argline *l, int lineno,
extern void pp_servo_init(struct pp_instance *ppi);
extern void pp_servo_got_sync(struct pp_instance *ppi); /* got t1 and t2 */
extern void pp_servo_got_resp(struct pp_instance *ppi); /* got all t1..t4 */
extern void pp_servo_got_psync(struct pp_instance *ppi); /* got t1 and t2 */
extern void pp_servo_got_presp(struct pp_instance *ppi); /* got all t3..t6 */
/* bmc.c */
extern void m1(struct pp_instance *ppi);
......@@ -392,17 +407,33 @@ extern void msg_unpack_announce(void *buf, MsgAnnounce *ann);
extern void msg_unpack_follow_up(void *buf, MsgFollowUp *flwup);
extern void msg_unpack_delay_req(void *buf, MsgDelayReq *delay_req);
extern void msg_unpack_delay_resp(void *buf, MsgDelayResp *resp);
/* pdelay */
extern void msg_unpack_pdelay_resp_follow_up(void *buf,
MsgPDelayRespFollowUp *
pdelay_resp_flwup);
extern void msg_pack_pdelay_resp_follow_up(struct pp_instance *ppi,
MsgHeader * hdr,
Timestamp * prec_orig_tstamp);
extern void msg_unpack_pdelay_resp(void *buf, MsgPDelayResp * presp);
extern void msg_pack_pdelay_resp(struct pp_instance *ppi,
MsgHeader * hdr, Timestamp * rcv_tstamp);
extern void msg_unpack_pdelay_req(void *buf, MsgPDelayReq * pdelay_req);
extern void msg_pack_pdelay_req(struct pp_instance *ppi,
Timestamp * orig_tstamp);
/* each of them returns 0 if ok, -1 in case of error in send, 1 if stamp err */
#define PP_SEND_OK 0
#define PP_SEND_ERROR -1
#define PP_SEND_NO_STAMP 1
extern void *msg_copy_header(MsgHeader *dest, MsgHeader *src); /* REMOVE ME!! */
extern int msg_issue_announce(struct pp_instance *ppi);
extern int msg_issue_sync_followup(struct pp_instance *ppi);
extern int msg_issue_delay_req(struct pp_instance *ppi);
extern int msg_issue_request(struct pp_instance *ppi);
extern int msg_issue_delay_resp(struct pp_instance *ppi, TimeInternal *time);
extern int msg_issue_pdelay_resp_followup(struct pp_instance *ppi,
TimeInternal * time);
extern int msg_issue_pdelay_resp(struct pp_instance *ppi, TimeInternal * time);
/* Functions for timestamp handling (internal to protocol format conversion*/
/* FIXME: add prefix in function name? */
......@@ -431,7 +462,7 @@ extern struct pp_state_table_item pp_state_table[]; /* 0-terminated */
/* Standard state-machine functions */
extern pp_action pp_initializing, pp_faulty, pp_disabled, pp_listening,
pp_pre_master, pp_master, pp_passive, pp_uncalibrated,
pp_slave;
pp_slave, pp_pclock;;
/* The engine */
extern int pp_state_machine(struct pp_instance *ppi, uint8_t *packet, int plen);
......
......@@ -50,6 +50,7 @@ static struct pp_instance ppi_static = {
/* We now have a structure with all globals, and multiple ppi inside */
static struct pp_globals ppg_static = {
.pp_instances = &ppi_static,
.delay_mech = HAS_P2P ? PP_P2P_MECH : PP_E2E_MECH,
.nlinks = 1,
.servo = &servo,
.defaultDS = &defaultDS,
......
......@@ -71,6 +71,14 @@ static int wr_listening(struct pp_instance *ppi, unsigned char *pkt, int plen)
return 0;
}
static int wr_handle_preq(struct pp_instance *ppi)
{
ppi->received_ptp_header.correctionfield.msb = 0;
ppi->received_ptp_header.correctionfield.lsb =
phase_to_cf_units(ppi->last_rcv_time.phase);
return 0;
}
static int wr_master_msg(struct pp_instance *ppi, unsigned char *pkt, int plen,
int msgtype)
{
......@@ -91,6 +99,11 @@ static int wr_master_msg(struct pp_instance *ppi, unsigned char *pkt, int plen,
msgtype = PPM_NOTHING_TO_DO;
break;
case PPM_PDELAY_REQ:
wr_handle_preq(ppi);
msgtype = PPM_NOTHING_TO_DO;
break;
/* This is missing in the standard protocol */
case PPM_SIGNALING:
msg_unpack_wrsig(ppi, pkt, &wrsig_msg,
......@@ -202,9 +215,51 @@ static int wr_handle_followup(struct pp_instance *ppi,
wr_servo_got_sync(ppi, precise_orig_timestamp,
&ppi->t2);
if (GLBS(ppi)->delay_mech == PP_P2P_MECH)
wr_servo_update(ppi);
return 1; /* the caller returns too */
}
static int wr_handle_presp(struct pp_instance *ppi)
{
MsgHeader *hdr = &ppi->received_ptp_header;
TimeInternal correction_field;
struct wr_dsport *wrp = WR_DSPOR(ppi);
TimeInternal *ofm = &DSCUR(ppi)->offsetFromMaster;
/* FIXME: check sub-nano relevance of correction filed */
cField_to_TimeInternal(&correction_field, hdr->correctionfield);
/*
* If no WR mode is on, run normal code, if T2/T3 are valid.
* After we adjusted the pps counter, stamps are invalid, so
* we'll have the Unix time instead, marked by "correct"
*/
if (!wrp->wrModeOn) {
if (!ppi->t3.correct || !ppi->t6.correct) {
pp_diag(ppi, servo, 1,
"T3 or T6 incorrect, discarding tuple\n");
return 0;
}
pp_servo_got_presp(ppi);
/*
* pps always on if offset less than 1 second,
* until ve have a configurable threshold */
if (ofm->seconds)
wrp->ops->enable_timing_output(ppi, 0);
else
wrp->ops->enable_timing_output(ppi, 1);
return 0;
}
ppi->t4_cf = hdr->correctionfield.lsb;
wr_servo_got_delay(ppi, ppi->t4_cf);
return 0;
}
static int wr_pack_announce(struct pp_instance *ppi)
{
pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
......@@ -237,6 +292,8 @@ struct pp_ext_hooks pp_hooks = {
.execute_slave = wr_execute_slave,
.handle_announce = wr_handle_announce,
.handle_followup = wr_handle_followup,
.handle_preq = wr_handle_preq,
.handle_presp = wr_handle_presp,
.pack_announce = wr_pack_announce,
.unpack_announce = wr_unpack_announce,
};
......@@ -156,7 +156,7 @@ struct wr_servo_state {
int32_t clock_period_ps;
/* These fields are used by servo code, across iterations */
TimeInternal t1, t2, t3, t4;
TimeInternal t1, t2, t3, t4, t5, t6;
int64_t delta_ms_prev;
int missed_iters;
......@@ -179,6 +179,13 @@ struct wr_servo_state {
TimeInternal update_time;
};
int wr_p2p_delay(struct pp_instance *ppi, struct wr_servo_state *s);
int wr_e2e_offset(struct pp_instance *ppi,
struct wr_servo_state *s, TimeInternal *ts_offset_hw);
int wr_p2p_offset(struct pp_instance *ppi,
struct wr_servo_state *s, TimeInternal *ts_offset_hw);
/* All data used as extension ppsi-wr must be put here */
struct wr_data {
struct wr_servo_state servo_state;
......
......@@ -239,31 +239,109 @@ int wr_servo_got_delay(struct pp_instance *ppi, Integer32 cf)
struct wr_servo_state *s =
&((struct wr_data *)ppi->ext_data)->servo_state;
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
s->t3 = ppi->t3;
/* s->t3.phase = 0; */
s->t4 = ppi->t4;
s->t4.correct = 1; /* clock->delay_req_receive_time.correct; */
s->t4.phase = (int64_t) cf * 1000LL / 65536LL;
if (GLBS(ppi)->delay_mech == PP_P2P_MECH) {
s->t5 = ppi->t5;
s->t5.correct = 1;
s->t5.phase = 0;
s->t6 = ppi->t6;
s->t6.phase = (int64_t) ppi->t6_cf * 1000LL / 65536LL;
wr_p2p_delay(ppi, s);
}
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END);
return 0;
}
int wr_p2p_delay(struct pp_instance *ppi, struct wr_servo_state *s)
{
uint64_t big_delta_fix;
static int errcount;
int wr_servo_update(struct pp_instance *ppi)
if (!s->t3.correct || !s->t4.correct ||
!s->t5.correct || !s->t6.correct) {
errcount++;
if (errcount > 5) /* a 2-3 in a row are expected */
pp_error("%s: TimestampsIncorrect: %d %d %d %d\n",
__func__, s->t3.correct, s->t4.correct,
s->t5.correct, s->t6.correct);
return 0;
}
errcount = 0;
s->update_count++;
s->mu = ts_sub(ts_sub(s->t6, s->t3), ts_sub(s->t5, s->t4));
if (__PP_DIAG_ALLOW(ppi, pp_dt_servo, 1)) {
dump_timestamp(ppi, "servo:t1", s->t1);
dump_timestamp(ppi, "servo:t2", s->t2);
dump_timestamp(ppi, "servo:t3", s->t3);
dump_timestamp(ppi, "servo:t4", s->t4);
dump_timestamp(ppi, "servo:t5", s->t5);
dump_timestamp(ppi, "servo:t6", s->t6);
dump_timestamp(ppi, "->mdelay", s->mu);
}
big_delta_fix = s->delta_tx_m + s->delta_tx_s
+ s->delta_rx_m + s->delta_rx_s;
s->delta_ms =
(((int64_t) (ts_to_picos(s->mu) - big_delta_fix) *
(int64_t) s->fiber_fix_alpha) >> FIX_ALPHA_FRACBITS)
+ ((ts_to_picos(s->mu) - big_delta_fix) >> 1)
+ s->delta_tx_m + s->delta_rx_s;
return 1;
}
int wr_p2p_offset(struct pp_instance *ppi,
struct wr_servo_state *s, TimeInternal *ts_offset_hw)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
struct wr_servo_state *s =
&((struct wr_data *)ppi->ext_data)->servo_state;
TimeInternal ts_offset;
static int errcount;
if (!s->t1.correct || !s->t2.correct) {
errcount++;
if (errcount > 5) /* a 2-3 in a row are expected */
pp_error("%s: TimestampsIncorrect: %d %d \n",
__func__, s->t1.correct, s->t2.correct);
return 0;
}
errcount = 0;
got_sync = 0;
s->update_count++;
ts_offset = ts_add(ts_sub(s->t1, s->t2), picos_to_ts(s->delta_ms));
*ts_offset_hw = ts_hardwarize(ts_offset, s->clock_period_ps);
/* is it possible to calculate it in client,
* but then t1 and t2 require shmem locks */
s->offset = ts_to_picos(ts_offset);
s->tracking_enabled = tracking_enabled;
return 1;
}
int wr_e2e_offset(struct pp_instance *ppi,
struct wr_servo_state *s, TimeInternal *ts_offset_hw)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
uint64_t big_delta_fix;
uint64_t delay_ms_fix;
TimeInternal ts_offset;
static int errcount;
int remaining_offset;
int64_t picos_mu_prev = 0;
TimeInternal ts_offset, ts_offset_hw /*, ts_phase_adjust */;
if(!got_sync)
return 0;
if(!s->t1.correct || !s->t2.correct ||
!s->t3.correct || !s->t4.correct) {
......@@ -312,7 +390,7 @@ int wr_servo_update(struct pp_instance *ppi)
+ s->delta_tx_m + s->delta_rx_s;
ts_offset = ts_add(ts_sub(s->t1, s->t2), picos_to_ts(delay_ms_fix));
ts_offset_hw = ts_hardwarize(ts_offset, s->clock_period_ps);
*ts_offset_hw = ts_hardwarize(ts_offset, s->clock_period_ps);
/* is it possible to calculate it in client,
* but then t1 and t2 require shmem locks */
......@@ -322,6 +400,33 @@ int wr_servo_update(struct pp_instance *ppi)
s->delta_ms = delay_ms_fix;
return 1;
}
int wr_servo_update(struct pp_instance *ppi)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
struct wr_servo_state *s =
&((struct wr_data *)ppi->ext_data)->servo_state;
int remaining_offset;
int64_t picos_mu_prev = 0;
TimeInternal ts_offset_hw /*, ts_phase_adjust */ ;
if (!got_sync)
return 0;
/* shmem lock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
if (GLBS(ppi)->delay_mech == PP_P2P_MECH) {
if (!wr_p2p_offset(ppi, s, &ts_offset_hw))
goto out;
} else {
if (!wr_e2e_offset(ppi, s, &ts_offset_hw))
goto out;
}
if (wrp->ops->locking_poll(ppi, 0) != WR_SPLL_READY) {
pp_diag(ppi, servo, 1, "PLL OutOfLock, should restart sync\n");
wrp->ops->enable_timing_output(ppi, 0);
......
......@@ -8,6 +8,7 @@
#include <ppsi/ppsi.h>
#include "common-fun.h"
#include "../lib/network_types.h"
#include "../proto-ext-whiterabbit/wr-api.h" /* FIXME: phase_to_cf_units */
#ifdef CONFIG_ARCH_WRS
#define ARCH_IS_WRS 1
......@@ -15,7 +16,7 @@
#define ARCH_IS_WRS 0
#endif
static void *msg_copy_header(MsgHeader *dest, MsgHeader *src)
void *msg_copy_header(MsgHeader *dest, MsgHeader *src)
{
return memcpy(dest, src, sizeof(MsgHeader));
}
......@@ -185,7 +186,63 @@ int st_com_slave_handle_sync(struct pp_instance *ppi, unsigned char *buf,
ppi->flags &= ~PPI_FLAG_WAITING_FOR_F_UP;
to_TimeInternal(&ppi->t1,
&sync.originTimestamp);
pp_servo_got_sync(ppi);
if (GLBS(ppi)->delay_mech)
pp_servo_got_psync(ppi);
else
pp_servo_got_sync(ppi);
return 0;
}
int st_com_peer_handle_pres(struct pp_instance *ppi, unsigned char *buf,
int len)
{
MsgPDelayResp resp;
MsgHeader *hdr = &ppi->received_ptp_header;
if (len < PP_PDELAY_RESP_LENGTH)
return -1;
msg_unpack_pdelay_resp(buf, &resp);
if ((memcmp(&DSPOR(ppi)->portIdentity.clockIdentity,
&resp.requestingPortIdentity.clockIdentity,
PP_CLOCK_IDENTITY_LENGTH) == 0) &&
((ppi->sent_seq[PPM_PDELAY_REQ]) ==
hdr->sequenceId) &&
(DSPOR(ppi)->portIdentity.portNumber ==
resp.requestingPortIdentity.portNumber) &&
(ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT)) {
to_TimeInternal(&ppi->t4, &resp.requestReceiptTimestamp);
ppi->t6 = ppi->last_rcv_time;
ppi->t6_cf = phase_to_cf_units(ppi->last_rcv_time.phase);
ppi->flags |= PPI_FLAG_WAITING_FOR_RF_UP;
/* todo: in one clock the presp carries t5-t4 */
} else {
pp_diag(ppi, frames, 2, "pp_pclock : "
"PDelay Resp doesn't match PDelay Req\n");
}
return 0;
}
int st_com_peer_handle_preq(struct pp_instance *ppi, unsigned char *buf,
int len)
{
int e = 0;
if (len < PP_PDELAY_REQ_LENGTH)
return -1;
if (pp_hooks.handle_preq)
e = pp_hooks.handle_preq(ppi);
if (e)
return e;
msg_issue_pdelay_resp(ppi, &ppi->last_rcv_time);
msg_issue_pdelay_resp_followup(ppi, &ppi->last_snt_time);
return 0;
}
......@@ -231,7 +288,11 @@ int st_com_slave_handle_followup(struct pp_instance *ppi, unsigned char *buf,
if (ret < 0)
return ret;
pp_servo_got_sync(ppi);
if (GLBS(ppi)->delay_mech)
pp_servo_got_psync(ppi);
else
pp_servo_got_sync(ppi);
return 0;
}
......
......@@ -35,11 +35,23 @@ int st_com_master_handle_sync(struct pp_instance *ppi, unsigned char *buf,
int st_com_slave_handle_followup(struct pp_instance *ppi, unsigned char *buf,
int len);
int st_com_peer_handle_preq(struct pp_instance *ppi, unsigned char *buf,
int len);
int st_com_peer_handle_pres(struct pp_instance *ppi, unsigned char *buf,
int len);
static inline int __send_and_log(struct pp_instance *ppi, int msglen,
int msgtype, int chtype)
{
int pdelay_addr = 0;
if (msgtype == PPM_PDELAY_REQ || msgtype == PPM_PDELAY_RESP)
pdelay_addr = 1;
if (ppi->n_ops->send(ppi, ppi->tx_frame, msglen + ppi->tx_offset,
&ppi->last_snt_time, chtype, 0) < msglen) {
&ppi->last_snt_time, chtype,
pdelay_addr) < msglen) {
pp_diag(ppi, frames, 1, "%s(%d) Message can't be sent\n",
pp_msg_names[msgtype], msgtype);
return PP_SEND_ERROR;
......
......@@ -217,6 +217,40 @@ static void msg_pack_follow_up(struct pp_instance *ppi, Timestamp *prec_orig_tst
htonl(prec_orig_tstamp->nanosecondsField);
}
/* Pack PDelay Follow Up message into out buffer of ppi*/
void msg_pack_pdelay_resp_follow_up(struct pp_instance *ppi,
MsgHeader * hdr,
Timestamp * prec_orig_tstamp)
{
void *buf;
buf = ppi->tx_ptp;
/* header */
*(char *)(buf + 0) = *(char *)(buf + 0) & 0xF0;
/* RAZ messageType */
*(char *)(buf + 0) = *(char *)(buf + 0) | 0x0A;
*(UInteger16 *) (buf + 2) = htons(PP_PDELAY_RESP_LENGTH);
*(UInteger8 *) (buf + 4) = hdr->domainNumber;
/* copy the correction field, 11.4.3 c.3) */
*(Integer32 *) (buf + 8) = htonl(hdr->correctionfield.msb);
*(Integer32 *) (buf + 12) = htonl(hdr->correctionfield.lsb);
*(UInteger16 *) (buf + 30) = htons(hdr->sequenceId);
*(UInteger8 *) (buf + 32) = 0x05; /* controlField */
/* requestReceiptTimestamp */
*(UInteger16 *) (buf + 34) = htons(prec_orig_tstamp->secondsField.msb);
*(UInteger32 *) (buf + 36) = htonl(prec_orig_tstamp->secondsField.lsb);
*(UInteger32 *) (buf + 40) = htonl(prec_orig_tstamp->nanosecondsField);
/* requestingPortIdentity */
memcpy((buf + 44), &hdr->sourcePortIdentity.clockIdentity,
PP_CLOCK_IDENTITY_LENGTH);
*(UInteger16 *) (buf + 52) = htons(hdr->sourcePortIdentity.portNumber);
}
/* Unpack FollowUp message from in buffer of ppi to msgtmp.follow */
void msg_unpack_follow_up(void *buf, MsgFollowUp *flwup)
{
......@@ -228,6 +262,22 @@ void msg_unpack_follow_up(void *buf, MsgFollowUp *flwup)
htonl(*(UInteger32 *) (buf + 40));
}
/* Unpack PDelay Resp FollowUp message from in buffer of ppi to msgtmp.follow */
void msg_unpack_pdelay_resp_follow_up(void *buf,
MsgPDelayRespFollowUp * pdelay_resp_flwup)
{
pdelay_resp_flwup->responseOriginTimestamp.secondsField.msb =
htons(*(UInteger16 *) (buf + 34));
pdelay_resp_flwup->responseOriginTimestamp.secondsField.lsb =
htonl(*(UInteger32 *) (buf + 36));
pdelay_resp_flwup->responseOriginTimestamp.nanosecondsField =
htonl(*(UInteger32 *) (buf + 40));
memcpy(&pdelay_resp_flwup->requestingPortIdentity.clockIdentity,
(buf + 44), PP_CLOCK_IDENTITY_LENGTH);
pdelay_resp_flwup->requestingPortIdentity.portNumber =
htons(*(UInteger16 *) (buf + 52));
}
/* pack DelayReq message into out buffer of ppi */
static void msg_pack_delay_req(struct pp_instance *ppi, Timestamp *orig_tstamp)
{
......@@ -258,6 +308,69 @@ static void msg_pack_delay_req(struct pp_instance *ppi, Timestamp *orig_tstamp)
*(UInteger32 *) (buf + 40) = htonl(orig_tstamp->nanosecondsField);
}
/* pack DelayReq message into out buffer of ppi */
void msg_pack_pdelay_req(struct pp_instance *ppi, Timestamp * orig_tstamp)
{
void *buf;
buf = ppi->tx_ptp;
/* changes in header 11.4.3 */
*(char *)(buf + 0) = *(char *)(buf + 0) & 0xF0;
/* RAZ messageType */
*(char *)(buf + 0) = *(char *)(buf + 0) | 0x02;
*(UInteger16 *) (buf + 2) = htons(PP_PDELAY_REQ_LENGTH);
ppi->sent_seq[PPM_DELAY_REQ]++;
/* TO DO, 11.4.3 a.1) if synthed peer-to-peer TC */
/* *(char *)(buf + 4) = 0 .- not sythonized / X synt domain */
memset((buf + 8), 0, 8);
*(UInteger16 *) (buf + 30) = htons(ppi->sent_seq[PPM_PDELAY_REQ]);
*(UInteger8 *) (buf + 32) = 0x05;
/* Table 23 */
*(Integer8 *) (buf + 33) = 0x7F;
/* PDelay_req message */
*(UInteger16 *) (buf + 34) = htons(orig_tstamp->secondsField.msb);
*(UInteger32 *) (buf + 36) = htonl(orig_tstamp->secondsField.lsb);
*(UInteger32 *) (buf + 40) = htonl(orig_tstamp->nanosecondsField);
}
/* pack PDelayResp message into OUT buffer of ppi */
void msg_pack_pdelay_resp(struct pp_instance *ppi,
MsgHeader * hdr, Timestamp * rcv_tstamp)
{
void *buf;
buf = ppi->tx_ptp;
/* header */
*(char *)(buf + 0) = *(char *)(buf + 0) & 0xF0;
/* RAZ messageType */
*(char *)(buf + 0) = *(char *)(buf + 0) | 0x03;
*(UInteger16 *) (buf + 2) = htons(PP_PDELAY_RESP_LENGTH);
*(UInteger8 *) (buf + 4) = hdr->domainNumber;
/* set 0 the correction field, 11.4.3 c.3) */
memset((buf + 8), 0, 8);
*(UInteger16 *) (buf + 30) = htons(hdr->sequenceId);
*(UInteger8 *) (buf + 32) = 0x05; /* controlField */
/* requestReceiptTimestamp */
*(UInteger16 *) (buf + 34) = htons(rcv_tstamp->secondsField.msb);
*(UInteger32 *) (buf + 36) = htonl(rcv_tstamp->secondsField.lsb);
*(UInteger32 *) (buf + 40) = htonl(rcv_tstamp->nanosecondsField);
/* requestingPortIdentity */
memcpy((buf + 44), &hdr->sourcePortIdentity.clockIdentity,
PP_CLOCK_IDENTITY_LENGTH);
*(UInteger16 *) (buf + 52) = htons(hdr->sourcePortIdentity.portNumber);
}
/* pack DelayResp message into OUT buffer of ppi */
static void msg_pack_delay_resp(struct pp_instance *ppi,
MsgHeader *hdr, Timestamp *rcv_tstamp)
......@@ -311,6 +424,17 @@ void msg_unpack_delay_req(void *buf, MsgDelayReq *delay_req)
htonl(*(UInteger32 *) (buf + 40));
}
/* Unpack PDelayReq message from in buffer of ppi to msgtmp.req */
void msg_unpack_pdelay_req(void *buf, MsgPDelayReq * pdelay_req)
{
pdelay_req->originTimestamp.secondsField.msb =
htons(*(UInteger16 *) (buf + 34));
pdelay_req->originTimestamp.secondsField.lsb =
htonl(*(UInteger32 *) (buf + 36));
pdelay_req->originTimestamp.nanosecondsField =
htonl(*(UInteger32 *) (buf + 40));
}
/* Unpack delayResp message from IN buffer of ppi to msgtmp.presp */
void msg_unpack_delay_resp(void *buf, MsgDelayResp *resp)
{
......@@ -326,6 +450,21 @@ void msg_unpack_delay_resp(void *buf, MsgDelayResp *resp)
htons(*(UInteger16 *) (buf + 52));
}
/* Unpack PDelayResp message from IN buffer of ppi to msgtmp.presp */
void msg_unpack_pdelay_resp(void *buf, MsgPDelayResp * presp)
{
presp->requestReceiptTimestamp.secondsField.msb =
htons(*(UInteger16 *) (buf + 34));
presp->requestReceiptTimestamp.secondsField.lsb =
htonl(*(UInteger32 *) (buf + 36));
presp->requestReceiptTimestamp.nanosecondsField =
htonl(*(UInteger32 *) (buf + 40));
memcpy(&presp->requestingPortIdentity.clockIdentity,
(buf + 44), PP_CLOCK_IDENTITY_LENGTH);
presp->requestingPortIdentity.portNumber =
htons(*(UInteger16 *) (buf + 52));
}
const char const *pp_msg_names[16] = {
[PPM_SYNC] = "sync",
[PPM_DELAY_REQ] = "delay_req",
......@@ -372,8 +511,21 @@ int msg_issue_sync_followup(struct pp_instance *ppi)
PP_NP_GEN);
}
/* Pack and send on general multicast ip address a FollowUp message */
int msg_issue_pdelay_resp_followup(struct pp_instance *ppi, TimeInternal * time)
{
Timestamp prec_orig_tstamp;
from_TimeInternal(time, &prec_orig_tstamp);
msg_pack_pdelay_resp_follow_up(ppi, &ppi->received_ptp_header,
&prec_orig_tstamp);
return __send_and_log(ppi, PP_PDELAY_RESP_FOLLOW_UP_LENGTH,
PPM_PDELAY_RESP_FOLLOW_UP, PP_NP_GEN);
}
/* Pack and send on event multicast ip adress a DelayReq message */
int msg_issue_delay_req(struct pp_instance *ppi)
static int msg_issue_delay_req(struct pp_instance *ppi)
{
Timestamp orig_tstamp;
TimeInternal now;
......@@ -386,6 +538,27 @@ int msg_issue_delay_req(struct pp_instance *ppi)
PP_NP_EVT);
}
/* Pack and send on event multicast ip adress a PDelayReq message */
static int msg_issue_pdelay_req(struct pp_instance *ppi)
{
Timestamp orig_tstamp;
TimeInternal now;
ppi->t_ops->get(ppi, &now);
from_TimeInternal(&now, &orig_tstamp);
msg_pack_pdelay_req(ppi, &orig_tstamp);
return __send_and_log(ppi, PP_PDELAY_REQ_LENGTH, PPM_PDELAY_REQ,
PP_NP_EVT);
}
int msg_issue_request(struct pp_instance *ppi)
{
if (ppi->glbs->delay_mech == PP_E2E_MECH)
return msg_issue_delay_req(ppi);
return msg_issue_pdelay_req(ppi);
}
/* Pack and send on event multicast ip adress a DelayResp message */
int msg_issue_delay_resp(struct pp_instance *ppi, TimeInternal *time)
{
......@@ -397,3 +570,15 @@ int msg_issue_delay_resp(struct pp_instance *ppi, TimeInternal *time)
return __send_and_log(ppi, PP_DELAY_RESP_LENGTH, PPM_DELAY_RESP,
PP_NP_GEN);
}
/* Pack and send on event multicast ip adress a DelayResp message */
int msg_issue_pdelay_resp(struct pp_instance *ppi, TimeInternal * time)
{
Timestamp rcv_tstamp;
from_TimeInternal(time, &rcv_tstamp);
msg_pack_pdelay_resp(ppi, &ppi->received_ptp_header, &rcv_tstamp);
return __send_and_log(ppi, PP_PDELAY_RESP_LENGTH, PPM_PDELAY_RESP,
PP_NP_EVT);
}
......@@ -8,6 +8,13 @@
#include <ppsi/ppsi.h>
static void pp_servo_mpd_fltr(struct pp_instance *, struct pp_avg_fltr *,
TimeInternal *);
static void pp_servo_offset_master(struct pp_instance *, TimeInternal *,
TimeInternal *, TimeInternal *);
static Integer32 pp_servo_pi_controller(struct pp_instance *, TimeInternal *);
void pp_servo_init(struct pp_instance *ppi)
{
int d;
......@@ -62,6 +69,45 @@ void pp_servo_got_sync(struct pp_instance *ppi)
fmt_TI(&ppi->cField));
}
/* Called by slave and uncalib when we have t1 and t2 */
void pp_servo_got_psync(struct pp_instance *ppi)
{
TimeInternal *m_to_s_dly = &SRV(ppi)->m_to_s_dly;
TimeInternal *mpd = &DSCUR(ppi)->meanPathDelay;
TimeInternal *ofm = &DSCUR(ppi)->offsetFromMaster;
Integer32 adj;
pp_diag(ppi, servo, 2, "T1: %s\n", fmt_TI(&ppi->t1));
pp_diag(ppi, servo, 2, "T2: %s\n", fmt_TI(&ppi->t2));
/*
* calc 'master_to_slave_delay', removing the correction field
* added by transparent clocks in the path.
*/
sub_TimeInternal(m_to_s_dly, &ppi->t2, &ppi->t1);
sub_TimeInternal(m_to_s_dly, m_to_s_dly, &ppi->cField);
pp_diag(ppi, servo, 3, "correction field 1: %s\n",
fmt_TI(&ppi->cField));
/* update 'offsetFromMaster', (End to End mode) */
pp_servo_offset_master(ppi, mpd, ofm, m_to_s_dly);
/* PI controller */
adj = pp_servo_pi_controller(ppi, ofm);
/* apply controller output as a clock tick rate adjustment, if
* provided by arch, or as a raw offset otherwise */
if (pp_can_adjust(ppi)) {
if (ppi->t_ops->adjust_freq)
ppi->t_ops->adjust_freq(ppi, -adj);
else
ppi->t_ops->adjust_offset(ppi, -adj);
}
pp_diag(ppi, servo, 2, "Observed drift: %9i\n",
(int)SRV(ppi)->obs_drift >> 10);
}
/*
* This function makes the necessary checks to discard a set of t1..t4.
* It relies on mpd to be already calculated.
......@@ -103,13 +149,7 @@ void pp_servo_got_resp(struct pp_instance *ppi)
TimeInternal *mpd = &DSCUR(ppi)->meanPathDelay;
TimeInternal *ofm = &DSCUR(ppi)->offsetFromMaster;
struct pp_avg_fltr *mpd_fltr = &SRV(ppi)->mpd_fltr;
long long I_term;
long long P_term;
long long tmp;
int I_sign;
int P_sign;
Integer32 adj;
int s;
/* We sometimes enter here before we got sync/f-up */
......@@ -142,6 +182,72 @@ void pp_servo_got_resp(struct pp_instance *ppi)
if (pp_servo_bad_event(ppi))
return;
/* mean path delay filtering */
pp_servo_mpd_fltr(ppi, mpd_fltr, mpd);
/* update 'offsetFromMaster', (End to End mode) */
pp_servo_offset_master(ppi, mpd, ofm, m_to_s_dly);
/* PI controller */
adj = pp_servo_pi_controller(ppi, ofm);
/* apply controller output as a clock tick rate adjustment, if
* provided by arch, or as a raw offset otherwise */
if (pp_can_adjust(ppi)) {
if (ppi->t_ops->adjust_freq)
ppi->t_ops->adjust_freq(ppi, -adj);
else
ppi->t_ops->adjust_offset(ppi, -adj);
}
pp_diag(ppi, servo, 2, "Observed drift: %9i\n",
(int)SRV(ppi)->obs_drift >> 10);
}
/* called by slave states when delay_resp is received (all t1..t4 are valid) */
void pp_servo_got_presp(struct pp_instance *ppi)
{
TimeInternal *m_to_s_dly = &SRV(ppi)->m_to_s_dly;
TimeInternal *s_to_m_dly = &SRV(ppi)->s_to_m_dly;
TimeInternal *mpd = &DSCUR(ppi)->meanPathDelay;
struct pp_avg_fltr *mpd_fltr = &SRV(ppi)->mpd_fltr;
/*
* calc 'slave_to_master_delay', removing the correction field
* added by transparent clocks in the path.
*/
sub_TimeInternal(s_to_m_dly, &ppi->t6, &ppi->t5);
sub_TimeInternal(s_to_m_dly, s_to_m_dly, &ppi->cField);
pp_diag(ppi, servo, 3, "correction field 2: %s\n",
fmt_TI(&ppi->cField));
sub_TimeInternal(m_to_s_dly, &ppi->t4, &ppi->t3);
pp_diag(ppi, servo, 2, "T3: %s\n", fmt_TI(&ppi->t3));
pp_diag(ppi, servo, 2, "T4: %s\n", fmt_TI(&ppi->t4));
pp_diag(ppi, servo, 2, "T5: %s\n", fmt_TI(&ppi->t5));
pp_diag(ppi, servo, 2, "T6: %s\n", fmt_TI(&ppi->t6));
pp_diag(ppi, servo, 1, "Master to slave: %s\n", fmt_TI(m_to_s_dly));
pp_diag(ppi, servo, 1, "Slave to master: %s\n", fmt_TI(s_to_m_dly));
/* Calc mean path delay, used later to calc "offset from master" */
add_TimeInternal(mpd, &SRV(ppi)->m_to_s_dly, &SRV(ppi)->s_to_m_dly);
div2_TimeInternal(mpd);
pp_diag(ppi, servo, 1, "meanPathDelay: %s\n", fmt_TI(mpd));
/* if this succeeds mpd->seconds == 0 is true */
if (pp_servo_bad_event(ppi))
return;
pp_servo_mpd_fltr(ppi, mpd_fltr, mpd);
}
static
void pp_servo_mpd_fltr(struct pp_instance *ppi, struct pp_avg_fltr *mpd_fltr,
TimeInternal * mpd)
{
int s;
if (mpd_fltr->s_exp < 1) {
/* First time, keep what we have */
mpd_fltr->y = mpd->nanoseconds;
......@@ -186,13 +292,19 @@ void pp_servo_got_resp(struct pp_instance *ppi)
}
/* filter 'meanPathDelay' (running average) */
mpd_fltr->y = (mpd_fltr->y * (mpd_fltr->s_exp - 1) + mpd->nanoseconds)
/ mpd_fltr->s_exp;
/ mpd_fltr->s_exp;
mpd->nanoseconds = mpd_fltr->y;
pp_diag(ppi, servo, 1, "After avg(%i), meanPathDelay: %i\n",
(int)mpd_fltr->s_exp, mpd->nanoseconds);
}
static
void pp_servo_offset_master(struct pp_instance *ppi, TimeInternal * mpd,
TimeInternal * ofm, TimeInternal * m_to_s_dly)
{
Integer32 adj;
/* update 'offsetFromMaster', (End to End mode) */
sub_TimeInternal(ofm, m_to_s_dly, mpd);
pp_diag(ppi, servo, 1, "Offset from master: %s\n", fmt_TI(ofm));
......@@ -235,10 +347,17 @@ void pp_servo_got_resp(struct pp_instance *ppi)
}
return; /* ok */
}
}
/*
* What follows is the PI controller
*/
static
Integer32 pp_servo_pi_controller(struct pp_instance * ppi, TimeInternal * ofm)
{
long long I_term;
long long P_term;
long long tmp;
int I_sign;
int P_sign;
Integer32 adj;
/* the accumulator for the I component, shift by 10 to avoid losing bits
* later in the division */
......@@ -282,15 +401,5 @@ void pp_servo_got_resp(struct pp_instance *ppi)
else
adj = -((-tmp) >> 10);
/* apply controller output as a clock tick rate adjustment, if
* provided by arch, or as a raw offset otherwise */
if (pp_can_adjust(ppi)) {
if (ppi->t_ops->adjust_freq)
ppi->t_ops->adjust_freq(ppi, -adj);
else
ppi->t_ops->adjust_offset(ppi, -adj);
}
pp_diag(ppi, servo, 2, "Observed drift: %9i\n",
(int)SRV(ppi)->obs_drift >> 10);
return adj;
}
......@@ -12,14 +12,31 @@
int pp_listening(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
int e = 0; /* error var, to check errors in msg handling */
MsgHeader *hdr = &ppi->received_ptp_header;
MsgPDelayRespFollowUp respFllw;
if (pp_hooks.listening)
e = pp_hooks.listening(ppi, pkt, plen);
if (e)
goto out;
if (ppi->is_new_state)
if (ppi->is_new_state) {
pp_timeout_restart_annrec(ppi);
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
}
/* when the clock is using peer-delay, listening must send it too */
if (ppi->glbs->delay_mech == PP_P2P_MECH
&& pp_timeout_z(ppi, PP_TO_REQUEST)) {
e = msg_issue_request(ppi);
ppi->t3 = ppi->last_snt_time;
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
}
if (plen == 0)
goto out;
......@@ -34,6 +51,47 @@ int pp_listening(struct pp_instance *ppi, unsigned char *pkt, int plen)
e = st_com_master_handle_sync(ppi, pkt, plen);
break;
case PPM_PDELAY_REQ:
st_com_peer_handle_preq(ppi, pkt, plen);
break;
case PPM_PDELAY_RESP:
e = st_com_peer_handle_pres(ppi, pkt, plen);
break;
case PPM_PDELAY_RESP_FOLLOW_UP:
if (plen < PP_PDELAY_RESP_FOLLOW_UP_LENGTH)
break;
msg_unpack_pdelay_resp_follow_up(pkt, &respFllw);
if ((memcmp(&DSPOR(ppi)->portIdentity.clockIdentity,
&respFllw.requestingPortIdentity.clockIdentity,
PP_CLOCK_IDENTITY_LENGTH) == 0) &&
((ppi->sent_seq[PPM_PDELAY_REQ]) ==
hdr->sequenceId) &&
(DSPOR(ppi)->portIdentity.portNumber ==
respFllw.requestingPortIdentity.portNumber) &&
(ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT)) {
to_TimeInternal(&ppi->t5,
&respFllw.responseOriginTimestamp);
ppi->flags |= PPI_FLAG_WAITING_FOR_RF_UP;
if (pp_hooks.handle_presp)
e = pp_hooks.handle_presp(ppi);
else
pp_servo_got_presp(ppi);
if (e)
goto out;
} else {
pp_diag(ppi, frames, 2, "%s: "
"PDelay Resp F-up doesn't match PDelay Req\n",
__func__);
}
break;
default:
/* disregard, nothing to do */
break;
......
......@@ -64,9 +64,13 @@ int pp_master(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
int msgtype, d1, d2;
int e = 0; /* error var, to check errors in msg handling */
MsgHeader *hdr = &ppi->received_ptp_header;
MsgPDelayRespFollowUp respFllw;
if (ppi->is_new_state) {
pp_timeout_rand(ppi, PP_TO_SYNC, DSPOR(ppi)->logSyncInterval);
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
pp_timeout_rand(ppi, PP_TO_ANN_INTERVAL,
DSPOR(ppi)->logAnnounceInterval);
......@@ -93,6 +97,18 @@ int pp_master(struct pp_instance *ppi, unsigned char *pkt, int plen)
DSPOR(ppi)->logAnnounceInterval);
}
/* when the clock is using peer-delay, the muster mast send it too */
if (ppi->glbs->delay_mech == PP_P2P_MECH
&& pp_timeout_z(ppi, PP_TO_REQUEST)) {
e = msg_issue_request(ppi);
ppi->t3 = ppi->last_snt_time;
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
}
if (plen == 0)
goto out;
......@@ -126,12 +142,46 @@ int pp_master(struct pp_instance *ppi, unsigned char *pkt, int plen)
msg_issue_delay_resp(ppi, &ppi->last_rcv_time);
break;
/*
* We are not supporting pdelay (not configured to, see
* 9.5.13.1, p 106), so all the code about pdelay is removed
* as a whole by one commit in our history. It can be recoverd
* and fixed if needed
*/
case PPM_PDELAY_REQ:
st_com_peer_handle_preq(ppi, pkt, plen);
break;
case PPM_PDELAY_RESP:
e = st_com_peer_handle_pres(ppi, pkt, plen);
break;
case PPM_PDELAY_RESP_FOLLOW_UP:
if (plen < PP_PDELAY_RESP_FOLLOW_UP_LENGTH)
break;
msg_unpack_pdelay_resp_follow_up(pkt, &respFllw);
if ((memcmp(&DSPOR(ppi)->portIdentity.clockIdentity,
&respFllw.requestingPortIdentity.clockIdentity,
PP_CLOCK_IDENTITY_LENGTH) == 0) &&
((ppi->sent_seq[PPM_PDELAY_REQ]) ==
hdr->sequenceId) &&
(DSPOR(ppi)->portIdentity.portNumber ==
respFllw.requestingPortIdentity.portNumber) &&
(ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT)) {
to_TimeInternal(&ppi->t5,
&respFllw.responseOriginTimestamp);
ppi->flags |= PPI_FLAG_WAITING_FOR_RF_UP;
if (pp_hooks.handle_presp)
e = pp_hooks.handle_presp(ppi);
else
pp_servo_got_presp(ppi);
if (e)
goto out;
} else {
pp_diag(ppi, frames, 2, "%s: "
"PDelay Resp F-up doesn't match PDelay Req\n",
__func__);
}
break;
default:
/* disregard, nothing to do */
......
......@@ -12,9 +12,26 @@
int pp_passive(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
int e = 0; /* error var, to check errors in msg handling */
MsgHeader *hdr = &ppi->received_ptp_header;
MsgPDelayRespFollowUp respFllw;
if (ppi->is_new_state)
if (ppi->is_new_state) {
pp_timeout_restart_annrec(ppi);
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
}
/* when the clock is using peer-delay, listening must send it too */
if (ppi->glbs->delay_mech == PP_P2P_MECH
&& pp_timeout_z(ppi, PP_TO_REQUEST)) {
e = msg_issue_request(ppi);
ppi->t3 = ppi->last_snt_time;
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
}
if (plen == 0)
goto no_incoming_msg;
......@@ -29,6 +46,45 @@ int pp_passive(struct pp_instance *ppi, unsigned char *pkt, int plen)
e = st_com_master_handle_sync(ppi, pkt, plen);
break;
case PPM_PDELAY_REQ:
st_com_peer_handle_preq(ppi, pkt, plen);
break;
case PPM_PDELAY_RESP:
e = st_com_peer_handle_pres(ppi, pkt, plen);
break;
case PPM_PDELAY_RESP_FOLLOW_UP:
if (plen < PP_PDELAY_RESP_FOLLOW_UP_LENGTH)
break;
msg_unpack_pdelay_resp_follow_up(pkt, &respFllw);
if ((memcmp(&DSPOR(ppi)->portIdentity.clockIdentity,
&respFllw.requestingPortIdentity.clockIdentity,
PP_CLOCK_IDENTITY_LENGTH) == 0) &&
((ppi->sent_seq[PPM_PDELAY_REQ]) ==
hdr->sequenceId) &&
(DSPOR(ppi)->portIdentity.portNumber ==
respFllw.requestingPortIdentity.portNumber) &&
(ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT)) {
to_TimeInternal(&ppi->t5,
&respFllw.responseOriginTimestamp);
ppi->flags |= PPI_FLAG_WAITING_FOR_RF_UP;
if (pp_hooks.handle_presp)
e = pp_hooks.handle_presp(ppi);
else
pp_servo_got_presp(ppi);
} else {
pp_diag(ppi, frames, 2, "%s: "
"PDelay Resp F-up doesn't match PDelay Req\n",
__func__);
}
break;
default:
/* disreguard, nothing to do */
break;
......
/*
* Copyright (C) 2011 CERN (www.cern.ch)
* Author: Aurelio Colosimo
* Copyright (C) 2014 GSI (www.gsi.de)
* Author: Cesar Prados
* Based on PTPd project v. 2.1.0 (see AUTHORS for details)
*
* Released according to the GNU LGPL, version 2.1 or any later version.
......@@ -14,6 +16,7 @@ int pp_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
int e = 0; /* error var, to check errors in msg handling */
MsgHeader *hdr = &ppi->received_ptp_header;
MsgDelayResp resp;
MsgPDelayRespFollowUp respFllw;
int d1, d2;
if (ppi->is_new_state) {
......@@ -25,11 +28,11 @@ int pp_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (e)
goto out;
ppi->flags &= ~PPI_FLAG_WAITING_FOR_F_UP;
ppi->flags &= ~PPI_FLAGS_WAITING;
pp_timeout_restart_annrec(ppi);
pp_timeout_rand(ppi, PP_TO_DELAYREQ,
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
}
......@@ -55,10 +58,7 @@ int pp_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
break;
case PPM_DELAY_RESP:
e = (plen < PP_DELAY_RESP_LENGTH);
if (e)
if (plen < PP_DELAY_RESP_LENGTH)
break;
msg_unpack_delay_resp(pkt, &resp);
......@@ -97,36 +97,63 @@ int pp_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
break;
/*
* We are not supporting pdelay (not configured to, see
* 9.5.13.1, p 106), so all the code about pdelay is removed
* as a whole by one commit in our history. It can be recoverd
* and fixed if needed
*/
case PPM_PDELAY_REQ:
e = st_com_peer_handle_preq(ppi, pkt, plen);
break;
case PPM_PDELAY_RESP:
e = st_com_peer_handle_pres(ppi, pkt, plen);
break;
case PPM_PDELAY_RESP_FOLLOW_UP:
if (plen < PP_PDELAY_RESP_FOLLOW_UP_LENGTH)
break;
msg_unpack_pdelay_resp_follow_up(pkt, &respFllw);
if ((memcmp(&DSPOR(ppi)->portIdentity.clockIdentity,
&respFllw.requestingPortIdentity.clockIdentity,
PP_CLOCK_IDENTITY_LENGTH) == 0) &&
((ppi->sent_seq[PPM_PDELAY_REQ]) ==
hdr->sequenceId) &&
(DSPOR(ppi)->portIdentity.portNumber ==
respFllw.requestingPortIdentity.portNumber) &&
(ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT)) {
to_TimeInternal(&ppi->t5,
&respFllw.responseOriginTimestamp);
ppi->flags |= PPI_FLAG_WAITING_FOR_RF_UP;
if (pp_hooks.handle_presp)
e = pp_hooks.handle_presp(ppi);
else
pp_servo_got_presp(ppi);
if (e)
goto out;
} else {
pp_diag(ppi, frames, 2, "pp_pclock : "
"PDelay Resp F-up doesn't match PDelay Req\n");
}
break;
default:
/* disregard, nothing to do */
break;
}
out:
if (e == 0)
e = st_com_execute_slave(ppi);
if (pp_timeout_z(ppi, PP_TO_DELAYREQ)) {
e = msg_issue_delay_req(ppi);
if (pp_timeout_z(ppi, PP_TO_REQUEST)) {
e = msg_issue_request(ppi);
ppi->t3 = ppi->last_snt_time;
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_DELAYREQ,
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
/* Add latency */
add_TimeInternal(&ppi->t3,
&ppi->t3,
&OPTS(ppi)->outbound_latency);
}
switch(e) {
......@@ -143,13 +170,13 @@ out:
if (ppi->next_state != ppi->state) {
pp_timeout_clr(ppi, PP_TO_ANN_RECEIPT);
pp_timeout_clr(ppi, PP_TO_DELAYREQ);
pp_timeout_clr(ppi, PP_TO_REQUEST);
pp_servo_init(ppi);
}
d1 = d2 = pp_ms_to_timeout(ppi, PP_TO_ANN_RECEIPT);
if (ppi->timeouts[PP_TO_DELAYREQ])
d2 = pp_ms_to_timeout(ppi, PP_TO_DELAYREQ);
if (ppi->timeouts[PP_TO_REQUEST])
d2 = pp_ms_to_timeout(ppi, PP_TO_REQUEST);
ppi->next_delay = d1 < d2 ? d1 : d2;
return e;
}
......@@ -9,14 +9,13 @@
#define N(n) [n] = #n
static char *timeout_names[__PP_TO_ARRAY_SIZE] __attribute__((used)) = {
N(PP_TO_DELAYREQ),
N(PP_TO_REQUEST),
N(PP_TO_SYNC),
N(PP_TO_ANN_RECEIPT),
N(PP_TO_ANN_INTERVAL),
N(PP_TO_FAULTY),
N(PP_TO_EXT_0),
N(PP_TO_EXT_1),
N(PP_TO_EXT_2),
};
/*
......
......@@ -32,7 +32,10 @@ static int bare_net_send(struct pp_instance *ppi, void *pkt, int len,
hdr->h_proto = htons(ETH_P_1588);
memcpy(hdr->h_dest, PP_MCAST_MACADDRESS, 6);
if (use_pdelay_addr)
memcpy(hdr->h_dest, PP_PDELAY_MACADDRESS, 6);
else
memcpy(hdr->h_dest, PP_MCAST_MACADDRESS, 6);
/* raw socket implementation always uses gen socket */
memcpy(hdr->h_source, ppi->ch[PP_NP_GEN].addr, 6);
......
......@@ -203,7 +203,10 @@ static int unix_net_send(struct pp_instance *ppi, void *pkt, int len,
ch = ppi->ch + PP_NP_GEN;
hdr->h_proto = htons(ETH_P_1588);
memcpy(hdr->h_dest, PP_MCAST_MACADDRESS, ETH_ALEN);
if (use_pdelay_addr)
memcpy(hdr->h_dest, PP_PDELAY_MACADDRESS, ETH_ALEN);
else
memcpy(hdr->h_dest, PP_MCAST_MACADDRESS, ETH_ALEN);
memcpy(hdr->h_source, ch->addr, ETH_ALEN);
if (t)
......@@ -226,7 +229,10 @@ static int unix_net_send(struct pp_instance *ppi, void *pkt, int len,
vhdr->h_tci = htons(ppi->peer_vid); /* prio is 0 */
vhdr->h_tpid = htons(0x8100);
memcpy(vhdr->h_dest, PP_MCAST_MACADDRESS, ETH_ALEN);
if (use_pdelay_addr)
memcpy(hdr->h_dest, PP_PDELAY_MACADDRESS, ETH_ALEN);
else
memcpy(hdr->h_dest, PP_MCAST_MACADDRESS, ETH_ALEN);
memcpy(vhdr->h_source, ch->addr, ETH_ALEN);
if (t)
......@@ -316,6 +322,11 @@ static int unix_open_ch_raw(struct pp_instance *ppi, char *ifname, int chtype)
memcpy(pmr.mr_address, PP_MCAST_MACADDRESS, ETH_ALEN);
setsockopt(sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
&pmr, sizeof(pmr)); /* lazily ignore errors */
/* add peer delay multicast address */
memcpy(pmr.mr_address, PP_PDELAY_MACADDRESS, ETH_ALEN);
setsockopt(sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
&pmr, sizeof(pmr)); /* lazily ignore errors */
/* make timestamps available through recvmsg() -- FIXME: hw? */
temp = 1;
......@@ -419,6 +430,23 @@ static int unix_open_ch_udp(struct pp_instance *ppi, char *ifname, int chtype)
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&imr, sizeof(struct ip_mreq)) < 0)
goto err_out;
/* Init Peer multicast IP address */
memcpy(addr_str, PP_PDELAY_DOMAIN_ADDRESS, INET_ADDRSTRLEN);
context = addr_str;
errno = EINVAL;
if (!inet_aton(addr_str, &net_addr))
goto err_out;
ppi->mcast_addr = net_addr.s_addr;
imr.imr_multiaddr.s_addr = net_addr.s_addr;
/* join multicast group (for receiving) on specified interface */
context = "setsockopt(IP_ADD_MEMBERSHIP)";
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&imr, sizeof(struct ip_mreq)) < 0)
goto err_out;
/* End of General multicast Ip address init */
/* set socket time-to-live */
......
......@@ -27,10 +27,12 @@ static int wrpc_open_ch(struct pp_instance *ppi)
struct wrpc_socket *sock;
mac_addr_t mac;
struct wr_sockaddr addr;
char *macaddr = PP_MCAST_MACADDRESS;
if (ppi->glbs->delay_mech == PP_P2P_MECH)
macaddr = PP_PDELAY_MACADDRESS;
addr.ethertype = ETH_P_1588;
memcpy(addr.mac, PP_MCAST_MACADDRESS, sizeof(mac_addr_t));
memcpy(addr.mac, macaddr, sizeof(mac_addr_t));
sock = ptpd_netif_create_socket(&__static_ptp_socket, &addr,
PTPD_SOCK_RAW_ETHERNET, 0);
if (!sock)
......
......@@ -479,7 +479,10 @@ static int wrs_net_send(struct pp_instance *ppi, void *pkt, int len,
if (drop)
hdr->h_proto++;
memcpy(hdr->h_dest, PP_MCAST_MACADDRESS, ETH_ALEN);
if (use_pdelay_addr)
memcpy(hdr->h_dest, PP_PDELAY_MACADDRESS, ETH_ALEN);
else
memcpy(hdr->h_dest, PP_MCAST_MACADDRESS, ETH_ALEN);
memcpy(hdr->h_source, ch->addr, ETH_ALEN);
if (t)
......@@ -512,7 +515,11 @@ static int wrs_net_send(struct pp_instance *ppi, void *pkt, int len,
if (drop)
hdr->h_proto++;
memcpy(vhdr->h_dest, PP_MCAST_MACADDRESS, ETH_ALEN);
if (use_pdelay_addr)
memcpy(vhdr->h_dest, PP_PDELAY_MACADDRESS, ETH_ALEN);
else
memcpy(vhdr->h_dest, PP_MCAST_MACADDRESS, ETH_ALEN);
memcpy(vhdr->h_source, ch->addr, ETH_ALEN);
if (t)
......
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