Commit 4abdc94a authored by Adam Wujek's avatar Adam Wujek 💬

Merge branch adam-wrs-switch into master

Merge commits needed due to changes in the switch:
--uplift of the buildroot
--change names of the interfaces from wrX (0-17) to wriX (1-18)
Signed-off-by: Adam Wujek's avatarAdam Wujek <adam.wujek@cern.ch>
parents 25d7dbe4 23f92684
......@@ -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
......
......@@ -51,7 +51,7 @@ CFLAGS += -O2 -ggdb -Iinclude -fno-common
CFLAGS += -DPPSI_VERSION=\"$(VERSION)\"
# to avoid ifdef as much as possible, I use the kernel trick for OBJ variables
OBJ-y := fsm.o diag.o
OBJ-y := fsm.o diag.o timeout.o
# Include arch code. Each arch chooses its own time directory..
include arch-$(ARCH)/Makefile
......
......@@ -8,7 +8,7 @@
#include <ppsi/ppsi.h>
#include "ppsi-sim.h"
static int f_ppm_real(int lineno, struct pp_globals *ppg,
static int f_ppm_real(struct pp_argline *l, int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
{
struct pp_instance *ppi_slave;
......@@ -20,7 +20,7 @@ static int f_ppm_real(int lineno, struct pp_globals *ppg,
return 0;
}
static int f_ppm_servo(int lineno, struct pp_globals *ppg,
static int f_ppm_servo(struct pp_argline *l, int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
{
struct pp_instance *ppi_slave;
......@@ -32,7 +32,7 @@ static int f_ppm_servo(int lineno, struct pp_globals *ppg,
return 0;
}
static int f_ofm(int lineno, struct pp_globals *ppg,
static int f_ofm(struct pp_argline *l, int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
{
struct pp_sim_time_instance *t_master, *t_slave;
......@@ -45,7 +45,7 @@ static int f_ofm(int lineno, struct pp_globals *ppg,
return 0;
}
static int f_init_time(int lineno, struct pp_globals *ppg,
static int f_init_time(struct pp_argline *l, int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
{
struct pp_sim_time_instance *t_inst;
......@@ -57,8 +57,8 @@ static int f_init_time(int lineno, struct pp_globals *ppg,
return 0;
}
static int f_fwd_t_prop(int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
static int f_fwd_t_prop(struct pp_argline *l, int lineno,
struct pp_globals *ppg, union pp_cfg_arg *arg)
{
struct sim_ppi_arch_data *data;
data = SIM_PPI_ARCH(pp_sim_get_master(ppg));
......@@ -66,8 +66,8 @@ static int f_fwd_t_prop(int lineno, struct pp_globals *ppg,
return 0;
}
static int f_bckwd_t_prop(int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
static int f_bckwd_t_prop(struct pp_argline *l, int lineno,
struct pp_globals *ppg, union pp_cfg_arg *arg)
{
struct sim_ppi_arch_data *data;
data = SIM_PPI_ARCH(pp_sim_get_slave(ppg));
......@@ -75,15 +75,15 @@ static int f_bckwd_t_prop(int lineno, struct pp_globals *ppg,
return 0;
}
static int f_t_prop(int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
static int f_t_prop(struct pp_argline *l, int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
{
f_fwd_t_prop(lineno, ppg, arg);
f_bckwd_t_prop(lineno, ppg, arg);
f_fwd_t_prop(l, lineno, ppg, arg);
f_bckwd_t_prop(l, lineno, ppg, arg);
return 0;
}
static int f_fwd_jit(int lineno, struct pp_globals *ppg,
static int f_fwd_jit(struct pp_argline *l, int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
{
struct sim_ppi_arch_data *data;
......@@ -93,7 +93,7 @@ static int f_fwd_jit(int lineno, struct pp_globals *ppg,
}
static int f_bckwd_jit(int lineno, struct pp_globals *ppg,
static int f_bckwd_jit(struct pp_argline *l, int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
{
struct sim_ppi_arch_data *data;
......@@ -102,15 +102,15 @@ static int f_bckwd_jit(int lineno, struct pp_globals *ppg,
return 0;
}
static int f_jit(int lineno, struct pp_globals *ppg,
static int f_jit(struct pp_argline *l, int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
{
f_fwd_jit(lineno, ppg, arg);
f_bckwd_jit(lineno, ppg, arg);
f_fwd_jit(l, lineno, ppg, arg);
f_bckwd_jit(l, lineno, ppg, arg);
return 0;
}
static int f_iter(int lineno, struct pp_globals *ppg,
static int f_iter(struct pp_argline *l, int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
{
SIM_PPG_ARCH(ppg)->sim_iter_max = arg->i;
......@@ -118,17 +118,17 @@ static int f_iter(int lineno, struct pp_globals *ppg,
}
struct pp_argline pp_arch_arglines[] = {
{f_ppm_real, "sim_ppm_real", ARG_INT},
{f_ppm_servo, "sim_init_ppm_servo", ARG_INT},
{f_ofm, "sim_init_ofm", ARG_TIME},
{f_init_time, "sim_init_master_time", ARG_TIME},
{f_t_prop, "sim_t_prop_ns", ARG_INT},
{f_fwd_t_prop, "sim_fwd_t_prop_ns", ARG_INT},
{f_bckwd_t_prop,"sim_bckwd_t_prop_ns", ARG_INT},
{f_jit, "sim_jit_ns", ARG_INT},
{f_fwd_jit, "sim_fwd_jit_ns", ARG_INT},
{f_bckwd_jit, "sim_bckwd_jit_ns", ARG_INT},
{f_iter, "sim_iter_max", ARG_TIME},
LEGACY_OPTION(f_ppm_real, "sim_ppm_real", ARG_INT),
LEGACY_OPTION(f_ppm_servo, "sim_init_ppm_servo", ARG_INT),
LEGACY_OPTION(f_ofm, "sim_init_ofm", ARG_TIME),
LEGACY_OPTION(f_init_time, "sim_init_master_time", ARG_TIME),
LEGACY_OPTION(f_t_prop, "sim_t_prop_ns", ARG_INT),
LEGACY_OPTION(f_fwd_t_prop, "sim_fwd_t_prop_ns", ARG_INT),
LEGACY_OPTION(f_bckwd_t_prop, "sim_bckwd_t_prop", ARG_INT),
LEGACY_OPTION(f_jit, "sim_jit_ns", ARG_INT),
LEGACY_OPTION(f_fwd_jit, "sim_fwd_jit_ns", ARG_INT),
LEGACY_OPTION(f_bckwd_jit, "sim_bckwd_jit_ns", ARG_INT),
LEGACY_OPTION(f_iter, "sim_iter_max", ARG_TIME),
{}
};
......
......@@ -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;
......
......@@ -8,20 +8,8 @@
#include <ppsi/ppsi.h>
static int f_rxdrop(int lineno, struct pp_globals *ppg, union pp_cfg_arg *arg)
{
ppg->rxdrop = arg->i;
return 0;
}
static int f_txdrop(int lineno, struct pp_globals *ppg, union pp_cfg_arg *arg)
{
ppg->txdrop = arg->i;
return 0;
}
struct pp_argline pp_arch_arglines[] = {
{ f_rxdrop, "rx-drop", ARG_INT},
{ f_txdrop, "tx-drop", ARG_INT},
GLOB_OPTION_INT("rx-drop", ARG_INT, NULL, rxdrop),
GLOB_OPTION_INT("tx-drop", ARG_INT, NULL, txdrop),
{}
};
......@@ -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));
......
......@@ -94,6 +94,7 @@ static struct pp_globals ppg_static = {
.parentDS = &parentDS,
.timePropertiesDS = &timePropertiesDS,
.global_ext_data = &servo_state,
.delay_mech = HAS_P2P ? PP_P2P_MECH : PP_E2E_MECH,
};
int wrc_ptp_init()
......@@ -188,6 +189,22 @@ int wrc_ptp_get_mode()
return ptp_mode;
}
void wrc_ptp_set_sync_mech(int mech)
{
struct pp_instance *ppi = &ppi_static;
struct pp_globals *ppg = ppi->glbs;
wrc_ptp_stop();
ppg->delay_mech = mech;
}
int wrc_ptp_get_sync_mech()
{
struct pp_instance *ppi = &ppi_static;
struct pp_globals *ppg = ppi->glbs;
return ppg->delay_mech;
}
int wrc_ptp_start()
{
struct pp_instance *ppi = &ppi_static;
......
......@@ -18,11 +18,14 @@
#define WRC_MODE_GM 1
#define WRC_MODE_MASTER 2
#define WRC_MODE_SLAVE 3
extern int ptp_mode;
int wrc_ptp_init(void);
int wrc_ptp_set_mode(int mode);
int wrc_ptp_get_mode(void);
void wrc_ptp_set_sync_mech(int mech);
int wrc_ptp_get_sync_mech(void);
int wrc_ptp_start(void);
int wrc_ptp_stop(void);
int wrc_ptp_update(void);
......
......@@ -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
......@@ -1224,12 +1224,6 @@ a list of the other ones please see the help message.
levels for fsm, time, frames, servo, bmc, extension (in that order).
See @ref{Diagnostic Macros} for details.
@item -b <ifname>
Specify which interface to use, for Ethernet mode (default:
architecture-dependent, but @t{eth0} for Linux builds). This
option can only be used in single-port operation.
@item -e
Run in Ethernet mode (by default PPSi uses UDP if the architecture
......
......@@ -119,6 +119,8 @@ int pp_state_machine(struct pp_instance *ppi, uint8_t *packet, int plen)
if (ppi->state != ppi->next_state) {
ppi->state = ppi->next_state;
ppi->is_new_state = 1;
pp_timeout_setall(ppi);
ppi->flags &= ~PPI_FLAGS_WAITING;
pp_diag_fsm(ppi, ip->name, STATE_LEAVE, 0);
return 0; /* next_delay unused: go to new state now */
}
......
......@@ -52,15 +52,14 @@
/* We use an array of timeouts, with these indexes */
enum pp_timeouts {
PP_TO_DELAYREQ = 0,
PP_TO_SYNC,
PP_TO_REQUEST = 0,
PP_TO_SYNC_SEND,
PP_TO_ANN_RECEIPT,
PP_TO_ANN_INTERVAL,
PP_TO_ANN_SEND,
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;
......
......@@ -153,7 +153,8 @@ struct pp_instance {
uint16_t peer_vid; /* Our peer's VID (for PROTO_VLAN) */
/* Times, for the various offset computations */
TimeInternal t1, t2, t3, t4; /* *the* stamps */
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 */
......@@ -173,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;
......@@ -187,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 */
......@@ -211,6 +214,9 @@ struct pp_globals {
DSParent *parentDS; /* page 68 */
DSTimeProperties *timePropertiesDS; /* page 70 */
/* Sync Mechanism */
int delay_mech; /* PP_E2E_MECH, PP_P2P_MECH */
/* Index of the pp_instance receiving the "Ebest" clock */
int ebest_idx;
int ebest_updated; /* set to 1 when ebest_idx changes */
......
......@@ -9,8 +9,21 @@
#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>
#include <ppsi/lib.h>
#include <ppsi/ieee1588_types.h>
#include <ppsi/constants.h>
......@@ -44,6 +57,10 @@ struct pp_vlanhdr {
uint16_t h_proto;
};
/* Helpers for the fsm (fsm-lib.c) */
extern int pp_lib_may_issue_sync(struct pp_instance *ppi);
extern int pp_lib_may_issue_announce(struct pp_instance *ppi);
extern int pp_lib_may_issue_request(struct pp_instance *ppi);
/* We use data sets a lot, so have these helpers */
static inline struct pp_globals *GLBS(struct pp_instance *ppi)
......@@ -135,6 +152,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);
};
......@@ -178,7 +197,6 @@ struct pp_time_operations {
int (*adjust_offset)(struct pp_instance *ppi, long offset_ns);
int (*adjust_freq)(struct pp_instance *ppi, long freq_ppb);
int (*init_servo)(struct pp_instance *ppi);
/* calc_timeout cannot return zero */
unsigned long (*calc_timeout)(struct pp_instance *ppi, int millisec);
};
......@@ -197,69 +215,21 @@ extern struct pp_time_operations unix_time_ops;
#define PP_ADJ_FREQ_MAX 512000
/*
* Timeouts. I renamed from "timer" to "timeout" to avoid
* misread/miswrite with the time operations above. A timeout, actually,
* is just a number that must be compared with the current counter.
* Timeouts.
*
* A timeout, is just a number that must be compared with the current counter.
* So we don't need struct operations, as it is one function only,
* which is folded into the "pp_time_operations" above.
*/
static inline void pp_timeout_set(struct pp_instance *ppi, int index,
int millisec)
{
ppi->timeouts[index] = ppi->t_ops->calc_timeout(ppi, millisec);
}
extern void pp_timeout_rand(struct pp_instance *ppi, int index, int logval);
static inline void pp_timeout_clr(struct pp_instance *ppi, int index)
{
ppi->timeouts[index] = 0;
}
extern void pp_timeout_log(struct pp_instance *ppi, int index);
static inline int pp_timeout(struct pp_instance *ppi, int index)
{
int ret = ppi->timeouts[index] &&
time_after_eq(ppi->t_ops->calc_timeout(ppi, 0),
ppi->timeouts[index]);
if (ret)
pp_timeout_log(ppi, index);
return ret;
}
static inline int pp_timeout_z(struct pp_instance *ppi, int index)
{
int ret = pp_timeout(ppi, index);
if (ret)
pp_timeout_clr(ppi, index);
return ret;
}
/* how many ms to wait for the timeout to happen, for ppi->next_delay */
static inline int pp_ms_to_timeout(struct pp_instance *ppi, int index)
{
signed long ret;
if (!ppi->timeouts[index]) /* not pending, nothing to wait for */
return 0;
ret = ppi->timeouts[index] - ppi->t_ops->calc_timeout(ppi, 0);
return ret <= 0 ? 0 : ret;
}
/* called several times, only sets a timeout, so inline it here */
static inline void pp_timeout_restart_annrec(struct pp_instance *ppi)
{
/* This timeout is a number of the announce interval lapses */
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT,
((DSPOR(ppi)->announceReceiptTimeout) <<
DSPOR(ppi)->logAnnounceInterval) * 1000);
}
extern void pp_timeout_init(struct pp_instance *ppi);
extern void __pp_timeout_set(struct pp_instance *ppi, int index, int millisec);
extern void pp_timeout_set(struct pp_instance *ppi, int index);
extern void pp_timeout_setall(struct pp_instance *ppi);
extern int pp_timeout(struct pp_instance *ppi, int index)
__attribute__((warn_unused_result));
extern int pp_next_delay_1(struct pp_instance *ppi, int i1);
extern int pp_next_delay_2(struct pp_instance *ppi, int i1, int i2);
extern int pp_next_delay_3(struct pp_instance *ppi, int i1, int i2, int i3);
/* The channel for an instance must be created and possibly destroyed. */
extern int pp_init_globals(struct pp_globals *ppg, struct pp_runtime_opts *opts);
......@@ -278,6 +248,7 @@ struct pp_cfg_time {
* added inside here, without redefining cfg_handler prototype */
union pp_cfg_arg {
int i;
int i2[2];
char *s;
struct pp_cfg_time ts;
};
......@@ -285,8 +256,10 @@ union pp_cfg_arg {
/*
* Configuration: we are structure-based, and a typedef simplifies things
*/
typedef int (*cfg_handler)(int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg);
struct pp_argline;
typedef int (*cfg_handler)(struct pp_argline *l, int lineno,
struct pp_globals *ppg, union pp_cfg_arg *arg);
struct pp_argname {
char *name;
......@@ -295,6 +268,7 @@ struct pp_argname {
enum pp_argtype {
ARG_NONE,
ARG_INT,
ARG_INT2,
ARG_STR,
ARG_NAMES,
ARG_TIME,
......@@ -304,8 +278,48 @@ struct pp_argline {
char *keyword; /* Each line starts with a keyword */
enum pp_argtype t;
struct pp_argname *args;
size_t field_offset;
int needs_port;
};
/* Below are macros for setting up pp_argline arrays */
#define OFFS(s,f) offsetof(struct s, f)
#define OPTION(s,func,k,typ,a,field,i) \
{ \
.f = func, \
.keyword = k, \
.t = typ, \
.args = a, \
.field_offset = OFFS(s,field), \
.needs_port = i, \
}
#define LEGACY_OPTION(func,k,typ) \
{ \
.f = func, \
.keyword = k, \
.t = typ, \
}
#define INST_OPTION(func,k,t,a,field) \
OPTION(pp_instance,func,k,t,a,field,1)
#define INST_OPTION_INT(k,t,a,field) \
INST_OPTION(f_simple_int,k,t,a,field)
#define RT_OPTION(func,k,t,a,field) \
OPTION(pp_runtime_opts,func,k,t,a,field,0)
#define GLOB_OPTION(func,k,t,a,field) \
OPTION(pp_globals,func,k,t,a,field,0)
#define RT_OPTION_INT(k,t,a,field) \
RT_OPTION(f_simple_int,k,t,a,field)
#define GLOB_OPTION_INT(k,t,a,field) \
GLOB_OPTION(f_simple_int,k,t,a,field)
/* Both the architecture and the extension can provide config arguments */
extern struct pp_argline pp_arch_arglines[];
extern struct pp_argline pp_ext_arglines[];
......@@ -313,6 +327,8 @@ extern struct pp_argline pp_ext_arglines[];
/* Note: config_string modifies the string it receives */
extern int pp_config_string(struct pp_globals *ppg, char *s);
extern int pp_config_file(struct pp_globals *ppg, int force, char *fname);
extern int f_simple_int(struct pp_argline *l, int lineno,
struct pp_globals *ppg, union pp_cfg_arg *arg);
#define PPSI_PROTO_RAW 0
#define PPSI_PROTO_UDP 1
......@@ -330,7 +346,8 @@ extern int pp_config_file(struct pp_globals *ppg, int force, char *fname);
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);
......@@ -345,17 +362,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? */
......@@ -384,7 +417,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,
......
......@@ -28,30 +28,13 @@ static struct cmd_line_opt cmd_line_list[] = {
{"-d STRING", "diagnostic level (see diag-macros.h)"},
CMD_LINE_SEPARATOR,
{"-x", "do not reset the clock if off by more than one second"},
{"-O NUMBER", "do not reset the clock if offset is more than NUMBER nanoseconds"},
{"-M NUMBER", "do not accept delay values of more than NUMBER nanoseconds"},
{"-t", "do not adjust the system clock"},
{"-a NUMBER,NUMBER", "specify clock servo P and I values (min == 1)"},
{"-w NUMBER", "specify meanPathDelay filter stiffness"},
CMD_LINE_SEPARATOR,
{"-b NAME", "bind PTP to network interface NAME"},
//{"-u ADDRESS", "also send uni-cast to ADDRESS\n"}, -- FIXME: useful?
{"-e", "run in ethernet mode (level2)"},
/* {"-h", "run in End to End mode"}, -- we only support end-to-end */
/* {"-G", "run in gPTP mode (implies -e)"}, -- no peer-to-peer mode */
{"-l NUMBER,NUMBER", "specify inbound, outbound latency in nsec"},
CMD_LINE_SEPARATOR,
{"-i NUMBER", "specify PTP domain number"},
CMD_LINE_SEPARATOR,
{"-n NUMBER", "specify announce interval in 2^NUMBER sec"},
{"-y NUMBER", "specify sync interval in 2^NUMBER sec"},
CMD_LINE_SEPARATOR,
{"-g", "run as slave only"},
{"-v NUMBER", "specify system clock allen variance"},
{"-r NUMBER", "specify system clock accuracy"},
{"-s NUMBER", "specify system clock class"},
{"-p NUMBER", "specify priority1 attribute"},
{"-q NUMBER", "specify priority2 attribute"},
CMD_LINE_SEPARATOR,
{NULL, NULL}
};
......@@ -70,28 +53,11 @@ static void cmd_line_print_help(void)
}
}
static void cmd_line_parse_two(char *a, int *n1, int *n2)
{
int i, comma = 0;
*n1 = *n2 = 0;
for (i = 0; a[i] != '\0'; i++) {
if (a[i] == ',') {
comma = i;
a[i] = '\0';
*n1 = atoi(a);
break;
}
}
*n2 = atoi(&a[comma+1]);
a[comma] = ',';
}
int pp_parse_cmdline(struct pp_globals *ppg, int argc, char **argv)
{
int i, err = 0;
int j;
char *a; /* cmd line argument */
int n1, n2; /* used by cmd_line_parse_two */
for (i = 1; i < argc; i++) {
a = argv[i];
......@@ -123,76 +89,13 @@ int pp_parse_cmdline(struct pp_globals *ppg, int argc, char **argv)
case 'x':
GOPTS(ppg)->flags |= PP_FLAG_NO_RESET;
break;
case 'O':
a = argv[++i];
GOPTS(ppg)->max_rst = atoi(a);
if (GOPTS(ppg)->max_rst > PP_NSEC_PER_SEC) {
pp_printf("Use -x to prevent jumps of"
" more than one second\n");
return -1;
}
break;
case 'M':
a = argv[++i];
GOPTS(ppg)->max_dly = atoi(a);
if (GOPTS(ppg)->max_dly > PP_NSEC_PER_SEC) {
pp_printf("Use -x to prevent jumps of"
" more than one second\n");
return -1;
}
break;
case 't':
GOPTS(ppg)->flags |= PP_FLAG_NO_ADJUST;
break;
case 'a':
a = argv[++i];
cmd_line_parse_two(a, &n1, &n2);
/* no negative or zero attenuation */
if (n1 < 1 || n2 < 1)
return -1;
GOPTS(ppg)->ap = n1;
GOPTS(ppg)->ai = n2;
break;
case 'w':
a = argv[++i];
GOPTS(ppg)->s = atoi(a);
break;
case 'b':
a = argv[++i];
if (ppg->nlinks == 1) {
INST(ppg, 0)->iface_name = a;
INST(ppg, 0)->port_name = a;
} else {
/* If ppsi.conf exists and more than one link is
* configured, it makes no sense trying to set an iface
* name */
pp_printf("Can not use -b option in multi-link conf");
return -1;
}
break;
case 'l':
a = argv[++i];
cmd_line_parse_two(a, &n1, &n2);
GOPTS(ppg)->inbound_latency.nanoseconds = n1;
GOPTS(ppg)->outbound_latency.nanoseconds = n2;
break;
case 'i':
a = argv[++i];
GOPTS(ppg)->domain_number = atoi(a);
break;
case 'y':
a = argv[++i];
GOPTS(ppg)->sync_intvl = atoi(a);
break;
case 'n':
a = argv[++i];
/* Page 237 says 0 to 4 (1s .. 16s) */
GOPTS(ppg)->announce_intvl = atoi(a);
if (GOPTS(ppg)->announce_intvl < 0)
GOPTS(ppg)->announce_intvl = 0;
if (GOPTS(ppg)->announce_intvl > 4)
GOPTS(ppg)->announce_intvl = 4;
break;
case 'g':
GOPTS(ppg)->clock_quality.clockClass
= PP_CLASS_SLAVE_ONLY;
......@@ -200,37 +103,9 @@ int pp_parse_cmdline(struct pp_globals *ppg, int argc, char **argv)
for (j = 0; j < ppg->nlinks; j++)
INST(ppg, j)->role = PPSI_ROLE_SLAVE;
break;
case 'v':
a = argv[++i];
GOPTS(ppg)->clock_quality.
offsetScaledLogVariance = atoi(a);
break;
case 'r':
a = argv[++i];
GOPTS(ppg)->clock_quality.clockAccuracy =
atoi(a);
break;
case 's':
a = argv[++i];
GOPTS(ppg)->clock_quality.clockClass =
atoi(a);
break;
case 'p':
a = argv[++i];
GOPTS(ppg)->prio1 = atoi(a);
break;
case 'q':
a = argv[++i];
GOPTS(ppg)->prio2 = atoi(a);
break;
case 'h':
/* ignored: was "GOPTS(ppg)->e2e_mode = 1;" */
break;
case 'e':
/* Apply -e option globally, to each configured link */
for (j = 0; j < ppg->nlinks; j++)
INST(ppg, j)->proto = PPSI_PROTO_RAW;
break;
case 'G':
/* gptp_mode not supported: fall through */
default:
......
......@@ -22,7 +22,8 @@ static inline struct pp_instance *CUR_PPI(struct pp_globals *ppg)
}
/* A "port" (or "link", for compatibility) line creates or uses a pp instance */
static int f_port(int lineno, struct pp_globals *ppg, union pp_cfg_arg *arg)
static int f_port(struct pp_argline *l, int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
{
int i;
......@@ -62,52 +63,35 @@ static int f_port(int lineno, struct pp_globals *ppg, union pp_cfg_arg *arg)
return -1; \
}})
static int f_if(int lineno, struct pp_globals *ppg, union pp_cfg_arg *arg)
static inline void ASSIGN_INT_FIELD(struct pp_argline *l,
struct pp_globals *ppg,
int v)
{
CHECK_PPI(1);
strcpy(CUR_PPI(ppg)->cfg.iface_name, arg->s);
return 0;
}
/* The following ones are so similar. Bah... set a pointer somewhere? */
static int f_proto(int lineno, struct pp_globals *ppg, union pp_cfg_arg *arg)
{
CHECK_PPI(1);
CUR_PPI(ppg)->proto = arg->i;
return 0;
if (l->needs_port)
*(int *)(((void *)CUR_PPI(ppg)) + l->field_offset) = v;
else
*(int *)(((void *)GOPTS(ppg)) + l->field_offset) = v;
}
static int f_role(int lineno, struct pp_globals *ppg, union pp_cfg_arg *arg)
int f_simple_int(struct pp_argline *l, int lineno,
struct pp_globals *ppg, union pp_cfg_arg *arg)
{
CHECK_PPI(1);
CUR_PPI(ppg)->role = arg->i;
CHECK_PPI(l->needs_port);
ASSIGN_INT_FIELD(l, ppg, arg->i);
return 0;
}
static int f_ext(int lineno, struct pp_globals *ppg, union pp_cfg_arg *arg)
static int f_if(struct pp_argline *l, int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
{
CHECK_PPI(1);
CUR_PPI(ppg)->cfg.ext = arg->i;
return 0;
}
/* The following two are identical as well. I really need a pointer... */
static int f_class(int lineno, struct pp_globals *ppg, union pp_cfg_arg *arg)
{
CHECK_PPI(0);
GOPTS(ppg)->clock_quality.clockClass = arg->i;
return 0;
}
static int f_accuracy(int lineno, struct pp_globals *ppg, union pp_cfg_arg *arg)
{
CHECK_PPI(0);
GOPTS(ppg)->clock_quality.clockAccuracy = arg->i;
strcpy(CUR_PPI(ppg)->cfg.iface_name, arg->s);
return 0;
}
/* Diagnostics can be per-port or global */
static int f_diag(int lineno, struct pp_globals *ppg, union pp_cfg_arg *arg)
static int f_diag(struct pp_argline *l, int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
{
unsigned long level = pp_diag_parse(arg->s);
......@@ -119,7 +103,8 @@ static int f_diag(int lineno, struct pp_globals *ppg, union pp_cfg_arg *arg)
}
/* VLAN support is per-port, and it depends on configuration itmes */
static int f_vlan(int lineno, struct pp_globals *ppg, union pp_cfg_arg *arg)
static int f_vlan(struct pp_argline *l, int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
{
struct pp_instance *ppi = CUR_PPI(ppg);
int i, n, *v;
......@@ -183,6 +168,48 @@ static int f_vlan(int lineno, struct pp_globals *ppg, union pp_cfg_arg *arg)
return 0;
}
static int f_servo_pi(struct pp_argline *l, int lineno,
struct pp_globals *ppg, union pp_cfg_arg *arg)
{
int n1, n2;
CHECK_PPI(0);
n1 = arg->i2[0]; n2 = arg->i2[1];
/* no negative or zero attenuation */
if (n1 < 1 || n2 < 1)
return -1;
GOPTS(ppg)->ap = n1;
GOPTS(ppg)->ai = n2;
return 0;
}
static int f_latency(struct pp_argline *l, int lineno, struct pp_globals *ppg,
union pp_cfg_arg *arg)
{
int n1, n2;
CHECK_PPI(0);
n1 = arg->i2[0]; n2 = arg->i2[1];
GOPTS(ppg)->inbound_latency.nanoseconds = n1;
GOPTS(ppg)->outbound_latency.nanoseconds = n2;
return 0;
}
static int f_announce_intvl(struct pp_argline *l, int lineno,
struct pp_globals *ppg, union pp_cfg_arg *arg)
{
int i = arg->i;
CHECK_PPI(0);
if (i < 0 || i > 4) {
i = i < 0 ? 0 : 4;
pp_printf("config line %i: announce interval out of range: %i, "
"forced to %i\n", lineno, arg->i, i);
}
GOPTS(ppg)->announce_intvl = i;
return 0;
}
/* These are the tables for the parser */
static struct pp_argname arg_proto[] = {
{"raw", PPSI_PROTO_RAW},
......@@ -203,16 +230,26 @@ static struct pp_argname arg_ext[] = {
};
static struct pp_argline pp_global_arglines[] = {
{ f_port, "port", ARG_STR},
{ f_port, "link", ARG_STR}, /* old name for "port" */
{ f_if, "iface", ARG_STR},
{ f_proto, "proto", ARG_NAMES, arg_proto},
{ f_role, "role", ARG_NAMES, arg_role},
{ f_ext, "extension", ARG_NAMES, arg_ext},
{ f_vlan, "vlan", ARG_STR},
{ f_diag, "diagnostics", ARG_STR},
{ f_class, "clock-class", ARG_INT},
{ f_accuracy, "clock-accuracy", ARG_INT},
LEGACY_OPTION(f_port, "port", ARG_STR),
LEGACY_OPTION(f_port, "link", ARG_STR), /* Old name for port */
LEGACY_OPTION(f_if, "iface", ARG_STR),
INST_OPTION_INT("proto", ARG_NAMES, arg_proto, proto),
INST_OPTION_INT("role", ARG_NAMES, arg_role, role),
INST_OPTION_INT("extension", ARG_NAMES, arg_ext, cfg.ext),
LEGACY_OPTION(f_vlan, "vlan", ARG_STR),
LEGACY_OPTION(f_diag, "diagnostic", ARG_STR),
RT_OPTION_INT("clock-class", ARG_INT, NULL, clock_quality.clockClass),
RT_OPTION_INT("clock-accuracy", ARG_INT, NULL,
clock_quality.clockAccuracy),
RT_OPTION_INT("clock-allan-variance", ARG_INT, NULL,
clock_quality.offsetScaledLogVariance),
LEGACY_OPTION(f_servo_pi, "servo-pi", ARG_INT2),
LEGACY_OPTION(f_latency, "latency", ARG_INT2),
RT_OPTION_INT("domain-number", ARG_INT, NULL, domain_number),
LEGACY_OPTION(f_announce_intvl, "announce-interval", ARG_INT),
RT_OPTION_INT("sync-interval", ARG_INT, NULL, sync_intvl),
RT_OPTION_INT("priority1", ARG_INT, NULL, prio1),
RT_OPTION_INT("priority2", ARG_INT, NULL, prio2),
{}
};
......@@ -380,6 +417,14 @@ static int pp_config_line(struct pp_globals *ppg, char *line, int lineno)
}
break;
case ARG_INT2:
if (sscanf(line, "%i,%i", cfg_arg.i2, &cfg_arg.i2[1]) < 0) {
pp_diag(NULL, config, 1, "line %i: wrong arg \"%s\""
" for \"%s\"\n", lineno, line, word);
return -1;
}
break;
case ARG_STR:
while (*line && blank(*line))
line++;
......@@ -408,7 +453,7 @@ static int pp_config_line(struct pp_globals *ppg, char *line, int lineno)
break;
}
if (l->f(lineno, ppg, &cfg_arg))
if (l->f(l, lineno, ppg, &cfg_arg))
return -1;
return 0;
......
......@@ -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,
......@@ -173,7 +186,6 @@ static int wr_execute_slave(struct pp_instance *ppi)
return 0;
ppi->next_state = PPS_INITIALIZING;
pp_timeout_restart_annrec(ppi);
WR_DSPOR(ppi)->doRestart = FALSE;
return 1; /* the caller returns too */
}
......@@ -202,9 +214,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 +291,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,
};
......@@ -19,9 +19,9 @@ int wr_calibrated(struct pp_instance *ppi, unsigned char *pkt, int plen)
MsgSignaling wrsig_msg;
if (ppi->is_new_state)
pp_timeout_set(ppi, PP_TO_EXT_0, wrp->wrStateTimeout);
__pp_timeout_set(ppi, PP_TO_EXT_0, wrp->wrStateTimeout);
if (pp_timeout_z(ppi, PP_TO_EXT_0)) {
if (pp_timeout(ppi, PP_TO_EXT_0)) {
/*
* FIXME: We should implement a retry by re-sending
* the "calibrated" message, moving it here from the
......
......@@ -22,7 +22,7 @@ int wr_calibration(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (ppi->is_new_state) {
wrp->wrStateRetry = WR_STATE_RETRY;
sendmsg = 1;
} else if (pp_timeout_z(ppi, PP_TO_EXT_0)) {
} else if (pp_timeout(ppi, PP_TO_EXT_0)) {
if (wr_handshake_retry(ppi))
sendmsg = 1;
else
......@@ -30,8 +30,7 @@ int wr_calibration(struct pp_instance *ppi, unsigned char *pkt, int plen)
}
if (sendmsg) {
pp_timeout_set(ppi, PP_TO_EXT_0,
wrp->calPeriod);
__pp_timeout_set(ppi, PP_TO_EXT_0, wrp->calPeriod);
e = msg_issue_wrsig(ppi, CALIBRATE);
wrp->wrPortState = WR_PORT_CALIBRATION_0;
if (wrp->calibrated)
......
......@@ -22,7 +22,7 @@ int wr_locked(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (ppi->is_new_state) {
wrp->wrStateRetry = WR_STATE_RETRY;
sendmsg = 1;
} else if (pp_timeout_z(ppi, PP_TO_EXT_0)) {
} else if (pp_timeout(ppi, PP_TO_EXT_0)) {
if (wr_handshake_retry(ppi))
sendmsg = 1;
else
......@@ -30,8 +30,7 @@ int wr_locked(struct pp_instance *ppi, unsigned char *pkt, int plen)
}
if (sendmsg) {
pp_timeout_set(ppi, PP_TO_EXT_0,
wrp->wrStateTimeout);
__pp_timeout_set(ppi, PP_TO_EXT_0, wrp->wrStateTimeout);
e = msg_issue_wrsig(ppi, LOCKED);
}
......
......@@ -22,7 +22,7 @@ int wr_m_lock(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (ppi->is_new_state) {
wrp->wrStateRetry = WR_STATE_RETRY;
sendmsg = 1;
} else if (pp_timeout_z(ppi, PP_TO_EXT_0)) {
} else if (pp_timeout(ppi, PP_TO_EXT_0)) {
if (wr_handshake_retry(ppi))
sendmsg = 1;
else
......@@ -31,7 +31,7 @@ int wr_m_lock(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (sendmsg) {
e = msg_issue_wrsig(ppi, LOCK);
pp_timeout_set(ppi, PP_TO_EXT_0, WR_M_LOCK_TIMEOUT_MS);
__pp_timeout_set(ppi, PP_TO_EXT_0, WR_M_LOCK_TIMEOUT_MS);
}
if (plen == 0)
......
......@@ -26,7 +26,7 @@ int wr_present(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (ppi->is_new_state) {
wrp->wrStateRetry = WR_STATE_RETRY;
sendmsg = 1;
} else if (pp_timeout_z(ppi, PP_TO_EXT_0)) {
} else if (pp_timeout(ppi, PP_TO_EXT_0)) {
if (wr_handshake_retry(ppi))
sendmsg = 1;
else
......@@ -34,9 +34,7 @@ int wr_present(struct pp_instance *ppi, unsigned char *pkt, int plen)
}
if (sendmsg) {
pp_timeout_set(ppi, PP_TO_EXT_0,
WR_WRS_PRESENT_TIMEOUT_MS);
pp_timeout_restart_annrec(ppi);
__pp_timeout_set(ppi, PP_TO_EXT_0, WR_WRS_PRESENT_TIMEOUT_MS);
e = msg_issue_wrsig(ppi, SLAVE_PRESENT);
}
......@@ -58,9 +56,6 @@ out:
else
ppi->next_state = PPS_FAULTY;
if (ppi->next_state != ppi->state)
pp_timeout_clr(ppi, PP_TO_ANN_RECEIPT);
ppi->next_delay = WR_DSPOR(ppi)->wrStateTimeout;
return e;
......
......@@ -19,7 +19,7 @@ int wr_resp_calib_req(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (ppi->is_new_state) {
wrp->wrStateRetry = WR_STATE_RETRY;
enable = 1;
} else if (pp_timeout_z(ppi, PP_TO_EXT_0)) {
} else if (pp_timeout(ppi, PP_TO_EXT_0)) {
if (send_pattern)
wrp->ops->calib_pattern_disable(ppi);
if (wr_handshake_retry(ppi))
......@@ -31,7 +31,7 @@ int wr_resp_calib_req(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (enable) { /* first or retry */
if (send_pattern)
wrp->ops->calib_pattern_enable(ppi, 0, 0, 0);
pp_timeout_set(ppi, PP_TO_EXT_0,
__pp_timeout_set(ppi, PP_TO_EXT_0,
wrp->otherNodeCalPeriod / 1000);
}
......
......@@ -17,7 +17,7 @@ int wr_s_lock(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (ppi->is_new_state) {
wrp->wrStateRetry = WR_STATE_RETRY;
enable = 1;
} else if (pp_timeout_z(ppi, PP_TO_EXT_0)) {
} else if (pp_timeout(ppi, PP_TO_EXT_0)) {
wrp->ops->locking_disable(ppi);
if (wr_handshake_retry(ppi))
enable = 1;
......@@ -27,7 +27,7 @@ int wr_s_lock(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (enable) {
wrp->ops->locking_enable(ppi);
pp_timeout_set(ppi, PP_TO_EXT_0, WR_S_LOCK_TIMEOUT_MS);
__pp_timeout_set(ppi, PP_TO_EXT_0, WR_S_LOCK_TIMEOUT_MS);
}
if (wrp->ops->locking_poll(ppi, 0) == WR_SPLL_READY) {
......
......@@ -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);
......
......@@ -4,6 +4,7 @@
D := proto-standard
OBJ-y += $D/fsm-table.o \
$D/fsm-lib.o \
$D/state-initializing.o \
$D/state-faulty.o \
$D/state-disabled.o \
......@@ -19,5 +20,4 @@ OBJ-y += $D/fsm-table.o \
$D/arith.o \
$D/servo.o \
$D/hooks.o \
$D/timeout.o \
$D/open-close.o
......@@ -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));
}
......@@ -86,14 +87,14 @@ int st_com_execute_slave(struct pp_instance *ppi)
if (ret < 0)
return ret;
if (pp_timeout_z(ppi, PP_TO_ANN_RECEIPT)) {
if (pp_timeout(ppi, PP_TO_ANN_RECEIPT)) {
ppi->frgn_rec_num = 0;
if (DSDEF(ppi)->clockQuality.clockClass != PP_CLASS_SLAVE_ONLY
&& (ppi->role != PPSI_ROLE_SLAVE)) {
ppi->next_state = PPS_MASTER;
} else {
ppi->next_state = PPS_LISTENING;
pp_timeout_restart_annrec(ppi);
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
}
}
return 0;
......@@ -150,7 +151,7 @@ int st_com_slave_handle_announce(struct pp_instance *ppi, unsigned char *buf,
st_com_add_foreign(ppi, buf);
/*Reset Timer handling Announce receipt timeout*/
pp_timeout_restart_annrec(ppi);
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
ppi->next_state = bmc(ppi); /* got a new announce: run bmc */
......@@ -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;
......
/*
* Copyright (C) 2011 CERN (www.cern.ch)
* Author: Aurelio Colosimo
* Copyright (C) 2014 GSI (www.gsi.de)
* Author: Alessandro Rubin
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#include <ppsi/ppsi.h>
/* Local functions that build to nothing when Kconfig selects 0/1 vlans */
static int pp_vlan_issue_announce(struct pp_instance *ppi)
{
int i, vlan = 0;
if (CONFIG_VLAN_ARRAY_SIZE && ppi->nvlans == 1)
vlan = ppi->vlans[0];
if (CONFIG_VLAN_ARRAY_SIZE <= 1 || ppi->nvlans <= 1) {
ppi->peer_vid = vlan;
return msg_issue_announce(ppi);
}
/*
* If Kconfig selected 0/1 vlans, this code is not built.
* If we have several vlans, we replace peer_vid and proceed;
*/
for (i = 0; i < ppi->nvlans; i++) {
ppi->peer_vid = ppi->vlans[i];
msg_issue_announce(ppi);
/* ignore errors: each vlan is separate */
}
return 0;
}
static int pp_vlan_issue_sync_followup(struct pp_instance *ppi)
{
int i, vlan = 0;
if (CONFIG_VLAN_ARRAY_SIZE && ppi->nvlans == 1)
vlan = ppi->vlans[0];
if (CONFIG_VLAN_ARRAY_SIZE <= 1 || ppi->nvlans <= 1) {
ppi->peer_vid = vlan;
return msg_issue_sync_followup(ppi);
}
/*
* If Kconfig selected 0/1 vlans, this code is not built.
* If we have several vlans, we replace peer_vid and proceed;
*/
for (i = 0; i < ppi->nvlans; i++) {
ppi->peer_vid = ppi->vlans[i];
msg_issue_sync_followup(ppi);
/* ignore errors: each vlan is separate */
}
return 0;
}
/*
* The following set of functions help the states in the state machine.
* Ideally, we should manage to get to a completely table-driven fsm
* implementation based on these helpers
*/
int pp_lib_may_issue_sync(struct pp_instance *ppi)
{
int e;
if (!pp_timeout(ppi, PP_TO_SYNC_SEND))
return 0;
pp_timeout_set(ppi, PP_TO_SYNC_SEND);
e = pp_vlan_issue_sync_followup(ppi);
if (e)
pp_diag(ppi, frames, 1, "could not send sync\n");
return e;
}
int pp_lib_may_issue_announce(struct pp_instance *ppi)
{
int e;
if (!pp_timeout(ppi, PP_TO_ANN_SEND))
return 0;
pp_timeout_set(ppi, PP_TO_ANN_SEND);
e = pp_vlan_issue_announce(ppi);
if (e)
pp_diag(ppi, frames, 1, "could not send announce\n");
return e;
}
int pp_lib_may_issue_request(struct pp_instance *ppi)
{
int e = 0;
if (!pp_timeout(ppi, PP_TO_REQUEST))
return 0;
pp_timeout_set(ppi, PP_TO_REQUEST);
e = msg_issue_request(ppi); /* FIXME: what about multiple vlans? */
if (e) {
pp_diag(ppi, frames, 1, "could not send request\n");
return e;
}
ppi->t3 = ppi->last_snt_time;
return 0;
}
......@@ -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;
}
......@@ -15,14 +15,10 @@
int pp_faulty(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
if (ppi->is_new_state) {
pp_timeout_set(ppi, PP_TO_FAULTY, 4000);
}
if (pp_timeout(ppi, PP_TO_FAULTY)) {
ppi->next_state = PPS_INITIALIZING;
return 0;
}
ppi->next_delay = pp_ms_to_timeout(ppi, PP_TO_FAULTY);
ppi->next_delay = pp_next_delay_1(ppi, PP_TO_FAULTY);
return 0;
}
......@@ -8,6 +8,30 @@
#include <ppsi/ppsi.h>
/*
* Initialize parentDS
*/
static void init_parent_ds(struct pp_instance *ppi)
{
/* 8.2.3.2 */
DSPAR(ppi)->parentPortIdentity.clockIdentity =
DSDEF(ppi)->clockIdentity;
/* FIXME: portNumber ? */
/* 8.2.3.3 skipped (parentStats is not used) */
/* 8.2.3.4 */
DSPAR(ppi)->observedParentOffsetScaledLogVariance = 0xffff;
/* 8.2.3.5 */
DSPAR(ppi)->observedParentClockPhaseChangeRate = 0x7fffffffUL;
/* 8.2.3.6 */
DSPAR(ppi)->grandmasterIdentity = DSDEF(ppi)->clockIdentity;
/* 8.2.3.7 */
DSPAR(ppi)->grandmasterClockQuality = DSDEF(ppi)->clockQuality;
/* 8.2.3.8 */
DSPAR(ppi)->grandmasterPriority1 = DSDEF(ppi)->priority1;
/* 8.2.3.9 */
DSPAR(ppi)->grandmasterPriority2 = DSDEF(ppi)->priority2;
}
/*
* Initializes network and other stuff
*/
......@@ -22,6 +46,8 @@ int pp_initializing(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (ppi->n_ops->init(ppi) < 0) /* it must handle being called twice */
goto failure;
init_parent_ds(ppi);
/* Clock identity comes from mac address with 0xff:0xfe intermixed */
id = (unsigned char *)&DSDEF(ppi)->clockIdentity;
mac = ppi->ch[PP_NP_GEN].addr;
......@@ -46,6 +72,7 @@ int pp_initializing(struct pp_instance *ppi, unsigned char *pkt, int plen)
port->announceReceiptTimeout = PP_DEFAULT_ANNOUNCE_RECEIPT_TIMEOUT;
port->logSyncInterval = opt->sync_intvl;
port->versionNumber = PP_VERSION_PTP;
pp_timeout_init(ppi);
if (pp_hooks.init)
ret = pp_hooks.init(ppi, pkt, plen);
......
......@@ -12,14 +12,17 @@
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)
pp_timeout_restart_annrec(ppi);
/* when the clock is using peer-delay, listening must send it too */
if (ppi->glbs->delay_mech == PP_P2P_MECH)
e = pp_lib_may_issue_request(ppi);
if (plen == 0)
goto out;
......@@ -34,6 +37,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;
......@@ -46,11 +90,7 @@ out:
if (e != 0)
ppi->next_state = PPS_FAULTY;
/* Leaving this state */
if (ppi->next_state != ppi->state)
pp_timeout_clr(ppi, PP_TO_ANN_RECEIPT);
ppi->next_delay = pp_ms_to_timeout(ppi, PP_TO_ANN_RECEIPT);
ppi->next_delay = pp_next_delay_1(ppi, PP_TO_ANN_RECEIPT);
return 0;
}
......@@ -9,89 +9,22 @@
#include <ppsi/ppsi.h>
#include "common-fun.h"
/* Local functions that build to nothing when Kconfig selects 0/1 vlans */
static int pp_master_issue_announce(struct pp_instance *ppi)
{
int i, vlan = 0;
if (CONFIG_VLAN_ARRAY_SIZE && ppi->nvlans == 1)
vlan = ppi->vlans[0];
if (CONFIG_VLAN_ARRAY_SIZE <= 1 || ppi->nvlans <= 1) {
ppi->peer_vid = vlan;
return msg_issue_announce(ppi);
}
/*
* If Kconfig selected 0/1 vlans, this code is not built.
* If we have several vlans, we replace peer_vid and proceed;
*/
for (i = 0; i < ppi->nvlans; i++) {
ppi->peer_vid = ppi->vlans[i];
msg_issue_announce(ppi);
/* ignore errors: each vlan is separate */
}
return 0;
}
static int pp_master_issue_sync_followup(struct pp_instance *ppi)
{
int i, vlan = 0;
if (CONFIG_VLAN_ARRAY_SIZE && ppi->nvlans == 1)
vlan = ppi->vlans[0];
if (CONFIG_VLAN_ARRAY_SIZE <= 1 || ppi->nvlans <= 1) {
ppi->peer_vid = vlan;
return msg_issue_sync_followup(ppi);
}
/*
* If Kconfig selected 0/1 vlans, this code is not built.
* If we have several vlans, we replace peer_vid and proceed;
*/
for (i = 0; i < ppi->nvlans; i++) {
ppi->peer_vid = ppi->vlans[i];
msg_issue_sync_followup(ppi);
/* ignore errors: each vlan is separate */
}
return 0;
}
/* The real state function, relying on the two above for sending */
int pp_master(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
int msgtype, d1, d2;
int msgtype;
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_ANN_INTERVAL,
DSPOR(ppi)->logAnnounceInterval);
/* Send an announce immediately, when becomes master */
if ((e = pp_master_issue_announce(ppi)) < 0)
goto out;
}
if (pp_timeout_z(ppi, PP_TO_SYNC)) {
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_SYNC, DSPOR(ppi)->logSyncInterval);
if ((e = pp_master_issue_sync_followup(ppi) < 0))
goto out;
}
if (pp_timeout_z(ppi, PP_TO_ANN_INTERVAL)) {
if ((e = pp_master_issue_announce(ppi) < 0))
goto out;
/* ignore errors; we are not getting FAULTY if not transmitting */
pp_lib_may_issue_sync(ppi);
pp_lib_may_issue_announce(ppi);
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_ANN_INTERVAL,
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_lib_may_issue_request(ppi);
else
pp_timeout_set(ppi, PP_TO_REQUEST);
if (plen == 0)
goto out;
......@@ -126,12 +59,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 */
......@@ -154,9 +121,8 @@ out:
break;
}
d1 = pp_ms_to_timeout(ppi, PP_TO_ANN_INTERVAL);
d2 = pp_ms_to_timeout(ppi, PP_TO_SYNC);
ppi->next_delay = d1 < d2 ? d1 : d2;
ppi->next_delay = pp_next_delay_3(ppi,
PP_TO_ANN_SEND, PP_TO_SYNC_SEND, PP_TO_REQUEST);
return e;
out_fault:
......
......@@ -12,9 +12,12 @@
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)
pp_timeout_restart_annrec(ppi);
/* when the clock is using peer-delay, listening must send it too */
if (ppi->glbs->delay_mech == PP_P2P_MECH)
e = pp_lib_may_issue_request(ppi);
if (plen == 0)
goto no_incoming_msg;
......@@ -29,6 +32,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;
......@@ -42,10 +84,6 @@ no_incoming_msg:
if (e != 0)
ppi->next_state = PPS_FAULTY;
if (ppi->next_state != ppi->state) {
pp_timeout_clr(ppi, PP_TO_ANN_RECEIPT);
}
ppi->next_delay = PP_DEFAULT_NEXT_DELAY_MS;
return 0;
......
/*
* 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,7 +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;
int d1, d2;
MsgPDelayRespFollowUp respFllw;
if (ppi->is_new_state) {
memset(&ppi->t1, 0, sizeof(ppi->t1));
......@@ -24,15 +26,10 @@ int pp_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
e = pp_hooks.new_slave(ppi, pkt, plen);
if (e)
goto out;
ppi->flags &= ~PPI_FLAG_WAITING_FOR_F_UP;
pp_timeout_restart_annrec(ppi);
pp_timeout_rand(ppi, PP_TO_DELAYREQ,
DSPOR(ppi)->logMinDelayReqInterval);
}
e = pp_lib_may_issue_request(ppi);
if (plen == 0)
goto out;
......@@ -55,10 +52,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,38 +91,55 @@ 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);
ppi->t3 = ppi->last_snt_time;
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_DELAYREQ,
DSPOR(ppi)->logMinDelayReqInterval);
/* Add latency */
add_TimeInternal(&ppi->t3,
&ppi->t3,
&OPTS(ppi)->outbound_latency);
}
switch(e) {
case PP_SEND_OK: /* 0 */
break;
......@@ -142,14 +153,10 @@ out:
}
if (ppi->next_state != ppi->state) {
pp_timeout_clr(ppi, PP_TO_ANN_RECEIPT);
pp_timeout_clr(ppi, PP_TO_DELAYREQ);
pp_servo_init(ppi);
return e;
}
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);
ppi->next_delay = d1 < d2 ? d1 : d2;
ppi->next_delay = pp_next_delay_2(ppi,
PP_TO_ANN_RECEIPT, PP_TO_REQUEST);
return e;
}
/*
* Copyright (C) 2013 CERN (www.cern.ch)
* Author: Alessandro Rubini
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#include <ppsi/ppsi.h>
#define N(n) [n] = #n
static char *timeout_names[__PP_TO_ARRAY_SIZE] __attribute__((used)) = {
N(PP_TO_DELAYREQ),
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),
};
/*
* Log means messages
*/
void pp_timeout_log(struct pp_instance *ppi, int index)
{
pp_diag(ppi, time, 1, "timeout expired: %s\n", timeout_names[index]);
}
/*
* And "rand" means logarithm...
*
* Randomize a timeout. We are required to fit between 70% and 130%
* of the value for 90% of the time, at least. But making it "almost
* exact" is bad in a big network. So randomize between 80% and 120%:
* constant part is 80% and variable is 40%.
*/
void pp_timeout_rand(struct pp_instance *ppi, int index, int logval)
{
static uint32_t seed;
uint32_t rval;
int millisec;
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;
millisec = (1 << logval) * 400; /* This is 40% of the nominal value */
millisec = (millisec * 2) + rval % millisec;
pp_timeout_set(ppi, index, millisec);
}
......@@ -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);
......
......@@ -92,15 +92,11 @@ static unsigned long bare_calc_timeout(struct pp_instance *ppi, int millisec)
{
struct bare_timespec now;
uint64_t now_ms;
unsigned long result;
if (!millisec)
millisec = 1;
sys_clock_gettime(CLOCK_MONOTONIC, &now);
now_ms = 1000LL * now.tv_sec + now.tv_nsec / 1000 / 1000;
result = now_ms + millisec;
return result ? result : 1; /* cannot return 0 */
return now_ms + millisec;
}
struct pp_time_operations bare_time_ops = {
......
......@@ -110,10 +110,7 @@ static inline int sim_init_servo(struct pp_instance *ppi)
static unsigned long sim_calc_timeout(struct pp_instance *ppi, int millisec)
{
unsigned long res;
res = millisec + SIM_PPI_ARCH(ppi)->time.current_ns / 1000LL / 1000LL;
return res ? res : 1;
return millisec + SIM_PPI_ARCH(ppi)->time.current_ns / 1000LL / 1000LL;
}
struct pp_time_operations sim_time_ops = {
......
......@@ -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 */
......@@ -469,6 +497,10 @@ static int unix_net_init(struct pp_instance *ppi)
/* The buffer is inside ppi, but we need to set pointers and align */
pp_prepare_pointers(ppi);
if (!ppi->iface_name || !ppi->iface_name[0])
/* No interface name, set it to port name */
ppi->iface_name = ppi->port_name;
switch(ppi->proto) {
case PPSI_PROTO_RAW:
pp_diag(ppi, frames, 1, "unix_net_init raw Ethernet\n");
......
......@@ -117,15 +117,11 @@ static unsigned long unix_calc_timeout(struct pp_instance *ppi, int millisec)
{
struct timespec now;
uint64_t now_ms;
unsigned long result;
if (!millisec)
millisec = 1;
clock_gettime(CLOCK_MONOTONIC, &now);
now_ms = 1000LL * now.tv_sec + now.tv_nsec / 1000 / 1000;
result = now_ms + millisec;
return result ? result : 1; /* cannot return 0 */
return now_ms + millisec;
}
struct pp_time_operations unix_time_ops = {
......
......@@ -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)
......
......@@ -61,10 +61,7 @@ static int wrpc_time_adjust(struct pp_instance *ppi, long offset_ns,
static unsigned long wrpc_calc_timeout(struct pp_instance *ppi, int millisec)
{
unsigned long now_ms = timer_get_tics();
now_ms += millisec;
return now_ms ? now_ms : 1; /* cannot return 0 */
return timer_get_tics() + millisec;
}
struct pp_time_operations wrpc_time_ops = {
......
......@@ -478,7 +478,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)
......@@ -511,7 +514,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)
......
/*
* Copyright (C) 2013 CERN (www.cern.ch)
* Author: Alessandro Rubini
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#include <ppsi/ppsi.h>
struct timeout_config {
char *name;
int isrand;
int value;
};
/* most timeouts have a static configuration. Save it here */
static struct timeout_config to_configs[__PP_TO_ARRAY_SIZE] = {
[PP_TO_REQUEST] = {"REQUEST", 1,},
[PP_TO_SYNC_SEND] = {"SYNC_SEND", 1,},
[PP_TO_ANN_RECEIPT] = {"ANN_RECEIPT", 0,},
[PP_TO_ANN_SEND] = {"ANN_SEND", 1,},
[PP_TO_FAULTY] = {"FAULTY", 0, 4000},
/* extension timeouts are explicitly set to a value */
};
/* Init fills the timeout values; they are not changed after program startup */
void pp_timeout_init(struct pp_instance *ppi)
{
struct DSPort *port = ppi->portDS;
to_configs[PP_TO_REQUEST].value =
port->logMinDelayReqInterval;
to_configs[PP_TO_SYNC_SEND].value =
port->logSyncInterval;
to_configs[PP_TO_ANN_RECEIPT].value = 1000 * (
port->announceReceiptTimeout << port->logAnnounceInterval);
to_configs[PP_TO_ANN_SEND].value = port->logAnnounceInterval;
}
static void pp_timeout_log(struct pp_instance *ppi, int index)
{
pp_diag(ppi, time, 1, "timeout expired: %s\n",
to_configs[index].name);
}
void __pp_timeout_set(struct pp_instance *ppi, int index, int millisec)
{
ppi->timeouts[index] = ppi->t_ops->calc_timeout(ppi, millisec);
}
/*
* Randomize a timeout. We are required to fit between 70% and 130%
* of the value for 90% of the time, at least. But making it "almost
* exact" is bad in a big network. So randomize between 80% and 120%:
* constant part is 80% and variable is 40%.
*/
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 (!to_configs[index].isrand){
__pp_timeout_set(ppi, index, logval); /* not a logval */
return;
}
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;
millisec = (1 << logval) * 400; /* This is 40% of the nominal value */
millisec = (millisec * 2) + rval % millisec;
__pp_timeout_set(ppi, index, millisec);
}
/*
* When we enter a new fsm state, we init all timeouts. Who cares if
* some of them are not used (and even if some have no default timeout)
*/
void pp_timeout_setall(struct pp_instance *ppi)
{
int i;
for (i = 0; i < __PP_TO_ARRAY_SIZE; i++)
pp_timeout_set(ppi, i);
/* but announce_send must be send soon */
__pp_timeout_set(ppi, PP_TO_ANN_SEND, 20);
}
int pp_timeout(struct pp_instance *ppi, int index)
{
int ret = time_after_eq(ppi->t_ops->calc_timeout(ppi, 0),
ppi->timeouts[index]);
if (ret)
pp_timeout_log(ppi, index);
return ret;
}
/*
* How many ms to wait for the timeout to happen, for ppi->next_delay.
* It is not allowed for a timeout to not be pending
*/
int pp_next_delay_1(struct pp_instance *ppi, int i1)
{
unsigned long now = ppi->t_ops->calc_timeout(ppi, 0);
signed long r1;
r1 = ppi->timeouts[i1] - now;
return r1 < 0 ? 0 : r1;
}
int pp_next_delay_2(struct pp_instance *ppi, int i1, int i2)
{
unsigned long now = ppi->t_ops->calc_timeout(ppi, 0);
signed long r1, r2;
r1 = ppi->timeouts[i1] - now;
r2 = ppi->timeouts[i2] - now;
if (r2 < r1)
r1 = r2;
return r1 < 0 ? 0 : r1;
}
int pp_next_delay_3(struct pp_instance *ppi, int i1, int i2, int i3)
{
unsigned long now = ppi->t_ops->calc_timeout(ppi, 0);
signed long r1, r2, r3;
r1 = ppi->timeouts[i1] - now;
r2 = ppi->timeouts[i2] - now;
r3 = ppi->timeouts[i3] - now;
if (r2 < r1)
r1 = r2;
if (r3 < r1)
r1 = r3;
return r1 < 0 ? 0 : r1;
}
......@@ -55,6 +55,7 @@ int main(int argc, char **argv)
{
int sock, ret;
struct packet_mreq req;
struct sockaddr_ll addr;
struct ifreq ifr;
char *ifname = "eth0";
......@@ -73,12 +74,25 @@ int main(int argc, char **argv)
ifname, strerror(errno));
exit(1);
}
memset(&addr, 0, sizeof(addr));
addr.sll_family = AF_PACKET;
addr.sll_protocol = htons(ETH_P_ALL); /* ETH_P_1588, but also vlan */
addr.sll_ifindex = ifr.ifr_ifindex;
addr.sll_pkttype = PACKET_MULTICAST;
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
fprintf(stderr, "%s: bind(%s)): %s\n", argv[0],
ifname, strerror(errno));
exit(1);
}
fprintf(stderr, "Dumping PTP packets from interface \"%s\"\n", ifname);
memset(&req, 0, sizeof(req));
req.mr_ifindex = ifr.ifr_ifindex;
req.mr_type = PACKET_MR_PROMISC;
if (setsockopt(3, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
&req, sizeof(req)) < 0) {
fprintf(stderr, "%s: set promiscuous(%s): %s\n", argv[0],
......
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