aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/ccids/ccid2.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/ccids/ccid2.c')
-rw-r--r--net/dccp/ccids/ccid2.c204
1 files changed, 134 insertions, 70 deletions
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index e9615627dcd6..457dd3db7f41 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -27,7 +27,6 @@
27 * 27 *
28 * BUGS: 28 * BUGS:
29 * - sequence number wrapping 29 * - sequence number wrapping
30 * - jiffies wrapping
31 */ 30 */
32 31
33#include "../ccid.h" 32#include "../ccid.h"
@@ -36,8 +35,7 @@
36 35
37static int ccid2_debug; 36static int ccid2_debug;
38 37
39#undef CCID2_DEBUG 38#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
40#ifdef CCID2_DEBUG
41#define ccid2_pr_debug(format, a...) \ 39#define ccid2_pr_debug(format, a...) \
42 do { if (ccid2_debug) \ 40 do { if (ccid2_debug) \
43 printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \ 41 printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \
@@ -46,9 +44,7 @@ static int ccid2_debug;
46#define ccid2_pr_debug(format, a...) 44#define ccid2_pr_debug(format, a...)
47#endif 45#endif
48 46
49static const int ccid2_seq_len = 128; 47#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
50
51#ifdef CCID2_DEBUG
52static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) 48static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx)
53{ 49{
54 int len = 0; 50 int len = 0;
@@ -71,8 +67,8 @@ static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx)
71 67
72 /* packets are sent sequentially */ 68 /* packets are sent sequentially */
73 BUG_ON(seqp->ccid2s_seq <= prev->ccid2s_seq); 69 BUG_ON(seqp->ccid2s_seq <= prev->ccid2s_seq);
74 BUG_ON(seqp->ccid2s_sent < prev->ccid2s_sent); 70 BUG_ON(time_before(seqp->ccid2s_sent,
75 BUG_ON(len > ccid2_seq_len); 71 prev->ccid2s_sent));
76 72
77 seqp = prev; 73 seqp = prev;
78 } 74 }
@@ -84,16 +80,57 @@ static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx)
84 do { 80 do {
85 seqp = seqp->ccid2s_prev; 81 seqp = seqp->ccid2s_prev;
86 len++; 82 len++;
87 BUG_ON(len > ccid2_seq_len);
88 } while (seqp != hctx->ccid2hctx_seqh); 83 } while (seqp != hctx->ccid2hctx_seqh);
89 84
90 BUG_ON(len != ccid2_seq_len);
91 ccid2_pr_debug("total len=%d\n", len); 85 ccid2_pr_debug("total len=%d\n", len);
86 BUG_ON(len != hctx->ccid2hctx_seqbufc * CCID2_SEQBUF_LEN);
92} 87}
93#else 88#else
94#define ccid2_hc_tx_check_sanity(hctx) do {} while (0) 89#define ccid2_hc_tx_check_sanity(hctx) do {} while (0)
95#endif 90#endif
96 91
92static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx, int num,
93 gfp_t gfp)
94{
95 struct ccid2_seq *seqp;
96 int i;
97
98 /* check if we have space to preserve the pointer to the buffer */
99 if (hctx->ccid2hctx_seqbufc >= (sizeof(hctx->ccid2hctx_seqbuf) /
100 sizeof(struct ccid2_seq*)))
101 return -ENOMEM;
102
103 /* allocate buffer and initialize linked list */
104 seqp = kmalloc(sizeof(*seqp) * num, gfp);
105 if (seqp == NULL)
106 return -ENOMEM;
107
108 for (i = 0; i < (num - 1); i++) {
109 seqp[i].ccid2s_next = &seqp[i + 1];
110 seqp[i + 1].ccid2s_prev = &seqp[i];
111 }
112 seqp[num - 1].ccid2s_next = seqp;
113 seqp->ccid2s_prev = &seqp[num - 1];
114
115 /* This is the first allocation. Initiate the head and tail. */
116 if (hctx->ccid2hctx_seqbufc == 0)
117 hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqt = seqp;
118 else {
119 /* link the existing list with the one we just created */
120 hctx->ccid2hctx_seqh->ccid2s_next = seqp;
121 seqp->ccid2s_prev = hctx->ccid2hctx_seqh;
122
123 hctx->ccid2hctx_seqt->ccid2s_prev = &seqp[num - 1];
124 seqp[num - 1].ccid2s_next = hctx->ccid2hctx_seqt;
125 }
126
127 /* store the original pointer to the buffer so we can free it */
128 hctx->ccid2hctx_seqbuf[hctx->ccid2hctx_seqbufc] = seqp;
129 hctx->ccid2hctx_seqbufc++;
130
131 return 0;
132}
133
97static int ccid2_hc_tx_send_packet(struct sock *sk, 134static int ccid2_hc_tx_send_packet(struct sock *sk,
98 struct sk_buff *skb, int len) 135 struct sk_buff *skb, int len)
99{ 136{
@@ -122,7 +159,7 @@ static int ccid2_hc_tx_send_packet(struct sock *sk,
122 } 159 }
123 } 160 }
124 161
125 return 100; /* XXX */ 162 return 1; /* XXX CCID should dequeue when ready instead of polling */
126} 163}
127 164
128static void ccid2_change_l_ack_ratio(struct sock *sk, int val) 165static void ccid2_change_l_ack_ratio(struct sock *sk, int val)
@@ -150,10 +187,8 @@ static void ccid2_change_l_ack_ratio(struct sock *sk, int val)
150 dp->dccps_l_ack_ratio = val; 187 dp->dccps_l_ack_ratio = val;
151} 188}
152 189
153static void ccid2_change_cwnd(struct sock *sk, int val) 190static void ccid2_change_cwnd(struct ccid2_hc_tx_sock *hctx, int val)
154{ 191{
155 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
156
157 if (val == 0) 192 if (val == 0)
158 val = 1; 193 val = 1;
159 194
@@ -164,6 +199,17 @@ static void ccid2_change_cwnd(struct sock *sk, int val)
164 hctx->ccid2hctx_cwnd = val; 199 hctx->ccid2hctx_cwnd = val;
165} 200}
166 201
202static void ccid2_change_srtt(struct ccid2_hc_tx_sock *hctx, long val)
203{
204 ccid2_pr_debug("change SRTT to %ld\n", val);
205 hctx->ccid2hctx_srtt = val;
206}
207
208static void ccid2_change_pipe(struct ccid2_hc_tx_sock *hctx, long val)
209{
210 hctx->ccid2hctx_pipe = val;
211}
212
167static void ccid2_start_rto_timer(struct sock *sk); 213static void ccid2_start_rto_timer(struct sock *sk);
168 214
169static void ccid2_hc_tx_rto_expire(unsigned long data) 215static void ccid2_hc_tx_rto_expire(unsigned long data)
@@ -193,11 +239,11 @@ static void ccid2_hc_tx_rto_expire(unsigned long data)
193 ccid2_start_rto_timer(sk); 239 ccid2_start_rto_timer(sk);
194 240
195 /* adjust pipe, cwnd etc */ 241 /* adjust pipe, cwnd etc */
196 hctx->ccid2hctx_pipe = 0; 242 ccid2_change_pipe(hctx, 0);
197 hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd >> 1; 243 hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd >> 1;
198 if (hctx->ccid2hctx_ssthresh < 2) 244 if (hctx->ccid2hctx_ssthresh < 2)
199 hctx->ccid2hctx_ssthresh = 2; 245 hctx->ccid2hctx_ssthresh = 2;
200 ccid2_change_cwnd(sk, 1); 246 ccid2_change_cwnd(hctx, 1);
201 247
202 /* clear state about stuff we sent */ 248 /* clear state about stuff we sent */
203 hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh; 249 hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh;
@@ -232,13 +278,14 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len)
232{ 278{
233 struct dccp_sock *dp = dccp_sk(sk); 279 struct dccp_sock *dp = dccp_sk(sk);
234 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); 280 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
281 struct ccid2_seq *next;
235 u64 seq; 282 u64 seq;
236 283
237 ccid2_hc_tx_check_sanity(hctx); 284 ccid2_hc_tx_check_sanity(hctx);
238 285
239 BUG_ON(!hctx->ccid2hctx_sendwait); 286 BUG_ON(!hctx->ccid2hctx_sendwait);
240 hctx->ccid2hctx_sendwait = 0; 287 hctx->ccid2hctx_sendwait = 0;
241 hctx->ccid2hctx_pipe++; 288 ccid2_change_pipe(hctx, hctx->ccid2hctx_pipe + 1);
242 BUG_ON(hctx->ccid2hctx_pipe < 0); 289 BUG_ON(hctx->ccid2hctx_pipe < 0);
243 290
244 /* There is an issue. What if another packet is sent between 291 /* There is an issue. What if another packet is sent between
@@ -251,15 +298,23 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len)
251 hctx->ccid2hctx_seqh->ccid2s_seq = seq; 298 hctx->ccid2hctx_seqh->ccid2s_seq = seq;
252 hctx->ccid2hctx_seqh->ccid2s_acked = 0; 299 hctx->ccid2hctx_seqh->ccid2s_acked = 0;
253 hctx->ccid2hctx_seqh->ccid2s_sent = jiffies; 300 hctx->ccid2hctx_seqh->ccid2s_sent = jiffies;
254 hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqh->ccid2s_next;
255 301
256 ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->ccid2hctx_cwnd, 302 next = hctx->ccid2hctx_seqh->ccid2s_next;
257 hctx->ccid2hctx_pipe); 303 /* check if we need to alloc more space */
304 if (next == hctx->ccid2hctx_seqt) {
305 int rc;
306
307 ccid2_pr_debug("allocating more space in history\n");
308 rc = ccid2_hc_tx_alloc_seq(hctx, CCID2_SEQBUF_LEN, GFP_KERNEL);
309 BUG_ON(rc); /* XXX what do we do? */
258 310
259 if (hctx->ccid2hctx_seqh == hctx->ccid2hctx_seqt) { 311 next = hctx->ccid2hctx_seqh->ccid2s_next;
260 /* XXX allocate more space */ 312 BUG_ON(next == hctx->ccid2hctx_seqt);
261 WARN_ON(1);
262 } 313 }
314 hctx->ccid2hctx_seqh = next;
315
316 ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->ccid2hctx_cwnd,
317 hctx->ccid2hctx_pipe);
263 318
264 hctx->ccid2hctx_sent++; 319 hctx->ccid2hctx_sent++;
265 320
@@ -295,7 +350,7 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len)
295 if (!timer_pending(&hctx->ccid2hctx_rtotimer)) 350 if (!timer_pending(&hctx->ccid2hctx_rtotimer))
296 ccid2_start_rto_timer(sk); 351 ccid2_start_rto_timer(sk);
297 352
298#ifdef CCID2_DEBUG 353#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
299 ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe); 354 ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe);
300 ccid2_pr_debug("Sent: seq=%llu\n", seq); 355 ccid2_pr_debug("Sent: seq=%llu\n", seq);
301 do { 356 do {
@@ -398,7 +453,7 @@ static inline void ccid2_new_ack(struct sock *sk,
398 /* increase every 2 acks */ 453 /* increase every 2 acks */
399 hctx->ccid2hctx_ssacks++; 454 hctx->ccid2hctx_ssacks++;
400 if (hctx->ccid2hctx_ssacks == 2) { 455 if (hctx->ccid2hctx_ssacks == 2) {
401 ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd + 1); 456 ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd+1);
402 hctx->ccid2hctx_ssacks = 0; 457 hctx->ccid2hctx_ssacks = 0;
403 *maxincr = *maxincr - 1; 458 *maxincr = *maxincr - 1;
404 } 459 }
@@ -411,26 +466,28 @@ static inline void ccid2_new_ack(struct sock *sk,
411 hctx->ccid2hctx_acks++; 466 hctx->ccid2hctx_acks++;
412 467
413 if (hctx->ccid2hctx_acks >= hctx->ccid2hctx_cwnd) { 468 if (hctx->ccid2hctx_acks >= hctx->ccid2hctx_cwnd) {
414 ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd + 1); 469 ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd + 1);
415 hctx->ccid2hctx_acks = 0; 470 hctx->ccid2hctx_acks = 0;
416 } 471 }
417 } 472 }
418 473
419 /* update RTO */ 474 /* update RTO */
420 if (hctx->ccid2hctx_srtt == -1 || 475 if (hctx->ccid2hctx_srtt == -1 ||
421 (jiffies - hctx->ccid2hctx_lastrtt) >= hctx->ccid2hctx_srtt) { 476 time_after(jiffies, hctx->ccid2hctx_lastrtt + hctx->ccid2hctx_srtt)) {
422 unsigned long r = jiffies - seqp->ccid2s_sent; 477 unsigned long r = (long)jiffies - (long)seqp->ccid2s_sent;
423 int s; 478 int s;
424 479
425 /* first measurement */ 480 /* first measurement */
426 if (hctx->ccid2hctx_srtt == -1) { 481 if (hctx->ccid2hctx_srtt == -1) {
427 ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n", 482 ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n",
428 r, jiffies, seqp->ccid2s_seq); 483 r, jiffies, seqp->ccid2s_seq);
429 hctx->ccid2hctx_srtt = r; 484 ccid2_change_srtt(hctx, r);
430 hctx->ccid2hctx_rttvar = r >> 1; 485 hctx->ccid2hctx_rttvar = r >> 1;
431 } else { 486 } else {
432 /* RTTVAR */ 487 /* RTTVAR */
433 long tmp = hctx->ccid2hctx_srtt - r; 488 long tmp = hctx->ccid2hctx_srtt - r;
489 long srtt;
490
434 if (tmp < 0) 491 if (tmp < 0)
435 tmp *= -1; 492 tmp *= -1;
436 493
@@ -440,10 +497,12 @@ static inline void ccid2_new_ack(struct sock *sk,
440 hctx->ccid2hctx_rttvar += tmp; 497 hctx->ccid2hctx_rttvar += tmp;
441 498
442 /* SRTT */ 499 /* SRTT */
443 hctx->ccid2hctx_srtt *= 7; 500 srtt = hctx->ccid2hctx_srtt;
444 hctx->ccid2hctx_srtt >>= 3; 501 srtt *= 7;
502 srtt >>= 3;
445 tmp = r >> 3; 503 tmp = r >> 3;
446 hctx->ccid2hctx_srtt += tmp; 504 srtt += tmp;
505 ccid2_change_srtt(hctx, srtt);
447 } 506 }
448 s = hctx->ccid2hctx_rttvar << 2; 507 s = hctx->ccid2hctx_rttvar << 2;
449 /* clock granularity is 1 when based on jiffies */ 508 /* clock granularity is 1 when based on jiffies */
@@ -479,13 +538,29 @@ static void ccid2_hc_tx_dec_pipe(struct sock *sk)
479{ 538{
480 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); 539 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
481 540
482 hctx->ccid2hctx_pipe--; 541 ccid2_change_pipe(hctx, hctx->ccid2hctx_pipe-1);
483 BUG_ON(hctx->ccid2hctx_pipe < 0); 542 BUG_ON(hctx->ccid2hctx_pipe < 0);
484 543
485 if (hctx->ccid2hctx_pipe == 0) 544 if (hctx->ccid2hctx_pipe == 0)
486 ccid2_hc_tx_kill_rto_timer(sk); 545 ccid2_hc_tx_kill_rto_timer(sk);
487} 546}
488 547
548static void ccid2_congestion_event(struct ccid2_hc_tx_sock *hctx,
549 struct ccid2_seq *seqp)
550{
551 if (time_before(seqp->ccid2s_sent, hctx->ccid2hctx_last_cong)) {
552 ccid2_pr_debug("Multiple losses in an RTT---treating as one\n");
553 return;
554 }
555
556 hctx->ccid2hctx_last_cong = jiffies;
557
558 ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd >> 1);
559 hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd;
560 if (hctx->ccid2hctx_ssthresh < 2)
561 hctx->ccid2hctx_ssthresh = 2;
562}
563
489static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) 564static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
490{ 565{
491 struct dccp_sock *dp = dccp_sk(sk); 566 struct dccp_sock *dp = dccp_sk(sk);
@@ -496,7 +571,6 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
496 unsigned char veclen; 571 unsigned char veclen;
497 int offset = 0; 572 int offset = 0;
498 int done = 0; 573 int done = 0;
499 int loss = 0;
500 unsigned int maxincr = 0; 574 unsigned int maxincr = 0;
501 575
502 ccid2_hc_tx_check_sanity(hctx); 576 ccid2_hc_tx_check_sanity(hctx);
@@ -582,15 +656,16 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
582 * run length 656 * run length
583 */ 657 */
584 while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) { 658 while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) {
585 const u8 state = (*vector & 659 const u8 state = *vector &
586 DCCP_ACKVEC_STATE_MASK) >> 6; 660 DCCP_ACKVEC_STATE_MASK;
587 661
588 /* new packet received or marked */ 662 /* new packet received or marked */
589 if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED && 663 if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED &&
590 !seqp->ccid2s_acked) { 664 !seqp->ccid2s_acked) {
591 if (state == 665 if (state ==
592 DCCP_ACKVEC_STATE_ECN_MARKED) { 666 DCCP_ACKVEC_STATE_ECN_MARKED) {
593 loss = 1; 667 ccid2_congestion_event(hctx,
668 seqp);
594 } else 669 } else
595 ccid2_new_ack(sk, seqp, 670 ccid2_new_ack(sk, seqp,
596 &maxincr); 671 &maxincr);
@@ -642,7 +717,13 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
642 /* check for lost packets */ 717 /* check for lost packets */
643 while (1) { 718 while (1) {
644 if (!seqp->ccid2s_acked) { 719 if (!seqp->ccid2s_acked) {
645 loss = 1; 720 ccid2_pr_debug("Packet lost: %llu\n",
721 seqp->ccid2s_seq);
722 /* XXX need to traverse from tail -> head in
723 * order to detect multiple congestion events in
724 * one ack vector.
725 */
726 ccid2_congestion_event(hctx, seqp);
646 ccid2_hc_tx_dec_pipe(sk); 727 ccid2_hc_tx_dec_pipe(sk);
647 } 728 }
648 if (seqp == hctx->ccid2hctx_seqt) 729 if (seqp == hctx->ccid2hctx_seqt)
@@ -661,53 +742,33 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
661 hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqt->ccid2s_next; 742 hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqt->ccid2s_next;
662 } 743 }
663 744
664 if (loss) {
665 /* XXX do bit shifts guarantee a 0 as the new bit? */
666 ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd >> 1);
667 hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd;
668 if (hctx->ccid2hctx_ssthresh < 2)
669 hctx->ccid2hctx_ssthresh = 2;
670 }
671
672 ccid2_hc_tx_check_sanity(hctx); 745 ccid2_hc_tx_check_sanity(hctx);
673} 746}
674 747
675static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) 748static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
676{ 749{
677 struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid); 750 struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid);
678 int seqcount = ccid2_seq_len;
679 int i;
680 751
681 /* XXX init variables with proper values */ 752 ccid2_change_cwnd(hctx, 1);
682 hctx->ccid2hctx_cwnd = 1; 753 /* Initialize ssthresh to infinity. This means that we will exit the
683 hctx->ccid2hctx_ssthresh = 10; 754 * initial slow-start after the first packet loss. This is what we
755 * want.
756 */
757 hctx->ccid2hctx_ssthresh = ~0;
684 hctx->ccid2hctx_numdupack = 3; 758 hctx->ccid2hctx_numdupack = 3;
759 hctx->ccid2hctx_seqbufc = 0;
685 760
686 /* XXX init ~ to window size... */ 761 /* XXX init ~ to window size... */
687 hctx->ccid2hctx_seqbuf = kmalloc(sizeof(*hctx->ccid2hctx_seqbuf) * 762 if (ccid2_hc_tx_alloc_seq(hctx, CCID2_SEQBUF_LEN, GFP_ATOMIC) != 0)
688 seqcount, gfp_any());
689 if (hctx->ccid2hctx_seqbuf == NULL)
690 return -ENOMEM; 763 return -ENOMEM;
691 764
692 for (i = 0; i < (seqcount - 1); i++) {
693 hctx->ccid2hctx_seqbuf[i].ccid2s_next =
694 &hctx->ccid2hctx_seqbuf[i + 1];
695 hctx->ccid2hctx_seqbuf[i + 1].ccid2s_prev =
696 &hctx->ccid2hctx_seqbuf[i];
697 }
698 hctx->ccid2hctx_seqbuf[seqcount - 1].ccid2s_next =
699 hctx->ccid2hctx_seqbuf;
700 hctx->ccid2hctx_seqbuf->ccid2s_prev =
701 &hctx->ccid2hctx_seqbuf[seqcount - 1];
702
703 hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqbuf;
704 hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh;
705 hctx->ccid2hctx_sent = 0; 765 hctx->ccid2hctx_sent = 0;
706 hctx->ccid2hctx_rto = 3 * HZ; 766 hctx->ccid2hctx_rto = 3 * HZ;
707 hctx->ccid2hctx_srtt = -1; 767 ccid2_change_srtt(hctx, -1);
708 hctx->ccid2hctx_rttvar = -1; 768 hctx->ccid2hctx_rttvar = -1;
709 hctx->ccid2hctx_lastrtt = 0; 769 hctx->ccid2hctx_lastrtt = 0;
710 hctx->ccid2hctx_rpdupack = -1; 770 hctx->ccid2hctx_rpdupack = -1;
771 hctx->ccid2hctx_last_cong = jiffies;
711 772
712 hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire; 773 hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire;
713 hctx->ccid2hctx_rtotimer.data = (unsigned long)sk; 774 hctx->ccid2hctx_rtotimer.data = (unsigned long)sk;
@@ -720,10 +781,13 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
720static void ccid2_hc_tx_exit(struct sock *sk) 781static void ccid2_hc_tx_exit(struct sock *sk)
721{ 782{
722 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); 783 struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk);
784 int i;
723 785
724 ccid2_hc_tx_kill_rto_timer(sk); 786 ccid2_hc_tx_kill_rto_timer(sk);
725 kfree(hctx->ccid2hctx_seqbuf); 787
726 hctx->ccid2hctx_seqbuf = NULL; 788 for (i = 0; i < hctx->ccid2hctx_seqbufc; i++)
789 kfree(hctx->ccid2hctx_seqbuf[i]);
790 hctx->ccid2hctx_seqbufc = 0;
727} 791}
728 792
729static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) 793static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)