diff options
Diffstat (limited to 'net/dccp/ccids/ccid2.c')
| -rw-r--r-- | net/dccp/ccids/ccid2.c | 143 |
1 files changed, 44 insertions, 99 deletions
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 6576eae9e779..e96d5e810039 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c | |||
| @@ -246,68 +246,6 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len) | |||
| 246 | #endif | 246 | #endif |
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | /* XXX Lame code duplication! | ||
| 250 | * returns -1 if none was found. | ||
| 251 | * else returns the next offset to use in the function call. | ||
| 252 | */ | ||
| 253 | static int ccid2_ackvector(struct sock *sk, struct sk_buff *skb, int offset, | ||
| 254 | unsigned char **vec, unsigned char *veclen) | ||
| 255 | { | ||
| 256 | const struct dccp_hdr *dh = dccp_hdr(skb); | ||
| 257 | unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb); | ||
| 258 | unsigned char *opt_ptr; | ||
| 259 | const unsigned char *opt_end = (unsigned char *)dh + | ||
| 260 | (dh->dccph_doff * 4); | ||
| 261 | unsigned char opt, len; | ||
| 262 | unsigned char *value; | ||
| 263 | |||
| 264 | BUG_ON(offset < 0); | ||
| 265 | options += offset; | ||
| 266 | opt_ptr = options; | ||
| 267 | if (opt_ptr >= opt_end) | ||
| 268 | return -1; | ||
| 269 | |||
| 270 | while (opt_ptr != opt_end) { | ||
| 271 | opt = *opt_ptr++; | ||
| 272 | len = 0; | ||
| 273 | value = NULL; | ||
| 274 | |||
| 275 | /* Check if this isn't a single byte option */ | ||
| 276 | if (opt > DCCPO_MAX_RESERVED) { | ||
| 277 | if (opt_ptr == opt_end) | ||
| 278 | goto out_invalid_option; | ||
| 279 | |||
| 280 | len = *opt_ptr++; | ||
| 281 | if (len < 3) | ||
| 282 | goto out_invalid_option; | ||
| 283 | /* | ||
| 284 | * Remove the type and len fields, leaving | ||
| 285 | * just the value size | ||
| 286 | */ | ||
| 287 | len -= 2; | ||
| 288 | value = opt_ptr; | ||
| 289 | opt_ptr += len; | ||
| 290 | |||
| 291 | if (opt_ptr > opt_end) | ||
| 292 | goto out_invalid_option; | ||
| 293 | } | ||
| 294 | |||
| 295 | switch (opt) { | ||
| 296 | case DCCPO_ACK_VECTOR_0: | ||
| 297 | case DCCPO_ACK_VECTOR_1: | ||
| 298 | *vec = value; | ||
| 299 | *veclen = len; | ||
| 300 | return offset + (opt_ptr - options); | ||
| 301 | } | ||
| 302 | } | ||
| 303 | |||
| 304 | return -1; | ||
| 305 | |||
| 306 | out_invalid_option: | ||
| 307 | DCCP_BUG("Invalid option - this should not happen (previous parsing)!"); | ||
| 308 | return -1; | ||
| 309 | } | ||
| 310 | |||
| 311 | /** | 249 | /** |
| 312 | * ccid2_rtt_estimator - Sample RTT and compute RTO using RFC2988 algorithm | 250 | * ccid2_rtt_estimator - Sample RTT and compute RTO using RFC2988 algorithm |
| 313 | * This code is almost identical with TCP's tcp_rtt_estimator(), since | 251 | * This code is almost identical with TCP's tcp_rtt_estimator(), since |
| @@ -432,16 +370,28 @@ static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp) | |||
| 432 | ccid2_change_l_ack_ratio(sk, hc->tx_cwnd); | 370 | ccid2_change_l_ack_ratio(sk, hc->tx_cwnd); |
| 433 | } | 371 | } |
| 434 | 372 | ||
| 373 | static int ccid2_hc_tx_parse_options(struct sock *sk, u8 packet_type, | ||
| 374 | u8 option, u8 *optval, u8 optlen) | ||
| 375 | { | ||
| 376 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); | ||
| 377 | |||
| 378 | switch (option) { | ||
| 379 | case DCCPO_ACK_VECTOR_0: | ||
| 380 | case DCCPO_ACK_VECTOR_1: | ||
| 381 | return dccp_ackvec_parsed_add(&hc->tx_av_chunks, optval, optlen, | ||
| 382 | option - DCCPO_ACK_VECTOR_0); | ||
| 383 | } | ||
| 384 | return 0; | ||
| 385 | } | ||
| 386 | |||
| 435 | static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | 387 | static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) |
| 436 | { | 388 | { |
| 437 | struct dccp_sock *dp = dccp_sk(sk); | 389 | struct dccp_sock *dp = dccp_sk(sk); |
| 438 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); | 390 | struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); |
| 439 | const bool sender_was_blocked = ccid2_cwnd_network_limited(hc); | 391 | const bool sender_was_blocked = ccid2_cwnd_network_limited(hc); |
| 392 | struct dccp_ackvec_parsed *avp; | ||
| 440 | u64 ackno, seqno; | 393 | u64 ackno, seqno; |
| 441 | struct ccid2_seq *seqp; | 394 | struct ccid2_seq *seqp; |
| 442 | unsigned char *vector; | ||
| 443 | unsigned char veclen; | ||
| 444 | int offset = 0; | ||
| 445 | int done = 0; | 395 | int done = 0; |
| 446 | unsigned int maxincr = 0; | 396 | unsigned int maxincr = 0; |
| 447 | 397 | ||
| @@ -475,17 +425,12 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 475 | } | 425 | } |
| 476 | 426 | ||
| 477 | /* check forward path congestion */ | 427 | /* check forward path congestion */ |
| 478 | /* still didn't send out new data packets */ | 428 | if (dccp_packet_without_ack(skb)) |
| 479 | if (hc->tx_seqh == hc->tx_seqt) | ||
| 480 | return; | 429 | return; |
| 481 | 430 | ||
| 482 | switch (DCCP_SKB_CB(skb)->dccpd_type) { | 431 | /* still didn't send out new data packets */ |
| 483 | case DCCP_PKT_ACK: | 432 | if (hc->tx_seqh == hc->tx_seqt) |
| 484 | case DCCP_PKT_DATAACK: | 433 | goto done; |
| 485 | break; | ||
| 486 | default: | ||
| 487 | return; | ||
| 488 | } | ||
| 489 | 434 | ||
| 490 | ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq; | 435 | ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq; |
| 491 | if (after48(ackno, hc->tx_high_ack)) | 436 | if (after48(ackno, hc->tx_high_ack)) |
| @@ -509,16 +454,16 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 509 | maxincr = DIV_ROUND_UP(dp->dccps_l_ack_ratio, 2); | 454 | maxincr = DIV_ROUND_UP(dp->dccps_l_ack_ratio, 2); |
| 510 | 455 | ||
| 511 | /* go through all ack vectors */ | 456 | /* go through all ack vectors */ |
| 512 | while ((offset = ccid2_ackvector(sk, skb, offset, | 457 | list_for_each_entry(avp, &hc->tx_av_chunks, node) { |
| 513 | &vector, &veclen)) != -1) { | ||
| 514 | /* go through this ack vector */ | 458 | /* go through this ack vector */ |
| 515 | while (veclen--) { | 459 | for (; avp->len--; avp->vec++) { |
| 516 | const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; | 460 | u64 ackno_end_rl = SUB48(ackno, |
| 517 | u64 ackno_end_rl = SUB48(ackno, rl); | 461 | dccp_ackvec_runlen(avp->vec)); |
| 518 | 462 | ||
| 519 | ccid2_pr_debug("ackvec start:%llu end:%llu\n", | 463 | ccid2_pr_debug("ackvec %llu |%u,%u|\n", |
| 520 | (unsigned long long)ackno, | 464 | (unsigned long long)ackno, |
| 521 | (unsigned long long)ackno_end_rl); | 465 | dccp_ackvec_state(avp->vec) >> 6, |
| 466 | dccp_ackvec_runlen(avp->vec)); | ||
| 522 | /* if the seqno we are analyzing is larger than the | 467 | /* if the seqno we are analyzing is larger than the |
| 523 | * current ackno, then move towards the tail of our | 468 | * current ackno, then move towards the tail of our |
| 524 | * seqnos. | 469 | * seqnos. |
| @@ -537,17 +482,15 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 537 | * run length | 482 | * run length |
| 538 | */ | 483 | */ |
| 539 | while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) { | 484 | while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) { |
| 540 | const u8 state = *vector & | 485 | const u8 state = dccp_ackvec_state(avp->vec); |
| 541 | DCCP_ACKVEC_STATE_MASK; | ||
| 542 | 486 | ||
| 543 | /* new packet received or marked */ | 487 | /* new packet received or marked */ |
| 544 | if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED && | 488 | if (state != DCCPAV_NOT_RECEIVED && |
| 545 | !seqp->ccid2s_acked) { | 489 | !seqp->ccid2s_acked) { |
| 546 | if (state == | 490 | if (state == DCCPAV_ECN_MARKED) |
| 547 | DCCP_ACKVEC_STATE_ECN_MARKED) { | ||
| 548 | ccid2_congestion_event(sk, | 491 | ccid2_congestion_event(sk, |
| 549 | seqp); | 492 | seqp); |
| 550 | } else | 493 | else |
| 551 | ccid2_new_ack(sk, seqp, | 494 | ccid2_new_ack(sk, seqp, |
| 552 | &maxincr); | 495 | &maxincr); |
| 553 | 496 | ||
| @@ -566,7 +509,6 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 566 | break; | 509 | break; |
| 567 | 510 | ||
| 568 | ackno = SUB48(ackno_end_rl, 1); | 511 | ackno = SUB48(ackno_end_rl, 1); |
| 569 | vector++; | ||
| 570 | } | 512 | } |
| 571 | if (done) | 513 | if (done) |
| 572 | break; | 514 | break; |
| @@ -634,10 +576,11 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 634 | sk_stop_timer(sk, &hc->tx_rtotimer); | 576 | sk_stop_timer(sk, &hc->tx_rtotimer); |
| 635 | else | 577 | else |
| 636 | sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto); | 578 | sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto); |
| 637 | 579 | done: | |
| 638 | /* check if incoming Acks allow pending packets to be sent */ | 580 | /* check if incoming Acks allow pending packets to be sent */ |
| 639 | if (sender_was_blocked && !ccid2_cwnd_network_limited(hc)) | 581 | if (sender_was_blocked && !ccid2_cwnd_network_limited(hc)) |
| 640 | tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet); | 582 | tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet); |
| 583 | dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks); | ||
| 641 | } | 584 | } |
| 642 | 585 | ||
| 643 | static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) | 586 | static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) |
| @@ -666,6 +609,7 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) | |||
| 666 | hc->tx_last_cong = ccid2_time_stamp; | 609 | hc->tx_last_cong = ccid2_time_stamp; |
| 667 | setup_timer(&hc->tx_rtotimer, ccid2_hc_tx_rto_expire, | 610 | setup_timer(&hc->tx_rtotimer, ccid2_hc_tx_rto_expire, |
| 668 | (unsigned long)sk); | 611 | (unsigned long)sk); |
| 612 | INIT_LIST_HEAD(&hc->tx_av_chunks); | ||
| 669 | return 0; | 613 | return 0; |
| 670 | } | 614 | } |
| 671 | 615 | ||
| @@ -699,16 +643,17 @@ static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 699 | } | 643 | } |
| 700 | 644 | ||
| 701 | struct ccid_operations ccid2_ops = { | 645 | struct ccid_operations ccid2_ops = { |
| 702 | .ccid_id = DCCPC_CCID2, | 646 | .ccid_id = DCCPC_CCID2, |
| 703 | .ccid_name = "TCP-like", | 647 | .ccid_name = "TCP-like", |
| 704 | .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock), | 648 | .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock), |
| 705 | .ccid_hc_tx_init = ccid2_hc_tx_init, | 649 | .ccid_hc_tx_init = ccid2_hc_tx_init, |
| 706 | .ccid_hc_tx_exit = ccid2_hc_tx_exit, | 650 | .ccid_hc_tx_exit = ccid2_hc_tx_exit, |
| 707 | .ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet, | 651 | .ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet, |
| 708 | .ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent, | 652 | .ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent, |
| 709 | .ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv, | 653 | .ccid_hc_tx_parse_options = ccid2_hc_tx_parse_options, |
| 710 | .ccid_hc_rx_obj_size = sizeof(struct ccid2_hc_rx_sock), | 654 | .ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv, |
| 711 | .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv, | 655 | .ccid_hc_rx_obj_size = sizeof(struct ccid2_hc_rx_sock), |
| 656 | .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv, | ||
| 712 | }; | 657 | }; |
| 713 | 658 | ||
| 714 | #ifdef CONFIG_IP_DCCP_CCID2_DEBUG | 659 | #ifdef CONFIG_IP_DCCP_CCID2_DEBUG |
