Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
net
ipv4
tcp_hybla.c
Go to the documentation of this file.
1
/*
2
* TCP HYBLA
3
*
4
* TCP-HYBLA Congestion control algorithm, based on:
5
* C.Caini, R.Firrincieli, "TCP-Hybla: A TCP Enhancement
6
* for Heterogeneous Networks",
7
* International Journal on satellite Communications,
8
* September 2004
9
* Daniele Lacamera
10
* root at danielinux.net
11
*/
12
13
#include <linux/module.h>
14
#include <
net/tcp.h
>
15
16
/* Tcp Hybla structure. */
17
struct
hybla
{
18
bool
hybla_en
;
19
u32
snd_cwnd_cents
;
/* Keeps increment values when it is <1, <<7 */
20
u32
rho
;
/* Rho parameter, integer part */
21
u32
rho2
;
/* Rho * Rho, integer part */
22
u32
rho_3ls
;
/* Rho parameter, <<3 */
23
u32
rho2_7ls
;
/* Rho^2, <<7 */
24
u32
minrtt
;
/* Minimum smoothed round trip time value seen */
25
};
26
27
/* Hybla reference round trip time (default= 1/40 sec = 25 ms), in ms */
28
static
int
rtt0 = 25;
29
module_param
(rtt0,
int
, 0644);
30
MODULE_PARM_DESC
(rtt0,
"reference rout trip time (ms)"
);
31
32
33
/* This is called to refresh values for hybla parameters */
34
static
inline
void
hybla_recalc_param (
struct
sock
*
sk
)
35
{
36
struct
hybla
*
ca
= inet_csk_ca(sk);
37
38
ca->
rho_3ls
=
max_t
(
u32
, tcp_sk(sk)->srtt /
msecs_to_jiffies
(rtt0), 8);
39
ca->
rho
= ca->
rho_3ls
>> 3;
40
ca->
rho2_7ls
= (ca->
rho_3ls
* ca->
rho_3ls
) << 1;
41
ca->
rho2
= ca->
rho2_7ls
>> 7;
42
}
43
44
static
void
hybla_init(
struct
sock
*sk)
45
{
46
struct
tcp_sock
*tp = tcp_sk(sk);
47
struct
hybla
*ca = inet_csk_ca(sk);
48
49
ca->
rho
= 0;
50
ca->
rho2
= 0;
51
ca->
rho_3ls
= 0;
52
ca->
rho2_7ls
= 0;
53
ca->
snd_cwnd_cents
= 0;
54
ca->
hybla_en
=
true
;
55
tp->
snd_cwnd
= 2;
56
tp->
snd_cwnd_clamp
= 65535;
57
58
/* 1st Rho measurement based on initial srtt */
59
hybla_recalc_param(sk);
60
61
/* set minimum rtt as this is the 1st ever seen */
62
ca->
minrtt
= tp->
srtt
;
63
tp->
snd_cwnd
= ca->
rho
;
64
}
65
66
static
void
hybla_state(
struct
sock
*sk,
u8
ca_state)
67
{
68
struct
hybla
*ca = inet_csk_ca(sk);
69
70
ca->
hybla_en
= (ca_state ==
TCP_CA_Open
);
71
}
72
73
static
inline
u32
hybla_fraction(
u32
odds)
74
{
75
static
const
u32
fractions[] = {
76
128, 139, 152, 165, 181, 197, 215, 234,
77
};
78
79
return
(odds <
ARRAY_SIZE
(fractions)) ? fractions[odds] : 128;
80
}
81
82
/* TCP Hybla main routine.
83
* This is the algorithm behavior:
84
* o Recalc Hybla parameters if min_rtt has changed
85
* o Give cwnd a new value based on the model proposed
86
* o remember increments <1
87
*/
88
static
void
hybla_cong_avoid(
struct
sock
*sk,
u32
ack
,
u32
in_flight)
89
{
90
struct
tcp_sock
*tp = tcp_sk(sk);
91
struct
hybla
*ca = inet_csk_ca(sk);
92
u32
increment, odd, rho_fractions;
93
int
is_slowstart = 0;
94
95
/* Recalculate rho only if this srtt is the lowest */
96
if
(tp->
srtt
< ca->
minrtt
){
97
hybla_recalc_param(sk);
98
ca->
minrtt
= tp->
srtt
;
99
}
100
101
if
(!
tcp_is_cwnd_limited
(sk, in_flight))
102
return
;
103
104
if
(!ca->
hybla_en
) {
105
tcp_reno_cong_avoid
(sk, ack, in_flight);
106
return
;
107
}
108
109
if
(ca->
rho
== 0)
110
hybla_recalc_param(sk);
111
112
rho_fractions = ca->
rho_3ls
- (ca->
rho
<< 3);
113
114
if
(tp->
snd_cwnd
< tp->
snd_ssthresh
) {
115
/*
116
* slow start
117
* INC = 2^RHO - 1
118
* This is done by splitting the rho parameter
119
* into 2 parts: an integer part and a fraction part.
120
* Inrement<<7 is estimated by doing:
121
* [2^(int+fract)]<<7
122
* that is equal to:
123
* (2^int) * [(2^fract) <<7]
124
* 2^int is straightly computed as 1<<int,
125
* while we will use hybla_slowstart_fraction_increment() to
126
* calculate 2^fract in a <<7 value.
127
*/
128
is_slowstart = 1;
129
increment = ((1 <<
min
(ca->
rho
, 16
U
)) *
130
hybla_fraction(rho_fractions)) - 128;
131
}
else
{
132
/*
133
* congestion avoidance
134
* INC = RHO^2 / W
135
* as long as increment is estimated as (rho<<7)/window
136
* it already is <<7 and we can easily count its fractions.
137
*/
138
increment = ca->
rho2_7ls
/ tp->
snd_cwnd
;
139
if
(increment < 128)
140
tp->
snd_cwnd_cnt
++;
141
}
142
143
odd = increment % 128;
144
tp->
snd_cwnd
+= increment >> 7;
145
ca->
snd_cwnd_cents
+= odd;
146
147
/* check when fractions goes >=128 and increase cwnd by 1. */
148
while
(ca->
snd_cwnd_cents
>= 128) {
149
tp->
snd_cwnd
++;
150
ca->
snd_cwnd_cents
-= 128;
151
tp->
snd_cwnd_cnt
= 0;
152
}
153
/* check when cwnd has not been incremented for a while */
154
if
(increment == 0 && odd == 0 && tp->
snd_cwnd_cnt
>= tp->
snd_cwnd
) {
155
tp->
snd_cwnd
++;
156
tp->
snd_cwnd_cnt
= 0;
157
}
158
/* clamp down slowstart cwnd to ssthresh value. */
159
if
(is_slowstart)
160
tp->
snd_cwnd
=
min
(tp->
snd_cwnd
, tp->
snd_ssthresh
);
161
162
tp->
snd_cwnd
=
min_t
(
u32
, tp->
snd_cwnd
, tp->
snd_cwnd_clamp
);
163
}
164
165
static
struct
tcp_congestion_ops
tcp_hybla
__read_mostly
= {
166
.init = hybla_init,
167
.ssthresh =
tcp_reno_ssthresh
,
168
.min_cwnd =
tcp_reno_min_cwnd
,
169
.cong_avoid = hybla_cong_avoid,
170
.set_state = hybla_state,
171
172
.owner =
THIS_MODULE
,
173
.name =
"hybla"
174
};
175
176
static
int
__init
hybla_register(
void
)
177
{
178
BUILD_BUG_ON
(
sizeof
(
struct
hybla
) >
ICSK_CA_PRIV_SIZE
);
179
return
tcp_register_congestion_control
(&tcp_hybla);
180
}
181
182
static
void
__exit
hybla_unregister(
void
)
183
{
184
tcp_unregister_congestion_control
(&tcp_hybla);
185
}
186
187
module_init
(hybla_register);
188
module_exit
(hybla_unregister);
189
190
MODULE_AUTHOR
(
"Daniele Lacamera"
);
191
MODULE_LICENSE
(
"GPL"
);
192
MODULE_DESCRIPTION
(
"TCP Hybla"
);
Generated on Thu Jan 10 2013 14:58:51 for Linux Kernel by
1.8.2