Commit 89185bf9 authored by Alessandro Rubini's avatar Alessandro Rubini

timeout: randomize intervals as required

The frames should be sent with some dispersion around the timeout
point.  The new function calculates the correct dispersion, but we
need to change the setting of next_delay in order to actually spread
the distribution of announce and other messages.

Also, this commit doesn't spread all message times, some work on the
field is still needed.
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent dc343a13
......@@ -313,6 +313,8 @@ static inline void pp_timeout_set(struct pp_instance *ppi, int index,
ppi->timeouts[index] = pp_calc_timeout(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;
......
......@@ -19,10 +19,9 @@ int pp_master(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (ppi->is_new_state) {
DSPOR(ppi)->portState = PPS_MASTER;
pp_timeout_set(ppi, PP_TO_SYNC,
(1 << DSPOR(ppi)->logSyncInterval) * 1000);
pp_timeout_set(ppi, PP_TO_ANN_INTERVAL,
(1 << DSPOR(ppi)->logAnnounceInterval) * 1000);
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 (msg_issue_announce(ppi) < 0)
......@@ -43,8 +42,7 @@ int pp_master(struct pp_instance *ppi, unsigned char *pkt, int plen)
goto out;
/* Restart the timeout for next time */
pp_timeout_set(ppi, PP_TO_SYNC,
(1 << DSPOR(ppi)->logSyncInterval) * 1000);
pp_timeout_rand(ppi, PP_TO_SYNC, DSPOR(ppi)->logSyncInterval);
}
if (pp_timeout_z(ppi, PP_TO_ANN_INTERVAL)) {
......@@ -52,8 +50,8 @@ int pp_master(struct pp_instance *ppi, unsigned char *pkt, int plen)
goto out;
/* Restart the timeout for next time */
pp_timeout_set(ppi, PP_TO_ANN_INTERVAL,
(1 << DSPOR(ppi)->logAnnounceInterval) * 1000);
pp_timeout_rand(ppi, PP_TO_ANN_INTERVAL,
DSPOR(ppi)->logAnnounceInterval);
}
if (plen == 0)
......
......@@ -30,8 +30,8 @@ int pp_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
st_com_restart_annrec_timer(ppi);
pp_timeout_set(ppi, PP_TO_DELAYREQ,
(1 << DSPOR(ppi)->logMinDelayReqInterval) * 1000);
pp_timeout_rand(ppi, PP_TO_DELAYREQ,
DSPOR(ppi)->logMinDelayReqInterval);
}
if (st_com_check_record_update(ppi))
......
......@@ -26,3 +26,41 @@ void pp_timeout_log(struct pp_instance *ppi, int index)
PP_VPRINTF("timeout expire event: %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);
}
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