diff options
Diffstat (limited to 'net/dccp/ccids/ccid2.c')
-rw-r--r-- | net/dccp/ccids/ccid2.c | 135 |
1 files changed, 42 insertions, 93 deletions
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 813d5cd40e8b..bbf16b35734d 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c | |||
@@ -317,68 +317,6 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len) | |||
317 | #endif | 317 | #endif |
318 | } | 318 | } |
319 | 319 | ||
320 | /* XXX Lame code duplication! | ||
321 | * returns -1 if none was found. | ||
322 | * else returns the next offset to use in the function call. | ||
323 | */ | ||
324 | static int ccid2_ackvector(struct sock *sk, struct sk_buff *skb, int offset, | ||
325 | unsigned char **vec, unsigned char *veclen) | ||
326 | { | ||
327 | const struct dccp_hdr *dh = dccp_hdr(skb); | ||
328 | unsigned char *options = (unsigned char *)dh + dccp_hdr_len(skb); | ||
329 | unsigned char *opt_ptr; | ||
330 | const unsigned char *opt_end = (unsigned char *)dh + | ||
331 | (dh->dccph_doff * 4); | ||
332 | unsigned char opt, len; | ||
333 | unsigned char *value; | ||
334 | |||
335 | BUG_ON(offset < 0); | ||
336 | options += offset; | ||
337 | opt_ptr = options; | ||
338 | if (opt_ptr >= opt_end) | ||
339 | return -1; | ||
340 | |||
341 | while (opt_ptr != opt_end) { | ||
342 | opt = *opt_ptr++; | ||
343 | len = 0; | ||
344 | value = NULL; | ||
345 | |||
346 | /* Check if this isn't a single byte option */ | ||
347 | if (opt > DCCPO_MAX_RESERVED) { | ||
348 | if (opt_ptr == opt_end) | ||
349 | goto out_invalid_option; | ||
350 | |||
351 | len = *opt_ptr++; | ||
352 | if (len < 3) | ||
353 | goto out_invalid_option; | ||
354 | /* | ||
355 | * Remove the type and len fields, leaving | ||
356 | * just the value size | ||
357 | */ | ||
358 | len -= 2; | ||
359 | value = opt_ptr; | ||
360 | opt_ptr += len; | ||
361 | |||
362 | if (opt_ptr > opt_end) | ||
363 | goto out_invalid_option; | ||
364 | } | ||
365 | |||
366 | switch (opt) { | ||
367 | case DCCPO_ACK_VECTOR_0: | ||
368 | case DCCPO_ACK_VECTOR_1: | ||
369 | *vec = value; | ||
370 | *veclen = len; | ||
371 | return offset + (opt_ptr - options); | ||
372 | } | ||
373 | } | ||
374 | |||
375 | return -1; | ||
376 | |||
377 | out_invalid_option: | ||
378 | DCCP_BUG("Invalid option - this should not happen (previous parsing)!"); | ||
379 | return -1; | ||
380 | } | ||
381 | |||
382 | static void ccid2_hc_tx_kill_rto_timer(struct sock *sk) | 320 | static void ccid2_hc_tx_kill_rto_timer(struct sock *sk) |
383 | { | 321 | { |
384 | struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); | 322 | struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); |
@@ -499,15 +437,27 @@ static void ccid2_congestion_event(struct sock *sk, struct ccid2_seq *seqp) | |||
499 | ccid2_change_l_ack_ratio(sk, hctx->cwnd); | 437 | ccid2_change_l_ack_ratio(sk, hctx->cwnd); |
500 | } | 438 | } |
501 | 439 | ||
440 | static int ccid2_hc_tx_parse_options(struct sock *sk, u8 packet_type, | ||
441 | u8 option, u8 *optval, u8 optlen) | ||
442 | { | ||
443 | struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); | ||
444 | |||
445 | switch (option) { | ||
446 | case DCCPO_ACK_VECTOR_0: | ||
447 | case DCCPO_ACK_VECTOR_1: | ||
448 | return dccp_ackvec_parsed_add(&hctx->av_chunks, optval, optlen, | ||
449 | option - DCCPO_ACK_VECTOR_0); | ||
450 | } | ||
451 | return 0; | ||
452 | } | ||
453 | |||
502 | static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | 454 | static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) |
503 | { | 455 | { |
504 | struct dccp_sock *dp = dccp_sk(sk); | 456 | struct dccp_sock *dp = dccp_sk(sk); |
505 | struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); | 457 | struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); |
458 | struct dccp_ackvec_parsed *avp; | ||
506 | u64 ackno, seqno; | 459 | u64 ackno, seqno; |
507 | struct ccid2_seq *seqp; | 460 | struct ccid2_seq *seqp; |
508 | unsigned char *vector; | ||
509 | unsigned char veclen; | ||
510 | int offset = 0; | ||
511 | int done = 0; | 461 | int done = 0; |
512 | unsigned int maxincr = 0; | 462 | unsigned int maxincr = 0; |
513 | 463 | ||
@@ -542,17 +492,12 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
542 | } | 492 | } |
543 | 493 | ||
544 | /* check forward path congestion */ | 494 | /* check forward path congestion */ |
545 | /* still didn't send out new data packets */ | 495 | if (dccp_packet_without_ack(skb)) |
546 | if (hctx->seqh == hctx->seqt) | ||
547 | return; | 496 | return; |
548 | 497 | ||
549 | switch (DCCP_SKB_CB(skb)->dccpd_type) { | 498 | /* still didn't send out new data packets */ |
550 | case DCCP_PKT_ACK: | 499 | if (hctx->seqh == hctx->seqt) |
551 | case DCCP_PKT_DATAACK: | 500 | goto done; |
552 | break; | ||
553 | default: | ||
554 | return; | ||
555 | } | ||
556 | 501 | ||
557 | ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq; | 502 | ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq; |
558 | if (after48(ackno, hctx->high_ack)) | 503 | if (after48(ackno, hctx->high_ack)) |
@@ -576,15 +521,16 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
576 | maxincr = DIV_ROUND_UP(dp->dccps_l_ack_ratio, 2); | 521 | maxincr = DIV_ROUND_UP(dp->dccps_l_ack_ratio, 2); |
577 | 522 | ||
578 | /* go through all ack vectors */ | 523 | /* go through all ack vectors */ |
579 | while ((offset = ccid2_ackvector(sk, skb, offset, | 524 | list_for_each_entry(avp, &hctx->av_chunks, node) { |
580 | &vector, &veclen)) != -1) { | ||
581 | /* go through this ack vector */ | 525 | /* go through this ack vector */ |
582 | while (veclen--) { | 526 | for (; avp->len--; avp->vec++) { |
583 | u64 ackno_end_rl = SUB48(ackno, dccp_ackvec_runlen(vector)); | 527 | u64 ackno_end_rl = SUB48(ackno, |
528 | dccp_ackvec_runlen(avp->vec)); | ||
584 | 529 | ||
585 | ccid2_pr_debug("ackvec start:%llu end:%llu\n", | 530 | ccid2_pr_debug("ackvec %llu |%u,%u|\n", |
586 | (unsigned long long)ackno, | 531 | (unsigned long long)ackno, |
587 | (unsigned long long)ackno_end_rl); | 532 | dccp_ackvec_state(avp->vec) >> 6, |
533 | dccp_ackvec_runlen(avp->vec)); | ||
588 | /* if the seqno we are analyzing is larger than the | 534 | /* if the seqno we are analyzing is larger than the |
589 | * current ackno, then move towards the tail of our | 535 | * current ackno, then move towards the tail of our |
590 | * seqnos. | 536 | * seqnos. |
@@ -603,7 +549,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
603 | * run length | 549 | * run length |
604 | */ | 550 | */ |
605 | while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) { | 551 | while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) { |
606 | const u8 state = dccp_ackvec_state(vector); | 552 | const u8 state = dccp_ackvec_state(avp->vec); |
607 | 553 | ||
608 | /* new packet received or marked */ | 554 | /* new packet received or marked */ |
609 | if (state != DCCPAV_NOT_RECEIVED && | 555 | if (state != DCCPAV_NOT_RECEIVED && |
@@ -630,7 +576,6 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
630 | break; | 576 | break; |
631 | 577 | ||
632 | ackno = SUB48(ackno_end_rl, 1); | 578 | ackno = SUB48(ackno_end_rl, 1); |
633 | vector++; | ||
634 | } | 579 | } |
635 | if (done) | 580 | if (done) |
636 | break; | 581 | break; |
@@ -694,6 +639,8 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
694 | } | 639 | } |
695 | 640 | ||
696 | ccid2_hc_tx_check_sanity(hctx); | 641 | ccid2_hc_tx_check_sanity(hctx); |
642 | done: | ||
643 | dccp_ackvec_parsed_cleanup(&hctx->av_chunks); | ||
697 | } | 644 | } |
698 | 645 | ||
699 | static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) | 646 | static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) |
@@ -727,6 +674,7 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) | |||
727 | hctx->rpdupack = -1; | 674 | hctx->rpdupack = -1; |
728 | hctx->last_cong = jiffies; | 675 | hctx->last_cong = jiffies; |
729 | setup_timer(&hctx->rtotimer, ccid2_hc_tx_rto_expire, (unsigned long)sk); | 676 | setup_timer(&hctx->rtotimer, ccid2_hc_tx_rto_expire, (unsigned long)sk); |
677 | INIT_LIST_HEAD(&hctx->av_chunks); | ||
730 | 678 | ||
731 | ccid2_hc_tx_check_sanity(hctx); | 679 | ccid2_hc_tx_check_sanity(hctx); |
732 | return 0; | 680 | return 0; |
@@ -762,17 +710,18 @@ static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
762 | } | 710 | } |
763 | 711 | ||
764 | static struct ccid_operations ccid2 = { | 712 | static struct ccid_operations ccid2 = { |
765 | .ccid_id = DCCPC_CCID2, | 713 | .ccid_id = DCCPC_CCID2, |
766 | .ccid_name = "TCP-like", | 714 | .ccid_name = "TCP-like", |
767 | .ccid_owner = THIS_MODULE, | 715 | .ccid_owner = THIS_MODULE, |
768 | .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock), | 716 | .ccid_hc_tx_obj_size = sizeof(struct ccid2_hc_tx_sock), |
769 | .ccid_hc_tx_init = ccid2_hc_tx_init, | 717 | .ccid_hc_tx_init = ccid2_hc_tx_init, |
770 | .ccid_hc_tx_exit = ccid2_hc_tx_exit, | 718 | .ccid_hc_tx_exit = ccid2_hc_tx_exit, |
771 | .ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet, | 719 | .ccid_hc_tx_send_packet = ccid2_hc_tx_send_packet, |
772 | .ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent, | 720 | .ccid_hc_tx_packet_sent = ccid2_hc_tx_packet_sent, |
773 | .ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv, | 721 | .ccid_hc_tx_parse_options = ccid2_hc_tx_parse_options, |
774 | .ccid_hc_rx_obj_size = sizeof(struct ccid2_hc_rx_sock), | 722 | .ccid_hc_tx_packet_recv = ccid2_hc_tx_packet_recv, |
775 | .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv, | 723 | .ccid_hc_rx_obj_size = sizeof(struct ccid2_hc_rx_sock), |
724 | .ccid_hc_rx_packet_recv = ccid2_hc_rx_packet_recv, | ||
776 | }; | 725 | }; |
777 | 726 | ||
778 | #ifdef CONFIG_IP_DCCP_CCID2_DEBUG | 727 | #ifdef CONFIG_IP_DCCP_CCID2_DEBUG |