Commit 6305e770 authored by Alessandro Rubini's avatar Alessandro Rubini

general: change timeout API

Several changes to the timeout API, simplifying the code and allowing
more simplification later.

 * TO_ANN_INTERVAL renamed to TO_ANN_SEND (as opposed to TO_ANN_RECEIPT)

 * TO_SYNC renamed to TO_SYNC_SEND for symmetry with above

 * added timeout_init() to take not of the waiting values

 * timeout_set now receives only the index, not the value (see above)

 * __timeout_set added for those that want a specific value

 * timeout_rand is gone, as timeout_set knows which to randomize

 * all users fixed
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent a91328cb
......@@ -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,
......
......@@ -218,15 +218,17 @@ extern struct pp_time_operations unix_time_ops;
* So we don't need struct operations, as it is one function only,
* which is folded into the "pp_time_operations" above.
*/
extern void pp_timeout_set(struct pp_instance *ppi, int index, int millisec);
extern void pp_timeout_rand(struct pp_instance *ppi, int index, int logval);
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 void pp_timeout_clr(struct pp_instance *ppi, int index);
extern int pp_timeout(struct pp_instance *ppi, int index);
extern int pp_timeout(struct pp_instance *ppi, int index)
__attribute__((warn_unused_result));
extern int pp_timeout_z(struct pp_instance *ppi, int index);
extern int pp_ms_to_timeout(struct pp_instance *ppi, int index);
extern void pp_timeout_restart_annrec(struct pp_instance *ppi);
/* 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);
extern int pp_close_globals(struct pp_globals *ppg);
......
......@@ -19,7 +19,7 @@ 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)) {
/*
......
......@@ -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)
......
......@@ -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);
}
......
......@@ -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)
......
......@@ -34,8 +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_set(ppi, PP_TO_EXT_0, WR_WRS_PRESENT_TIMEOUT_MS);
pp_timeout_restart_annrec(ppi);
e = msg_issue_wrsig(ppi, SLAVE_PRESENT);
}
......
......@@ -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);
}
......
......@@ -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) {
......
......@@ -16,7 +16,7 @@
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);
pp_timeout_set(ppi, PP_TO_FAULTY);
}
if (pp_timeout(ppi, PP_TO_FAULTY)) {
......
......@@ -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);
......
......@@ -22,8 +22,7 @@ int pp_listening(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (ppi->is_new_state) {
pp_timeout_restart_annrec(ppi);
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
pp_timeout_set(ppi, PP_TO_REQUEST);
}
/* when the clock is using peer-delay, listening must send it too */
......@@ -34,8 +33,7 @@ int pp_listening(struct pp_instance *ppi, unsigned char *pkt, int plen)
ppi->t3 = ppi->last_snt_time;
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
pp_timeout_set(ppi, PP_TO_REQUEST);
}
if (plen == 0)
......
......@@ -68,33 +68,30 @@ int pp_master(struct pp_instance *ppi, unsigned char *pkt, int plen)
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);
pp_timeout_set(ppi, PP_TO_SYNC_SEND);
pp_timeout_set(ppi, PP_TO_REQUEST);
pp_timeout_set(ppi, PP_TO_ANN_SEND);
/* 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)) {
if (pp_timeout_z(ppi, PP_TO_SYNC_SEND)) {
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_SYNC, DSPOR(ppi)->logSyncInterval);
pp_timeout_set(ppi, PP_TO_SYNC_SEND);
if ((e = pp_master_issue_sync_followup(ppi) < 0))
goto out;
}
if (pp_timeout_z(ppi, PP_TO_ANN_INTERVAL)) {
if (pp_timeout_z(ppi, PP_TO_ANN_SEND)) {
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);
pp_timeout_set(ppi, PP_TO_ANN_SEND);
}
/* when the clock is using peer-delay, the muster mast send it too */
......@@ -105,8 +102,7 @@ int pp_master(struct pp_instance *ppi, unsigned char *pkt, int plen)
ppi->t3 = ppi->last_snt_time;
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
pp_timeout_set(ppi, PP_TO_REQUEST);
}
if (plen == 0)
......@@ -204,8 +200,8 @@ out:
break;
}
d1 = pp_ms_to_timeout(ppi, PP_TO_ANN_INTERVAL);
d2 = pp_ms_to_timeout(ppi, PP_TO_SYNC);
d1 = pp_ms_to_timeout(ppi, PP_TO_ANN_SEND);
d2 = pp_ms_to_timeout(ppi, PP_TO_SYNC_SEND);
ppi->next_delay = d1 < d2 ? d1 : d2;
return e;
......
......@@ -17,8 +17,7 @@ int pp_passive(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (ppi->is_new_state) {
pp_timeout_restart_annrec(ppi);
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
pp_timeout_set(ppi, PP_TO_REQUEST);
}
/* when the clock is using peer-delay, listening must send it too */
......@@ -29,8 +28,7 @@ int pp_passive(struct pp_instance *ppi, unsigned char *pkt, int plen)
ppi->t3 = ppi->last_snt_time;
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
pp_timeout_set(ppi, PP_TO_REQUEST);
}
if (plen == 0)
......
......@@ -32,8 +32,7 @@ int pp_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
pp_timeout_restart_annrec(ppi);
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
pp_timeout_set(ppi, PP_TO_REQUEST);
}
if (plen == 0)
......@@ -152,8 +151,7 @@ out:
ppi->t3 = ppi->last_snt_time;
/* Restart the timeout for next time */
pp_timeout_rand(ppi, PP_TO_REQUEST,
DSPOR(ppi)->logMinDelayReqInterval);
pp_timeout_set(ppi, PP_TO_REQUEST);
}
switch(e) {
......
......@@ -6,40 +6,66 @@
*/
#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),
struct timeout_config {
char *name;
int isrand;
int value;
};
/*
* Log means messages
*/
/* 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", timeout_names[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);
}
/*
* 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)
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;
......@@ -61,13 +87,7 @@ void pp_timeout_rand(struct pp_instance *ppi, int index, int logval)
millisec = (1 << logval) * 400; /* This is 40% of the nominal value */
millisec = (millisec * 2) + rval % millisec;
pp_timeout_set(ppi, index, millisec);
}
void pp_timeout_set(struct pp_instance *ppi, int index,
int millisec)
{
ppi->timeouts[index] = ppi->t_ops->calc_timeout(ppi, millisec);
__pp_timeout_set(ppi, index, millisec);
}
void pp_timeout_clr(struct pp_instance *ppi, int index)
......@@ -110,8 +130,5 @@ int pp_ms_to_timeout(struct pp_instance *ppi, int index)
/* called several times, only sets a timeout, so inline it here */
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);
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
}
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