Commit fea217df authored by Alessandro Rubini's avatar Alessandro Rubini

Merge branch 'timeout-cleanup'

parents fbce8f05 6d7bf7e3
......@@ -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
......
......@@ -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 */
}
......
......@@ -53,9 +53,9 @@
/* We use an array of timeouts, with these indexes */
enum pp_timeouts {
PP_TO_REQUEST = 0,
PP_TO_SYNC,
PP_TO_SYNC_SEND,
PP_TO_ANN_RECEIPT,
PP_TO_ANN_INTERVAL,
PP_TO_ANN_SEND,
PP_TO_FAULTY,
/* Two timeouts for the protocol extension */
PP_TO_EXT_0,
......
......@@ -57,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)
......@@ -193,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);
};
......@@ -212,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);
......
......@@ -186,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 */
}
......
......@@ -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) {
......
......@@ -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
......@@ -87,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;
......@@ -151,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 */
......
/*
* 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;
}
......@@ -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;
}
......@@ -46,6 +46,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);
......
......@@ -20,23 +20,9 @@ int pp_listening(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (e)
goto out;
if (ppi->is_new_state) {
pp_timeout_restart_annrec(ppi);
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
}
/* when the clock is using peer-delay, listening must send it too */
if (ppi->glbs->delay_mech == PP_P2P_MECH
&& pp_timeout_z(ppi, PP_TO_REQUEST)) {
e = msg_issue_request(ppi);
ppi->t3 = ppi->last_snt_time;
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
}
if (ppi->glbs->delay_mech == PP_P2P_MECH)
e = pp_lib_may_issue_request(ppi);
if (plen == 0)
goto out;
......@@ -104,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,105 +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_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
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;
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_ANN_INTERVAL,
DSPOR(ppi)->logAnnounceInterval);
}
/* ignore errors; we are not getting FAULTY if not transmitting */
pp_lib_may_issue_sync(ppi);
pp_lib_may_issue_announce(ppi);
/* when the clock is using peer-delay, the muster mast send it too */
if (ppi->glbs->delay_mech == PP_P2P_MECH
&& pp_timeout_z(ppi, PP_TO_REQUEST)) {
e = msg_issue_request(ppi);
ppi->t3 = ppi->last_snt_time;
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
}
if (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;
......@@ -204,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:
......
......@@ -15,23 +15,9 @@ int pp_passive(struct pp_instance *ppi, unsigned char *pkt, int plen)
MsgHeader *hdr = &ppi->received_ptp_header;
MsgPDelayRespFollowUp respFllw;
if (ppi->is_new_state) {
pp_timeout_restart_annrec(ppi);
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
}
/* when the clock is using peer-delay, listening must send it too */
if (ppi->glbs->delay_mech == PP_P2P_MECH
&& pp_timeout_z(ppi, PP_TO_REQUEST)) {
e = msg_issue_request(ppi);
ppi->t3 = ppi->last_snt_time;
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
}
if (ppi->glbs->delay_mech == PP_P2P_MECH)
e = pp_lib_may_issue_request(ppi);
if (plen == 0)
goto no_incoming_msg;
......@@ -98,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;
......
......@@ -17,7 +17,6 @@ int pp_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
MsgHeader *hdr = &ppi->received_ptp_header;
MsgDelayResp resp;
MsgPDelayRespFollowUp respFllw;
int d1, d2;
if (ppi->is_new_state) {
memset(&ppi->t1, 0, sizeof(ppi->t1));
......@@ -27,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_FLAGS_WAITING;
pp_timeout_restart_annrec(ppi);
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
}
e = pp_lib_may_issue_request(ppi);
if (plen == 0)
goto out;
......@@ -146,16 +140,6 @@ out:
if (e == 0)
e = st_com_execute_slave(ppi);
if (pp_timeout_z(ppi, PP_TO_REQUEST)) {
e = msg_issue_request(ppi);
ppi->t3 = ppi->last_snt_time;
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
}
switch(e) {
case PP_SEND_OK: /* 0 */
break;
......@@ -169,14 +153,10 @@ out:
}
if (ppi->next_state != ppi->state) {
pp_timeout_clr(ppi, PP_TO_ANN_RECEIPT);
pp_timeout_clr(ppi, PP_TO_REQUEST);
pp_servo_init(ppi);
return e;
}
d1 = d2 = pp_ms_to_timeout(ppi, PP_TO_ANN_RECEIPT);
if (ppi->timeouts[PP_TO_REQUEST])
d2 = pp_ms_to_timeout(ppi, PP_TO_REQUEST);
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_REQUEST),
N(PP_TO_SYNC),
N(PP_TO_ANN_RECEIPT),
N(PP_TO_ANN_INTERVAL),
N(PP_TO_FAULTY),
N(PP_TO_EXT_0),
N(PP_TO_EXT_1),
};
/*
* 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);
}
......@@ -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 = {
......
......@@ -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 = {
......
......@@ -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 = {
......
/*
* 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;
}
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