diff options
Diffstat (limited to 'net/dccp/ccids/ccid2.c')
-rw-r--r-- | net/dccp/ccids/ccid2.c | 204 |
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 | ||
37 | static int ccid2_debug; | 36 | static 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 | ||
49 | static const int ccid2_seq_len = 128; | 47 | #ifdef CONFIG_IP_DCCP_CCID2_DEBUG |
50 | |||
51 | #ifdef CCID2_DEBUG | ||
52 | static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) | 48 | static 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 | ||
92 | static 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 | |||
97 | static int ccid2_hc_tx_send_packet(struct sock *sk, | 134 | static 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 | ||
128 | static void ccid2_change_l_ack_ratio(struct sock *sk, int val) | 165 | static 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 | ||
153 | static void ccid2_change_cwnd(struct sock *sk, int val) | 190 | static 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 | ||
202 | static 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 | |||
208 | static void ccid2_change_pipe(struct ccid2_hc_tx_sock *hctx, long val) | ||
209 | { | ||
210 | hctx->ccid2hctx_pipe = val; | ||
211 | } | ||
212 | |||
167 | static void ccid2_start_rto_timer(struct sock *sk); | 213 | static void ccid2_start_rto_timer(struct sock *sk); |
168 | 214 | ||
169 | static void ccid2_hc_tx_rto_expire(unsigned long data) | 215 | static 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 | ||
548 | static 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 | |||
489 | static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | 564 | static 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 | ||
675 | static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) | 748 | static 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) | |||
720 | static void ccid2_hc_tx_exit(struct sock *sk) | 781 | static 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 | ||
729 | static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | 793 | static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) |