blob: 3328d23c4be73f72aa1750b9ccd075b31e8d7b54 [file] [log] [blame]
Andrea Bittau2a91aa32006-03-20 17:41:47 -08001/*
2 * net/dccp/ccids/ccid2.c
3 *
4 * Copyright (c) 2005, 2006 Andrea Bittau <a.bittau@cs.ucl.ac.uk>
5 *
6 * Changes to meet Linux coding standards, and DCCP infrastructure fixes.
7 *
8 * Copyright (c) 2006 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25/*
26 * This implementation should follow: draft-ietf-dccp-ccid2-10.txt
27 *
28 * BUGS:
29 * - sequence number wrapping
30 * - jiffies wrapping
31 */
32
33#include <linux/config.h>
34#include "../ccid.h"
35#include "../dccp.h"
36#include "ccid2.h"
37
38static int ccid2_debug;
39
40#if 0
41#define CCID2_DEBUG
42#endif
43
44#ifdef CCID2_DEBUG
45#define ccid2_pr_debug(format, a...) \
46 do { if (ccid2_debug) \
47 printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \
48 } while (0)
49#else
50#define ccid2_pr_debug(format, a...)
51#endif
52
53static const int ccid2_seq_len = 128;
54
55static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk)
56{
57 return dccp_sk(sk)->dccps_hc_tx_ccid_private;
58}
59
60static inline struct ccid2_hc_rx_sock *ccid2_hc_rx_sk(const struct sock *sk)
61{
62 return dccp_sk(sk)->dccps_hc_rx_ccid_private;
63}
64
65#ifdef CCID2_DEBUG
66static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx)
67{
68 int len = 0;
69 struct ccid2_seq *seqp;
70 int pipe = 0;
71
72 seqp = hctx->ccid2hctx_seqh;
73
74 /* there is data in the chain */
75 if (seqp != hctx->ccid2hctx_seqt) {
76 seqp = seqp->ccid2s_prev;
77 len++;
78 if (!seqp->ccid2s_acked)
79 pipe++;
80
81 while (seqp != hctx->ccid2hctx_seqt) {
82 struct ccid2_seq *prev;
83
84 prev = seqp->ccid2s_prev;
85 len++;
86 if (!prev->ccid2s_acked)
87 pipe++;
88
89 /* packets are sent sequentially */
90 BUG_ON(seqp->ccid2s_seq <= prev->ccid2s_seq);
91 BUG_ON(seqp->ccid2s_sent < prev->ccid2s_sent);
92 BUG_ON(len > ccid2_seq_len);
93
94 seqp = prev;
95 }
96 }
97
98 BUG_ON(pipe != hctx->ccid2hctx_pipe);
99 ccid2_pr_debug("len of chain=%d\n", len);
100
101 do {
102 seqp = seqp->ccid2s_prev;
103 len++;
104 BUG_ON(len > ccid2_seq_len);
105 } while(seqp != hctx->ccid2hctx_seqh);
106
107 BUG_ON(len != ccid2_seq_len);
108 ccid2_pr_debug("total len=%d\n", len);
109}
110#else
111#define ccid2_hc_tx_check_sanity(hctx) do {} while (0)
112#endif
113
114static int ccid2_hc_tx_send_packet(struct sock *sk,
115 struct sk_buff *skb, int len)
116{
117 struct ccid2_hc_tx_sock *hctx;
118
119 switch (DCCP_SKB_CB(skb)->dccpd_type) {
120 case 0: /* XXX data packets from userland come through like this */
121 case DCCP_PKT_DATA:
122 case DCCP_PKT_DATAACK:
123 break;
124 /* No congestion control on other packets */
125 default:
126 return 0;
127 }
128
129 hctx = ccid2_hc_tx_sk(sk);
130
131 ccid2_pr_debug("pipe=%d cwnd=%d\n", hctx->ccid2hctx_pipe,
132 hctx->ccid2hctx_cwnd);
133
134 if (hctx->ccid2hctx_pipe < hctx->ccid2hctx_cwnd) {
135 /* OK we can send... make sure previous packet was sent off */
136 if (!hctx->ccid2hctx_sendwait) {
137 hctx->ccid2hctx_sendwait = 1;
138 return 0;
139 }
140 }
141
142 return 100; /* XXX */
143}
144
145static void ccid2_change_l_ack_ratio(struct sock *sk, int val)
146{
147 struct dccp_sock *dp = dccp_sk(sk);
148 /*
149 * XXX I don't really agree with val != 2. If cwnd is 1, ack ratio
150 * should be 1... it shouldn't be allowed to become 2.
151 * -sorbo.
152 */
153 if (val != 2) {
154 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
155 int max = hctx->ccid2hctx_cwnd / 2;
156
157 /* round up */
158 if (hctx->ccid2hctx_cwnd & 1)
159 max++;
160
161 if (val > max)
162 val = max;
163 }
164
165 ccid2_pr_debug("changing local ack ratio to %d\n", val);
166 WARN_ON(val <= 0);
167 dp->dccps_l_ack_ratio = val;
168}
169
170static void ccid2_change_cwnd(struct sock *sk, int val)
171{
172 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
173
174 if (val == 0)
175 val = 1;
176
177 /* XXX do we need to change ack ratio? */
178 ccid2_pr_debug("change cwnd to %d\n", val);
179
180 BUG_ON(val < 1);
181 hctx->ccid2hctx_cwnd = val;
182}
183
184static void ccid2_start_rto_timer(struct sock *sk);
185
186static void ccid2_hc_tx_rto_expire(unsigned long data)
187{
188 struct sock *sk = (struct sock *)data;
189 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
190 long s;
191
192 /* XXX I don't think i'm locking correctly
193 * -sorbo.
194 */
195 bh_lock_sock(sk);
196 if (sock_owned_by_user(sk)) {
197 sk_reset_timer(sk, &hctx->ccid2hctx_rtotimer,
198 jiffies + HZ / 5);
199 goto out;
200 }
201
202 ccid2_pr_debug("RTO_EXPIRE\n");
203
204 ccid2_hc_tx_check_sanity(hctx);
205
206 /* back-off timer */
207 hctx->ccid2hctx_rto <<= 1;
208
209 s = hctx->ccid2hctx_rto / HZ;
210 if (s > 60)
211 hctx->ccid2hctx_rto = 60 * HZ;
212
213 ccid2_start_rto_timer(sk);
214
215 /* adjust pipe, cwnd etc */
216 hctx->ccid2hctx_pipe = 0;
217 hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd >> 1;
218 if (hctx->ccid2hctx_ssthresh < 2)
219 hctx->ccid2hctx_ssthresh = 2;
220 ccid2_change_cwnd(sk, 1);
221
222 /* clear state about stuff we sent */
223 hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh;
224 hctx->ccid2hctx_ssacks = 0;
225 hctx->ccid2hctx_acks = 0;
226 hctx->ccid2hctx_sent = 0;
227
228 /* clear ack ratio state. */
229 hctx->ccid2hctx_arsent = 0;
230 hctx->ccid2hctx_ackloss = 0;
231 hctx->ccid2hctx_rpseq = 0;
232 hctx->ccid2hctx_rpdupack = -1;
233 ccid2_change_l_ack_ratio(sk, 1);
234 ccid2_hc_tx_check_sanity(hctx);
235out:
236 bh_unlock_sock(sk);
Andrea Bittau77ff72d2006-03-20 17:57:52 -0800237 sock_put(sk);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800238}
239
240static void ccid2_start_rto_timer(struct sock *sk)
241{
242 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
243
244 ccid2_pr_debug("setting RTO timeout=%ld\n", hctx->ccid2hctx_rto);
245
246 BUG_ON(timer_pending(&hctx->ccid2hctx_rtotimer));
247 sk_reset_timer(sk, &hctx->ccid2hctx_rtotimer,
248 jiffies + hctx->ccid2hctx_rto);
249}
250
251static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len)
252{
253 struct dccp_sock *dp = dccp_sk(sk);
254 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
255 u64 seq;
256
257 ccid2_hc_tx_check_sanity(hctx);
258
259 BUG_ON(!hctx->ccid2hctx_sendwait);
260 hctx->ccid2hctx_sendwait = 0;
261 hctx->ccid2hctx_pipe++;
262 BUG_ON(hctx->ccid2hctx_pipe < 0);
263
264 /* There is an issue. What if another packet is sent between
265 * packet_send() and packet_sent(). Then the sequence number would be
266 * wrong.
267 * -sorbo.
268 */
269 seq = dp->dccps_gss;
270
271 hctx->ccid2hctx_seqh->ccid2s_seq = seq;
272 hctx->ccid2hctx_seqh->ccid2s_acked = 0;
273 hctx->ccid2hctx_seqh->ccid2s_sent = jiffies;
274 hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqh->ccid2s_next;
275
276 ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->ccid2hctx_cwnd,
277 hctx->ccid2hctx_pipe);
278
279 if (hctx->ccid2hctx_seqh == hctx->ccid2hctx_seqt) {
280 /* XXX allocate more space */
281 WARN_ON(1);
282 }
283
284 hctx->ccid2hctx_sent++;
285
286 /* Ack Ratio. Need to maintain a concept of how many windows we sent */
287 hctx->ccid2hctx_arsent++;
288 /* We had an ack loss in this window... */
289 if (hctx->ccid2hctx_ackloss) {
290 if (hctx->ccid2hctx_arsent >= hctx->ccid2hctx_cwnd) {
291 hctx->ccid2hctx_arsent = 0;
292 hctx->ccid2hctx_ackloss = 0;
293 }
294 }
295 /* No acks lost up to now... */
296 else {
297 /* decrease ack ratio if enough packets were sent */
298 if (dp->dccps_l_ack_ratio > 1) {
299 /* XXX don't calculate denominator each time */
300 int denom;
301
302 denom = dp->dccps_l_ack_ratio * dp->dccps_l_ack_ratio -
303 dp->dccps_l_ack_ratio;
304 denom = hctx->ccid2hctx_cwnd * hctx->ccid2hctx_cwnd / denom;
305
306 if (hctx->ccid2hctx_arsent >= denom) {
307 ccid2_change_l_ack_ratio(sk, dp->dccps_l_ack_ratio - 1);
308 hctx->ccid2hctx_arsent = 0;
309 }
310 }
311 /* we can't increase ack ratio further [1] */
312 else {
313 hctx->ccid2hctx_arsent = 0; /* or maybe set it to cwnd*/
314 }
315 }
316
317 /* setup RTO timer */
318 if (!timer_pending(&hctx->ccid2hctx_rtotimer)) {
319 ccid2_start_rto_timer(sk);
320 }
321#ifdef CCID2_DEBUG
322 ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe);
323 ccid2_pr_debug("Sent: seq=%llu\n", seq);
324 do {
325 struct ccid2_seq *seqp = hctx->ccid2hctx_seqt;
326
327 while (seqp != hctx->ccid2hctx_seqh) {
328 ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n",
329 seqp->ccid2s_seq, seqp->ccid2s_acked,
330 seqp->ccid2s_sent);
331 seqp = seqp->ccid2s_next;
332 }
333 } while(0);
334 ccid2_pr_debug("=========\n");
335 ccid2_hc_tx_check_sanity(hctx);
336#endif
337}
338
339/* XXX Lame code duplication!
340 * returns -1 if none was found.
341 * else returns the next offset to use in the function call.
342 */
343static int ccid2_ackvector(struct sock *sk, struct sk_buff *skb, int offset,
344 unsigned char **vec, unsigned char *veclen)
345{
346 const struct dccp_hdr *dh = dccp_hdr(skb);
347 unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);
348 unsigned char *opt_ptr;
349 const unsigned char *opt_end = (unsigned char *)dh +
350 (dh->dccph_doff * 4);
351 unsigned char opt, len;
352 unsigned char *value;
353
354 BUG_ON(offset < 0);
355 options += offset;
356 opt_ptr = options;
357 if (opt_ptr >= opt_end)
358 return -1;
359
360 while (opt_ptr != opt_end) {
361 opt = *opt_ptr++;
362 len = 0;
363 value = NULL;
364
365 /* Check if this isn't a single byte option */
366 if (opt > DCCPO_MAX_RESERVED) {
367 if (opt_ptr == opt_end)
368 goto out_invalid_option;
369
370 len = *opt_ptr++;
371 if (len < 3)
372 goto out_invalid_option;
373 /*
374 * Remove the type and len fields, leaving
375 * just the value size
376 */
377 len -= 2;
378 value = opt_ptr;
379 opt_ptr += len;
380
381 if (opt_ptr > opt_end)
382 goto out_invalid_option;
383 }
384
385 switch (opt) {
386 case DCCPO_ACK_VECTOR_0:
387 case DCCPO_ACK_VECTOR_1:
388 *vec = value;
389 *veclen = len;
390 return offset + (opt_ptr - options);
391 break;
392 }
393 }
394
395 return -1;
396
397out_invalid_option:
398 BUG_ON(1); /* should never happen... options were previously parsed ! */
399 return -1;
400}
401
Andrea Bittau77ff72d2006-03-20 17:57:52 -0800402static void ccid2_hc_tx_kill_rto_timer(struct sock *sk)
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800403{
Andrea Bittau77ff72d2006-03-20 17:57:52 -0800404 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
405
406 sk_stop_timer(sk, &hctx->ccid2hctx_rtotimer);
407 ccid2_pr_debug("deleted RTO timer\n");
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800408}
409
410static inline void ccid2_new_ack(struct sock *sk,
411 struct ccid2_seq *seqp,
412 unsigned int *maxincr)
413{
414 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
415
416 /* slow start */
417 if (hctx->ccid2hctx_cwnd < hctx->ccid2hctx_ssthresh) {
418 hctx->ccid2hctx_acks = 0;
419
420 /* We can increase cwnd at most maxincr [ack_ratio/2] */
421 if (*maxincr) {
422 /* increase every 2 acks */
423 hctx->ccid2hctx_ssacks++;
424 if (hctx->ccid2hctx_ssacks == 2) {
425 ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd + 1);
426 hctx->ccid2hctx_ssacks = 0;
427 *maxincr = *maxincr - 1;
428 }
429 }
430 /* increased cwnd enough for this single ack */
431 else {
432 hctx->ccid2hctx_ssacks = 0;
433 }
434 }
435 else {
436 hctx->ccid2hctx_ssacks = 0;
437 hctx->ccid2hctx_acks++;
438
439 if (hctx->ccid2hctx_acks >= hctx->ccid2hctx_cwnd) {
440 ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd + 1);
441 hctx->ccid2hctx_acks = 0;
442 }
443 }
444
445 /* update RTO */
446 if (hctx->ccid2hctx_srtt == -1 ||
447 (jiffies - hctx->ccid2hctx_lastrtt) >= hctx->ccid2hctx_srtt) {
448 unsigned long r = jiffies - seqp->ccid2s_sent;
449 int s;
450
451 /* first measurement */
452 if (hctx->ccid2hctx_srtt == -1) {
453 ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n",
454 r, jiffies, seqp->ccid2s_seq);
455 hctx->ccid2hctx_srtt = r;
456 hctx->ccid2hctx_rttvar = r >> 1;
457 }
458 else {
459 /* RTTVAR */
460 long tmp = hctx->ccid2hctx_srtt - r;
461 if (tmp < 0)
462 tmp *= -1;
463
464 tmp >>= 2;
465 hctx->ccid2hctx_rttvar *= 3;
466 hctx->ccid2hctx_rttvar >>= 2;
467 hctx->ccid2hctx_rttvar += tmp;
468
469 /* SRTT */
470 hctx->ccid2hctx_srtt *= 7;
471 hctx->ccid2hctx_srtt >>= 3;
472 tmp = r >> 3;
473 hctx->ccid2hctx_srtt += tmp;
474 }
475 s = hctx->ccid2hctx_rttvar << 2;
476 /* clock granularity is 1 when based on jiffies */
477 if (!s)
478 s = 1;
479 hctx->ccid2hctx_rto = hctx->ccid2hctx_srtt + s;
480
481 /* must be at least a second */
482 s = hctx->ccid2hctx_rto / HZ;
483 /* DCCP doesn't require this [but I like it cuz my code sux] */
484#if 1
485 if (s < 1)
486 hctx->ccid2hctx_rto = HZ;
487#endif
488 /* max 60 seconds */
489 if (s > 60)
490 hctx->ccid2hctx_rto = HZ * 60;
491
492 hctx->ccid2hctx_lastrtt = jiffies;
493
494 ccid2_pr_debug("srtt: %ld rttvar: %ld rto: %ld (HZ=%d) R=%lu\n",
495 hctx->ccid2hctx_srtt, hctx->ccid2hctx_rttvar,
496 hctx->ccid2hctx_rto, HZ, r);
497 hctx->ccid2hctx_sent = 0;
498 }
499
500 /* we got a new ack, so re-start RTO timer */
Andrea Bittau77ff72d2006-03-20 17:57:52 -0800501 ccid2_hc_tx_kill_rto_timer(sk);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800502 ccid2_start_rto_timer(sk);
503}
504
Andrea Bittau77ff72d2006-03-20 17:57:52 -0800505static void ccid2_hc_tx_dec_pipe(struct sock *sk)
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800506{
Andrea Bittau77ff72d2006-03-20 17:57:52 -0800507 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
508
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800509 hctx->ccid2hctx_pipe--;
510 BUG_ON(hctx->ccid2hctx_pipe < 0);
511
512 if (hctx->ccid2hctx_pipe == 0)
Andrea Bittau77ff72d2006-03-20 17:57:52 -0800513 ccid2_hc_tx_kill_rto_timer(sk);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800514}
515
516static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
517{
518 struct dccp_sock *dp = dccp_sk(sk);
519 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
520 u64 ackno, seqno;
521 struct ccid2_seq *seqp;
522 unsigned char *vector;
523 unsigned char veclen;
524 int offset = 0;
525 int done = 0;
526 int loss = 0;
527 unsigned int maxincr = 0;
528
529 ccid2_hc_tx_check_sanity(hctx);
530 /* check reverse path congestion */
531 seqno = DCCP_SKB_CB(skb)->dccpd_seq;
532
533 /* XXX this whole "algorithm" is broken. Need to fix it to keep track
534 * of the seqnos of the dupacks so that rpseq and rpdupack are correct
535 * -sorbo.
536 */
537 /* need to bootstrap */
538 if (hctx->ccid2hctx_rpdupack == -1) {
539 hctx->ccid2hctx_rpdupack = 0;
540 hctx->ccid2hctx_rpseq = seqno;
541 }
542 else {
543 /* check if packet is consecutive */
544 if ((hctx->ccid2hctx_rpseq + 1) == seqno) {
545 hctx->ccid2hctx_rpseq++;
546 }
547 /* it's a later packet */
548 else if (after48(seqno, hctx->ccid2hctx_rpseq)) {
549 hctx->ccid2hctx_rpdupack++;
550
551 /* check if we got enough dupacks */
552 if (hctx->ccid2hctx_rpdupack >=
553 hctx->ccid2hctx_numdupack) {
554
555 hctx->ccid2hctx_rpdupack = -1; /* XXX lame */
556 hctx->ccid2hctx_rpseq = 0;
557
558 ccid2_change_l_ack_ratio(sk, dp->dccps_l_ack_ratio << 1);
559 }
560 }
561 }
562
563 /* check forward path congestion */
564 /* still didn't send out new data packets */
565 if (hctx->ccid2hctx_seqh == hctx->ccid2hctx_seqt)
566 return;
567
568 switch (DCCP_SKB_CB(skb)->dccpd_type) {
569 case DCCP_PKT_ACK:
570 case DCCP_PKT_DATAACK:
571 break;
572
573 default:
574 return;
575 }
576
577 ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq;
578 seqp = hctx->ccid2hctx_seqh->ccid2s_prev;
579
580 /* If in slow-start, cwnd can increase at most Ack Ratio / 2 packets for
581 * this single ack. I round up.
582 * -sorbo.
583 */
584 maxincr = dp->dccps_l_ack_ratio >> 1;
585 maxincr++;
586
587 /* go through all ack vectors */
588 while ((offset = ccid2_ackvector(sk, skb, offset,
589 &vector, &veclen)) != -1) {
590 /* go through this ack vector */
591 while (veclen--) {
592 const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;
593 u64 ackno_end_rl;
594
595 dccp_set_seqno(&ackno_end_rl, ackno - rl);
596 ccid2_pr_debug("ackvec start:%llu end:%llu\n", ackno,
597 ackno_end_rl);
598 /* if the seqno we are analyzing is larger than the
599 * current ackno, then move towards the tail of our
600 * seqnos.
601 */
602 while (after48(seqp->ccid2s_seq, ackno)) {
603 if (seqp == hctx->ccid2hctx_seqt) {
604 done = 1;
605 break;
606 }
607 seqp = seqp->ccid2s_prev;
608 }
609 if (done)
610 break;
611
612 /* check all seqnos in the range of the vector
613 * run length
614 */
615 while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) {
616 const u8 state = (*vector &
617 DCCP_ACKVEC_STATE_MASK) >> 6;
618
619 /* new packet received or marked */
620 if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED &&
621 !seqp->ccid2s_acked) {
622 if (state ==
623 DCCP_ACKVEC_STATE_ECN_MARKED) {
624 loss = 1;
625 }
626 else {
627 ccid2_new_ack(sk, seqp,
628 &maxincr);
629 }
630
631 seqp->ccid2s_acked = 1;
632 ccid2_pr_debug("Got ack for %llu\n",
633 seqp->ccid2s_seq);
Andrea Bittau77ff72d2006-03-20 17:57:52 -0800634 ccid2_hc_tx_dec_pipe(sk);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800635 }
636 if (seqp == hctx->ccid2hctx_seqt) {
637 done = 1;
638 break;
639 }
640 seqp = seqp->ccid2s_next;
641 }
642 if (done)
643 break;
644
645
646 dccp_set_seqno(&ackno, ackno_end_rl - 1);
647 vector++;
648 }
649 if (done)
650 break;
651 }
652
653 /* The state about what is acked should be correct now
654 * Check for NUMDUPACK
655 */
656 seqp = hctx->ccid2hctx_seqh->ccid2s_prev;
657 done = 0;
658 while (1) {
659 if (seqp->ccid2s_acked) {
660 done++;
661 if (done == hctx->ccid2hctx_numdupack) {
662 break;
663 }
664 }
665 if (seqp == hctx->ccid2hctx_seqt) {
666 break;
667 }
668 seqp = seqp->ccid2s_prev;
669 }
670
671 /* If there are at least 3 acknowledgements, anything unacknowledged
672 * below the last sequence number is considered lost
673 */
674 if (done == hctx->ccid2hctx_numdupack) {
675 struct ccid2_seq *last_acked = seqp;
676
677 /* check for lost packets */
678 while (1) {
679 if (!seqp->ccid2s_acked) {
680 loss = 1;
Andrea Bittau77ff72d2006-03-20 17:57:52 -0800681 ccid2_hc_tx_dec_pipe(sk);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800682 }
683 if (seqp == hctx->ccid2hctx_seqt)
684 break;
685 seqp = seqp->ccid2s_prev;
686 }
687
688 hctx->ccid2hctx_seqt = last_acked;
689 }
690
691 /* trim acked packets in tail */
692 while (hctx->ccid2hctx_seqt != hctx->ccid2hctx_seqh) {
693 if (!hctx->ccid2hctx_seqt->ccid2s_acked)
694 break;
695
696 hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqt->ccid2s_next;
697 }
698
699 if (loss) {
700 /* XXX do bit shifts guarantee a 0 as the new bit? */
701 ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd >> 1);
702 hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd;
703 if (hctx->ccid2hctx_ssthresh < 2)
704 hctx->ccid2hctx_ssthresh = 2;
705 }
706
707 ccid2_hc_tx_check_sanity(hctx);
708}
709
710static int ccid2_hc_tx_init(struct sock *sk)
711{
712 struct dccp_sock *dp = dccp_sk(sk);
713 struct ccid2_hc_tx_sock *hctx;
714 int seqcount = ccid2_seq_len;
715 int i;
716
717 dp->dccps_hc_tx_ccid_private = kzalloc(sizeof(*hctx), gfp_any());
718 if (dp->dccps_hc_tx_ccid_private == NULL)
719 return -ENOMEM;
720
721 hctx = ccid2_hc_tx_sk(sk);
722
723 /* XXX init variables with proper values */
724 hctx->ccid2hctx_cwnd = 1;
725 hctx->ccid2hctx_ssthresh = 10;
726 hctx->ccid2hctx_numdupack = 3;
727
728 /* XXX init ~ to window size... */
729 hctx->ccid2hctx_seqbuf = kmalloc(sizeof(*hctx->ccid2hctx_seqbuf) *
730 seqcount, gfp_any());
731 if (hctx->ccid2hctx_seqbuf == NULL) {
732 kfree(dp->dccps_hc_tx_ccid_private);
733 dp->dccps_hc_tx_ccid_private = NULL;
734 return -ENOMEM;
735 }
736 for (i = 0; i < (seqcount - 1); i++) {
737 hctx->ccid2hctx_seqbuf[i].ccid2s_next =
738 &hctx->ccid2hctx_seqbuf[i + 1];
739 hctx->ccid2hctx_seqbuf[i + 1].ccid2s_prev =
740 &hctx->ccid2hctx_seqbuf[i];
741 }
742 hctx->ccid2hctx_seqbuf[seqcount - 1].ccid2s_next =
743 hctx->ccid2hctx_seqbuf;
744 hctx->ccid2hctx_seqbuf->ccid2s_prev =
745 &hctx->ccid2hctx_seqbuf[seqcount - 1];
746
747 hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqbuf;
748 hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh;
749 hctx->ccid2hctx_sent = 0;
750 hctx->ccid2hctx_rto = 3 * HZ;
751 hctx->ccid2hctx_srtt = -1;
752 hctx->ccid2hctx_rttvar = -1;
753 hctx->ccid2hctx_lastrtt = 0;
754 hctx->ccid2hctx_rpdupack = -1;
755
756 hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire;
757 hctx->ccid2hctx_rtotimer.data = (unsigned long)sk;
758 init_timer(&hctx->ccid2hctx_rtotimer);
759
760 ccid2_hc_tx_check_sanity(hctx);
761 return 0;
762}
763
764static void ccid2_hc_tx_exit(struct sock *sk)
765{
766 struct dccp_sock *dp = dccp_sk(sk);
Andrea Bittau77ff72d2006-03-20 17:57:52 -0800767 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800768
Andrea Bittau77ff72d2006-03-20 17:57:52 -0800769 ccid2_hc_tx_kill_rto_timer(sk);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800770
771 kfree(hctx->ccid2hctx_seqbuf);
772
773 kfree(dp->dccps_hc_tx_ccid_private);
774 dp->dccps_hc_tx_ccid_private = NULL;
775}
776
777static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
778{
779 const struct dccp_sock *dp = dccp_sk(sk);
780 struct ccid2_hc_rx_sock *hcrx = ccid2_hc_rx_sk(sk);
781
782 switch (DCCP_SKB_CB(skb)->dccpd_type) {
783 case DCCP_PKT_DATA:
784 case DCCP_PKT_DATAACK:
785 hcrx->ccid2hcrx_data++;
786 if (hcrx->ccid2hcrx_data >= dp->dccps_r_ack_ratio) {
787 dccp_send_ack(sk);
788 hcrx->ccid2hcrx_data = 0;
789 }
790 break;
791 }
792}
793
794static int ccid2_hc_rx_init(struct sock *sk)
795{
796 struct dccp_sock *dp = dccp_sk(sk);
797 dp->dccps_hc_rx_ccid_private = kzalloc(sizeof(struct ccid2_hc_rx_sock),
798 gfp_any());
799 return dp->dccps_hc_rx_ccid_private == NULL ? -ENOMEM : 0;
800}
801
802static void ccid2_hc_rx_exit(struct sock *sk)
803{
804 struct dccp_sock *dp = dccp_sk(sk);
805
806 kfree(dp->dccps_hc_rx_ccid_private);
807 dp->dccps_hc_rx_ccid_private = NULL;
808}
809
810static struct ccid ccid2 = {
811 .ccid_id = 2,
812 .ccid_name = "ccid2",
813 .ccid_owner = THIS_MODULE,
814 .ccid_hc_tx_init = ccid2_hc_tx_init,
815 .ccid_hc_tx_exit = ccid2_hc_tx_exit,
816 .ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet,
817 .ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent,
818 .ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv,
819 .ccid_hc_rx_init = ccid2_hc_rx_init,
820 .ccid_hc_rx_exit = ccid2_hc_rx_exit,
821 .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv,
822};
823
824module_param(ccid2_debug, int, 0444);
825MODULE_PARM_DESC(ccid2_debug, "Enable debug messages");
826
827static __init int ccid2_module_init(void)
828{
829 return ccid_register(&ccid2);
830}
831module_init(ccid2_module_init);
832
833static __exit void ccid2_module_exit(void)
834{
835 ccid_unregister(&ccid2);
836}
837module_exit(ccid2_module_exit);
838
839MODULE_AUTHOR("Andrea Bittau <a.bittau@cs.ucl.ac.uk>");
840MODULE_DESCRIPTION("DCCP TCP CCID2 CCID");
841MODULE_LICENSE("GPL");
842MODULE_ALIAS("net-dccp-ccid-2");