ccid2.c revision ff49e27089ec363b7fc3849504e0435d447ab18a
1/*
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 RFC 4341
27 */
28#include "../feat.h"
29#include "../ccid.h"
30#include "../dccp.h"
31#include "ccid2.h"
32
33
34#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
35static int ccid2_debug;
36#define ccid2_pr_debug(format, a...)	DCCP_PR_DEBUG(ccid2_debug, format, ##a)
37
38static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx)
39{
40	int len = 0;
41	int pipe = 0;
42	struct ccid2_seq *seqp = hctx->seqh;
43
44	/* there is data in the chain */
45	if (seqp != hctx->seqt) {
46		seqp = seqp->ccid2s_prev;
47		len++;
48		if (!seqp->ccid2s_acked)
49			pipe++;
50
51		while (seqp != hctx->seqt) {
52			struct ccid2_seq *prev = seqp->ccid2s_prev;
53
54			len++;
55			if (!prev->ccid2s_acked)
56				pipe++;
57
58			/* packets are sent sequentially */
59			BUG_ON(dccp_delta_seqno(seqp->ccid2s_seq,
60						prev->ccid2s_seq ) >= 0);
61			BUG_ON(time_before(seqp->ccid2s_sent,
62					   prev->ccid2s_sent));
63
64			seqp = prev;
65		}
66	}
67
68	BUG_ON(pipe != hctx->pipe);
69	ccid2_pr_debug("len of chain=%d\n", len);
70
71	do {
72		seqp = seqp->ccid2s_prev;
73		len++;
74	} while (seqp != hctx->seqh);
75
76	ccid2_pr_debug("total len=%d\n", len);
77	BUG_ON(len != hctx->seqbufc * CCID2_SEQBUF_LEN);
78}
79#else
80#define ccid2_pr_debug(format, a...)
81#define ccid2_hc_tx_check_sanity(hctx)
82#endif
83
84static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx)
85{
86	struct ccid2_seq *seqp;
87	int i;
88
89	/* check if we have space to preserve the pointer to the buffer */
90	if (hctx->seqbufc >= sizeof(hctx->seqbuf) / sizeof(struct ccid2_seq *))
91		return -ENOMEM;
92
93	/* allocate buffer and initialize linked list */
94	seqp = kmalloc(CCID2_SEQBUF_LEN * sizeof(struct ccid2_seq), gfp_any());
95	if (seqp == NULL)
96		return -ENOMEM;
97
98	for (i = 0; i < (CCID2_SEQBUF_LEN - 1); i++) {
99		seqp[i].ccid2s_next = &seqp[i + 1];
100		seqp[i + 1].ccid2s_prev = &seqp[i];
101	}
102	seqp[CCID2_SEQBUF_LEN - 1].ccid2s_next = seqp;
103	seqp->ccid2s_prev = &seqp[CCID2_SEQBUF_LEN - 1];
104
105	/* This is the first allocation.  Initiate the head and tail.  */
106	if (hctx->seqbufc == 0)
107		hctx->seqh = hctx->seqt = seqp;
108	else {
109		/* link the existing list with the one we just created */
110		hctx->seqh->ccid2s_next = seqp;
111		seqp->ccid2s_prev = hctx->seqh;
112
113		hctx->seqt->ccid2s_prev = &seqp[CCID2_SEQBUF_LEN - 1];
114		seqp[CCID2_SEQBUF_LEN - 1].ccid2s_next = hctx->seqt;
115	}
116
117	/* store the original pointer to the buffer so we can free it */
118	hctx->seqbuf[hctx->seqbufc] = seqp;
119	hctx->seqbufc++;
120
121	return 0;
122}
123
124static int ccid2_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
125{
126	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
127
128	if (hctx->pipe < hctx->cwnd)
129		return 0;
130
131	return 1; /* XXX CCID should dequeue when ready instead of polling */
132}
133
134static void ccid2_change_l_ack_ratio(struct sock *sk, u32 val)
135{
136	struct dccp_sock *dp = dccp_sk(sk);
137	u32 max_ratio = DIV_ROUND_UP(ccid2_hc_tx_sk(sk)->cwnd, 2);
138
139	/*
140	 * Ensure that Ack Ratio does not exceed ceil(cwnd/2), which is (2) from
141	 * RFC 4341, 6.1.2. We ignore the statement that Ack Ratio 2 is always
142	 * acceptable since this causes starvation/deadlock whenever cwnd < 2.
143	 * The same problem arises when Ack Ratio is 0 (ie. Ack Ratio disabled).
144	 */
145	if (val == 0 || val > max_ratio) {
146		DCCP_WARN("Limiting Ack Ratio (%u) to %u\n", val, max_ratio);
147		val = max_ratio;
148	}
149	if (val > DCCPF_ACK_RATIO_MAX)
150		val = DCCPF_ACK_RATIO_MAX;
151
152	if (val == dp->dccps_l_ack_ratio)
153		return;
154
155	ccid2_pr_debug("changing local ack ratio to %u\n", val);
156	dp->dccps_l_ack_ratio = val;
157}
158
159static void ccid2_change_srtt(struct ccid2_hc_tx_sock *hctx, long val)
160{
161	ccid2_pr_debug("change SRTT to %ld\n", val);
162	hctx->srtt = val;
163}
164
165static void ccid2_start_rto_timer(struct sock *sk);
166
167static void ccid2_hc_tx_rto_expire(unsigned long data)
168{
169	struct sock *sk = (struct sock *)data;
170	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
171	long s;
172
173	bh_lock_sock(sk);
174	if (sock_owned_by_user(sk)) {
175		sk_reset_timer(sk, &hctx->rtotimer, jiffies + HZ / 5);
176		goto out;
177	}
178
179	ccid2_pr_debug("RTO_EXPIRE\n");
180
181	ccid2_hc_tx_check_sanity(hctx);
182
183	/* back-off timer */
184	hctx->rto <<= 1;
185
186	s = hctx->rto / HZ;
187	if (s > 60)
188		hctx->rto = 60 * HZ;
189
190	ccid2_start_rto_timer(sk);
191
192	/* adjust pipe, cwnd etc */
193	hctx->ssthresh = hctx->cwnd / 2;
194	if (hctx->ssthresh < 2)
195		hctx->ssthresh = 2;
196	hctx->cwnd = 1;
197	hctx->pipe = 0;
198
199	/* clear state about stuff we sent */
200	hctx->seqt = hctx->seqh;
201	hctx->packets_acked = 0;
202
203	/* clear ack ratio state. */
204	hctx->rpseq    = 0;
205	hctx->rpdupack = -1;
206	ccid2_change_l_ack_ratio(sk, 1);
207	ccid2_hc_tx_check_sanity(hctx);
208out:
209	bh_unlock_sock(sk);
210	sock_put(sk);
211}
212
213static void ccid2_start_rto_timer(struct sock *sk)
214{
215	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
216
217	ccid2_pr_debug("setting RTO timeout=%ld\n", hctx->rto);
218
219	BUG_ON(timer_pending(&hctx->rtotimer));
220	sk_reset_timer(sk, &hctx->rtotimer,
221		       jiffies + hctx->rto);
222}
223
224static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len)
225{
226	struct dccp_sock *dp = dccp_sk(sk);
227	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
228	struct ccid2_seq *next;
229
230	hctx->pipe++;
231
232	hctx->seqh->ccid2s_seq   = dp->dccps_gss;
233	hctx->seqh->ccid2s_acked = 0;
234	hctx->seqh->ccid2s_sent  = jiffies;
235
236	next = hctx->seqh->ccid2s_next;
237	/* check if we need to alloc more space */
238	if (next == hctx->seqt) {
239		if (ccid2_hc_tx_alloc_seq(hctx)) {
240			DCCP_CRIT("packet history - out of memory!");
241			/* FIXME: find a more graceful way to bail out */
242			return;
243		}
244		next = hctx->seqh->ccid2s_next;
245		BUG_ON(next == hctx->seqt);
246	}
247	hctx->seqh = next;
248
249	ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->cwnd, hctx->pipe);
250
251	/*
252	 * FIXME: The code below is broken and the variables have been removed
253	 * from the socket struct. The `ackloss' variable was always set to 0,
254	 * and with arsent there are several problems:
255	 *  (i) it doesn't just count the number of Acks, but all sent packets;
256	 *  (ii) it is expressed in # of packets, not # of windows, so the
257	 *  comparison below uses the wrong formula: Appendix A of RFC 4341
258	 *  comes up with the number K = cwnd / (R^2 - R) of consecutive windows
259	 *  of data with no lost or marked Ack packets. If arsent were the # of
260	 *  consecutive Acks received without loss, then Ack Ratio needs to be
261	 *  decreased by 1 when
262	 *	      arsent >=  K * cwnd / R  =  cwnd^2 / (R^3 - R^2)
263	 *  where cwnd / R is the number of Acks received per window of data
264	 *  (cf. RFC 4341, App. A). The problems are that
265	 *  - arsent counts other packets as well;
266	 *  - the comparison uses a formula different from RFC 4341;
267	 *  - computing a cubic/quadratic equation each time is too complicated.
268	 *  Hence a different algorithm is needed.
269	 */
270#if 0
271	/* Ack Ratio.  Need to maintain a concept of how many windows we sent */
272	hctx->arsent++;
273	/* We had an ack loss in this window... */
274	if (hctx->ackloss) {
275		if (hctx->arsent >= hctx->cwnd) {
276			hctx->arsent  = 0;
277			hctx->ackloss = 0;
278		}
279	} else {
280		/* No acks lost up to now... */
281		/* decrease ack ratio if enough packets were sent */
282		if (dp->dccps_l_ack_ratio > 1) {
283			/* XXX don't calculate denominator each time */
284			int denom = dp->dccps_l_ack_ratio * dp->dccps_l_ack_ratio -
285				    dp->dccps_l_ack_ratio;
286
287			denom = hctx->cwnd * hctx->cwnd / denom;
288
289			if (hctx->arsent >= denom) {
290				ccid2_change_l_ack_ratio(sk, dp->dccps_l_ack_ratio - 1);
291				hctx->arsent = 0;
292			}
293		} else {
294			/* we can't increase ack ratio further [1] */
295			hctx->arsent = 0; /* or maybe set it to cwnd*/
296		}
297	}
298#endif
299
300	/* setup RTO timer */
301	if (!timer_pending(&hctx->rtotimer))
302		ccid2_start_rto_timer(sk);
303
304#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
305	do {
306		struct ccid2_seq *seqp = hctx->seqt;
307
308		while (seqp != hctx->seqh) {
309			ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n",
310				       (unsigned long long)seqp->ccid2s_seq,
311				       seqp->ccid2s_acked, seqp->ccid2s_sent);
312			seqp = seqp->ccid2s_next;
313		}
314	} while (0);
315	ccid2_pr_debug("=========\n");
316	ccid2_hc_tx_check_sanity(hctx);
317#endif
318}
319
320/* XXX Lame code duplication!
321 * returns -1 if none was found.
322 * else returns the next offset to use in the function call.
323 */
324static int ccid2_ackvector(struct sock *sk, struct sk_buff *skb, int offset,
325			   unsigned char **vec, unsigned char *veclen)
326{
327	const struct dccp_hdr *dh = dccp_hdr(skb);
328	unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);
329	unsigned char *opt_ptr;
330	const unsigned char *opt_end = (unsigned char *)dh +
331					(dh->dccph_doff * 4);
332	unsigned char opt, len;
333	unsigned char *value;
334
335	BUG_ON(offset < 0);
336	options += offset;
337	opt_ptr = options;
338	if (opt_ptr >= opt_end)
339		return -1;
340
341	while (opt_ptr != opt_end) {
342		opt   = *opt_ptr++;
343		len   = 0;
344		value = NULL;
345
346		/* Check if this isn't a single byte option */
347		if (opt > DCCPO_MAX_RESERVED) {
348			if (opt_ptr == opt_end)
349				goto out_invalid_option;
350
351			len = *opt_ptr++;
352			if (len < 3)
353				goto out_invalid_option;
354			/*
355			 * Remove the type and len fields, leaving
356			 * just the value size
357			 */
358			len     -= 2;
359			value   = opt_ptr;
360			opt_ptr += len;
361
362			if (opt_ptr > opt_end)
363				goto out_invalid_option;
364		}
365
366		switch (opt) {
367		case DCCPO_ACK_VECTOR_0:
368		case DCCPO_ACK_VECTOR_1:
369			*vec	= value;
370			*veclen = len;
371			return offset + (opt_ptr - options);
372		}
373	}
374
375	return -1;
376
377out_invalid_option:
378	DCCP_BUG("Invalid option - this should not happen (previous parsing)!");
379	return -1;
380}
381
382static void ccid2_hc_tx_kill_rto_timer(struct sock *sk)
383{
384	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
385
386	sk_stop_timer(sk, &hctx->rtotimer);
387	ccid2_pr_debug("deleted RTO timer\n");
388}
389
390static inline void ccid2_new_ack(struct sock *sk,
391				 struct ccid2_seq *seqp,
392				 unsigned int *maxincr)
393{
394	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
395
396	if (hctx->cwnd < hctx->ssthresh) {
397		if (*maxincr > 0 && ++hctx->packets_acked == 2) {
398			hctx->cwnd += 1;
399			*maxincr   -= 1;
400			hctx->packets_acked = 0;
401		}
402	} else if (++hctx->packets_acked >= hctx->cwnd) {
403			hctx->cwnd += 1;
404			hctx->packets_acked = 0;
405	}
406
407	/* update RTO */
408	if (hctx->srtt == -1 ||
409	    time_after(jiffies, hctx->lastrtt + hctx->srtt)) {
410		unsigned long r = (long)jiffies - (long)seqp->ccid2s_sent;
411		int s;
412
413		/* first measurement */
414		if (hctx->srtt == -1) {
415			ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n",
416				       r, jiffies,
417				       (unsigned long long)seqp->ccid2s_seq);
418			ccid2_change_srtt(hctx, r);
419			hctx->rttvar = r >> 1;
420		} else {
421			/* RTTVAR */
422			long tmp = hctx->srtt - r;
423			long srtt;
424
425			if (tmp < 0)
426				tmp *= -1;
427
428			tmp >>= 2;
429			hctx->rttvar *= 3;
430			hctx->rttvar >>= 2;
431			hctx->rttvar += tmp;
432
433			/* SRTT */
434			srtt = hctx->srtt;
435			srtt *= 7;
436			srtt >>= 3;
437			tmp = r >> 3;
438			srtt += tmp;
439			ccid2_change_srtt(hctx, srtt);
440		}
441		s = hctx->rttvar << 2;
442		/* clock granularity is 1 when based on jiffies */
443		if (!s)
444			s = 1;
445		hctx->rto = hctx->srtt + s;
446
447		/* must be at least a second */
448		s = hctx->rto / HZ;
449		/* DCCP doesn't require this [but I like it cuz my code sux] */
450#if 1
451		if (s < 1)
452			hctx->rto = HZ;
453#endif
454		/* max 60 seconds */
455		if (s > 60)
456			hctx->rto = HZ * 60;
457
458		hctx->lastrtt = jiffies;
459
460		ccid2_pr_debug("srtt: %ld rttvar: %ld rto: %ld (HZ=%d) R=%lu\n",
461			       hctx->srtt, hctx->rttvar,
462			       hctx->rto, HZ, r);
463	}
464
465	/* we got a new ack, so re-start RTO timer */
466	ccid2_hc_tx_kill_rto_timer(sk);
467	ccid2_start_rto_timer(sk);
468}
469
470static void ccid2_hc_tx_dec_pipe(struct sock *sk)
471{
472	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
473
474	if (hctx->pipe == 0)
475		DCCP_BUG("pipe == 0");
476	else
477		hctx->pipe--;
478
479	if (hctx->pipe == 0)
480		ccid2_hc_tx_kill_rto_timer(sk);
481}
482
483static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp)
484{
485	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
486
487	if (time_before(seqp->ccid2s_sent, hctx->last_cong)) {
488		ccid2_pr_debug("Multiple losses in an RTT---treating as one\n");
489		return;
490	}
491
492	hctx->last_cong = jiffies;
493
494	hctx->cwnd     = hctx->cwnd / 2 ? : 1U;
495	hctx->ssthresh = max(hctx->cwnd, 2U);
496
497	/* Avoid spurious timeouts resulting from Ack Ratio > cwnd */
498	if (dccp_sk(sk)->dccps_l_ack_ratio > hctx->cwnd)
499		ccid2_change_l_ack_ratio(sk, hctx->cwnd);
500}
501
502static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
503{
504	struct dccp_sock *dp = dccp_sk(sk);
505	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
506	u64 ackno, seqno;
507	struct ccid2_seq *seqp;
508	unsigned char *vector;
509	unsigned char veclen;
510	int offset = 0;
511	int done = 0;
512	unsigned int maxincr = 0;
513
514	ccid2_hc_tx_check_sanity(hctx);
515	/* check reverse path congestion */
516	seqno = DCCP_SKB_CB(skb)->dccpd_seq;
517
518	/* XXX this whole "algorithm" is broken.  Need to fix it to keep track
519	 * of the seqnos of the dupacks so that rpseq and rpdupack are correct
520	 * -sorbo.
521	 */
522	/* need to bootstrap */
523	if (hctx->rpdupack == -1) {
524		hctx->rpdupack = 0;
525		hctx->rpseq = seqno;
526	} else {
527		/* check if packet is consecutive */
528		if (dccp_delta_seqno(hctx->rpseq, seqno) == 1)
529			hctx->rpseq = seqno;
530		/* it's a later packet */
531		else if (after48(seqno, hctx->rpseq)) {
532			hctx->rpdupack++;
533
534			/* check if we got enough dupacks */
535			if (hctx->rpdupack >= NUMDUPACK) {
536				hctx->rpdupack = -1; /* XXX lame */
537				hctx->rpseq = 0;
538
539				ccid2_change_l_ack_ratio(sk, 2 * dp->dccps_l_ack_ratio);
540			}
541		}
542	}
543
544	/* check forward path congestion */
545	/* still didn't send out new data packets */
546	if (hctx->seqh == hctx->seqt)
547		return;
548
549	switch (DCCP_SKB_CB(skb)->dccpd_type) {
550	case DCCP_PKT_ACK:
551	case DCCP_PKT_DATAACK:
552		break;
553	default:
554		return;
555	}
556
557	ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq;
558	if (after48(ackno, hctx->high_ack))
559		hctx->high_ack = ackno;
560
561	seqp = hctx->seqt;
562	while (before48(seqp->ccid2s_seq, ackno)) {
563		seqp = seqp->ccid2s_next;
564		if (seqp == hctx->seqh) {
565			seqp = hctx->seqh->ccid2s_prev;
566			break;
567		}
568	}
569
570	/*
571	 * In slow-start, cwnd can increase up to a maximum of Ack Ratio/2
572	 * packets per acknowledgement. Rounding up avoids that cwnd is not
573	 * advanced when Ack Ratio is 1 and gives a slight edge otherwise.
574	 */
575	if (hctx->cwnd < hctx->ssthresh)
576		maxincr = DIV_ROUND_UP(dp->dccps_l_ack_ratio, 2);
577
578	/* go through all ack vectors */
579	while ((offset = ccid2_ackvector(sk, skb, offset,
580					 &vector, &veclen)) != -1) {
581		/* go through this ack vector */
582		while (veclen--) {
583			u64 ackno_end_rl = SUB48(ackno, dccp_ackvec_runlen(vector));
584
585			ccid2_pr_debug("ackvec start:%llu end:%llu\n",
586				       (unsigned long long)ackno,
587				       (unsigned long long)ackno_end_rl);
588			/* if the seqno we are analyzing is larger than the
589			 * current ackno, then move towards the tail of our
590			 * seqnos.
591			 */
592			while (after48(seqp->ccid2s_seq, ackno)) {
593				if (seqp == hctx->seqt) {
594					done = 1;
595					break;
596				}
597				seqp = seqp->ccid2s_prev;
598			}
599			if (done)
600				break;
601
602			/* check all seqnos in the range of the vector
603			 * run length
604			 */
605			while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) {
606				const u8 state = dccp_ackvec_state(vector);
607
608				/* new packet received or marked */
609				if (state != DCCPAV_NOT_RECEIVED &&
610				    !seqp->ccid2s_acked) {
611					if (state == DCCPAV_ECN_MARKED)
612						ccid2_congestion_event(sk,
613								       seqp);
614					else
615						ccid2_new_ack(sk, seqp,
616							      &maxincr);
617
618					seqp->ccid2s_acked = 1;
619					ccid2_pr_debug("Got ack for %llu\n",
620						       (unsigned long long)seqp->ccid2s_seq);
621					ccid2_hc_tx_dec_pipe(sk);
622				}
623				if (seqp == hctx->seqt) {
624					done = 1;
625					break;
626				}
627				seqp = seqp->ccid2s_prev;
628			}
629			if (done)
630				break;
631
632			ackno = SUB48(ackno_end_rl, 1);
633			vector++;
634		}
635		if (done)
636			break;
637	}
638
639	/* The state about what is acked should be correct now
640	 * Check for NUMDUPACK
641	 */
642	seqp = hctx->seqt;
643	while (before48(seqp->ccid2s_seq, hctx->high_ack)) {
644		seqp = seqp->ccid2s_next;
645		if (seqp == hctx->seqh) {
646			seqp = hctx->seqh->ccid2s_prev;
647			break;
648		}
649	}
650	done = 0;
651	while (1) {
652		if (seqp->ccid2s_acked) {
653			done++;
654			if (done == NUMDUPACK)
655				break;
656		}
657		if (seqp == hctx->seqt)
658			break;
659		seqp = seqp->ccid2s_prev;
660	}
661
662	/* If there are at least 3 acknowledgements, anything unacknowledged
663	 * below the last sequence number is considered lost
664	 */
665	if (done == NUMDUPACK) {
666		struct ccid2_seq *last_acked = seqp;
667
668		/* check for lost packets */
669		while (1) {
670			if (!seqp->ccid2s_acked) {
671				ccid2_pr_debug("Packet lost: %llu\n",
672					       (unsigned long long)seqp->ccid2s_seq);
673				/* XXX need to traverse from tail -> head in
674				 * order to detect multiple congestion events in
675				 * one ack vector.
676				 */
677				ccid2_congestion_event(sk, seqp);
678				ccid2_hc_tx_dec_pipe(sk);
679			}
680			if (seqp == hctx->seqt)
681				break;
682			seqp = seqp->ccid2s_prev;
683		}
684
685		hctx->seqt = last_acked;
686	}
687
688	/* trim acked packets in tail */
689	while (hctx->seqt != hctx->seqh) {
690		if (!hctx->seqt->ccid2s_acked)
691			break;
692
693		hctx->seqt = hctx->seqt->ccid2s_next;
694	}
695
696	ccid2_hc_tx_check_sanity(hctx);
697}
698
699static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
700{
701	struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid);
702	struct dccp_sock *dp = dccp_sk(sk);
703	u32 max_ratio;
704
705	/* RFC 4341, 5: initialise ssthresh to arbitrarily high (max) value */
706	hctx->ssthresh = ~0U;
707
708	/*
709	 * RFC 4341, 5: "The cwnd parameter is initialized to at most four
710	 * packets for new connections, following the rules from [RFC3390]".
711	 * We need to convert the bytes of RFC3390 into the packets of RFC 4341.
712	 */
713	hctx->cwnd = clamp(4380U / dp->dccps_mss_cache, 2U, 4U);
714
715	/* Make sure that Ack Ratio is enabled and within bounds. */
716	max_ratio = DIV_ROUND_UP(hctx->cwnd, 2);
717	if (dp->dccps_l_ack_ratio == 0 || dp->dccps_l_ack_ratio > max_ratio)
718		dp->dccps_l_ack_ratio = max_ratio;
719
720	/* XXX init ~ to window size... */
721	if (ccid2_hc_tx_alloc_seq(hctx))
722		return -ENOMEM;
723
724	hctx->rto	 = 3 * HZ;
725	ccid2_change_srtt(hctx, -1);
726	hctx->rttvar	= -1;
727	hctx->rpdupack  = -1;
728	hctx->last_cong = jiffies;
729	setup_timer(&hctx->rtotimer, ccid2_hc_tx_rto_expire, (unsigned long)sk);
730
731	ccid2_hc_tx_check_sanity(hctx);
732	return 0;
733}
734
735static void ccid2_hc_tx_exit(struct sock *sk)
736{
737	struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
738	int i;
739
740	ccid2_hc_tx_kill_rto_timer(sk);
741
742	for (i = 0; i < hctx->seqbufc; i++)
743		kfree(hctx->seqbuf[i]);
744	hctx->seqbufc = 0;
745}
746
747static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
748{
749	const struct dccp_sock *dp = dccp_sk(sk);
750	struct ccid2_hc_rx_sock *hcrx = ccid2_hc_rx_sk(sk);
751
752	switch (DCCP_SKB_CB(skb)->dccpd_type) {
753	case DCCP_PKT_DATA:
754	case DCCP_PKT_DATAACK:
755		hcrx->data++;
756		if (hcrx->data >= dp->dccps_r_ack_ratio) {
757			dccp_send_ack(sk);
758			hcrx->data = 0;
759		}
760		break;
761	}
762}
763
764static struct ccid_operations ccid2 = {
765	.ccid_id		= DCCPC_CCID2,
766	.ccid_name		= "TCP-like",
767	.ccid_owner		= THIS_MODULE,
768	.ccid_hc_tx_obj_size	= sizeof(struct ccid2_hc_tx_sock),
769	.ccid_hc_tx_init	= ccid2_hc_tx_init,
770	.ccid_hc_tx_exit	= ccid2_hc_tx_exit,
771	.ccid_hc_tx_send_packet	= ccid2_hc_tx_send_packet,
772	.ccid_hc_tx_packet_sent	= ccid2_hc_tx_packet_sent,
773	.ccid_hc_tx_packet_recv	= ccid2_hc_tx_packet_recv,
774	.ccid_hc_rx_obj_size	= sizeof(struct ccid2_hc_rx_sock),
775	.ccid_hc_rx_packet_recv	= ccid2_hc_rx_packet_recv,
776};
777
778#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
779module_param(ccid2_debug, bool, 0644);
780MODULE_PARM_DESC(ccid2_debug, "Enable debug messages");
781#endif
782
783static __init int ccid2_module_init(void)
784{
785	return ccid_register(&ccid2);
786}
787module_init(ccid2_module_init);
788
789static __exit void ccid2_module_exit(void)
790{
791	ccid_unregister(&ccid2);
792}
793module_exit(ccid2_module_exit);
794
795MODULE_AUTHOR("Andrea Bittau <a.bittau@cs.ucl.ac.uk>");
796MODULE_DESCRIPTION("DCCP TCP-Like (CCID2) CCID");
797MODULE_LICENSE("GPL");
798MODULE_ALIAS("net-dccp-ccid-2");
799