This source file includes following definitions.
- rtt_reset
- tcp_illinois_init
- tcp_illinois_acked
- max_delay
- avg_delay
- alpha
- beta
- update_params
- tcp_illinois_state
- tcp_illinois_cong_avoid
- tcp_illinois_ssthresh
- tcp_illinois_info
- tcp_illinois_register
- tcp_illinois_unregister
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 #include <linux/module.h>
17 #include <linux/skbuff.h>
18 #include <linux/inet_diag.h>
19 #include <asm/div64.h>
20 #include <net/tcp.h>
21
22 #define ALPHA_SHIFT 7
23 #define ALPHA_SCALE (1u<<ALPHA_SHIFT)
24 #define ALPHA_MIN ((3*ALPHA_SCALE)/10)
25 #define ALPHA_MAX (10*ALPHA_SCALE)
26 #define ALPHA_BASE ALPHA_SCALE
27 #define RTT_MAX (U32_MAX / ALPHA_MAX)
28
29 #define BETA_SHIFT 6
30 #define BETA_SCALE (1u<<BETA_SHIFT)
31 #define BETA_MIN (BETA_SCALE/8)
32 #define BETA_MAX (BETA_SCALE/2)
33 #define BETA_BASE BETA_MAX
34
35 static int win_thresh __read_mostly = 15;
36 module_param(win_thresh, int, 0);
37 MODULE_PARM_DESC(win_thresh, "Window threshold for starting adaptive sizing");
38
39 static int theta __read_mostly = 5;
40 module_param(theta, int, 0);
41 MODULE_PARM_DESC(theta, "# of fast RTT's before full growth");
42
43
44 struct illinois {
45 u64 sum_rtt;
46 u16 cnt_rtt;
47 u32 base_rtt;
48 u32 max_rtt;
49 u32 end_seq;
50 u32 alpha;
51 u32 beta;
52 u16 acked;
53 u8 rtt_above;
54 u8 rtt_low;
55 };
56
57 static void rtt_reset(struct sock *sk)
58 {
59 struct tcp_sock *tp = tcp_sk(sk);
60 struct illinois *ca = inet_csk_ca(sk);
61
62 ca->end_seq = tp->snd_nxt;
63 ca->cnt_rtt = 0;
64 ca->sum_rtt = 0;
65
66
67 }
68
69 static void tcp_illinois_init(struct sock *sk)
70 {
71 struct illinois *ca = inet_csk_ca(sk);
72
73 ca->alpha = ALPHA_MAX;
74 ca->beta = BETA_BASE;
75 ca->base_rtt = 0x7fffffff;
76 ca->max_rtt = 0;
77
78 ca->acked = 0;
79 ca->rtt_low = 0;
80 ca->rtt_above = 0;
81
82 rtt_reset(sk);
83 }
84
85
86 static void tcp_illinois_acked(struct sock *sk, const struct ack_sample *sample)
87 {
88 struct illinois *ca = inet_csk_ca(sk);
89 s32 rtt_us = sample->rtt_us;
90
91 ca->acked = sample->pkts_acked;
92
93
94 if (rtt_us < 0)
95 return;
96
97
98 if (rtt_us > RTT_MAX)
99 rtt_us = RTT_MAX;
100
101
102 if (ca->base_rtt > rtt_us)
103 ca->base_rtt = rtt_us;
104
105
106 if (ca->max_rtt < rtt_us)
107 ca->max_rtt = rtt_us;
108
109 ++ca->cnt_rtt;
110 ca->sum_rtt += rtt_us;
111 }
112
113
114 static inline u32 max_delay(const struct illinois *ca)
115 {
116 return ca->max_rtt - ca->base_rtt;
117 }
118
119
120 static inline u32 avg_delay(const struct illinois *ca)
121 {
122 u64 t = ca->sum_rtt;
123
124 do_div(t, ca->cnt_rtt);
125 return t - ca->base_rtt;
126 }
127
128
129
130
131
132
133
134
135
136
137
138
139
140 static u32 alpha(struct illinois *ca, u32 da, u32 dm)
141 {
142 u32 d1 = dm / 100;
143
144 if (da <= d1) {
145
146 if (!ca->rtt_above)
147 return ALPHA_MAX;
148
149
150
151
152 if (++ca->rtt_low < theta)
153 return ca->alpha;
154
155 ca->rtt_low = 0;
156 ca->rtt_above = 0;
157 return ALPHA_MAX;
158 }
159
160 ca->rtt_above = 1;
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178 dm -= d1;
179 da -= d1;
180 return (dm * ALPHA_MAX) /
181 (dm + (da * (ALPHA_MAX - ALPHA_MIN)) / ALPHA_MIN);
182 }
183
184
185
186
187
188
189
190
191
192 static u32 beta(u32 da, u32 dm)
193 {
194 u32 d2, d3;
195
196 d2 = dm / 10;
197 if (da <= d2)
198 return BETA_MIN;
199
200 d3 = (8 * dm) / 10;
201 if (da >= d3 || d3 <= d2)
202 return BETA_MAX;
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217 return (BETA_MIN * d3 - BETA_MAX * d2 + (BETA_MAX - BETA_MIN) * da)
218 / (d3 - d2);
219 }
220
221
222 static void update_params(struct sock *sk)
223 {
224 struct tcp_sock *tp = tcp_sk(sk);
225 struct illinois *ca = inet_csk_ca(sk);
226
227 if (tp->snd_cwnd < win_thresh) {
228 ca->alpha = ALPHA_BASE;
229 ca->beta = BETA_BASE;
230 } else if (ca->cnt_rtt > 0) {
231 u32 dm = max_delay(ca);
232 u32 da = avg_delay(ca);
233
234 ca->alpha = alpha(ca, da, dm);
235 ca->beta = beta(da, dm);
236 }
237
238 rtt_reset(sk);
239 }
240
241
242
243
244 static void tcp_illinois_state(struct sock *sk, u8 new_state)
245 {
246 struct illinois *ca = inet_csk_ca(sk);
247
248 if (new_state == TCP_CA_Loss) {
249 ca->alpha = ALPHA_BASE;
250 ca->beta = BETA_BASE;
251 ca->rtt_low = 0;
252 ca->rtt_above = 0;
253 rtt_reset(sk);
254 }
255 }
256
257
258
259
260 static void tcp_illinois_cong_avoid(struct sock *sk, u32 ack, u32 acked)
261 {
262 struct tcp_sock *tp = tcp_sk(sk);
263 struct illinois *ca = inet_csk_ca(sk);
264
265 if (after(ack, ca->end_seq))
266 update_params(sk);
267
268
269 if (!tcp_is_cwnd_limited(sk))
270 return;
271
272
273 if (tcp_in_slow_start(tp))
274 tcp_slow_start(tp, acked);
275
276 else {
277 u32 delta;
278
279
280 tp->snd_cwnd_cnt += ca->acked;
281 ca->acked = 1;
282
283
284
285
286 delta = (tp->snd_cwnd_cnt * ca->alpha) >> ALPHA_SHIFT;
287 if (delta >= tp->snd_cwnd) {
288 tp->snd_cwnd = min(tp->snd_cwnd + delta / tp->snd_cwnd,
289 (u32)tp->snd_cwnd_clamp);
290 tp->snd_cwnd_cnt = 0;
291 }
292 }
293 }
294
295 static u32 tcp_illinois_ssthresh(struct sock *sk)
296 {
297 struct tcp_sock *tp = tcp_sk(sk);
298 struct illinois *ca = inet_csk_ca(sk);
299
300
301 return max(tp->snd_cwnd - ((tp->snd_cwnd * ca->beta) >> BETA_SHIFT), 2U);
302 }
303
304
305 static size_t tcp_illinois_info(struct sock *sk, u32 ext, int *attr,
306 union tcp_cc_info *info)
307 {
308 const struct illinois *ca = inet_csk_ca(sk);
309
310 if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) {
311 info->vegas.tcpv_enabled = 1;
312 info->vegas.tcpv_rttcnt = ca->cnt_rtt;
313 info->vegas.tcpv_minrtt = ca->base_rtt;
314 info->vegas.tcpv_rtt = 0;
315
316 if (info->vegas.tcpv_rttcnt > 0) {
317 u64 t = ca->sum_rtt;
318
319 do_div(t, info->vegas.tcpv_rttcnt);
320 info->vegas.tcpv_rtt = t;
321 }
322 *attr = INET_DIAG_VEGASINFO;
323 return sizeof(struct tcpvegas_info);
324 }
325 return 0;
326 }
327
328 static struct tcp_congestion_ops tcp_illinois __read_mostly = {
329 .init = tcp_illinois_init,
330 .ssthresh = tcp_illinois_ssthresh,
331 .undo_cwnd = tcp_reno_undo_cwnd,
332 .cong_avoid = tcp_illinois_cong_avoid,
333 .set_state = tcp_illinois_state,
334 .get_info = tcp_illinois_info,
335 .pkts_acked = tcp_illinois_acked,
336
337 .owner = THIS_MODULE,
338 .name = "illinois",
339 };
340
341 static int __init tcp_illinois_register(void)
342 {
343 BUILD_BUG_ON(sizeof(struct illinois) > ICSK_CA_PRIV_SIZE);
344 return tcp_register_congestion_control(&tcp_illinois);
345 }
346
347 static void __exit tcp_illinois_unregister(void)
348 {
349 tcp_unregister_congestion_control(&tcp_illinois);
350 }
351
352 module_init(tcp_illinois_register);
353 module_exit(tcp_illinois_unregister);
354
355 MODULE_AUTHOR("Stephen Hemminger, Shao Liu");
356 MODULE_LICENSE("GPL");
357 MODULE_DESCRIPTION("TCP Illinois");
358 MODULE_VERSION("1.0");