📄 rvroundtripstats.c
字号:
/******************************************************************************
Filename: rvroundtripstats.c
Description: class to keep round trip time statistics and compute
retransmission timeouts as outlined in RFC2988
*******************************************************************************
Copyright (c) 2001 RADVision Inc.
*******************************************************************************
NOTICE:
This document contains information that is proprietary to RADVision Inc.
No part of this publication may be reproduced in any form whatsoever without
written prior approval by RADVision Inc.
RADVision Inc. reserves the right to revise this publication and make changes
without obligation to notify any person of such revisions or changes.
******************************************************************************/
#include "rvroundtripstats.h"
#ifdef RV_PRINTSRTTINFO
#include <stdio.h>
#endif
#define RvHrtimeAbs(t) ((t) > 0 ? (t) : -(t))
#define RV_ROUNDTRIPSTATS_SRTTMAX ((RvHrtime)60 * RV_TIME_NSECPERSEC)
#define RV_ROUNDTRIPSTATS_DEFAULTDEVIATIONMULTIPLIER 15
RvRetransTimeoutLimits *rvRetransTimeoutLimitsConstruct(RvRetransTimeoutLimits *limits,
RvHrtime initial, RvHrtime min, RvHrtime max)
{
limits->initial = initial;
limits->min = min;
limits->max = max;
return limits;
}
RvRoundTripStats *rvRoundTripStatsConstruct(RvRoundTripStats *stats, RvRandomGenerator *randomGenerator)
{
stats->valid = rvFalse;
stats->k = RV_ROUNDTRIPSTATS_DEFAULTDEVIATIONMULTIPLIER;
stats->randGen = randomGenerator;
return stats;
}
void rvRoundTripStatsUpdate(RvRoundTripStats *stats, RvHrtime roundTripTime)
{
if(stats->valid)
{
static const int ax = 8; /* 1/alpha */
static const int bx = 4; /* 1/beta */
stats->rttvar = ((bx-1) * stats->rttvar
+ RvHrtimeAbs(stats->srtt - roundTripTime)) / bx;
stats->srtt = ((ax-1) * stats->srtt + roundTripTime) / ax;
}
else
{
stats->srtt = roundTripTime;
stats->rttvar = roundTripTime / 2;
stats->valid = rvTrue;
}
#ifdef RV_PRINTSRTTINFO
printf("sample %d, srtt %d, rttvar %d\n",
(int)(roundTripTime / RV_TIME_NSECPERMSEC),
(int)(stats->srtt / RV_TIME_NSECPERMSEC),
(int)(stats->rttvar / RV_TIME_NSECPERMSEC));
#endif
}
RvHrtime rvRoundTripStatsGetFirstRetransTimeout(RvRoundTripStats *stats, const RvRetransTimeoutLimits *limits)
{
RvHrtime timeout;
if(stats->valid)
{
RvTimespec timespec;
const RvHrtime resolution = rvTimeConvertHrtime(rvTimeGetHrtimeRes(×pec));
timeout = stats->k * stats->rttvar;
if(timeout < resolution)
timeout = resolution;
timeout += stats->srtt;
}
else
{
/* we have no rtt samples yet, so use configured initial timer value
and initialize srtt and rttvar. */
timeout = limits->initial;
stats->srtt = timeout;
stats->rttvar = timeout / 2;
}
timeout = timeout < limits->min ? limits->min :
timeout > limits->max ? limits->max : timeout;
#ifdef RV_PRINTSRTTINFO
printf("first timeout %d\n", (int)(timeout / RV_TIME_NSECPERMSEC));
#endif
return timeout;
}
RvHrtime rvRoundTripStatsGetNextRetransTimeout(RvRoundTripStats *stats, const RvRetransTimeoutLimits *limits)
{
RvHrtime timeout;
RvHrtime spray = rvRandomGeneratorGetValue(stats->randGen);
spray *= stats->srtt + 1;
spray /= (RvHrtime)rvRandomGeneratorGetMax(stats->randGen) + 1;
timeout = spray + stats->srtt + stats->k * stats->rttvar;
stats->srtt *= 2;
/* bound SRTT to avoid overflow */
if(stats->srtt > RV_ROUNDTRIPSTATS_SRTTMAX)
stats->srtt = RV_ROUNDTRIPSTATS_SRTTMAX;
timeout = timeout < limits->min ? limits->min :
timeout > limits->max ? limits->max : timeout;
#ifdef RV_PRINTSRTTINFO
printf("next timeout %d\n", (int)(timeout / RV_TIME_NSECPERMSEC));
#endif
return timeout;
}
unsigned int rvRoundTripStatsGetDeviationMultiplier(const RvRoundTripStats *stats)
{
return stats->k;
}
void rvRoundTripStatsSetDeviationMultiplier(RvRoundTripStats *stats, unsigned int k)
{
stats->k = k;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -