diff options
Diffstat (limited to 'net/dccp/ccids/ccid2.c')
| -rw-r--r-- | net/dccp/ccids/ccid2.c | 207 |
1 files changed, 135 insertions, 72 deletions
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index d4f9e2d33453..2efb505aeb35 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c | |||
| @@ -27,18 +27,15 @@ | |||
| 27 | * | 27 | * |
| 28 | * BUGS: | 28 | * BUGS: |
| 29 | * - sequence number wrapping | 29 | * - sequence number wrapping |
| 30 | * - jiffies wrapping | ||
| 31 | */ | 30 | */ |
| 32 | 31 | ||
| 33 | #include <linux/config.h> | ||
| 34 | #include "../ccid.h" | 32 | #include "../ccid.h" |
| 35 | #include "../dccp.h" | 33 | #include "../dccp.h" |
| 36 | #include "ccid2.h" | 34 | #include "ccid2.h" |
| 37 | 35 | ||
| 38 | static int ccid2_debug; | 36 | static int ccid2_debug; |
| 39 | 37 | ||
| 40 | #undef CCID2_DEBUG | 38 | #ifdef CONFIG_IP_DCCP_CCID2_DEBUG |
| 41 | #ifdef CCID2_DEBUG | ||
| 42 | #define ccid2_pr_debug(format, a...) \ | 39 | #define ccid2_pr_debug(format, a...) \ |
| 43 | do { if (ccid2_debug) \ | 40 | do { if (ccid2_debug) \ |
| 44 | printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \ | 41 | printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \ |
| @@ -47,9 +44,7 @@ static int ccid2_debug; | |||
| 47 | #define ccid2_pr_debug(format, a...) | 44 | #define ccid2_pr_debug(format, a...) |
| 48 | #endif | 45 | #endif |
| 49 | 46 | ||
| 50 | static const int ccid2_seq_len = 128; | 47 | #ifdef CONFIG_IP_DCCP_CCID2_DEBUG |
| 51 | |||
| 52 | #ifdef CCID2_DEBUG | ||
| 53 | 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) |
| 54 | { | 49 | { |
| 55 | int len = 0; | 50 | int len = 0; |
| @@ -72,8 +67,8 @@ static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) | |||
| 72 | 67 | ||
| 73 | /* packets are sent sequentially */ | 68 | /* packets are sent sequentially */ |
| 74 | BUG_ON(seqp->ccid2s_seq <= prev->ccid2s_seq); | 69 | BUG_ON(seqp->ccid2s_seq <= prev->ccid2s_seq); |
| 75 | BUG_ON(seqp->ccid2s_sent < prev->ccid2s_sent); | 70 | BUG_ON(time_before(seqp->ccid2s_sent, |
| 76 | BUG_ON(len > ccid2_seq_len); | 71 | prev->ccid2s_sent)); |
| 77 | 72 | ||
| 78 | seqp = prev; | 73 | seqp = prev; |
| 79 | } | 74 | } |
| @@ -85,16 +80,57 @@ static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) | |||
| 85 | do { | 80 | do { |
| 86 | seqp = seqp->ccid2s_prev; | 81 | seqp = seqp->ccid2s_prev; |
| 87 | len++; | 82 | len++; |
| 88 | BUG_ON(len > ccid2_seq_len); | ||
| 89 | } while (seqp != hctx->ccid2hctx_seqh); | 83 | } while (seqp != hctx->ccid2hctx_seqh); |
| 90 | 84 | ||
| 91 | BUG_ON(len != ccid2_seq_len); | ||
| 92 | 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); | ||
| 93 | } | 87 | } |
| 94 | #else | 88 | #else |
| 95 | #define ccid2_hc_tx_check_sanity(hctx) do {} while (0) | 89 | #define ccid2_hc_tx_check_sanity(hctx) do {} while (0) |
| 96 | #endif | 90 | #endif |
| 97 | 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 | |||
| 98 | static int ccid2_hc_tx_send_packet(struct sock *sk, | 134 | static int ccid2_hc_tx_send_packet(struct sock *sk, |
| 99 | struct sk_buff *skb, int len) | 135 | struct sk_buff *skb, int len) |
| 100 | { | 136 | { |
| @@ -123,7 +159,7 @@ static int ccid2_hc_tx_send_packet(struct sock *sk, | |||
| 123 | } | 159 | } |
| 124 | } | 160 | } |
| 125 | 161 | ||
| 126 | return 100; /* XXX */ | 162 | return 1; /* XXX CCID should dequeue when ready instead of polling */ |
| 127 | } | 163 | } |
| 128 | 164 | ||
| 129 | 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) |
| @@ -151,10 +187,8 @@ static void ccid2_change_l_ack_ratio(struct sock *sk, int val) | |||
| 151 | dp->dccps_l_ack_ratio = val; | 187 | dp->dccps_l_ack_ratio = val; |
| 152 | } | 188 | } |
| 153 | 189 | ||
| 154 | static void ccid2_change_cwnd(struct sock *sk, int val) | 190 | static void ccid2_change_cwnd(struct ccid2_hc_tx_sock *hctx, int val) |
| 155 | { | 191 | { |
| 156 | struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); | ||
| 157 | |||
| 158 | if (val == 0) | 192 | if (val == 0) |
| 159 | val = 1; | 193 | val = 1; |
| 160 | 194 | ||
| @@ -165,6 +199,17 @@ static void ccid2_change_cwnd(struct sock *sk, int val) | |||
| 165 | hctx->ccid2hctx_cwnd = val; | 199 | hctx->ccid2hctx_cwnd = val; |
| 166 | } | 200 | } |
| 167 | 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 | |||
| 168 | static void ccid2_start_rto_timer(struct sock *sk); | 213 | static void ccid2_start_rto_timer(struct sock *sk); |
| 169 | 214 | ||
| 170 | static void ccid2_hc_tx_rto_expire(unsigned long data) | 215 | static void ccid2_hc_tx_rto_expire(unsigned long data) |
| @@ -194,11 +239,11 @@ static void ccid2_hc_tx_rto_expire(unsigned long data) | |||
| 194 | ccid2_start_rto_timer(sk); | 239 | ccid2_start_rto_timer(sk); |
| 195 | 240 | ||
| 196 | /* adjust pipe, cwnd etc */ | 241 | /* adjust pipe, cwnd etc */ |
| 197 | hctx->ccid2hctx_pipe = 0; | 242 | ccid2_change_pipe(hctx, 0); |
| 198 | hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd >> 1; | 243 | hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd >> 1; |
| 199 | if (hctx->ccid2hctx_ssthresh < 2) | 244 | if (hctx->ccid2hctx_ssthresh < 2) |
| 200 | hctx->ccid2hctx_ssthresh = 2; | 245 | hctx->ccid2hctx_ssthresh = 2; |
| 201 | ccid2_change_cwnd(sk, 1); | 246 | ccid2_change_cwnd(hctx, 1); |
| 202 | 247 | ||
| 203 | /* clear state about stuff we sent */ | 248 | /* clear state about stuff we sent */ |
| 204 | hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh; | 249 | hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh; |
| @@ -233,13 +278,14 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len) | |||
| 233 | { | 278 | { |
| 234 | struct dccp_sock *dp = dccp_sk(sk); | 279 | struct dccp_sock *dp = dccp_sk(sk); |
| 235 | 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; | ||
| 236 | u64 seq; | 282 | u64 seq; |
| 237 | 283 | ||
| 238 | ccid2_hc_tx_check_sanity(hctx); | 284 | ccid2_hc_tx_check_sanity(hctx); |
| 239 | 285 | ||
| 240 | BUG_ON(!hctx->ccid2hctx_sendwait); | 286 | BUG_ON(!hctx->ccid2hctx_sendwait); |
| 241 | hctx->ccid2hctx_sendwait = 0; | 287 | hctx->ccid2hctx_sendwait = 0; |
| 242 | hctx->ccid2hctx_pipe++; | 288 | ccid2_change_pipe(hctx, hctx->ccid2hctx_pipe + 1); |
| 243 | BUG_ON(hctx->ccid2hctx_pipe < 0); | 289 | BUG_ON(hctx->ccid2hctx_pipe < 0); |
| 244 | 290 | ||
| 245 | /* There is an issue. What if another packet is sent between | 291 | /* There is an issue. What if another packet is sent between |
| @@ -252,15 +298,23 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len) | |||
| 252 | hctx->ccid2hctx_seqh->ccid2s_seq = seq; | 298 | hctx->ccid2hctx_seqh->ccid2s_seq = seq; |
| 253 | hctx->ccid2hctx_seqh->ccid2s_acked = 0; | 299 | hctx->ccid2hctx_seqh->ccid2s_acked = 0; |
| 254 | hctx->ccid2hctx_seqh->ccid2s_sent = jiffies; | 300 | hctx->ccid2hctx_seqh->ccid2s_sent = jiffies; |
| 255 | hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqh->ccid2s_next; | ||
| 256 | 301 | ||
| 257 | ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->ccid2hctx_cwnd, | 302 | next = hctx->ccid2hctx_seqh->ccid2s_next; |
| 258 | 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? */ | ||
| 259 | 310 | ||
| 260 | if (hctx->ccid2hctx_seqh == hctx->ccid2hctx_seqt) { | 311 | next = hctx->ccid2hctx_seqh->ccid2s_next; |
| 261 | /* XXX allocate more space */ | 312 | BUG_ON(next == hctx->ccid2hctx_seqt); |
| 262 | WARN_ON(1); | ||
| 263 | } | 313 | } |
| 314 | hctx->ccid2hctx_seqh = next; | ||
| 315 | |||
| 316 | ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->ccid2hctx_cwnd, | ||
| 317 | hctx->ccid2hctx_pipe); | ||
| 264 | 318 | ||
| 265 | hctx->ccid2hctx_sent++; | 319 | hctx->ccid2hctx_sent++; |
| 266 | 320 | ||
| @@ -296,7 +350,7 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len) | |||
| 296 | if (!timer_pending(&hctx->ccid2hctx_rtotimer)) | 350 | if (!timer_pending(&hctx->ccid2hctx_rtotimer)) |
| 297 | ccid2_start_rto_timer(sk); | 351 | ccid2_start_rto_timer(sk); |
| 298 | 352 | ||
| 299 | #ifdef CCID2_DEBUG | 353 | #ifdef CONFIG_IP_DCCP_CCID2_DEBUG |
| 300 | ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe); | 354 | ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe); |
| 301 | ccid2_pr_debug("Sent: seq=%llu\n", seq); | 355 | ccid2_pr_debug("Sent: seq=%llu\n", seq); |
| 302 | do { | 356 | do { |
| @@ -399,7 +453,7 @@ static inline void ccid2_new_ack(struct sock *sk, | |||
| 399 | /* increase every 2 acks */ | 453 | /* increase every 2 acks */ |
| 400 | hctx->ccid2hctx_ssacks++; | 454 | hctx->ccid2hctx_ssacks++; |
| 401 | if (hctx->ccid2hctx_ssacks == 2) { | 455 | if (hctx->ccid2hctx_ssacks == 2) { |
| 402 | ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd + 1); | 456 | ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd+1); |
| 403 | hctx->ccid2hctx_ssacks = 0; | 457 | hctx->ccid2hctx_ssacks = 0; |
| 404 | *maxincr = *maxincr - 1; | 458 | *maxincr = *maxincr - 1; |
| 405 | } | 459 | } |
| @@ -412,26 +466,28 @@ static inline void ccid2_new_ack(struct sock *sk, | |||
| 412 | hctx->ccid2hctx_acks++; | 466 | hctx->ccid2hctx_acks++; |
| 413 | 467 | ||
| 414 | if (hctx->ccid2hctx_acks >= hctx->ccid2hctx_cwnd) { | 468 | if (hctx->ccid2hctx_acks >= hctx->ccid2hctx_cwnd) { |
| 415 | ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd + 1); | 469 | ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd + 1); |
| 416 | hctx->ccid2hctx_acks = 0; | 470 | hctx->ccid2hctx_acks = 0; |
| 417 | } | 471 | } |
| 418 | } | 472 | } |
| 419 | 473 | ||
| 420 | /* update RTO */ | 474 | /* update RTO */ |
| 421 | if (hctx->ccid2hctx_srtt == -1 || | 475 | if (hctx->ccid2hctx_srtt == -1 || |
| 422 | (jiffies - hctx->ccid2hctx_lastrtt) >= hctx->ccid2hctx_srtt) { | 476 | time_after(jiffies, hctx->ccid2hctx_lastrtt + hctx->ccid2hctx_srtt)) { |
| 423 | unsigned long r = jiffies - seqp->ccid2s_sent; | 477 | unsigned long r = (long)jiffies - (long)seqp->ccid2s_sent; |
| 424 | int s; | 478 | int s; |
| 425 | 479 | ||
| 426 | /* first measurement */ | 480 | /* first measurement */ |
| 427 | if (hctx->ccid2hctx_srtt == -1) { | 481 | if (hctx->ccid2hctx_srtt == -1) { |
| 428 | ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n", | 482 | ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n", |
| 429 | r, jiffies, seqp->ccid2s_seq); | 483 | r, jiffies, seqp->ccid2s_seq); |
| 430 | hctx->ccid2hctx_srtt = r; | 484 | ccid2_change_srtt(hctx, r); |
| 431 | hctx->ccid2hctx_rttvar = r >> 1; | 485 | hctx->ccid2hctx_rttvar = r >> 1; |
| 432 | } else { | 486 | } else { |
| 433 | /* RTTVAR */ | 487 | /* RTTVAR */ |
| 434 | long tmp = hctx->ccid2hctx_srtt - r; | 488 | long tmp = hctx->ccid2hctx_srtt - r; |
| 489 | long srtt; | ||
| 490 | |||
| 435 | if (tmp < 0) | 491 | if (tmp < 0) |
| 436 | tmp *= -1; | 492 | tmp *= -1; |
| 437 | 493 | ||
| @@ -441,10 +497,12 @@ static inline void ccid2_new_ack(struct sock *sk, | |||
| 441 | hctx->ccid2hctx_rttvar += tmp; | 497 | hctx->ccid2hctx_rttvar += tmp; |
| 442 | 498 | ||
| 443 | /* SRTT */ | 499 | /* SRTT */ |
| 444 | hctx->ccid2hctx_srtt *= 7; | 500 | srtt = hctx->ccid2hctx_srtt; |
| 445 | hctx->ccid2hctx_srtt >>= 3; | 501 | srtt *= 7; |
| 502 | srtt >>= 3; | ||
| 446 | tmp = r >> 3; | 503 | tmp = r >> 3; |
| 447 | hctx->ccid2hctx_srtt += tmp; | 504 | srtt += tmp; |
| 505 | ccid2_change_srtt(hctx, srtt); | ||
| 448 | } | 506 | } |
| 449 | s = hctx->ccid2hctx_rttvar << 2; | 507 | s = hctx->ccid2hctx_rttvar << 2; |
| 450 | /* clock granularity is 1 when based on jiffies */ | 508 | /* clock granularity is 1 when based on jiffies */ |
| @@ -480,13 +538,29 @@ static void ccid2_hc_tx_dec_pipe(struct sock *sk) | |||
| 480 | { | 538 | { |
| 481 | struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); | 539 | struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); |
| 482 | 540 | ||
| 483 | hctx->ccid2hctx_pipe--; | 541 | ccid2_change_pipe(hctx, hctx->ccid2hctx_pipe-1); |
| 484 | BUG_ON(hctx->ccid2hctx_pipe < 0); | 542 | BUG_ON(hctx->ccid2hctx_pipe < 0); |
| 485 | 543 | ||
| 486 | if (hctx->ccid2hctx_pipe == 0) | 544 | if (hctx->ccid2hctx_pipe == 0) |
| 487 | ccid2_hc_tx_kill_rto_timer(sk); | 545 | ccid2_hc_tx_kill_rto_timer(sk); |
| 488 | } | 546 | } |
| 489 | 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 | |||
| 490 | 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) |
| 491 | { | 565 | { |
| 492 | struct dccp_sock *dp = dccp_sk(sk); | 566 | struct dccp_sock *dp = dccp_sk(sk); |
| @@ -497,7 +571,6 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 497 | unsigned char veclen; | 571 | unsigned char veclen; |
| 498 | int offset = 0; | 572 | int offset = 0; |
| 499 | int done = 0; | 573 | int done = 0; |
| 500 | int loss = 0; | ||
| 501 | unsigned int maxincr = 0; | 574 | unsigned int maxincr = 0; |
| 502 | 575 | ||
| 503 | ccid2_hc_tx_check_sanity(hctx); | 576 | ccid2_hc_tx_check_sanity(hctx); |
| @@ -583,15 +656,16 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 583 | * run length | 656 | * run length |
| 584 | */ | 657 | */ |
| 585 | while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) { | 658 | while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) { |
| 586 | const u8 state = (*vector & | 659 | const u8 state = *vector & |
| 587 | DCCP_ACKVEC_STATE_MASK) >> 6; | 660 | DCCP_ACKVEC_STATE_MASK; |
| 588 | 661 | ||
| 589 | /* new packet received or marked */ | 662 | /* new packet received or marked */ |
| 590 | if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED && | 663 | if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED && |
| 591 | !seqp->ccid2s_acked) { | 664 | !seqp->ccid2s_acked) { |
| 592 | if (state == | 665 | if (state == |
| 593 | DCCP_ACKVEC_STATE_ECN_MARKED) { | 666 | DCCP_ACKVEC_STATE_ECN_MARKED) { |
| 594 | loss = 1; | 667 | ccid2_congestion_event(hctx, |
| 668 | seqp); | ||
| 595 | } else | 669 | } else |
| 596 | ccid2_new_ack(sk, seqp, | 670 | ccid2_new_ack(sk, seqp, |
| 597 | &maxincr); | 671 | &maxincr); |
| @@ -643,7 +717,13 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 643 | /* check for lost packets */ | 717 | /* check for lost packets */ |
| 644 | while (1) { | 718 | while (1) { |
| 645 | if (!seqp->ccid2s_acked) { | 719 | if (!seqp->ccid2s_acked) { |
| 646 | 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); | ||
| 647 | ccid2_hc_tx_dec_pipe(sk); | 727 | ccid2_hc_tx_dec_pipe(sk); |
| 648 | } | 728 | } |
| 649 | if (seqp == hctx->ccid2hctx_seqt) | 729 | if (seqp == hctx->ccid2hctx_seqt) |
| @@ -662,53 +742,33 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 662 | hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqt->ccid2s_next; | 742 | hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqt->ccid2s_next; |
| 663 | } | 743 | } |
| 664 | 744 | ||
| 665 | if (loss) { | ||
| 666 | /* XXX do bit shifts guarantee a 0 as the new bit? */ | ||
| 667 | ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd >> 1); | ||
| 668 | hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd; | ||
| 669 | if (hctx->ccid2hctx_ssthresh < 2) | ||
| 670 | hctx->ccid2hctx_ssthresh = 2; | ||
| 671 | } | ||
| 672 | |||
| 673 | ccid2_hc_tx_check_sanity(hctx); | 745 | ccid2_hc_tx_check_sanity(hctx); |
| 674 | } | 746 | } |
| 675 | 747 | ||
| 676 | 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) |
| 677 | { | 749 | { |
| 678 | struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid); | 750 | struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid); |
| 679 | int seqcount = ccid2_seq_len; | ||
| 680 | int i; | ||
| 681 | 751 | ||
| 682 | /* XXX init variables with proper values */ | 752 | ccid2_change_cwnd(hctx, 1); |
| 683 | hctx->ccid2hctx_cwnd = 1; | 753 | /* Initialize ssthresh to infinity. This means that we will exit the |
| 684 | 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; | ||
| 685 | hctx->ccid2hctx_numdupack = 3; | 758 | hctx->ccid2hctx_numdupack = 3; |
| 759 | hctx->ccid2hctx_seqbufc = 0; | ||
| 686 | 760 | ||
| 687 | /* XXX init ~ to window size... */ | 761 | /* XXX init ~ to window size... */ |
| 688 | hctx->ccid2hctx_seqbuf = kmalloc(sizeof(*hctx->ccid2hctx_seqbuf) * | 762 | if (ccid2_hc_tx_alloc_seq(hctx, CCID2_SEQBUF_LEN, GFP_ATOMIC) != 0) |
| 689 | seqcount, gfp_any()); | ||
| 690 | if (hctx->ccid2hctx_seqbuf == NULL) | ||
| 691 | return -ENOMEM; | 763 | return -ENOMEM; |
| 692 | 764 | ||
| 693 | for (i = 0; i < (seqcount - 1); i++) { | ||
| 694 | hctx->ccid2hctx_seqbuf[i].ccid2s_next = | ||
| 695 | &hctx->ccid2hctx_seqbuf[i + 1]; | ||
| 696 | hctx->ccid2hctx_seqbuf[i + 1].ccid2s_prev = | ||
| 697 | &hctx->ccid2hctx_seqbuf[i]; | ||
| 698 | } | ||
| 699 | hctx->ccid2hctx_seqbuf[seqcount - 1].ccid2s_next = | ||
| 700 | hctx->ccid2hctx_seqbuf; | ||
| 701 | hctx->ccid2hctx_seqbuf->ccid2s_prev = | ||
| 702 | &hctx->ccid2hctx_seqbuf[seqcount - 1]; | ||
| 703 | |||
| 704 | hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqbuf; | ||
| 705 | hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh; | ||
| 706 | hctx->ccid2hctx_sent = 0; | 765 | hctx->ccid2hctx_sent = 0; |
| 707 | hctx->ccid2hctx_rto = 3 * HZ; | 766 | hctx->ccid2hctx_rto = 3 * HZ; |
| 708 | hctx->ccid2hctx_srtt = -1; | 767 | ccid2_change_srtt(hctx, -1); |
| 709 | hctx->ccid2hctx_rttvar = -1; | 768 | hctx->ccid2hctx_rttvar = -1; |
| 710 | hctx->ccid2hctx_lastrtt = 0; | 769 | hctx->ccid2hctx_lastrtt = 0; |
| 711 | hctx->ccid2hctx_rpdupack = -1; | 770 | hctx->ccid2hctx_rpdupack = -1; |
| 771 | hctx->ccid2hctx_last_cong = jiffies; | ||
| 712 | 772 | ||
| 713 | hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire; | 773 | hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire; |
| 714 | hctx->ccid2hctx_rtotimer.data = (unsigned long)sk; | 774 | hctx->ccid2hctx_rtotimer.data = (unsigned long)sk; |
| @@ -721,10 +781,13 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) | |||
| 721 | static void ccid2_hc_tx_exit(struct sock *sk) | 781 | static void ccid2_hc_tx_exit(struct sock *sk) |
| 722 | { | 782 | { |
| 723 | 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; | ||
| 724 | 785 | ||
| 725 | ccid2_hc_tx_kill_rto_timer(sk); | 786 | ccid2_hc_tx_kill_rto_timer(sk); |
| 726 | kfree(hctx->ccid2hctx_seqbuf); | 787 | |
| 727 | hctx->ccid2hctx_seqbuf = NULL; | 788 | for (i = 0; i < hctx->ccid2hctx_seqbufc; i++) |
| 789 | kfree(hctx->ccid2hctx_seqbuf[i]); | ||
| 790 | hctx->ccid2hctx_seqbufc = 0; | ||
| 728 | } | 791 | } |
| 729 | 792 | ||
| 730 | 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) |
| @@ -745,7 +808,7 @@ static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 745 | } | 808 | } |
| 746 | 809 | ||
| 747 | static struct ccid_operations ccid2 = { | 810 | static struct ccid_operations ccid2 = { |
| 748 | .ccid_id = 2, | 811 | .ccid_id = DCCPC_CCID2, |
| 749 | .ccid_name = "ccid2", | 812 | .ccid_name = "ccid2", |
| 750 | .ccid_owner = THIS_MODULE, | 813 | .ccid_owner = THIS_MODULE, |
| 751 | .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock), | 814 | .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock), |
