blob: f7f5069b1e8412413e2366e9c95dd02bf3ff05ce [file] [log] [blame]
Andrea Bittau2a91aa32006-03-20 17:41:47 -08001/*
Andrea Bittau2a91aa32006-03-20 17:41:47 -08002 * Copyright (c) 2005, 2006 Andrea Bittau <a.bittau@cs.ucl.ac.uk>
3 *
4 * Changes to meet Linux coding standards, and DCCP infrastructure fixes.
5 *
6 * Copyright (c) 2006 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23/*
Gerrit Renker0e64e942006-10-24 16:17:51 -070024 * This implementation should follow RFC 4341
Andrea Bittau2a91aa32006-03-20 17:41:47 -080025 */
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090026#include <linux/slab.h>
Gerrit Renkere8ef9672008-11-12 00:43:40 -080027#include "../feat.h"
Andrea Bittau2a91aa32006-03-20 17:41:47 -080028#include "../ccid.h"
29#include "../dccp.h"
30#include "ccid2.h"
31
Gerrit Renker84116712006-11-20 18:26:03 -020032
33#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
Andrea Bittau2a91aa32006-03-20 17:41:47 -080034static int ccid2_debug;
Gerrit Renker84116712006-11-20 18:26:03 -020035#define ccid2_pr_debug(format, a...) DCCP_PR_DEBUG(ccid2_debug, format, ##a)
Andrea Bittau2a91aa32006-03-20 17:41:47 -080036#else
Gerrit Renker84116712006-11-20 18:26:03 -020037#define ccid2_pr_debug(format, a...)
Andrea Bittau2a91aa32006-03-20 17:41:47 -080038#endif
39
Gerrit Renker77d2dd92009-10-05 00:53:12 +000040static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hc)
Andrea Bittau07978aa2006-09-19 13:13:37 -070041{
42 struct ccid2_seq *seqp;
43 int i;
44
45 /* check if we have space to preserve the pointer to the buffer */
Gerrit Renker77d2dd92009-10-05 00:53:12 +000046 if (hc->tx_seqbufc >= (sizeof(hc->tx_seqbuf) /
47 sizeof(struct ccid2_seq *)))
Andrea Bittau07978aa2006-09-19 13:13:37 -070048 return -ENOMEM;
49
50 /* allocate buffer and initialize linked list */
Gerrit Renkercd1f7d32007-10-04 14:41:00 -070051 seqp = kmalloc(CCID2_SEQBUF_LEN * sizeof(struct ccid2_seq), gfp_any());
Andrea Bittau07978aa2006-09-19 13:13:37 -070052 if (seqp == NULL)
53 return -ENOMEM;
54
Gerrit Renkercd1f7d32007-10-04 14:41:00 -070055 for (i = 0; i < (CCID2_SEQBUF_LEN - 1); i++) {
Andrea Bittau07978aa2006-09-19 13:13:37 -070056 seqp[i].ccid2s_next = &seqp[i + 1];
57 seqp[i + 1].ccid2s_prev = &seqp[i];
58 }
Gerrit Renkercd1f7d32007-10-04 14:41:00 -070059 seqp[CCID2_SEQBUF_LEN - 1].ccid2s_next = seqp;
60 seqp->ccid2s_prev = &seqp[CCID2_SEQBUF_LEN - 1];
Andrea Bittau07978aa2006-09-19 13:13:37 -070061
62 /* This is the first allocation. Initiate the head and tail. */
Gerrit Renker77d2dd92009-10-05 00:53:12 +000063 if (hc->tx_seqbufc == 0)
64 hc->tx_seqh = hc->tx_seqt = seqp;
Andrea Bittau07978aa2006-09-19 13:13:37 -070065 else {
66 /* link the existing list with the one we just created */
Gerrit Renker77d2dd92009-10-05 00:53:12 +000067 hc->tx_seqh->ccid2s_next = seqp;
68 seqp->ccid2s_prev = hc->tx_seqh;
Andrea Bittau07978aa2006-09-19 13:13:37 -070069
Gerrit Renker77d2dd92009-10-05 00:53:12 +000070 hc->tx_seqt->ccid2s_prev = &seqp[CCID2_SEQBUF_LEN - 1];
71 seqp[CCID2_SEQBUF_LEN - 1].ccid2s_next = hc->tx_seqt;
Andrea Bittau07978aa2006-09-19 13:13:37 -070072 }
73
74 /* store the original pointer to the buffer so we can free it */
Gerrit Renker77d2dd92009-10-05 00:53:12 +000075 hc->tx_seqbuf[hc->tx_seqbufc] = seqp;
76 hc->tx_seqbufc++;
Andrea Bittau07978aa2006-09-19 13:13:37 -070077
78 return 0;
79}
80
Gerrit Renker6b57c932006-11-28 19:55:06 -020081static int ccid2_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb)
Andrea Bittau2a91aa32006-03-20 17:41:47 -080082{
Gerrit Renker77d2dd92009-10-05 00:53:12 +000083 struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
Gerrit Renker410e27a2008-09-09 13:27:22 +020084
Gerrit Renker77d2dd92009-10-05 00:53:12 +000085 if (hc->tx_pipe < hc->tx_cwnd)
Gerrit Renker410e27a2008-09-09 13:27:22 +020086 return 0;
87
88 return 1; /* XXX CCID should dequeue when ready instead of polling */
Andrea Bittau2a91aa32006-03-20 17:41:47 -080089}
90
Gerrit Renkerdf054e12007-11-24 21:32:53 -020091static void ccid2_change_l_ack_ratio(struct sock *sk, u32 val)
Andrea Bittau2a91aa32006-03-20 17:41:47 -080092{
93 struct dccp_sock *dp = dccp_sk(sk);
Gerrit Renkerb1c00fe2009-10-05 00:53:10 +000094 u32 max_ratio = DIV_ROUND_UP(ccid2_hc_tx_sk(sk)->tx_cwnd, 2);
Gerrit Renkerd50ad162007-11-24 21:40:24 -020095
Andrea Bittau2a91aa32006-03-20 17:41:47 -080096 /*
Gerrit Renkerd50ad162007-11-24 21:40:24 -020097 * Ensure that Ack Ratio does not exceed ceil(cwnd/2), which is (2) from
98 * RFC 4341, 6.1.2. We ignore the statement that Ack Ratio 2 is always
99 * acceptable since this causes starvation/deadlock whenever cwnd < 2.
100 * The same problem arises when Ack Ratio is 0 (ie. Ack Ratio disabled).
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800101 */
Gerrit Renkerd50ad162007-11-24 21:40:24 -0200102 if (val == 0 || val > max_ratio) {
103 DCCP_WARN("Limiting Ack Ratio (%u) to %u\n", val, max_ratio);
104 val = max_ratio;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800105 }
Gerrit Renkere8ef9672008-11-12 00:43:40 -0800106 if (val > DCCPF_ACK_RATIO_MAX)
107 val = DCCPF_ACK_RATIO_MAX;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800108
Gerrit Renkerd50ad162007-11-24 21:40:24 -0200109 if (val == dp->dccps_l_ack_ratio)
110 return;
111
Gerrit Renkerdf054e12007-11-24 21:32:53 -0200112 ccid2_pr_debug("changing local ack ratio to %u\n", val);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800113 dp->dccps_l_ack_ratio = val;
114}
115
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000116static void ccid2_change_srtt(struct ccid2_hc_tx_sock *hc, long val)
Gerrit Renker410e27a2008-09-09 13:27:22 +0200117{
118 ccid2_pr_debug("change SRTT to %ld\n", val);
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000119 hc->tx_srtt = val;
Gerrit Renker410e27a2008-09-09 13:27:22 +0200120}
121
122static void ccid2_start_rto_timer(struct sock *sk);
123
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800124static void ccid2_hc_tx_rto_expire(unsigned long data)
125{
126 struct sock *sk = (struct sock *)data;
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000127 struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
Gerrit Renker410e27a2008-09-09 13:27:22 +0200128 long s;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800129
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800130 bh_lock_sock(sk);
131 if (sock_owned_by_user(sk)) {
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000132 sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + HZ / 5);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800133 goto out;
134 }
135
136 ccid2_pr_debug("RTO_EXPIRE\n");
137
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800138 /* back-off timer */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000139 hc->tx_rto <<= 1;
Gerrit Renker410e27a2008-09-09 13:27:22 +0200140
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000141 s = hc->tx_rto / HZ;
Gerrit Renker410e27a2008-09-09 13:27:22 +0200142 if (s > 60)
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000143 hc->tx_rto = 60 * HZ;
Gerrit Renker410e27a2008-09-09 13:27:22 +0200144
145 ccid2_start_rto_timer(sk);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800146
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800147 /* adjust pipe, cwnd etc */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000148 hc->tx_ssthresh = hc->tx_cwnd / 2;
149 if (hc->tx_ssthresh < 2)
150 hc->tx_ssthresh = 2;
Gerrit Renker67b67e32010-08-22 19:41:36 +0000151 hc->tx_cwnd = 1;
152 hc->tx_pipe = 0;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800153
154 /* clear state about stuff we sent */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000155 hc->tx_seqt = hc->tx_seqh;
156 hc->tx_packets_acked = 0;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800157
158 /* clear ack ratio state. */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000159 hc->tx_rpseq = 0;
160 hc->tx_rpdupack = -1;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800161 ccid2_change_l_ack_ratio(sk, 1);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800162out:
163 bh_unlock_sock(sk);
Andrea Bittau77ff72d2006-03-20 17:57:52 -0800164 sock_put(sk);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800165}
166
Gerrit Renker410e27a2008-09-09 13:27:22 +0200167static void ccid2_start_rto_timer(struct sock *sk)
168{
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000169 struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
Gerrit Renker410e27a2008-09-09 13:27:22 +0200170
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000171 ccid2_pr_debug("setting RTO timeout=%ld\n", hc->tx_rto);
Gerrit Renker410e27a2008-09-09 13:27:22 +0200172
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000173 BUG_ON(timer_pending(&hc->tx_rtotimer));
174 sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto);
Gerrit Renker410e27a2008-09-09 13:27:22 +0200175}
176
177static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len)
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800178{
179 struct dccp_sock *dp = dccp_sk(sk);
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000180 struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
Andrea Bittau07978aa2006-09-19 13:13:37 -0700181 struct ccid2_seq *next;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800182
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000183 hc->tx_pipe++;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800184
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000185 hc->tx_seqh->ccid2s_seq = dp->dccps_gss;
186 hc->tx_seqh->ccid2s_acked = 0;
187 hc->tx_seqh->ccid2s_sent = jiffies;
Andrea Bittau07978aa2006-09-19 13:13:37 -0700188
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000189 next = hc->tx_seqh->ccid2s_next;
Andrea Bittau07978aa2006-09-19 13:13:37 -0700190 /* check if we need to alloc more space */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000191 if (next == hc->tx_seqt) {
192 if (ccid2_hc_tx_alloc_seq(hc)) {
Gerrit Renker7d9e8932007-10-04 14:41:26 -0700193 DCCP_CRIT("packet history - out of memory!");
194 /* FIXME: find a more graceful way to bail out */
195 return;
196 }
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000197 next = hc->tx_seqh->ccid2s_next;
198 BUG_ON(next == hc->tx_seqt);
Andrea Bittau07978aa2006-09-19 13:13:37 -0700199 }
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000200 hc->tx_seqh = next;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800201
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000202 ccid2_pr_debug("cwnd=%d pipe=%d\n", hc->tx_cwnd, hc->tx_pipe);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800203
Gerrit Renker900bfed2007-11-24 21:58:33 -0200204 /*
205 * FIXME: The code below is broken and the variables have been removed
206 * from the socket struct. The `ackloss' variable was always set to 0,
207 * and with arsent there are several problems:
208 * (i) it doesn't just count the number of Acks, but all sent packets;
209 * (ii) it is expressed in # of packets, not # of windows, so the
210 * comparison below uses the wrong formula: Appendix A of RFC 4341
211 * comes up with the number K = cwnd / (R^2 - R) of consecutive windows
212 * of data with no lost or marked Ack packets. If arsent were the # of
213 * consecutive Acks received without loss, then Ack Ratio needs to be
214 * decreased by 1 when
215 * arsent >= K * cwnd / R = cwnd^2 / (R^3 - R^2)
216 * where cwnd / R is the number of Acks received per window of data
217 * (cf. RFC 4341, App. A). The problems are that
218 * - arsent counts other packets as well;
219 * - the comparison uses a formula different from RFC 4341;
220 * - computing a cubic/quadratic equation each time is too complicated.
221 * Hence a different algorithm is needed.
222 */
223#if 0
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800224 /* Ack Ratio. Need to maintain a concept of how many windows we sent */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000225 hc->tx_arsent++;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800226 /* We had an ack loss in this window... */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000227 if (hc->tx_ackloss) {
228 if (hc->tx_arsent >= hc->tx_cwnd) {
229 hc->tx_arsent = 0;
230 hc->tx_ackloss = 0;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800231 }
Arnaldo Carvalho de Meloc0c736d2006-03-20 22:05:37 -0800232 } else {
233 /* No acks lost up to now... */
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800234 /* decrease ack ratio if enough packets were sent */
235 if (dp->dccps_l_ack_ratio > 1) {
236 /* XXX don't calculate denominator each time */
Arnaldo Carvalho de Meloc0c736d2006-03-20 22:05:37 -0800237 int denom = dp->dccps_l_ack_ratio * dp->dccps_l_ack_ratio -
238 dp->dccps_l_ack_ratio;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800239
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000240 denom = hc->tx_cwnd * hc->tx_cwnd / denom;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800241
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000242 if (hc->tx_arsent >= denom) {
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800243 ccid2_change_l_ack_ratio(sk, dp->dccps_l_ack_ratio - 1);
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000244 hc->tx_arsent = 0;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800245 }
Arnaldo Carvalho de Meloc0c736d2006-03-20 22:05:37 -0800246 } else {
247 /* we can't increase ack ratio further [1] */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000248 hc->tx_arsent = 0; /* or maybe set it to cwnd*/
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800249 }
250 }
Gerrit Renker900bfed2007-11-24 21:58:33 -0200251#endif
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800252
253 /* setup RTO timer */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000254 if (!timer_pending(&hc->tx_rtotimer))
Gerrit Renker410e27a2008-09-09 13:27:22 +0200255 ccid2_start_rto_timer(sk);
Arnaldo Carvalho de Meloc0c736d2006-03-20 22:05:37 -0800256
Andrea Bittau8d424f62006-09-19 13:12:44 -0700257#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800258 do {
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000259 struct ccid2_seq *seqp = hc->tx_seqt;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800260
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000261 while (seqp != hc->tx_seqh) {
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800262 ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n",
Arnaldo Carvalho de Melo8109b022006-12-10 16:01:18 -0200263 (unsigned long long)seqp->ccid2s_seq,
Randy Dunlap234af482006-10-29 16:03:30 -0800264 seqp->ccid2s_acked, seqp->ccid2s_sent);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800265 seqp = seqp->ccid2s_next;
266 }
Arnaldo Carvalho de Meloc0c736d2006-03-20 22:05:37 -0800267 } while (0);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800268 ccid2_pr_debug("=========\n");
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800269#endif
270}
271
Gerrit Renker410e27a2008-09-09 13:27:22 +0200272/* XXX Lame code duplication!
273 * returns -1 if none was found.
274 * else returns the next offset to use in the function call.
Gerrit Renker14355622008-09-04 07:30:19 +0200275 */
Gerrit Renker410e27a2008-09-09 13:27:22 +0200276static int ccid2_ackvector(struct sock *sk, struct sk_buff *skb, int offset,
277 unsigned char **vec, unsigned char *veclen)
Gerrit Renker14355622008-09-04 07:30:19 +0200278{
Gerrit Renker410e27a2008-09-09 13:27:22 +0200279 const struct dccp_hdr *dh = dccp_hdr(skb);
280 unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb);
281 unsigned char *opt_ptr;
282 const unsigned char *opt_end = (unsigned char *)dh +
283 (dh->dccph_doff * 4);
284 unsigned char opt, len;
285 unsigned char *value;
Gerrit Renker14355622008-09-04 07:30:19 +0200286
Gerrit Renker410e27a2008-09-09 13:27:22 +0200287 BUG_ON(offset < 0);
288 options += offset;
289 opt_ptr = options;
290 if (opt_ptr >= opt_end)
291 return -1;
Gerrit Renker14355622008-09-04 07:30:19 +0200292
Gerrit Renker410e27a2008-09-09 13:27:22 +0200293 while (opt_ptr != opt_end) {
294 opt = *opt_ptr++;
295 len = 0;
296 value = NULL;
Gerrit Renker14355622008-09-04 07:30:19 +0200297
Gerrit Renker410e27a2008-09-09 13:27:22 +0200298 /* Check if this isn't a single byte option */
299 if (opt > DCCPO_MAX_RESERVED) {
300 if (opt_ptr == opt_end)
301 goto out_invalid_option;
302
303 len = *opt_ptr++;
304 if (len < 3)
305 goto out_invalid_option;
Gerrit Renker14355622008-09-04 07:30:19 +0200306 /*
Gerrit Renker410e27a2008-09-09 13:27:22 +0200307 * Remove the type and len fields, leaving
308 * just the value size
Gerrit Renker14355622008-09-04 07:30:19 +0200309 */
Gerrit Renker410e27a2008-09-09 13:27:22 +0200310 len -= 2;
311 value = opt_ptr;
312 opt_ptr += len;
Gerrit Renker14355622008-09-04 07:30:19 +0200313
Gerrit Renker410e27a2008-09-09 13:27:22 +0200314 if (opt_ptr > opt_end)
315 goto out_invalid_option;
Gerrit Renker14355622008-09-04 07:30:19 +0200316 }
317
Gerrit Renker410e27a2008-09-09 13:27:22 +0200318 switch (opt) {
319 case DCCPO_ACK_VECTOR_0:
320 case DCCPO_ACK_VECTOR_1:
321 *vec = value;
322 *veclen = len;
323 return offset + (opt_ptr - options);
Gerrit Renker14355622008-09-04 07:30:19 +0200324 }
325 }
326
Gerrit Renker410e27a2008-09-09 13:27:22 +0200327 return -1;
Gerrit Renker14355622008-09-04 07:30:19 +0200328
Gerrit Renker410e27a2008-09-09 13:27:22 +0200329out_invalid_option:
330 DCCP_BUG("Invalid option - this should not happen (previous parsing)!");
331 return -1;
Gerrit Renker14355622008-09-04 07:30:19 +0200332}
333
Gerrit Renker410e27a2008-09-09 13:27:22 +0200334static void ccid2_hc_tx_kill_rto_timer(struct sock *sk)
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800335{
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000336 struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800337
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000338 sk_stop_timer(sk, &hc->tx_rtotimer);
Gerrit Renker410e27a2008-09-09 13:27:22 +0200339 ccid2_pr_debug("deleted RTO timer\n");
340}
341
342static inline void ccid2_new_ack(struct sock *sk,
343 struct ccid2_seq *seqp,
344 unsigned int *maxincr)
345{
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000346 struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
Gerrit Renker410e27a2008-09-09 13:27:22 +0200347
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000348 if (hc->tx_cwnd < hc->tx_ssthresh) {
349 if (*maxincr > 0 && ++hc->tx_packets_acked == 2) {
350 hc->tx_cwnd += 1;
351 *maxincr -= 1;
352 hc->tx_packets_acked = 0;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800353 }
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000354 } else if (++hc->tx_packets_acked >= hc->tx_cwnd) {
355 hc->tx_cwnd += 1;
356 hc->tx_packets_acked = 0;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800357 }
Gerrit Renker410e27a2008-09-09 13:27:22 +0200358
359 /* update RTO */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000360 if (hc->tx_srtt == -1 ||
361 time_after(jiffies, hc->tx_lastrtt + hc->tx_srtt)) {
Gerrit Renker410e27a2008-09-09 13:27:22 +0200362 unsigned long r = (long)jiffies - (long)seqp->ccid2s_sent;
363 int s;
364
365 /* first measurement */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000366 if (hc->tx_srtt == -1) {
Gerrit Renker410e27a2008-09-09 13:27:22 +0200367 ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n",
368 r, jiffies,
369 (unsigned long long)seqp->ccid2s_seq);
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000370 ccid2_change_srtt(hc, r);
371 hc->tx_rttvar = r >> 1;
Gerrit Renker410e27a2008-09-09 13:27:22 +0200372 } else {
373 /* RTTVAR */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000374 long tmp = hc->tx_srtt - r;
Gerrit Renker410e27a2008-09-09 13:27:22 +0200375 long srtt;
376
377 if (tmp < 0)
378 tmp *= -1;
379
380 tmp >>= 2;
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000381 hc->tx_rttvar *= 3;
382 hc->tx_rttvar >>= 2;
383 hc->tx_rttvar += tmp;
Gerrit Renker410e27a2008-09-09 13:27:22 +0200384
385 /* SRTT */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000386 srtt = hc->tx_srtt;
Gerrit Renker410e27a2008-09-09 13:27:22 +0200387 srtt *= 7;
388 srtt >>= 3;
389 tmp = r >> 3;
390 srtt += tmp;
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000391 ccid2_change_srtt(hc, srtt);
Gerrit Renker410e27a2008-09-09 13:27:22 +0200392 }
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000393 s = hc->tx_rttvar << 2;
Gerrit Renker410e27a2008-09-09 13:27:22 +0200394 /* clock granularity is 1 when based on jiffies */
395 if (!s)
396 s = 1;
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000397 hc->tx_rto = hc->tx_srtt + s;
Gerrit Renker410e27a2008-09-09 13:27:22 +0200398
399 /* must be at least a second */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000400 s = hc->tx_rto / HZ;
Gerrit Renker410e27a2008-09-09 13:27:22 +0200401 /* DCCP doesn't require this [but I like it cuz my code sux] */
402#if 1
403 if (s < 1)
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000404 hc->tx_rto = HZ;
Gerrit Renker410e27a2008-09-09 13:27:22 +0200405#endif
406 /* max 60 seconds */
407 if (s > 60)
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000408 hc->tx_rto = HZ * 60;
Gerrit Renker410e27a2008-09-09 13:27:22 +0200409
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000410 hc->tx_lastrtt = jiffies;
Gerrit Renker410e27a2008-09-09 13:27:22 +0200411
412 ccid2_pr_debug("srtt: %ld rttvar: %ld rto: %ld (HZ=%d) R=%lu\n",
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000413 hc->tx_srtt, hc->tx_rttvar,
414 hc->tx_rto, HZ, r);
Gerrit Renker410e27a2008-09-09 13:27:22 +0200415 }
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800416}
417
Gerrit Renkerd50ad162007-11-24 21:40:24 -0200418static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp)
Andrea Bittau374bcf32006-09-19 13:14:43 -0700419{
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000420 struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
Gerrit Renkerd50ad162007-11-24 21:40:24 -0200421
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000422 if (time_before(seqp->ccid2s_sent, hc->tx_last_cong)) {
Andrea Bittau374bcf32006-09-19 13:14:43 -0700423 ccid2_pr_debug("Multiple losses in an RTT---treating as one\n");
424 return;
425 }
426
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000427 hc->tx_last_cong = jiffies;
Andrea Bittau374bcf32006-09-19 13:14:43 -0700428
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000429 hc->tx_cwnd = hc->tx_cwnd / 2 ? : 1U;
430 hc->tx_ssthresh = max(hc->tx_cwnd, 2U);
Gerrit Renkerd50ad162007-11-24 21:40:24 -0200431
432 /* Avoid spurious timeouts resulting from Ack Ratio > cwnd */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000433 if (dccp_sk(sk)->dccps_l_ack_ratio > hc->tx_cwnd)
434 ccid2_change_l_ack_ratio(sk, hc->tx_cwnd);
Gerrit Renkerc8bf4622008-09-04 07:30:19 +0200435}
436
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800437static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
438{
439 struct dccp_sock *dp = dccp_sk(sk);
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000440 struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800441 u64 ackno, seqno;
442 struct ccid2_seq *seqp;
Gerrit Renker410e27a2008-09-09 13:27:22 +0200443 unsigned char *vector;
444 unsigned char veclen;
445 int offset = 0;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800446 int done = 0;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800447 unsigned int maxincr = 0;
448
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800449 /* check reverse path congestion */
450 seqno = DCCP_SKB_CB(skb)->dccpd_seq;
451
452 /* XXX this whole "algorithm" is broken. Need to fix it to keep track
453 * of the seqnos of the dupacks so that rpseq and rpdupack are correct
454 * -sorbo.
455 */
456 /* need to bootstrap */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000457 if (hc->tx_rpdupack == -1) {
458 hc->tx_rpdupack = 0;
459 hc->tx_rpseq = seqno;
Arnaldo Carvalho de Meloc0c736d2006-03-20 22:05:37 -0800460 } else {
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800461 /* check if packet is consecutive */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000462 if (dccp_delta_seqno(hc->tx_rpseq, seqno) == 1)
463 hc->tx_rpseq = seqno;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800464 /* it's a later packet */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000465 else if (after48(seqno, hc->tx_rpseq)) {
466 hc->tx_rpdupack++;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800467
468 /* check if we got enough dupacks */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000469 if (hc->tx_rpdupack >= NUMDUPACK) {
470 hc->tx_rpdupack = -1; /* XXX lame */
471 hc->tx_rpseq = 0;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800472
Gerrit Renkerdf054e12007-11-24 21:32:53 -0200473 ccid2_change_l_ack_ratio(sk, 2 * dp->dccps_l_ack_ratio);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800474 }
475 }
476 }
477
478 /* check forward path congestion */
Gerrit Renker410e27a2008-09-09 13:27:22 +0200479 /* still didn't send out new data packets */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000480 if (hc->tx_seqh == hc->tx_seqt)
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800481 return;
482
Gerrit Renker410e27a2008-09-09 13:27:22 +0200483 switch (DCCP_SKB_CB(skb)->dccpd_type) {
484 case DCCP_PKT_ACK:
485 case DCCP_PKT_DATAACK:
486 break;
487 default:
488 return;
489 }
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800490
491 ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq;
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000492 if (after48(ackno, hc->tx_high_ack))
493 hc->tx_high_ack = ackno;
Andrea Bittau32aac182006-11-16 14:28:40 -0200494
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000495 seqp = hc->tx_seqt;
Andrea Bittau32aac182006-11-16 14:28:40 -0200496 while (before48(seqp->ccid2s_seq, ackno)) {
497 seqp = seqp->ccid2s_next;
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000498 if (seqp == hc->tx_seqh) {
499 seqp = hc->tx_seqh->ccid2s_prev;
Andrea Bittau32aac182006-11-16 14:28:40 -0200500 break;
501 }
502 }
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800503
Gerrit Renkera3020022007-11-24 22:10:29 -0200504 /*
505 * In slow-start, cwnd can increase up to a maximum of Ack Ratio/2
506 * packets per acknowledgement. Rounding up avoids that cwnd is not
507 * advanced when Ack Ratio is 1 and gives a slight edge otherwise.
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800508 */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000509 if (hc->tx_cwnd < hc->tx_ssthresh)
Gerrit Renkera3020022007-11-24 22:10:29 -0200510 maxincr = DIV_ROUND_UP(dp->dccps_l_ack_ratio, 2);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800511
512 /* go through all ack vectors */
Gerrit Renker410e27a2008-09-09 13:27:22 +0200513 while ((offset = ccid2_ackvector(sk, skb, offset,
514 &vector, &veclen)) != -1) {
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800515 /* go through this ack vector */
Gerrit Renker410e27a2008-09-09 13:27:22 +0200516 while (veclen--) {
517 const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK;
518 u64 ackno_end_rl = SUB48(ackno, rl);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800519
Gerrit Renker410e27a2008-09-09 13:27:22 +0200520 ccid2_pr_debug("ackvec start:%llu end:%llu\n",
Randy Dunlap234af482006-10-29 16:03:30 -0800521 (unsigned long long)ackno,
Gerrit Renker410e27a2008-09-09 13:27:22 +0200522 (unsigned long long)ackno_end_rl);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800523 /* if the seqno we are analyzing is larger than the
524 * current ackno, then move towards the tail of our
525 * seqnos.
526 */
527 while (after48(seqp->ccid2s_seq, ackno)) {
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000528 if (seqp == hc->tx_seqt) {
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800529 done = 1;
530 break;
531 }
532 seqp = seqp->ccid2s_prev;
533 }
534 if (done)
535 break;
536
537 /* check all seqnos in the range of the vector
538 * run length
539 */
540 while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) {
Gerrit Renker410e27a2008-09-09 13:27:22 +0200541 const u8 state = *vector &
542 DCCP_ACKVEC_STATE_MASK;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800543
544 /* new packet received or marked */
Gerrit Renker410e27a2008-09-09 13:27:22 +0200545 if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED &&
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800546 !seqp->ccid2s_acked) {
Gerrit Renker410e27a2008-09-09 13:27:22 +0200547 if (state ==
548 DCCP_ACKVEC_STATE_ECN_MARKED) {
Gerrit Renkerd50ad162007-11-24 21:40:24 -0200549 ccid2_congestion_event(sk,
Andrea Bittau374bcf32006-09-19 13:14:43 -0700550 seqp);
Gerrit Renker410e27a2008-09-09 13:27:22 +0200551 } else
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800552 ccid2_new_ack(sk, seqp,
553 &maxincr);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800554
555 seqp->ccid2s_acked = 1;
556 ccid2_pr_debug("Got ack for %llu\n",
Randy Dunlap234af482006-10-29 16:03:30 -0800557 (unsigned long long)seqp->ccid2s_seq);
Gerrit Renkerc38c92a2010-08-22 19:41:39 +0000558 hc->tx_pipe--;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800559 }
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000560 if (seqp == hc->tx_seqt) {
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800561 done = 1;
562 break;
563 }
Gerrit Renker3de54892007-11-24 20:37:48 -0200564 seqp = seqp->ccid2s_prev;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800565 }
566 if (done)
567 break;
568
Gerrit Renkercfbbeab2007-11-24 20:43:59 -0200569 ackno = SUB48(ackno_end_rl, 1);
Gerrit Renker410e27a2008-09-09 13:27:22 +0200570 vector++;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800571 }
572 if (done)
573 break;
574 }
575
576 /* The state about what is acked should be correct now
577 * Check for NUMDUPACK
578 */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000579 seqp = hc->tx_seqt;
580 while (before48(seqp->ccid2s_seq, hc->tx_high_ack)) {
Andrea Bittau32aac182006-11-16 14:28:40 -0200581 seqp = seqp->ccid2s_next;
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000582 if (seqp == hc->tx_seqh) {
583 seqp = hc->tx_seqh->ccid2s_prev;
Andrea Bittau32aac182006-11-16 14:28:40 -0200584 break;
585 }
586 }
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800587 done = 0;
588 while (1) {
589 if (seqp->ccid2s_acked) {
590 done++;
Gerrit Renker63df18a2007-11-24 22:04:35 -0200591 if (done == NUMDUPACK)
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800592 break;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800593 }
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000594 if (seqp == hc->tx_seqt)
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800595 break;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800596 seqp = seqp->ccid2s_prev;
597 }
598
599 /* If there are at least 3 acknowledgements, anything unacknowledged
600 * below the last sequence number is considered lost
601 */
Gerrit Renker63df18a2007-11-24 22:04:35 -0200602 if (done == NUMDUPACK) {
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800603 struct ccid2_seq *last_acked = seqp;
604
605 /* check for lost packets */
606 while (1) {
607 if (!seqp->ccid2s_acked) {
Andrea Bittau374bcf32006-09-19 13:14:43 -0700608 ccid2_pr_debug("Packet lost: %llu\n",
Randy Dunlap234af482006-10-29 16:03:30 -0800609 (unsigned long long)seqp->ccid2s_seq);
Andrea Bittau374bcf32006-09-19 13:14:43 -0700610 /* XXX need to traverse from tail -> head in
611 * order to detect multiple congestion events in
612 * one ack vector.
613 */
Gerrit Renkerd50ad162007-11-24 21:40:24 -0200614 ccid2_congestion_event(sk, seqp);
Gerrit Renkerc38c92a2010-08-22 19:41:39 +0000615 hc->tx_pipe--;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800616 }
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000617 if (seqp == hc->tx_seqt)
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800618 break;
619 seqp = seqp->ccid2s_prev;
620 }
621
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000622 hc->tx_seqt = last_acked;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800623 }
624
625 /* trim acked packets in tail */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000626 while (hc->tx_seqt != hc->tx_seqh) {
627 if (!hc->tx_seqt->ccid2s_acked)
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800628 break;
629
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000630 hc->tx_seqt = hc->tx_seqt->ccid2s_next;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800631 }
Gerrit Renkerc38c92a2010-08-22 19:41:39 +0000632
633 /* restart RTO timer if not all outstanding data has been acked */
634 if (hc->tx_pipe == 0)
635 sk_stop_timer(sk, &hc->tx_rtotimer);
636 else
637 sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800638}
639
Arnaldo Carvalho de Melo91f0ebf2006-03-20 19:21:44 -0800640static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800641{
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000642 struct ccid2_hc_tx_sock *hc = ccid_priv(ccid);
Gerrit Renkerb00d2bb2007-11-24 21:44:30 -0200643 struct dccp_sock *dp = dccp_sk(sk);
644 u32 max_ratio;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800645
Gerrit Renkerb00d2bb2007-11-24 21:44:30 -0200646 /* RFC 4341, 5: initialise ssthresh to arbitrarily high (max) value */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000647 hc->tx_ssthresh = ~0U;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800648
Gerrit Renker410e27a2008-09-09 13:27:22 +0200649 /*
650 * RFC 4341, 5: "The cwnd parameter is initialized to at most four
651 * packets for new connections, following the rules from [RFC3390]".
652 * We need to convert the bytes of RFC3390 into the packets of RFC 4341.
653 */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000654 hc->tx_cwnd = clamp(4380U / dp->dccps_mss_cache, 2U, 4U);
Gerrit Renkerb00d2bb2007-11-24 21:44:30 -0200655
656 /* Make sure that Ack Ratio is enabled and within bounds. */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000657 max_ratio = DIV_ROUND_UP(hc->tx_cwnd, 2);
Gerrit Renkerb00d2bb2007-11-24 21:44:30 -0200658 if (dp->dccps_l_ack_ratio == 0 || dp->dccps_l_ack_ratio > max_ratio)
659 dp->dccps_l_ack_ratio = max_ratio;
660
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800661 /* XXX init ~ to window size... */
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000662 if (ccid2_hc_tx_alloc_seq(hc))
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800663 return -ENOMEM;
Arnaldo Carvalho de Melo91f0ebf2006-03-20 19:21:44 -0800664
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000665 hc->tx_rto = 3 * HZ;
666 ccid2_change_srtt(hc, -1);
667 hc->tx_rttvar = -1;
668 hc->tx_rpdupack = -1;
669 hc->tx_last_cong = jiffies;
670 setup_timer(&hc->tx_rtotimer, ccid2_hc_tx_rto_expire,
Gerrit Renker410e27a2008-09-09 13:27:22 +0200671 (unsigned long)sk);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800672 return 0;
673}
674
675static void ccid2_hc_tx_exit(struct sock *sk)
676{
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000677 struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
Andrea Bittau07978aa2006-09-19 13:13:37 -0700678 int i;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800679
Gerrit Renker410e27a2008-09-09 13:27:22 +0200680 ccid2_hc_tx_kill_rto_timer(sk);
Andrea Bittau07978aa2006-09-19 13:13:37 -0700681
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000682 for (i = 0; i < hc->tx_seqbufc; i++)
683 kfree(hc->tx_seqbuf[i]);
684 hc->tx_seqbufc = 0;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800685}
686
687static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
688{
689 const struct dccp_sock *dp = dccp_sk(sk);
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000690 struct ccid2_hc_rx_sock *hc = ccid2_hc_rx_sk(sk);
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800691
692 switch (DCCP_SKB_CB(skb)->dccpd_type) {
693 case DCCP_PKT_DATA:
694 case DCCP_PKT_DATAACK:
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000695 hc->rx_data++;
696 if (hc->rx_data >= dp->dccps_r_ack_ratio) {
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800697 dccp_send_ack(sk);
Gerrit Renker77d2dd92009-10-05 00:53:12 +0000698 hc->rx_data = 0;
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800699 }
700 break;
701 }
702}
703
Gerrit Renkerddebc972009-01-04 21:42:53 -0800704struct ccid_operations ccid2_ops = {
Gerrit Renker410e27a2008-09-09 13:27:22 +0200705 .ccid_id = DCCPC_CCID2,
706 .ccid_name = "TCP-like",
Gerrit Renker410e27a2008-09-09 13:27:22 +0200707 .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock),
708 .ccid_hc_tx_init = ccid2_hc_tx_init,
709 .ccid_hc_tx_exit = ccid2_hc_tx_exit,
710 .ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet,
711 .ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent,
712 .ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv,
713 .ccid_hc_rx_obj_size = sizeof(struct ccid2_hc_rx_sock),
714 .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv,
Andrea Bittau2a91aa32006-03-20 17:41:47 -0800715};
716
Gerrit Renker84116712006-11-20 18:26:03 -0200717#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
Gerrit Renker43264992008-08-23 13:28:27 +0200718module_param(ccid2_debug, bool, 0644);
Gerrit Renkerddebc972009-01-04 21:42:53 -0800719MODULE_PARM_DESC(ccid2_debug, "Enable CCID-2 debug messages");
Gerrit Renker84116712006-11-20 18:26:03 -0200720#endif