blob: cfd11234d8f9100f63cdb9025bd973a39aae58f3 [file] [log] [blame]
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001/*
2 * net/dccp/ccids/ccid3.c
3 *
4 * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
Ian McDonald1bc09862005-08-20 00:23:43 -03005 * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07006 *
7 * An implementation of the DCCP protocol
8 *
9 * This code has been developed by the University of Waikato WAND
10 * research group. For further information please see http://www.wand.net.nz/
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -070011 *
12 * This code also uses code from Lulea University, rereleased as GPL by its
13 * authors:
14 * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
15 *
16 * Changes to meet Linux coding standards, to make it meet latest ccid3 draft
17 * and to make it work as a loadable module in the DCCP stack written by
18 * Arnaldo Carvalho de Melo <acme@conectiva.com.br>.
19 *
20 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
21 *
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 */
36
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -030037#include <linux/config.h>
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -070038#include "../ccid.h"
39#include "../dccp.h"
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -030040#include "../packet_history.h"
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -070041#include "ccid3.h"
42
Arnaldo Carvalho de Melo6b5e6332005-08-27 20:11:28 -030043/*
44 * Reason for maths with 10 here is to avoid 32 bit overflow when a is big.
45 */
46static inline u32 usecs_div(const u32 a, const u32 b)
47{
48 const u32 tmp = a * (USEC_PER_SEC / 10);
49 return b > 20 ? tmp / (b / 10) : tmp;
50}
51
Arnaldo Carvalho de Melocfc3c522005-08-27 20:20:37 -030052static int ccid3_debug;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -070053
Arnaldo Carvalho de Melocfc3c522005-08-27 20:20:37 -030054#ifdef CCID3_DEBUG
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -070055#define ccid3_pr_debug(format, a...) \
56 do { if (ccid3_debug) \
57 printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \
58 } while (0)
59#else
60#define ccid3_pr_debug(format, a...)
61#endif
62
Arnaldo Carvalho de Meloa1d3a352005-08-13 22:42:25 -030063static struct dccp_tx_hist *ccid3_tx_hist;
64static struct dccp_rx_hist *ccid3_rx_hist;
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -030065
Eric Dumazetba899662005-08-26 12:05:31 -070066static kmem_cache_t *ccid3_loss_interval_hist_slab __read_mostly;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -070067
Arnaldo Carvalho de Meloa1d3a352005-08-13 22:42:25 -030068static inline struct ccid3_loss_interval_hist_entry *
69 ccid3_loss_interval_hist_entry_new(const unsigned int __nocast prio)
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -070070{
71 return kmem_cache_alloc(ccid3_loss_interval_hist_slab, prio);
72}
73
74static inline void ccid3_loss_interval_hist_entry_delete(struct ccid3_loss_interval_hist_entry *entry)
75{
76 if (entry != NULL)
77 kmem_cache_free(ccid3_loss_interval_hist_slab, entry);
78}
79
80static void ccid3_loss_interval_history_delete(struct list_head *hist)
81{
82 struct ccid3_loss_interval_hist_entry *entry, *next;
83
84 list_for_each_entry_safe(entry, next, hist, ccid3lih_node) {
85 list_del_init(&entry->ccid3lih_node);
86 kmem_cache_free(ccid3_loss_interval_hist_slab, entry);
87 }
88}
89
90static int ccid3_init(struct sock *sk)
91{
92 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
93 return 0;
94}
95
96static void ccid3_exit(struct sock *sk)
97{
98 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
99}
100
101/* TFRC sender states */
102enum ccid3_hc_tx_states {
103 TFRC_SSTATE_NO_SENT = 1,
104 TFRC_SSTATE_NO_FBACK,
105 TFRC_SSTATE_FBACK,
106 TFRC_SSTATE_TERM,
107};
108
109#ifdef CCID3_DEBUG
110static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state)
111{
112 static char *ccid3_state_names[] = {
113 [TFRC_SSTATE_NO_SENT] = "NO_SENT",
114 [TFRC_SSTATE_NO_FBACK] = "NO_FBACK",
115 [TFRC_SSTATE_FBACK] = "FBACK",
116 [TFRC_SSTATE_TERM] = "TERM",
117 };
118
119 return ccid3_state_names[state];
120}
121#endif
122
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300123static inline void ccid3_hc_tx_set_state(struct sock *sk,
124 enum ccid3_hc_tx_states state)
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700125{
126 struct dccp_sock *dp = dccp_sk(sk);
127 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
128 enum ccid3_hc_tx_states oldstate = hctx->ccid3hctx_state;
129
130 ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300131 dccp_role(sk), sk, ccid3_tx_state_name(oldstate),
132 ccid3_tx_state_name(state));
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700133 WARN_ON(state == oldstate);
134 hctx->ccid3hctx_state = state;
135}
136
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700137#define CALCX_ARRSIZE 500
138
139#define CALCX_SPLIT 50000
140/* equivalent to 0.05 */
141
142static const u32 calcx_lookup[CALCX_ARRSIZE][2] = {
143 { 37172 , 8172 },
144 { 53499 , 11567 },
145 { 66664 , 14180 },
146 { 78298 , 16388 },
147 { 89021 , 18339 },
148 { 99147 , 20108 },
149 { 108858 , 21738 },
150 { 118273 , 23260 },
151 { 127474 , 24693 },
152 { 136520 , 26052 },
153 { 145456 , 27348 },
154 { 154316 , 28589 },
155 { 163130 , 29783 },
156 { 171919 , 30935 },
157 { 180704 , 32049 },
158 { 189502 , 33130 },
159 { 198328 , 34180 },
160 { 207194 , 35202 },
161 { 216114 , 36198 },
162 { 225097 , 37172 },
163 { 234153 , 38123 },
164 { 243294 , 39055 },
165 { 252527 , 39968 },
166 { 261861 , 40864 },
167 { 271305 , 41743 },
168 { 280866 , 42607 },
169 { 290553 , 43457 },
170 { 300372 , 44293 },
171 { 310333 , 45117 },
172 { 320441 , 45929 },
173 { 330705 , 46729 },
174 { 341131 , 47518 },
175 { 351728 , 48297 },
176 { 362501 , 49066 },
177 { 373460 , 49826 },
178 { 384609 , 50577 },
179 { 395958 , 51320 },
180 { 407513 , 52054 },
181 { 419281 , 52780 },
182 { 431270 , 53499 },
183 { 443487 , 54211 },
184 { 455940 , 54916 },
185 { 468635 , 55614 },
186 { 481581 , 56306 },
187 { 494785 , 56991 },
188 { 508254 , 57671 },
189 { 521996 , 58345 },
190 { 536019 , 59014 },
191 { 550331 , 59677 },
192 { 564939 , 60335 },
193 { 579851 , 60988 },
194 { 595075 , 61636 },
195 { 610619 , 62279 },
196 { 626491 , 62918 },
197 { 642700 , 63553 },
198 { 659253 , 64183 },
199 { 676158 , 64809 },
200 { 693424 , 65431 },
201 { 711060 , 66050 },
202 { 729073 , 66664 },
203 { 747472 , 67275 },
204 { 766266 , 67882 },
205 { 785464 , 68486 },
206 { 805073 , 69087 },
207 { 825103 , 69684 },
208 { 845562 , 70278 },
209 { 866460 , 70868 },
210 { 887805 , 71456 },
211 { 909606 , 72041 },
212 { 931873 , 72623 },
213 { 954614 , 73202 },
214 { 977839 , 73778 },
215 { 1001557 , 74352 },
216 { 1025777 , 74923 },
217 { 1050508 , 75492 },
218 { 1075761 , 76058 },
219 { 1101544 , 76621 },
220 { 1127867 , 77183 },
221 { 1154739 , 77741 },
222 { 1182172 , 78298 },
223 { 1210173 , 78852 },
224 { 1238753 , 79405 },
225 { 1267922 , 79955 },
226 { 1297689 , 80503 },
227 { 1328066 , 81049 },
228 { 1359060 , 81593 },
229 { 1390684 , 82135 },
230 { 1422947 , 82675 },
231 { 1455859 , 83213 },
232 { 1489430 , 83750 },
233 { 1523671 , 84284 },
234 { 1558593 , 84817 },
235 { 1594205 , 85348 },
236 { 1630518 , 85878 },
237 { 1667543 , 86406 },
238 { 1705290 , 86932 },
239 { 1743770 , 87457 },
240 { 1782994 , 87980 },
241 { 1822973 , 88501 },
242 { 1863717 , 89021 },
243 { 1905237 , 89540 },
244 { 1947545 , 90057 },
245 { 1990650 , 90573 },
246 { 2034566 , 91087 },
247 { 2079301 , 91600 },
248 { 2124869 , 92111 },
249 { 2171279 , 92622 },
250 { 2218543 , 93131 },
251 { 2266673 , 93639 },
252 { 2315680 , 94145 },
253 { 2365575 , 94650 },
254 { 2416371 , 95154 },
255 { 2468077 , 95657 },
256 { 2520707 , 96159 },
257 { 2574271 , 96660 },
258 { 2628782 , 97159 },
259 { 2684250 , 97658 },
260 { 2740689 , 98155 },
261 { 2798110 , 98651 },
262 { 2856524 , 99147 },
263 { 2915944 , 99641 },
264 { 2976382 , 100134 },
265 { 3037850 , 100626 },
266 { 3100360 , 101117 },
267 { 3163924 , 101608 },
268 { 3228554 , 102097 },
269 { 3294263 , 102586 },
270 { 3361063 , 103073 },
271 { 3428966 , 103560 },
272 { 3497984 , 104045 },
273 { 3568131 , 104530 },
274 { 3639419 , 105014 },
275 { 3711860 , 105498 },
276 { 3785467 , 105980 },
277 { 3860253 , 106462 },
278 { 3936229 , 106942 },
279 { 4013410 , 107422 },
280 { 4091808 , 107902 },
281 { 4171435 , 108380 },
282 { 4252306 , 108858 },
283 { 4334431 , 109335 },
284 { 4417825 , 109811 },
285 { 4502501 , 110287 },
286 { 4588472 , 110762 },
287 { 4675750 , 111236 },
288 { 4764349 , 111709 },
289 { 4854283 , 112182 },
290 { 4945564 , 112654 },
291 { 5038206 , 113126 },
292 { 5132223 , 113597 },
293 { 5227627 , 114067 },
294 { 5324432 , 114537 },
295 { 5422652 , 115006 },
296 { 5522299 , 115474 },
297 { 5623389 , 115942 },
298 { 5725934 , 116409 },
299 { 5829948 , 116876 },
300 { 5935446 , 117342 },
301 { 6042439 , 117808 },
302 { 6150943 , 118273 },
303 { 6260972 , 118738 },
304 { 6372538 , 119202 },
305 { 6485657 , 119665 },
306 { 6600342 , 120128 },
307 { 6716607 , 120591 },
308 { 6834467 , 121053 },
309 { 6953935 , 121514 },
310 { 7075025 , 121976 },
311 { 7197752 , 122436 },
312 { 7322131 , 122896 },
313 { 7448175 , 123356 },
314 { 7575898 , 123815 },
315 { 7705316 , 124274 },
316 { 7836442 , 124733 },
317 { 7969291 , 125191 },
318 { 8103877 , 125648 },
319 { 8240216 , 126105 },
320 { 8378321 , 126562 },
321 { 8518208 , 127018 },
322 { 8659890 , 127474 },
323 { 8803384 , 127930 },
324 { 8948702 , 128385 },
325 { 9095861 , 128840 },
326 { 9244875 , 129294 },
327 { 9395760 , 129748 },
328 { 9548529 , 130202 },
329 { 9703198 , 130655 },
330 { 9859782 , 131108 },
331 { 10018296 , 131561 },
332 { 10178755 , 132014 },
333 { 10341174 , 132466 },
334 { 10505569 , 132917 },
335 { 10671954 , 133369 },
336 { 10840345 , 133820 },
337 { 11010757 , 134271 },
338 { 11183206 , 134721 },
339 { 11357706 , 135171 },
340 { 11534274 , 135621 },
341 { 11712924 , 136071 },
342 { 11893673 , 136520 },
343 { 12076536 , 136969 },
344 { 12261527 , 137418 },
345 { 12448664 , 137867 },
346 { 12637961 , 138315 },
347 { 12829435 , 138763 },
348 { 13023101 , 139211 },
349 { 13218974 , 139658 },
350 { 13417071 , 140106 },
351 { 13617407 , 140553 },
352 { 13819999 , 140999 },
353 { 14024862 , 141446 },
354 { 14232012 , 141892 },
355 { 14441465 , 142339 },
356 { 14653238 , 142785 },
357 { 14867346 , 143230 },
358 { 15083805 , 143676 },
359 { 15302632 , 144121 },
360 { 15523842 , 144566 },
361 { 15747453 , 145011 },
362 { 15973479 , 145456 },
363 { 16201939 , 145900 },
364 { 16432847 , 146345 },
365 { 16666221 , 146789 },
366 { 16902076 , 147233 },
367 { 17140429 , 147677 },
368 { 17381297 , 148121 },
369 { 17624696 , 148564 },
370 { 17870643 , 149007 },
371 { 18119154 , 149451 },
372 { 18370247 , 149894 },
373 { 18623936 , 150336 },
374 { 18880241 , 150779 },
375 { 19139176 , 151222 },
376 { 19400759 , 151664 },
377 { 19665007 , 152107 },
378 { 19931936 , 152549 },
379 { 20201564 , 152991 },
380 { 20473907 , 153433 },
381 { 20748982 , 153875 },
382 { 21026807 , 154316 },
383 { 21307399 , 154758 },
384 { 21590773 , 155199 },
385 { 21876949 , 155641 },
386 { 22165941 , 156082 },
387 { 22457769 , 156523 },
388 { 22752449 , 156964 },
389 { 23049999 , 157405 },
390 { 23350435 , 157846 },
391 { 23653774 , 158287 },
392 { 23960036 , 158727 },
393 { 24269236 , 159168 },
394 { 24581392 , 159608 },
395 { 24896521 , 160049 },
396 { 25214642 , 160489 },
397 { 25535772 , 160929 },
398 { 25859927 , 161370 },
399 { 26187127 , 161810 },
400 { 26517388 , 162250 },
401 { 26850728 , 162690 },
402 { 27187165 , 163130 },
403 { 27526716 , 163569 },
404 { 27869400 , 164009 },
405 { 28215234 , 164449 },
406 { 28564236 , 164889 },
407 { 28916423 , 165328 },
408 { 29271815 , 165768 },
409 { 29630428 , 166208 },
410 { 29992281 , 166647 },
411 { 30357392 , 167087 },
412 { 30725779 , 167526 },
413 { 31097459 , 167965 },
414 { 31472452 , 168405 },
415 { 31850774 , 168844 },
416 { 32232445 , 169283 },
417 { 32617482 , 169723 },
418 { 33005904 , 170162 },
419 { 33397730 , 170601 },
420 { 33792976 , 171041 },
421 { 34191663 , 171480 },
422 { 34593807 , 171919 },
423 { 34999428 , 172358 },
424 { 35408544 , 172797 },
425 { 35821174 , 173237 },
426 { 36237335 , 173676 },
427 { 36657047 , 174115 },
428 { 37080329 , 174554 },
429 { 37507197 , 174993 },
430 { 37937673 , 175433 },
431 { 38371773 , 175872 },
432 { 38809517 , 176311 },
433 { 39250924 , 176750 },
434 { 39696012 , 177190 },
435 { 40144800 , 177629 },
436 { 40597308 , 178068 },
437 { 41053553 , 178507 },
438 { 41513554 , 178947 },
439 { 41977332 , 179386 },
440 { 42444904 , 179825 },
441 { 42916290 , 180265 },
442 { 43391509 , 180704 },
443 { 43870579 , 181144 },
444 { 44353520 , 181583 },
445 { 44840352 , 182023 },
446 { 45331092 , 182462 },
447 { 45825761 , 182902 },
448 { 46324378 , 183342 },
449 { 46826961 , 183781 },
450 { 47333531 , 184221 },
451 { 47844106 , 184661 },
452 { 48358706 , 185101 },
453 { 48877350 , 185541 },
454 { 49400058 , 185981 },
455 { 49926849 , 186421 },
456 { 50457743 , 186861 },
457 { 50992759 , 187301 },
458 { 51531916 , 187741 },
459 { 52075235 , 188181 },
460 { 52622735 , 188622 },
461 { 53174435 , 189062 },
462 { 53730355 , 189502 },
463 { 54290515 , 189943 },
464 { 54854935 , 190383 },
465 { 55423634 , 190824 },
466 { 55996633 , 191265 },
467 { 56573950 , 191706 },
468 { 57155606 , 192146 },
469 { 57741621 , 192587 },
470 { 58332014 , 193028 },
471 { 58926806 , 193470 },
472 { 59526017 , 193911 },
473 { 60129666 , 194352 },
474 { 60737774 , 194793 },
475 { 61350361 , 195235 },
476 { 61967446 , 195677 },
477 { 62589050 , 196118 },
478 { 63215194 , 196560 },
479 { 63845897 , 197002 },
480 { 64481179 , 197444 },
481 { 65121061 , 197886 },
482 { 65765563 , 198328 },
483 { 66414705 , 198770 },
484 { 67068508 , 199213 },
485 { 67726992 , 199655 },
486 { 68390177 , 200098 },
487 { 69058085 , 200540 },
488 { 69730735 , 200983 },
489 { 70408147 , 201426 },
490 { 71090343 , 201869 },
491 { 71777343 , 202312 },
492 { 72469168 , 202755 },
493 { 73165837 , 203199 },
494 { 73867373 , 203642 },
495 { 74573795 , 204086 },
496 { 75285124 , 204529 },
497 { 76001380 , 204973 },
498 { 76722586 , 205417 },
499 { 77448761 , 205861 },
500 { 78179926 , 206306 },
501 { 78916102 , 206750 },
502 { 79657310 , 207194 },
503 { 80403571 , 207639 },
504 { 81154906 , 208084 },
505 { 81911335 , 208529 },
506 { 82672880 , 208974 },
507 { 83439562 , 209419 },
508 { 84211402 , 209864 },
509 { 84988421 , 210309 },
510 { 85770640 , 210755 },
511 { 86558080 , 211201 },
512 { 87350762 , 211647 },
513 { 88148708 , 212093 },
514 { 88951938 , 212539 },
515 { 89760475 , 212985 },
516 { 90574339 , 213432 },
517 { 91393551 , 213878 },
518 { 92218133 , 214325 },
519 { 93048107 , 214772 },
520 { 93883493 , 215219 },
521 { 94724314 , 215666 },
522 { 95570590 , 216114 },
523 { 96422343 , 216561 },
524 { 97279594 , 217009 },
525 { 98142366 , 217457 },
526 { 99010679 , 217905 },
527 { 99884556 , 218353 },
528 { 100764018 , 218801 },
529 { 101649086 , 219250 },
530 { 102539782 , 219698 },
531 { 103436128 , 220147 },
532 { 104338146 , 220596 },
533 { 105245857 , 221046 },
534 { 106159284 , 221495 },
535 { 107078448 , 221945 },
536 { 108003370 , 222394 },
537 { 108934074 , 222844 },
538 { 109870580 , 223294 },
539 { 110812910 , 223745 },
540 { 111761087 , 224195 },
541 { 112715133 , 224646 },
542 { 113675069 , 225097 },
543 { 114640918 , 225548 },
544 { 115612702 , 225999 },
545 { 116590442 , 226450 },
546 { 117574162 , 226902 },
547 { 118563882 , 227353 },
548 { 119559626 , 227805 },
549 { 120561415 , 228258 },
550 { 121569272 , 228710 },
551 { 122583219 , 229162 },
552 { 123603278 , 229615 },
553 { 124629471 , 230068 },
554 { 125661822 , 230521 },
555 { 126700352 , 230974 },
556 { 127745083 , 231428 },
557 { 128796039 , 231882 },
558 { 129853241 , 232336 },
559 { 130916713 , 232790 },
560 { 131986475 , 233244 },
561 { 133062553 , 233699 },
562 { 134144966 , 234153 },
563 { 135233739 , 234608 },
564 { 136328894 , 235064 },
565 { 137430453 , 235519 },
566 { 138538440 , 235975 },
567 { 139652876 , 236430 },
568 { 140773786 , 236886 },
569 { 141901190 , 237343 },
570 { 143035113 , 237799 },
571 { 144175576 , 238256 },
572 { 145322604 , 238713 },
573 { 146476218 , 239170 },
574 { 147636442 , 239627 },
575 { 148803298 , 240085 },
576 { 149976809 , 240542 },
577 { 151156999 , 241000 },
578 { 152343890 , 241459 },
579 { 153537506 , 241917 },
580 { 154737869 , 242376 },
581 { 155945002 , 242835 },
582 { 157158929 , 243294 },
583 { 158379673 , 243753 },
584 { 159607257 , 244213 },
585 { 160841704 , 244673 },
586 { 162083037 , 245133 },
587 { 163331279 , 245593 },
588 { 164586455 , 246054 },
589 { 165848586 , 246514 },
590 { 167117696 , 246975 },
591 { 168393810 , 247437 },
592 { 169676949 , 247898 },
593 { 170967138 , 248360 },
594 { 172264399 , 248822 },
595 { 173568757 , 249284 },
596 { 174880235 , 249747 },
597 { 176198856 , 250209 },
598 { 177524643 , 250672 },
599 { 178857621 , 251136 },
600 { 180197813 , 251599 },
601 { 181545242 , 252063 },
602 { 182899933 , 252527 },
603 { 184261908 , 252991 },
604 { 185631191 , 253456 },
605 { 187007807 , 253920 },
606 { 188391778 , 254385 },
607 { 189783129 , 254851 },
608 { 191181884 , 255316 },
609 { 192588065 , 255782 },
610 { 194001698 , 256248 },
611 { 195422805 , 256714 },
612 { 196851411 , 257181 },
613 { 198287540 , 257648 },
614 { 199731215 , 258115 },
615 { 201182461 , 258582 },
616 { 202641302 , 259050 },
617 { 204107760 , 259518 },
618 { 205581862 , 259986 },
619 { 207063630 , 260454 },
620 { 208553088 , 260923 },
621 { 210050262 , 261392 },
622 { 211555174 , 261861 },
623 { 213067849 , 262331 },
624 { 214588312 , 262800 },
625 { 216116586 , 263270 },
626 { 217652696 , 263741 },
627 { 219196666 , 264211 },
628 { 220748520 , 264682 },
629 { 222308282 , 265153 },
630 { 223875978 , 265625 },
631 { 225451630 , 266097 },
632 { 227035265 , 266569 },
633 { 228626905 , 267041 },
634 { 230226576 , 267514 },
635 { 231834302 , 267986 },
636 { 233450107 , 268460 },
637 { 235074016 , 268933 },
638 { 236706054 , 269407 },
639 { 238346244 , 269881 },
640 { 239994613 , 270355 },
641 { 241651183 , 270830 },
642 { 243315981 , 271305 }
643};
644
645/* Calculate the send rate as per section 3.1 of RFC3448
646
647Returns send rate in bytes per second
648
649Integer maths and lookups are used as not allowed floating point in kernel
650
651The function for Xcalc as per section 3.1 of RFC3448 is:
652
653X = s
654 -------------------------------------------------------------
655 R*sqrt(2*b*p/3) + (t_RTO * (3*sqrt(3*b*p/8) * p * (1+32*p^2)))
656
657where
658X is the trasmit rate in bytes/second
659s is the packet size in bytes
660R is the round trip time in seconds
661p is the loss event rate, between 0 and 1.0, of the number of loss events
662 as a fraction of the number of packets transmitted
663t_RTO is the TCP retransmission timeout value in seconds
664b is the number of packets acknowledged by a single TCP acknowledgement
665
666we can assume that b = 1 and t_RTO is 4 * R. With this the equation becomes:
667
668X = s
669 -----------------------------------------------------------------------
670 R * sqrt(2 * p / 3) + (12 * R * (sqrt(3 * p / 8) * p * (1 + 32 * p^2)))
671
672
673which we can break down into:
674
675X = s
676 --------
677 R * f(p)
678
679where f(p) = sqrt(2 * p / 3) + (12 * sqrt(3 * p / 8) * p * (1 + 32 * p * p))
680
681Function parameters:
682s - bytes
683R - RTT in usecs
684p - loss rate (decimal fraction multiplied by 1,000,000)
685
686Returns Xcalc in bytes per second
687
688DON'T alter this code unless you run test cases against it as the code
689has been manipulated to stop underflow/overlow.
690
691*/
692static u32 ccid3_calc_x(u16 s, u32 R, u32 p)
693{
694 int index;
695 u32 f;
696 u64 tmp1, tmp2;
697
698 if (p < CALCX_SPLIT)
699 index = (p / (CALCX_SPLIT / CALCX_ARRSIZE)) - 1;
700 else
701 index = (p / (1000000 / CALCX_ARRSIZE)) - 1;
702
703 if (index < 0)
704 /* p should be 0 unless there is a bug in my code */
705 index = 0;
706
707 if (R == 0)
708 R = 1; /* RTT can't be zero or else divide by zero */
709
710 BUG_ON(index >= CALCX_ARRSIZE);
711
712 if (p >= CALCX_SPLIT)
713 f = calcx_lookup[index][0];
714 else
715 f = calcx_lookup[index][1];
716
717 tmp1 = ((u64)s * 100000000);
718 tmp2 = ((u64)R * (u64)f);
719 do_div(tmp2,10000);
720 do_div(tmp1,tmp2);
721 /* don't alter above math unless you test due to overflow on 32 bit */
722
723 return (u32)tmp1;
724}
725
726/* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */
727static inline void ccid3_calc_new_t_ipi(struct ccid3_hc_tx_sock *hctx)
728{
Arnaldo Carvalho de Melo6b5e6332005-08-27 20:11:28 -0300729 /*
730 * If no feedback spec says t_ipi is 1 second (set elsewhere and then
731 * doubles after every no feedback timer (separate function)
732 */
733 if (hctx->ccid3hctx_state != TFRC_SSTATE_NO_FBACK)
734 hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s,
735 hctx->ccid3hctx_x);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700736}
737
738/* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */
739static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx)
740{
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300741 hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2,
742 TFRC_OPSYS_HALF_TIME_GRAN);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700743}
744
745/*
746 * Update X by
747 * If (p > 0)
748 * x_calc = calcX(s, R, p);
749 * X = max(min(X_calc, 2 * X_recv), s / t_mbi);
750 * Else
751 * If (now - tld >= R)
752 * X = max(min(2 * X, 2 * X_recv), s / R);
753 * tld = now;
754 */
755static void ccid3_hc_tx_update_x(struct sock *sk)
756{
757 struct dccp_sock *dp = dccp_sk(sk);
758 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
759
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300760 /* To avoid large error in calcX */
761 if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) {
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700762 hctx->ccid3hctx_x_calc = ccid3_calc_x(hctx->ccid3hctx_s,
763 hctx->ccid3hctx_rtt,
764 hctx->ccid3hctx_p);
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300765 hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_calc,
766 2 * hctx->ccid3hctx_x_recv),
767 (hctx->ccid3hctx_s /
768 TFRC_MAX_BACK_OFF_TIME));
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -0300769 } else {
770 struct timeval now;
771
772 do_gettimeofday(&now);
773 if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >=
774 hctx->ccid3hctx_rtt) {
Arnaldo Carvalho de Melo6b5e6332005-08-27 20:11:28 -0300775 hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv,
776 hctx->ccid3hctx_x) * 2,
777 usecs_div(hctx->ccid3hctx_s,
778 hctx->ccid3hctx_rtt));
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -0300779 hctx->ccid3hctx_t_ld = now;
780 }
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700781 }
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700782}
783
784static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
785{
786 struct sock *sk = (struct sock *)data;
787 struct dccp_sock *dp = dccp_sk(sk);
788 unsigned long next_tmout = 0;
789 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700790
791 bh_lock_sock(sk);
792 if (sock_owned_by_user(sk)) {
793 /* Try again later. */
794 /* XXX: set some sensible MIB */
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300795 sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
796 jiffies + HZ / 5);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700797 goto out;
798 }
799
800 ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk,
801 ccid3_tx_state_name(hctx->ccid3hctx_state));
802
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700803 switch (hctx->ccid3hctx_state) {
804 case TFRC_SSTATE_TERM:
805 goto out;
806 case TFRC_SSTATE_NO_FBACK:
807 /* Halve send rate */
808 hctx->ccid3hctx_x /= 2;
Arnaldo Carvalho de Melo6b5e6332005-08-27 20:11:28 -0300809 if (hctx->ccid3hctx_x < (hctx->ccid3hctx_s /
810 TFRC_MAX_BACK_OFF_TIME))
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300811 hctx->ccid3hctx_x = (hctx->ccid3hctx_s /
812 TFRC_MAX_BACK_OFF_TIME);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700813
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300814 ccid3_pr_debug("%s, sk=%p, state=%s, updated tx rate to %d "
815 "bytes/s\n",
816 dccp_role(sk), sk,
817 ccid3_tx_state_name(hctx->ccid3hctx_state),
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700818 hctx->ccid3hctx_x);
Arnaldo Carvalho de Melo6b5e6332005-08-27 20:11:28 -0300819 next_tmout = max_t(u32, 2 * usecs_div(hctx->ccid3hctx_s,
820 hctx->ccid3hctx_x),
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300821 TFRC_INITIAL_TIMEOUT);
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300822 /*
823 * FIXME - not sure above calculation is correct. See section
824 * 5 of CCID3 11 should adjust tx_t_ipi and double that to
825 * achieve it really
826 */
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700827 break;
828 case TFRC_SSTATE_FBACK:
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300829 /*
830 * Check if IDLE since last timeout and recv rate is less than
831 * 4 packets per RTT
832 */
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300833 if (!hctx->ccid3hctx_idle ||
Arnaldo Carvalho de Melo6b5e6332005-08-27 20:11:28 -0300834 (hctx->ccid3hctx_x_recv >=
835 4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) {
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300836 ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n",
837 dccp_role(sk), sk,
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700838 ccid3_tx_state_name(hctx->ccid3hctx_state));
839 /* Halve sending rate */
840
841 /* If (X_calc > 2 * X_recv)
842 * X_recv = max(X_recv / 2, s / (2 * t_mbi));
843 * Else
844 * X_recv = X_calc / 4;
845 */
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300846 BUG_ON(hctx->ccid3hctx_p >= TFRC_SMALLEST_P &&
847 hctx->ccid3hctx_x_calc == 0);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700848
849 /* check also if p is zero -> x_calc is infinity? */
850 if (hctx->ccid3hctx_p < TFRC_SMALLEST_P ||
851 hctx->ccid3hctx_x_calc > 2 * hctx->ccid3hctx_x_recv)
852 hctx->ccid3hctx_x_recv = max_t(u32, hctx->ccid3hctx_x_recv / 2,
853 hctx->ccid3hctx_s / (2 * TFRC_MAX_BACK_OFF_TIME));
854 else
855 hctx->ccid3hctx_x_recv = hctx->ccid3hctx_x_calc / 4;
856
857 /* Update sending rate */
858 ccid3_hc_tx_update_x(sk);
859 }
Arnaldo Carvalho de Melo6b5e6332005-08-27 20:11:28 -0300860 /*
861 * Schedule no feedback timer to expire in
862 * max(4 * R, 2 * s / X)
863 */
Arnaldo Carvalho de Meloc68e64c2005-08-21 05:07:37 -0300864 next_tmout = max_t(u32, hctx->ccid3hctx_t_rto,
Arnaldo Carvalho de Melo6b5e6332005-08-27 20:11:28 -0300865 2 * usecs_div(hctx->ccid3hctx_s,
866 hctx->ccid3hctx_x));
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700867 break;
868 default:
869 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
870 __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state);
871 dump_stack();
872 goto out;
873 }
874
875 sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300876 jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout)));
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700877 hctx->ccid3hctx_idle = 1;
878out:
879 bh_unlock_sock(sk);
880 sock_put(sk);
881}
882
Arnaldo Carvalho de Melo27258ee2005-08-09 20:30:56 -0700883static int ccid3_hc_tx_send_packet(struct sock *sk,
884 struct sk_buff *skb, int len)
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700885{
886 struct dccp_sock *dp = dccp_sk(sk);
887 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -0300888 struct dccp_tx_hist_entry *new_packet;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700889 struct timeval now;
Arnaldo Carvalho de Melo27258ee2005-08-09 20:30:56 -0700890 long delay;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700891 int rc = -ENOTCONN;
892
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300893 /* Check if pure ACK or Terminating*/
894
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700895 /*
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300896 * XXX: We only call this function for DATA and DATAACK, on, these
897 * packets can have zero length, but why the comment about "pure ACK"?
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700898 */
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300899 if (hctx == NULL || len == 0 ||
900 hctx->ccid3hctx_state == TFRC_SSTATE_TERM)
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700901 goto out;
902
903 /* See if last packet allocated was not sent */
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -0300904 new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
905 if (new_packet == NULL || new_packet->dccphtx_sent) {
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300906 new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist,
907 SLAB_ATOMIC);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700908
909 rc = -ENOBUFS;
910 if (new_packet == NULL) {
911 ccid3_pr_debug("%s, sk=%p, not enough mem to add "
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300912 "to history, send refused\n",
913 dccp_role(sk), sk);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700914 goto out;
915 }
916
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -0300917 dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700918 }
919
920 do_gettimeofday(&now);
921
922 switch (hctx->ccid3hctx_state) {
923 case TFRC_SSTATE_NO_SENT:
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300924 ccid3_pr_debug("%s, sk=%p, first packet(%llu)\n",
925 dccp_role(sk), sk, dp->dccps_gss);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700926
927 hctx->ccid3hctx_no_feedback_timer.function = ccid3_hc_tx_no_feedback_timer;
928 hctx->ccid3hctx_no_feedback_timer.data = (unsigned long)sk;
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300929 sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
930 jiffies + usecs_to_jiffies(TFRC_INITIAL_TIMEOUT));
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700931 hctx->ccid3hctx_last_win_count = 0;
932 hctx->ccid3hctx_t_last_win_count = now;
933 ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK);
934 hctx->ccid3hctx_t_ipi = TFRC_INITIAL_TIMEOUT;
935
936 /* Set nominal send time for initial packet */
937 hctx->ccid3hctx_t_nom = now;
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -0300938 timeval_add_usecs(&hctx->ccid3hctx_t_nom,
939 hctx->ccid3hctx_t_ipi);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700940 ccid3_calc_new_delta(hctx);
941 rc = 0;
942 break;
943 case TFRC_SSTATE_NO_FBACK:
944 case TFRC_SSTATE_FBACK:
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -0300945 delay = (timeval_delta(&now, &hctx->ccid3hctx_t_nom) -
946 hctx->ccid3hctx_delta);
Arnaldo Carvalho de Melo27258ee2005-08-09 20:30:56 -0700947 ccid3_pr_debug("send_packet delay=%ld\n", delay);
948 delay /= -1000;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700949 /* divide by -1000 is to convert to ms and get sign right */
Arnaldo Carvalho de Melod6809c12005-08-27 03:06:35 -0300950 rc = delay > 0 ? delay : 0;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700951 break;
952 default:
953 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
954 __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state);
955 dump_stack();
956 rc = -EINVAL;
957 break;
958 }
959
960 /* Can we send? if so add options and add to packet history */
961 if (rc == 0)
Arnaldo Carvalho de Meloc1734372005-08-13 20:34:23 -0300962 new_packet->dccphtx_ccval =
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -0300963 DCCP_SKB_CB(skb)->dccpd_ccval =
964 hctx->ccid3hctx_last_win_count;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700965out:
966 return rc;
967}
968
969static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
970{
971 struct dccp_sock *dp = dccp_sk(sk);
972 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700973 struct timeval now;
974
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700975 BUG_ON(hctx == NULL);
976
977 if (hctx->ccid3hctx_state == TFRC_SSTATE_TERM) {
978 ccid3_pr_debug("%s, sk=%p, while state is TFRC_SSTATE_TERM!\n",
979 dccp_role(sk), sk);
980 return;
981 }
982
983 do_gettimeofday(&now);
984
985 /* check if we have sent a data packet */
986 if (len > 0) {
987 unsigned long quarter_rtt;
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -0300988 struct dccp_tx_hist_entry *packet;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700989
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -0300990 packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
991 if (packet == NULL) {
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300992 printk(KERN_CRIT "%s: packet doesn't exists in "
993 "history!\n", __FUNCTION__);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700994 return;
995 }
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -0300996 if (packet->dccphtx_sent) {
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -0300997 printk(KERN_CRIT "%s: no unsent packet in history!\n",
998 __FUNCTION__);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -0700999 return;
1000 }
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001001 packet->dccphtx_tstamp = now;
1002 packet->dccphtx_seqno = dp->dccps_gss;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001003 /*
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001004 * Check if win_count have changed
1005 * Algorithm in "8.1. Window Counter Valuer" in
1006 * draft-ietf-dccp-ccid3-11.txt
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001007 */
Arnaldo Carvalho de Melo6b5e6332005-08-27 20:11:28 -03001008 quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count);
1009 if (likely(hctx->ccid3hctx_rtt > 8))
1010 quarter_rtt /= hctx->ccid3hctx_rtt / 4;
1011
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001012 if (quarter_rtt > 0) {
1013 hctx->ccid3hctx_t_last_win_count = now;
1014 hctx->ccid3hctx_last_win_count = (hctx->ccid3hctx_last_win_count +
1015 min_t(unsigned long, quarter_rtt, 5)) % 16;
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001016 ccid3_pr_debug("%s, sk=%p, window changed from "
1017 "%u to %u!\n",
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001018 dccp_role(sk), sk,
Arnaldo Carvalho de Meloc1734372005-08-13 20:34:23 -03001019 packet->dccphtx_ccval,
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001020 hctx->ccid3hctx_last_win_count);
1021 }
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001022
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001023 hctx->ccid3hctx_idle = 0;
Arnaldo Carvalho de Meloc1734372005-08-13 20:34:23 -03001024 packet->dccphtx_rtt = hctx->ccid3hctx_rtt;
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001025 packet->dccphtx_sent = 1;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001026 } else
1027 ccid3_pr_debug("%s, sk=%p, seqno=%llu NOT inserted!\n",
1028 dccp_role(sk), sk, dp->dccps_gss);
1029
1030 switch (hctx->ccid3hctx_state) {
1031 case TFRC_SSTATE_NO_SENT:
1032 /* if first wasn't pure ack */
1033 if (len != 0)
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001034 printk(KERN_CRIT "%s: %s, First packet sent is noted "
1035 "as a data packet\n",
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001036 __FUNCTION__, dccp_role(sk));
1037 return;
1038 case TFRC_SSTATE_NO_FBACK:
1039 case TFRC_SSTATE_FBACK:
1040 if (len > 0) {
1041 hctx->ccid3hctx_t_nom = now;
1042 ccid3_calc_new_t_ipi(hctx);
1043 ccid3_calc_new_delta(hctx);
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -03001044 timeval_add_usecs(&hctx->ccid3hctx_t_nom,
1045 hctx->ccid3hctx_t_ipi);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001046 }
1047 break;
1048 default:
1049 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
1050 __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state);
1051 dump_stack();
1052 break;
1053 }
1054}
1055
1056static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
1057{
1058 struct dccp_sock *dp = dccp_sk(sk);
1059 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
1060 struct ccid3_options_received *opt_recv;
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001061 struct dccp_tx_hist_entry *packet;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001062 unsigned long next_tmout;
Ian McDonald1bc09862005-08-20 00:23:43 -03001063 u32 t_elapsed;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001064 u32 pinv;
1065 u32 x_recv;
1066 u32 r_sample;
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001067
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001068 if (hctx == NULL)
1069 return;
1070
1071 if (hctx->ccid3hctx_state == TFRC_SSTATE_TERM) {
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001072 ccid3_pr_debug("%s, sk=%p, received a packet when "
1073 "terminating!\n", dccp_role(sk), sk);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001074 return;
1075 }
1076
1077 /* we are only interested in ACKs */
1078 if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK ||
1079 DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_DATAACK))
1080 return;
1081
1082 opt_recv = &hctx->ccid3hctx_options_received;
1083
1084 t_elapsed = dp->dccps_options_received.dccpor_elapsed_time;
1085 x_recv = opt_recv->ccid3or_receive_rate;
1086 pinv = opt_recv->ccid3or_loss_event_rate;
1087
1088 switch (hctx->ccid3hctx_state) {
1089 case TFRC_SSTATE_NO_SENT:
1090 /* FIXME: what to do here? */
1091 return;
1092 case TFRC_SSTATE_NO_FBACK:
1093 case TFRC_SSTATE_FBACK:
1094 /* Calculate new round trip sample by
1095 * R_sample = (now - t_recvdata) - t_delay */
1096 /* get t_recvdata from history */
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001097 packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist,
1098 DCCP_SKB_CB(skb)->dccpd_ack_seq);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001099 if (packet == NULL) {
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001100 ccid3_pr_debug("%s, sk=%p, seqno %llu(%s) does't "
1101 "exist in history!\n",
1102 dccp_role(sk), sk,
1103 DCCP_SKB_CB(skb)->dccpd_ack_seq,
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001104 dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
1105 return;
1106 }
1107
1108 /* Update RTT */
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -03001109 r_sample = timeval_now_delta(&packet->dccphtx_tstamp);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001110 /* FIXME: */
1111 // r_sample -= usecs_to_jiffies(t_elapsed * 10);
1112
1113 /* Update RTT estimate by
1114 * If (No feedback recv)
1115 * R = R_sample;
1116 * Else
1117 * R = q * R + (1 - q) * R_sample;
1118 *
1119 * q is a constant, RFC 3448 recomments 0.9
1120 */
1121 if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) {
1122 ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK);
1123 hctx->ccid3hctx_rtt = r_sample;
1124 } else
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001125 hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 +
1126 r_sample / 10;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001127
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001128 ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, "
1129 "r_sample=%us\n", dccp_role(sk), sk,
1130 hctx->ccid3hctx_rtt, r_sample);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001131
1132 /* Update timeout interval */
Arnaldo Carvalho de Meloc68e64c2005-08-21 05:07:37 -03001133 hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt,
1134 USEC_PER_SEC);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001135
1136 /* Update receive rate */
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001137 hctx->ccid3hctx_x_recv = x_recv;/* X_recv in bytes per sec */
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001138
1139 /* Update loss event rate */
1140 if (pinv == ~0 || pinv == 0)
1141 hctx->ccid3hctx_p = 0;
1142 else {
1143 hctx->ccid3hctx_p = 1000000 / pinv;
1144
1145 if (hctx->ccid3hctx_p < TFRC_SMALLEST_P) {
1146 hctx->ccid3hctx_p = TFRC_SMALLEST_P;
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001147 ccid3_pr_debug("%s, sk=%p, Smallest p used!\n",
1148 dccp_role(sk), sk);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001149 }
1150 }
1151
1152 /* unschedule no feedback timer */
1153 sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);
1154
1155 /* Update sending rate */
1156 ccid3_hc_tx_update_x(sk);
1157
1158 /* Update next send time */
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -03001159 timeval_sub_usecs(&hctx->ccid3hctx_t_nom,
1160 hctx->ccid3hctx_t_ipi);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001161 ccid3_calc_new_t_ipi(hctx);
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -03001162 timeval_add_usecs(&hctx->ccid3hctx_t_nom,
1163 hctx->ccid3hctx_t_ipi);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001164 ccid3_calc_new_delta(hctx);
1165
1166 /* remove all packets older than the one acked from history */
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001167 dccp_tx_hist_purge_older(ccid3_tx_hist,
1168 &hctx->ccid3hctx_hist, packet);
1169
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001170 /*
1171 * Schedule no feedback timer to expire in
1172 * max(4 * R, 2 * s / X)
1173 */
Arnaldo Carvalho de Meloc68e64c2005-08-21 05:07:37 -03001174 next_tmout = max(hctx->ccid3hctx_t_rto,
Arnaldo Carvalho de Melo6b5e6332005-08-27 20:11:28 -03001175 2 * usecs_div(hctx->ccid3hctx_s,
1176 hctx->ccid3hctx_x));
1177
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001178 ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to "
1179 "expire in %lu jiffies (%luus)\n",
1180 dccp_role(sk), sk,
1181 usecs_to_jiffies(next_tmout), next_tmout);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001182
1183 sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer,
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001184 jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout)));
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001185
1186 /* set idle flag */
1187 hctx->ccid3hctx_idle = 1;
1188 break;
1189 default:
1190 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
1191 __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state);
1192 dump_stack();
1193 break;
1194 }
1195}
1196
1197static void ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb)
1198{
1199 const struct dccp_sock *dp = dccp_sk(sk);
1200 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
1201
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001202 if (hctx == NULL || !(sk->sk_state == DCCP_OPEN ||
1203 sk->sk_state == DCCP_PARTOPEN))
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001204 return;
1205
1206 DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;
1207}
1208
1209static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001210 unsigned char len, u16 idx,
1211 unsigned char *value)
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001212{
1213 int rc = 0;
1214 struct dccp_sock *dp = dccp_sk(sk);
1215 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
1216 struct ccid3_options_received *opt_recv;
1217
1218 if (hctx == NULL)
1219 return 0;
1220
1221 opt_recv = &hctx->ccid3hctx_options_received;
1222
1223 if (opt_recv->ccid3or_seqno != dp->dccps_gsr) {
1224 opt_recv->ccid3or_seqno = dp->dccps_gsr;
1225 opt_recv->ccid3or_loss_event_rate = ~0;
1226 opt_recv->ccid3or_loss_intervals_idx = 0;
1227 opt_recv->ccid3or_loss_intervals_len = 0;
1228 opt_recv->ccid3or_receive_rate = 0;
1229 }
1230
1231 switch (option) {
1232 case TFRC_OPT_LOSS_EVENT_RATE:
1233 if (len != 4) {
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001234 ccid3_pr_debug("%s, sk=%p, invalid len for "
1235 "TFRC_OPT_LOSS_EVENT_RATE\n",
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001236 dccp_role(sk), sk);
1237 rc = -EINVAL;
1238 } else {
1239 opt_recv->ccid3or_loss_event_rate = ntohl(*(u32 *)value);
1240 ccid3_pr_debug("%s, sk=%p, LOSS_EVENT_RATE=%u\n",
1241 dccp_role(sk), sk,
1242 opt_recv->ccid3or_loss_event_rate);
1243 }
1244 break;
1245 case TFRC_OPT_LOSS_INTERVALS:
1246 opt_recv->ccid3or_loss_intervals_idx = idx;
1247 opt_recv->ccid3or_loss_intervals_len = len;
1248 ccid3_pr_debug("%s, sk=%p, LOSS_INTERVALS=(%u, %u)\n",
1249 dccp_role(sk), sk,
1250 opt_recv->ccid3or_loss_intervals_idx,
1251 opt_recv->ccid3or_loss_intervals_len);
1252 break;
1253 case TFRC_OPT_RECEIVE_RATE:
1254 if (len != 4) {
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001255 ccid3_pr_debug("%s, sk=%p, invalid len for "
1256 "TFRC_OPT_RECEIVE_RATE\n",
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001257 dccp_role(sk), sk);
1258 rc = -EINVAL;
1259 } else {
1260 opt_recv->ccid3or_receive_rate = ntohl(*(u32 *)value);
1261 ccid3_pr_debug("%s, sk=%p, RECEIVE_RATE=%u\n",
1262 dccp_role(sk), sk,
1263 opt_recv->ccid3or_receive_rate);
1264 }
1265 break;
1266 }
1267
1268 return rc;
1269}
1270
1271static int ccid3_hc_tx_init(struct sock *sk)
1272{
1273 struct dccp_sock *dp = dccp_sk(sk);
1274 struct ccid3_hc_tx_sock *hctx;
1275
1276 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
1277
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001278 hctx = dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx),
1279 gfp_any());
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001280 if (hctx == NULL)
1281 return -ENOMEM;
1282
1283 memset(hctx, 0, sizeof(*hctx));
1284
1285 if (dp->dccps_avg_packet_size >= TFRC_MIN_PACKET_SIZE &&
1286 dp->dccps_avg_packet_size <= TFRC_MAX_PACKET_SIZE)
1287 hctx->ccid3hctx_s = (u16)dp->dccps_avg_packet_size;
1288 else
1289 hctx->ccid3hctx_s = TFRC_STD_PACKET_SIZE;
1290
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001291 /* Set transmission rate to 1 packet per second */
1292 hctx->ccid3hctx_x = hctx->ccid3hctx_s;
Arnaldo Carvalho de Meloc68e64c2005-08-21 05:07:37 -03001293 hctx->ccid3hctx_t_rto = USEC_PER_SEC;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001294 hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
1295 INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
1296 init_timer(&hctx->ccid3hctx_no_feedback_timer);
1297
1298 return 0;
1299}
1300
1301static void ccid3_hc_tx_exit(struct sock *sk)
1302{
1303 struct dccp_sock *dp = dccp_sk(sk);
1304 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001305
1306 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
1307 BUG_ON(hctx == NULL);
1308
1309 ccid3_hc_tx_set_state(sk, TFRC_SSTATE_TERM);
1310 sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);
1311
1312 /* Empty packet history */
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001313 dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001314
1315 kfree(dp->dccps_hc_tx_ccid_private);
1316 dp->dccps_hc_tx_ccid_private = NULL;
1317}
1318
1319/*
1320 * RX Half Connection methods
1321 */
1322
1323/* TFRC receiver states */
1324enum ccid3_hc_rx_states {
1325 TFRC_RSTATE_NO_DATA = 1,
1326 TFRC_RSTATE_DATA,
1327 TFRC_RSTATE_TERM = 127,
1328};
1329
1330#ifdef CCID3_DEBUG
1331static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state)
1332{
1333 static char *ccid3_rx_state_names[] = {
1334 [TFRC_RSTATE_NO_DATA] = "NO_DATA",
1335 [TFRC_RSTATE_DATA] = "DATA",
1336 [TFRC_RSTATE_TERM] = "TERM",
1337 };
1338
1339 return ccid3_rx_state_names[state];
1340}
1341#endif
1342
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001343static inline void ccid3_hc_rx_set_state(struct sock *sk,
1344 enum ccid3_hc_rx_states state)
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001345{
1346 struct dccp_sock *dp = dccp_sk(sk);
1347 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
1348 enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state;
1349
1350 ccid3_pr_debug("%s(%p) %-8.8s -> %s\n",
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001351 dccp_role(sk), sk, ccid3_rx_state_name(oldstate),
1352 ccid3_rx_state_name(state));
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001353 WARN_ON(state == oldstate);
1354 hcrx->ccid3hcrx_state = state;
1355}
1356
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001357static int ccid3_hc_rx_add_hist(struct sock *sk,
1358 struct dccp_rx_hist_entry *packet)
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001359{
1360 struct dccp_sock *dp = dccp_sk(sk);
1361 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001362 struct dccp_rx_hist_entry *entry, *next, *iter;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001363 u8 num_later = 0;
1364
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001365 iter = dccp_rx_hist_head(&hcrx->ccid3hcrx_hist);
1366 if (iter == NULL)
1367 dccp_rx_hist_add_entry(&hcrx->ccid3hcrx_hist, packet);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001368 else {
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001369 const u64 seqno = packet->dccphrx_seqno;
1370
1371 if (after48(seqno, iter->dccphrx_seqno))
1372 dccp_rx_hist_add_entry(&hcrx->ccid3hcrx_hist, packet);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001373 else {
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001374 if (dccp_rx_hist_entry_data_packet(iter))
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001375 num_later = 1;
1376
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001377 list_for_each_entry_continue(iter,
1378 &hcrx->ccid3hcrx_hist,
1379 dccphrx_node) {
1380 if (after48(seqno, iter->dccphrx_seqno)) {
1381 dccp_rx_hist_add_entry(&iter->dccphrx_node,
1382 packet);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001383 goto trim_history;
1384 }
1385
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001386 if (dccp_rx_hist_entry_data_packet(iter))
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001387 num_later++;
1388
1389 if (num_later == TFRC_RECV_NUM_LATE_LOSS) {
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001390 dccp_rx_hist_entry_delete(ccid3_rx_hist,
1391 packet);
1392 ccid3_pr_debug("%s, sk=%p, packet"
1393 "(%llu) already lost!\n",
1394 dccp_role(sk), sk,
1395 seqno);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001396 return 1;
1397 }
1398 }
1399
1400 if (num_later < TFRC_RECV_NUM_LATE_LOSS)
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001401 dccp_rx_hist_add_entry(&hcrx->ccid3hcrx_hist,
1402 packet);
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001403 /*
1404 * FIXME: else what? should we destroy the packet
1405 * like above?
1406 */
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001407 }
1408 }
1409
1410trim_history:
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001411 /*
1412 * Trim history (remove all packets after the NUM_LATE_LOSS + 1
1413 * data packets)
1414 */
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001415 num_later = TFRC_RECV_NUM_LATE_LOSS + 1;
1416
1417 if (!list_empty(&hcrx->ccid3hcrx_loss_interval_hist)) {
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001418 list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
1419 dccphrx_node) {
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001420 if (num_later == 0) {
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001421 list_del_init(&entry->dccphrx_node);
1422 dccp_rx_hist_entry_delete(ccid3_rx_hist, entry);
1423 } else if (dccp_rx_hist_entry_data_packet(entry))
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001424 --num_later;
1425 }
1426 } else {
1427 int step = 0;
1428 u8 win_count = 0; /* Not needed, but lets shut up gcc */
1429 int tmp;
1430 /*
1431 * We have no loss interval history so we need at least one
1432 * rtt:s of data packets to approximate rtt.
1433 */
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001434 list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
1435 dccphrx_node) {
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001436 if (num_later == 0) {
1437 switch (step) {
1438 case 0:
1439 step = 1;
1440 /* OK, find next data packet */
1441 num_later = 1;
1442 break;
1443 case 1:
1444 step = 2;
1445 /* OK, find next data packet */
1446 num_later = 1;
Arnaldo Carvalho de Meloc1734372005-08-13 20:34:23 -03001447 win_count = entry->dccphrx_ccval;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001448 break;
1449 case 2:
Arnaldo Carvalho de Meloc1734372005-08-13 20:34:23 -03001450 tmp = win_count - entry->dccphrx_ccval;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001451 if (tmp < 0)
1452 tmp += TFRC_WIN_COUNT_LIMIT;
1453 if (tmp > TFRC_WIN_COUNT_PER_RTT + 1) {
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001454 /*
1455 * We have found a packet older
1456 * than one rtt remove the rest
1457 */
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001458 step = 3;
1459 } else /* OK, find next data packet */
1460 num_later = 1;
1461 break;
1462 case 3:
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001463 list_del_init(&entry->dccphrx_node);
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001464 dccp_rx_hist_entry_delete(ccid3_rx_hist,
1465 entry);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001466 break;
1467 }
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001468 } else if (dccp_rx_hist_entry_data_packet(entry))
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001469 --num_later;
1470 }
1471 }
1472
1473 return 0;
1474}
1475
1476static void ccid3_hc_rx_send_feedback(struct sock *sk)
1477{
1478 struct dccp_sock *dp = dccp_sk(sk);
1479 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001480 struct dccp_rx_hist_entry *packet;
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -03001481 struct timeval now;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001482
1483 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
1484
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -03001485 do_gettimeofday(&now);
1486
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001487 switch (hcrx->ccid3hcrx_state) {
1488 case TFRC_RSTATE_NO_DATA:
1489 hcrx->ccid3hcrx_x_recv = 0;
1490 break;
1491 case TFRC_RSTATE_DATA: {
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -03001492 const u32 delta = timeval_delta(&now,
1493 &hcrx->ccid3hcrx_tstamp_last_feedback);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001494
Arnaldo Carvalho de Melocef07fd2005-08-10 13:29:27 -03001495 hcrx->ccid3hcrx_x_recv = (hcrx->ccid3hcrx_bytes_recv *
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -03001496 USEC_PER_SEC);
1497 if (likely(delta > 1))
1498 hcrx->ccid3hcrx_x_recv /= delta;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001499 }
1500 break;
1501 default:
1502 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
1503 __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state);
1504 dump_stack();
1505 return;
1506 }
1507
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001508 packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001509 if (packet == NULL) {
1510 printk(KERN_CRIT "%s: %s, sk=%p, no data packet in history!\n",
1511 __FUNCTION__, dccp_role(sk), sk);
1512 dump_stack();
1513 return;
1514 }
1515
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -03001516 hcrx->ccid3hcrx_tstamp_last_feedback = now;
Arnaldo Carvalho de Meloc1734372005-08-13 20:34:23 -03001517 hcrx->ccid3hcrx_last_counter = packet->dccphrx_ccval;
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001518 hcrx->ccid3hcrx_seqno_last_counter = packet->dccphrx_seqno;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001519 hcrx->ccid3hcrx_bytes_recv = 0;
1520
1521 /* Convert to multiples of 10us */
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -03001522 hcrx->ccid3hcrx_elapsed_time =
1523 timeval_delta(&now, &packet->dccphrx_tstamp) / 10;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001524 if (hcrx->ccid3hcrx_p == 0)
1525 hcrx->ccid3hcrx_pinv = ~0;
1526 else
1527 hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p;
1528 dccp_send_ack(sk);
1529}
1530
1531static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
1532{
1533 const struct dccp_sock *dp = dccp_sk(sk);
Arnaldo Carvalho de Melo4fded332005-08-23 21:51:59 -07001534 u32 x_recv, pinv;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001535 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
1536
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001537 if (hcrx == NULL || !(sk->sk_state == DCCP_OPEN ||
1538 sk->sk_state == DCCP_PARTOPEN))
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001539 return;
1540
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001541 DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter;
Arnaldo Carvalho de Melo4fded332005-08-23 21:51:59 -07001542
1543 if (dccp_packet_without_ack(skb))
1544 return;
1545
1546 if (hcrx->ccid3hcrx_elapsed_time != 0)
1547 dccp_insert_option_elapsed_time(sk, skb,
1548 hcrx->ccid3hcrx_elapsed_time);
1549 dccp_insert_option_timestamp(sk, skb);
1550 x_recv = htonl(hcrx->ccid3hcrx_x_recv);
1551 pinv = htonl(hcrx->ccid3hcrx_pinv);
1552 dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE,
1553 &pinv, sizeof(pinv));
1554 dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE,
1555 &x_recv, sizeof(x_recv));
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001556}
1557
1558/* Weights used to calculate loss event rate */
1559/*
1560 * These are integers as per section 8 of RFC3448. We can then divide by 4 *
1561 * when we use it.
1562 */
Arnaldo Carvalho de Meloa1d3a352005-08-13 22:42:25 -03001563static const int ccid3_hc_rx_w[TFRC_RECV_IVAL_F_LENGTH] = {
1564 4, 4, 4, 4, 3, 2, 1, 1,
1565};
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001566
1567/*
1568 * args: fvalue - function value to match
1569 * returns: p closest to that value
1570 *
1571 * both fvalue and p are multiplied by 1,000,000 to use ints
1572 */
Arnaldo Carvalho de Meloa1d3a352005-08-13 22:42:25 -03001573static u32 calcx_reverse_lookup(u32 fvalue) {
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001574 int ctr = 0;
1575 int small;
1576
1577 if (fvalue < calcx_lookup[0][1])
1578 return 0;
1579 if (fvalue <= calcx_lookup[CALCX_ARRSIZE-1][1])
1580 small = 1;
1581 else if (fvalue > calcx_lookup[CALCX_ARRSIZE-1][0])
1582 return 1000000;
1583 else
1584 small = 0;
1585 while (fvalue > calcx_lookup[ctr][small])
1586 ctr++;
1587 if (small)
1588 return (CALCX_SPLIT * ctr / CALCX_ARRSIZE);
1589 else
1590 return (1000000 * ctr / CALCX_ARRSIZE) ;
1591}
1592
1593/* calculate first loss interval
1594 *
1595 * returns estimated loss interval in usecs */
1596
1597static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
1598{
1599 struct dccp_sock *dp = dccp_sk(sk);
1600 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001601 struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001602 u32 rtt, delta, x_recv, fval, p, tmp2;
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -03001603 struct timeval tstamp = { 0, };
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001604 int interval = 0;
1605 int win_count = 0;
1606 int step = 0;
1607 u64 tmp1;
1608
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001609 list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
1610 dccphrx_node) {
1611 if (dccp_rx_hist_entry_data_packet(entry)) {
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001612 tail = entry;
1613
1614 switch (step) {
1615 case 0:
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001616 tstamp = entry->dccphrx_tstamp;
Arnaldo Carvalho de Meloc1734372005-08-13 20:34:23 -03001617 win_count = entry->dccphrx_ccval;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001618 step = 1;
1619 break;
1620 case 1:
Arnaldo Carvalho de Meloc1734372005-08-13 20:34:23 -03001621 interval = win_count - entry->dccphrx_ccval;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001622 if (interval < 0)
1623 interval += TFRC_WIN_COUNT_LIMIT;
1624 if (interval > 4)
1625 goto found;
1626 break;
1627 }
1628 }
1629 }
1630
1631 if (step == 0) {
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001632 printk(KERN_CRIT "%s: %s, sk=%p, packet history contains no "
1633 "data packets!\n",
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001634 __FUNCTION__, dccp_role(sk), sk);
1635 return ~0;
1636 }
1637
1638 if (interval == 0) {
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001639 ccid3_pr_debug("%s, sk=%p, Could not find a win_count "
1640 "interval > 0. Defaulting to 1\n",
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001641 dccp_role(sk), sk);
1642 interval = 1;
1643 }
1644found:
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -03001645 rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001646 ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n",
1647 dccp_role(sk), sk, rtt);
1648 if (rtt == 0)
1649 rtt = 1;
1650
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -03001651 delta = timeval_now_delta(&hcrx->ccid3hcrx_tstamp_last_feedback);
1652 x_recv = hcrx->ccid3hcrx_bytes_recv * USEC_PER_SEC;
1653 if (likely(delta > 1))
1654 x_recv /= delta;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001655
1656 tmp1 = (u64)x_recv * (u64)rtt;
1657 do_div(tmp1,10000000);
1658 tmp2 = (u32)tmp1;
1659 fval = (hcrx->ccid3hcrx_s * 100000) / tmp2;
1660 /* do not alter order above or you will get overflow on 32 bit */
1661 p = calcx_reverse_lookup(fval);
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001662 ccid3_pr_debug("%s, sk=%p, receive rate=%u bytes/s, implied "
1663 "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001664
1665 if (p == 0)
1666 return ~0;
1667 else
1668 return 1000000 / p;
1669}
1670
1671static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
1672{
1673 struct dccp_sock *dp = dccp_sk(sk);
1674 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
1675 struct ccid3_loss_interval_hist_entry *li_entry;
1676
1677 if (seq_loss != DCCP_MAX_SEQNO + 1) {
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001678 ccid3_pr_debug("%s, sk=%p, seq_loss=%llu, win_loss=%u, "
1679 "packet loss detected\n",
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001680 dccp_role(sk), sk, seq_loss, win_loss);
1681
1682 if (list_empty(&hcrx->ccid3hcrx_loss_interval_hist)) {
1683 struct ccid3_loss_interval_hist_entry *li_tail = NULL;
1684 int i;
1685
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001686 ccid3_pr_debug("%s, sk=%p, first loss event detected, "
1687 "creating history\n",
1688 dccp_role(sk), sk);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001689 for (i = 0; i <= TFRC_RECV_IVAL_F_LENGTH; ++i) {
1690 li_entry = ccid3_loss_interval_hist_entry_new(SLAB_ATOMIC);
1691 if (li_entry == NULL) {
1692 ccid3_loss_interval_history_delete(&hcrx->ccid3hcrx_loss_interval_hist);
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001693 ccid3_pr_debug("%s, sk=%p, not enough "
1694 "mem for creating "
1695 "history\n",
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001696 dccp_role(sk), sk);
1697 return;
1698 }
1699 if (li_tail == NULL)
1700 li_tail = li_entry;
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001701 list_add(&li_entry->ccid3lih_node,
1702 &hcrx->ccid3hcrx_loss_interval_hist);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001703 }
1704
1705 li_entry->ccid3lih_seqno = seq_loss;
1706 li_entry->ccid3lih_win_count = win_loss;
1707
1708 li_tail->ccid3lih_interval = ccid3_hc_rx_calc_first_li(sk);
1709 }
1710 }
1711 /* FIXME: find end of interval */
1712}
1713
1714static void ccid3_hc_rx_detect_loss(struct sock *sk)
1715{
1716 struct dccp_sock *dp = dccp_sk(sk);
1717 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001718 struct dccp_rx_hist_entry *entry, *next, *packet;
1719 struct dccp_rx_hist_entry *a_loss = NULL;
1720 struct dccp_rx_hist_entry *b_loss = NULL;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001721 u64 seq_loss = DCCP_MAX_SEQNO + 1;
1722 u8 win_loss = 0;
1723 u8 num_later = TFRC_RECV_NUM_LATE_LOSS;
1724
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001725 list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
1726 dccphrx_node) {
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001727 if (num_later == 0) {
1728 b_loss = entry;
1729 break;
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001730 } else if (dccp_rx_hist_entry_data_packet(entry))
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001731 --num_later;
1732 }
1733
1734 if (b_loss == NULL)
1735 goto out_update_li;
1736
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001737 num_later = 1;
Arnaldo Carvalho de Melo757f6122005-08-09 20:16:04 -07001738
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001739 list_for_each_entry_safe_continue(entry, next, &hcrx->ccid3hcrx_hist,
1740 dccphrx_node) {
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001741 if (num_later == 0) {
1742 a_loss = entry;
1743 break;
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001744 } else if (dccp_rx_hist_entry_data_packet(entry))
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001745 --num_later;
1746 }
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001747
1748 if (a_loss == NULL) {
1749 if (list_empty(&hcrx->ccid3hcrx_loss_interval_hist)) {
1750 /* no loss event have occured yet */
1751 ccid3_pr_debug("%s, sk=%p, TODO: find a lost data "
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001752 "packet by comparing to initial "
1753 "seqno\n",
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001754 dccp_role(sk), sk);
1755 goto out_update_li;
1756 } else {
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001757 pr_info("%s: %s, sk=%p, ERROR! Less than 4 data "
1758 "packets in history",
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001759 __FUNCTION__, dccp_role(sk), sk);
1760 return;
1761 }
1762 }
1763
1764 /* Locate a lost data packet */
1765 entry = packet = b_loss;
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001766 list_for_each_entry_safe_continue(entry, next, &hcrx->ccid3hcrx_hist,
1767 dccphrx_node) {
1768 u64 delta = dccp_delta_seqno(entry->dccphrx_seqno,
1769 packet->dccphrx_seqno);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001770
1771 if (delta != 0) {
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001772 if (dccp_rx_hist_entry_data_packet(packet))
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001773 --delta;
1774 /*
1775 * FIXME: check this, probably this % usage is because
1776 * in earlier drafts the ndp count was just 8 bits
1777 * long, but now it cam be up to 24 bits long.
1778 */
1779#if 0
1780 if (delta % DCCP_NDP_LIMIT !=
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001781 (packet->dccphrx_ndp -
1782 entry->dccphrx_ndp) % DCCP_NDP_LIMIT)
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001783#endif
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001784 if (delta !=
1785 packet->dccphrx_ndp - entry->dccphrx_ndp) {
1786 seq_loss = entry->dccphrx_seqno;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001787 dccp_inc_seqno(&seq_loss);
1788 }
1789 }
1790 packet = entry;
1791 if (packet == a_loss)
1792 break;
1793 }
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001794
1795 if (seq_loss != DCCP_MAX_SEQNO + 1)
Arnaldo Carvalho de Meloc1734372005-08-13 20:34:23 -03001796 win_loss = a_loss->dccphrx_ccval;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001797
1798out_update_li:
1799 ccid3_hc_rx_update_li(sk, seq_loss, win_loss);
1800}
1801
1802static u32 ccid3_hc_rx_calc_i_mean(struct sock *sk)
1803{
1804 struct dccp_sock *dp = dccp_sk(sk);
1805 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
1806 struct ccid3_loss_interval_hist_entry *li_entry, *li_next;
1807 int i = 0;
1808 u32 i_tot;
1809 u32 i_tot0 = 0;
1810 u32 i_tot1 = 0;
1811 u32 w_tot = 0;
1812
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001813 list_for_each_entry_safe(li_entry, li_next,
1814 &hcrx->ccid3hcrx_loss_interval_hist,
1815 ccid3lih_node) {
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001816 if (i < TFRC_RECV_IVAL_F_LENGTH) {
1817 i_tot0 += li_entry->ccid3lih_interval * ccid3_hc_rx_w[i];
1818 w_tot += ccid3_hc_rx_w[i];
1819 }
1820
1821 if (i != 0)
1822 i_tot1 += li_entry->ccid3lih_interval * ccid3_hc_rx_w[i - 1];
1823
1824 if (++i > TFRC_RECV_IVAL_F_LENGTH)
1825 break;
1826 }
1827
1828 if (i != TFRC_RECV_IVAL_F_LENGTH) {
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001829 pr_info("%s: %s, sk=%p, ERROR! Missing entry in "
1830 "interval history!\n",
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001831 __FUNCTION__, dccp_role(sk), sk);
1832 return 0;
1833 }
1834
1835 i_tot = max(i_tot0, i_tot1);
1836
1837 /* FIXME: Why do we do this? -Ian McDonald */
1838 if (i_tot * 4 < w_tot)
1839 i_tot = w_tot * 4;
1840
1841 return i_tot * 4 / w_tot;
1842}
1843
1844static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
1845{
1846 struct dccp_sock *dp = dccp_sk(sk);
1847 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
Arnaldo Carvalho de Melo4fded332005-08-23 21:51:59 -07001848 const struct dccp_options_received *opt_recv;
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001849 struct dccp_rx_hist_entry *packet;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001850 struct timeval now;
1851 u8 win_count;
1852 u32 p_prev;
1853 int ins;
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001854
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001855 if (hcrx == NULL)
1856 return;
1857
1858 BUG_ON(!(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA ||
1859 hcrx->ccid3hcrx_state == TFRC_RSTATE_DATA));
1860
Arnaldo Carvalho de Melo4fded332005-08-23 21:51:59 -07001861 opt_recv = &dp->dccps_options_received;
1862
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001863 switch (DCCP_SKB_CB(skb)->dccpd_type) {
1864 case DCCP_PKT_ACK:
1865 if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA)
1866 return;
1867 case DCCP_PKT_DATAACK:
Arnaldo Carvalho de Melo4fded332005-08-23 21:51:59 -07001868 if (opt_recv->dccpor_timestamp_echo == 0)
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001869 break;
1870 p_prev = hcrx->ccid3hcrx_rtt;
1871 do_gettimeofday(&now);
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -03001872 hcrx->ccid3hcrx_rtt = timeval_usecs(&now) -
Arnaldo Carvalho de Melo4fded332005-08-23 21:51:59 -07001873 (opt_recv->dccpor_timestamp_echo -
1874 opt_recv->dccpor_elapsed_time) * 10;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001875 if (p_prev != hcrx->ccid3hcrx_rtt)
Arnaldo Carvalho de Melo4fded332005-08-23 21:51:59 -07001876 ccid3_pr_debug("%s, New RTT=%luus, elapsed time=%u\n",
1877 dccp_role(sk), hcrx->ccid3hcrx_rtt,
1878 opt_recv->dccpor_elapsed_time);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001879 break;
1880 case DCCP_PKT_DATA:
1881 break;
1882 default:
1883 ccid3_pr_debug("%s, sk=%p, not DATA/DATAACK/ACK packet(%s)\n",
1884 dccp_role(sk), sk,
1885 dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type));
1886 return;
1887 }
1888
Arnaldo Carvalho de Melo4fded332005-08-23 21:51:59 -07001889 packet = dccp_rx_hist_entry_new(ccid3_rx_hist, opt_recv->dccpor_ndp,
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001890 skb, SLAB_ATOMIC);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001891 if (packet == NULL) {
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001892 ccid3_pr_debug("%s, sk=%p, Not enough mem to add rx packet "
1893 "to history (consider it lost)!",
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001894 dccp_role(sk), sk);
1895 return;
1896 }
1897
Arnaldo Carvalho de Meloc1734372005-08-13 20:34:23 -03001898 win_count = packet->dccphrx_ccval;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001899
1900 ins = ccid3_hc_rx_add_hist(sk, packet);
1901
1902 if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK)
1903 return;
1904
1905 switch (hcrx->ccid3hcrx_state) {
1906 case TFRC_RSTATE_NO_DATA:
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001907 ccid3_pr_debug("%s, sk=%p(%s), skb=%p, sending initial "
1908 "feedback\n",
1909 dccp_role(sk), sk,
1910 dccp_state_name(sk->sk_state), skb);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001911 ccid3_hc_rx_send_feedback(sk);
1912 ccid3_hc_rx_set_state(sk, TFRC_RSTATE_DATA);
1913 return;
1914 case TFRC_RSTATE_DATA:
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001915 hcrx->ccid3hcrx_bytes_recv += skb->len -
1916 dccp_hdr(skb)->dccph_doff * 4;
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -03001917 if (ins != 0)
1918 break;
1919
1920 do_gettimeofday(&now);
1921 if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >=
1922 hcrx->ccid3hcrx_rtt) {
1923 hcrx->ccid3hcrx_tstamp_last_ack = now;
1924 ccid3_hc_rx_send_feedback(sk);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001925 }
Arnaldo Carvalho de Melob6ee3d42005-08-27 18:18:18 -03001926 return;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001927 default:
1928 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
1929 __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state);
1930 dump_stack();
1931 return;
1932 }
1933
1934 /* Dealing with packet loss */
Arnaldo Carvalho de Melo4fded332005-08-23 21:51:59 -07001935 ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n",
1936 dccp_role(sk), sk, dccp_state_name(sk->sk_state));
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001937
1938 ccid3_hc_rx_detect_loss(sk);
1939 p_prev = hcrx->ccid3hcrx_p;
1940
1941 /* Calculate loss event rate */
1942 if (!list_empty(&hcrx->ccid3hcrx_loss_interval_hist))
1943 /* Scaling up by 1000000 as fixed decimal */
1944 hcrx->ccid3hcrx_p = 1000000 / ccid3_hc_rx_calc_i_mean(sk);
1945
1946 if (hcrx->ccid3hcrx_p > p_prev) {
1947 ccid3_hc_rx_send_feedback(sk);
1948 return;
1949 }
1950}
1951
1952static int ccid3_hc_rx_init(struct sock *sk)
1953{
1954 struct dccp_sock *dp = dccp_sk(sk);
1955 struct ccid3_hc_rx_sock *hcrx;
1956
1957 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
1958
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03001959 hcrx = dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx),
1960 gfp_any());
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001961 if (hcrx == NULL)
1962 return -ENOMEM;
1963
1964 memset(hcrx, 0, sizeof(*hcrx));
1965
1966 if (dp->dccps_avg_packet_size >= TFRC_MIN_PACKET_SIZE &&
1967 dp->dccps_avg_packet_size <= TFRC_MAX_PACKET_SIZE)
1968 hcrx->ccid3hcrx_s = (u16)dp->dccps_avg_packet_size;
1969 else
1970 hcrx->ccid3hcrx_s = TFRC_STD_PACKET_SIZE;
1971
1972 hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
1973 INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist);
1974 INIT_LIST_HEAD(&hcrx->ccid3hcrx_loss_interval_hist);
Arnaldo Carvalho de Melo4fded332005-08-23 21:51:59 -07001975 /*
1976 * XXX this seems to be paranoid, need to think more about this, for
1977 * now start with something different than zero. -acme
1978 */
1979 hcrx->ccid3hcrx_rtt = USEC_PER_SEC / 5;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001980 return 0;
1981}
1982
1983static void ccid3_hc_rx_exit(struct sock *sk)
1984{
1985 struct dccp_sock *dp = dccp_sk(sk);
1986 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
1987
1988 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
1989
1990 if (hcrx == NULL)
1991 return;
1992
1993 ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);
1994
1995 /* Empty packet history */
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03001996 dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07001997
1998 /* Empty loss interval history */
1999 ccid3_loss_interval_history_delete(&hcrx->ccid3hcrx_loss_interval_hist);
2000
2001 kfree(dp->dccps_hc_rx_ccid_private);
2002 dp->dccps_hc_rx_ccid_private = NULL;
2003}
2004
Arnaldo Carvalho de Melo2babe1f2005-08-23 21:52:35 -07002005static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
2006{
2007 const struct dccp_sock *dp = dccp_sk(sk);
2008 const struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
2009
2010 if (hcrx == NULL)
2011 return;
2012
2013 info->tcpi_ca_state = hcrx->ccid3hcrx_state;
2014 info->tcpi_options |= TCPI_OPT_TIMESTAMPS;
2015 info->tcpi_rcv_rtt = hcrx->ccid3hcrx_rtt;
2016}
2017
2018static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
2019{
2020 const struct dccp_sock *dp = dccp_sk(sk);
2021 const struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
2022
2023 if (hctx == NULL)
2024 return;
2025
2026 info->tcpi_rto = hctx->ccid3hctx_t_rto;
2027 info->tcpi_rtt = hctx->ccid3hctx_rtt;
2028}
2029
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07002030static struct ccid ccid3 = {
2031 .ccid_id = 3,
2032 .ccid_name = "ccid3",
2033 .ccid_owner = THIS_MODULE,
2034 .ccid_init = ccid3_init,
2035 .ccid_exit = ccid3_exit,
2036 .ccid_hc_tx_init = ccid3_hc_tx_init,
2037 .ccid_hc_tx_exit = ccid3_hc_tx_exit,
2038 .ccid_hc_tx_send_packet = ccid3_hc_tx_send_packet,
2039 .ccid_hc_tx_packet_sent = ccid3_hc_tx_packet_sent,
2040 .ccid_hc_tx_packet_recv = ccid3_hc_tx_packet_recv,
2041 .ccid_hc_tx_insert_options = ccid3_hc_tx_insert_options,
2042 .ccid_hc_tx_parse_options = ccid3_hc_tx_parse_options,
2043 .ccid_hc_rx_init = ccid3_hc_rx_init,
2044 .ccid_hc_rx_exit = ccid3_hc_rx_exit,
2045 .ccid_hc_rx_insert_options = ccid3_hc_rx_insert_options,
2046 .ccid_hc_rx_packet_recv = ccid3_hc_rx_packet_recv,
Arnaldo Carvalho de Melo2babe1f2005-08-23 21:52:35 -07002047 .ccid_hc_rx_get_info = ccid3_hc_rx_get_info,
2048 .ccid_hc_tx_get_info = ccid3_hc_tx_get_info,
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07002049};
2050
2051module_param(ccid3_debug, int, 0444);
2052MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
2053
2054static __init int ccid3_module_init(void)
2055{
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03002056 int rc = -ENOBUFS;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07002057
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03002058 ccid3_rx_hist = dccp_rx_hist_new("ccid3");
2059 if (ccid3_rx_hist == NULL)
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07002060 goto out;
2061
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03002062 ccid3_tx_hist = dccp_tx_hist_new("ccid3");
2063 if (ccid3_tx_hist == NULL)
2064 goto out_free_rx;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07002065
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03002066 ccid3_loss_interval_hist_slab = kmem_cache_create("li_hist_ccid3",
2067 sizeof(struct ccid3_loss_interval_hist_entry),
2068 0, SLAB_HWCACHE_ALIGN,
2069 NULL, NULL);
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07002070 if (ccid3_loss_interval_hist_slab == NULL)
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03002071 goto out_free_tx;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07002072
2073 rc = ccid_register(&ccid3);
2074 if (rc != 0)
2075 goto out_free_loss_interval_history;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07002076out:
2077 return rc;
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03002078
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07002079out_free_loss_interval_history:
2080 kmem_cache_destroy(ccid3_loss_interval_hist_slab);
2081 ccid3_loss_interval_hist_slab = NULL;
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03002082out_free_tx:
2083 dccp_tx_hist_delete(ccid3_tx_hist);
2084 ccid3_tx_hist = NULL;
2085out_free_rx:
2086 dccp_rx_hist_delete(ccid3_rx_hist);
2087 ccid3_rx_hist = NULL;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07002088 goto out;
2089}
2090module_init(ccid3_module_init);
2091
2092static __exit void ccid3_module_exit(void)
2093{
Arnaldo Carvalho de Melo725ba8e2005-08-13 20:35:39 -03002094#ifdef CONFIG_IP_DCCP_UNLOAD_HACK
2095 /*
2096 * Hack to use while developing, so that we get rid of the control
2097 * sock, that is what keeps a refcount on dccp.ko -acme
2098 */
2099 extern void dccp_ctl_sock_exit(void);
2100
2101 dccp_ctl_sock_exit();
2102#endif
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07002103 ccid_unregister(&ccid3);
2104
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03002105 if (ccid3_tx_hist != NULL) {
2106 dccp_tx_hist_delete(ccid3_tx_hist);
2107 ccid3_tx_hist = NULL;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07002108 }
Arnaldo Carvalho de Melo8c60f3f2005-08-10 12:59:38 -03002109 if (ccid3_rx_hist != NULL) {
2110 dccp_rx_hist_delete(ccid3_rx_hist);
2111 ccid3_rx_hist = NULL;
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07002112 }
2113 if (ccid3_loss_interval_hist_slab != NULL) {
2114 kmem_cache_destroy(ccid3_loss_interval_hist_slab);
2115 ccid3_loss_interval_hist_slab = NULL;
2116 }
2117}
2118module_exit(ccid3_module_exit);
2119
Arnaldo Carvalho de Melo1f2333a2005-08-27 03:51:58 -03002120MODULE_AUTHOR("Ian McDonald <iam4@cs.waikato.ac.nz>, "
2121 "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
Arnaldo Carvalho de Melo7c657872005-08-09 20:14:34 -07002122MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID");
2123MODULE_LICENSE("GPL");
2124MODULE_ALIAS("net-dccp-ccid-3");