forked from unpbook/unpv13e
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrtt.c
135 lines (110 loc) · 2.87 KB
/
rtt.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* include rtt1 */
#include "unprtt.h"
int rtt_d_flag = 0; /* debug flag; can be set by caller */
/*
* Calculate the RTO value based on current estimators:
* smoothed RTT plus four times the deviation
*/
#define RTT_RTOCALC(ptr) ((ptr)->rtt_srtt + (4.0 * (ptr)->rtt_rttvar))
static float
rtt_minmax(float rto)
{
if (rto < RTT_RXTMIN)
rto = RTT_RXTMIN;
else if (rto > RTT_RXTMAX)
rto = RTT_RXTMAX;
return(rto);
}
void
rtt_init(struct rtt_info *ptr)
{
struct timeval tv;
Gettimeofday(&tv, NULL);
ptr->rtt_base = tv.tv_sec; /* # sec since 1/1/1970 at start */
ptr->rtt_rtt = 0;
ptr->rtt_srtt = 0;
ptr->rtt_rttvar = 0.75;
ptr->rtt_rto = rtt_minmax(RTT_RTOCALC(ptr));
/* first RTO at (srtt + (4 * rttvar)) = 3 seconds */
}
/* end rtt1 */
/*
* Return the current timestamp.
* Our timestamps are 32-bit integers that count milliseconds since
* rtt_init() was called.
*/
/* include rtt_ts */
uint32_t
rtt_ts(struct rtt_info *ptr)
{
uint32_t ts;
struct timeval tv;
Gettimeofday(&tv, NULL);
ts = ((tv.tv_sec - ptr->rtt_base) * 1000) + (tv.tv_usec / 1000);
return(ts);
}
void
rtt_newpack(struct rtt_info *ptr)
{
ptr->rtt_nrexmt = 0;
}
int
rtt_start(struct rtt_info *ptr)
{
return((int) (ptr->rtt_rto + 0.5)); /* round float to int */
/* 4return value can be used as: alarm(rtt_start(&foo)) */
}
/* end rtt_ts */
/*
* A response was received.
* Stop the timer and update the appropriate values in the structure
* based on this packet's RTT. We calculate the RTT, then update the
* estimators of the RTT and its mean deviation.
* This function should be called right after turning off the
* timer with alarm(0), or right after a timeout occurs.
*/
/* include rtt_stop */
void
rtt_stop(struct rtt_info *ptr, uint32_t ms)
{
double delta;
ptr->rtt_rtt = ms / 1000.0; /* measured RTT in seconds */
/*
* Update our estimators of RTT and mean deviation of RTT.
* See Jacobson's SIGCOMM '88 paper, Appendix A, for the details.
* We use floating point here for simplicity.
*/
delta = ptr->rtt_rtt - ptr->rtt_srtt;
ptr->rtt_srtt += delta / 8; /* g = 1/8 */
if (delta < 0.0)
delta = -delta; /* |delta| */
ptr->rtt_rttvar += (delta - ptr->rtt_rttvar) / 4; /* h = 1/4 */
ptr->rtt_rto = rtt_minmax(RTT_RTOCALC(ptr));
}
/* end rtt_stop */
/*
* A timeout has occurred.
* Return -1 if it's time to give up, else return 0.
*/
/* include rtt_timeout */
int
rtt_timeout(struct rtt_info *ptr)
{
ptr->rtt_rto *= 2; /* next RTO */
if (++ptr->rtt_nrexmt > RTT_MAXNREXMT)
return(-1); /* time to give up for this packet */
return(0);
}
/* end rtt_timeout */
/*
* Print debugging information on stderr, if the "rtt_d_flag" is nonzero.
*/
void
rtt_debug(struct rtt_info *ptr)
{
if (rtt_d_flag == 0)
return;
fprintf(stderr, "rtt = %.3f, srtt = %.3f, rttvar = %.3f, rto = %.3f\n",
ptr->rtt_rtt, ptr->rtt_srtt, ptr->rtt_rttvar, ptr->rtt_rto);
fflush(stderr);
}