aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/input.c
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:30:19 -0400
committerGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:45:39 -0400
commitddab05568eaa70fc92b2aae957136f188f724e9c (patch)
tree895f53c4e418987c97aec350996d34e166dedfdc /net/dccp/input.c
parent6224877b2ca4be5de96270a8ae490fe2ba11b0e0 (diff)
dccp: Clean up slow-path input processing
This patch rearranges the order of statements of the slow-path input processing (i.e. any other state than OPEN), to resolve the following issues. 1. Dependencies: the order of statements now better matches RFC 4340, 8.5, i.e. step 7 is before step 9 (previously 9 was before 7), and parsing options in step 8 (which can consume resources) now comes after step 7. 2. Bug-fix: in state CLOSED, there should not be any sequence number checking or option processing. This is why the test for CLOSED has been moved after the test for LISTEN. 3. As before sequence number checks are omitted if in state LISTEN/REQUEST, due to the note underneath the table in RFC 4340, 7.5.3. 4. Packets are now passed on to Ack Vector / CCID processing only after - step 7 (receive unexpected packets), - step 9 (receive Reset), - step 13 (receive CloseReq), - step 14 (receive Close) and only if the state is PARTOPEN. This simplifies CCID processing: - in LISTEN/CLOSED the CCIDs are non-existent; - in RESPOND/REQUEST the CCIDs have not yet been negotiated; - in CLOSEREQ and active-CLOSING the node has already closed this socket; - in passive-CLOSING the client is waiting for its Reset. In the last case, RFC 4340, 8.3 leaves it open to ignore further incoming data, which is the approach taken here. As a result of (3), CCID processing is now indeed confined to OPEN/PARTOPEN states, i.e. congestion control is performed only on the flow of data packets. This avoids pathological cases of doing congestion control on those messages which set up and terminate the connection. I have done a few checks to see if this creates a problem in other parts of the code. This seems not to be the case; even if there were one, it would be better to fix it than to perform congestion control on Close/Request/Response messages. Similarly for Ack Vectors (as they depend on the negotiated CCID). Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Diffstat (limited to 'net/dccp/input.c')
-rw-r--r--net/dccp/input.c68
1 files changed, 33 insertions, 35 deletions
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 9a108ce17fc7..b1e38bf94456 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -603,22 +603,36 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
603 /* Caller (dccp_v4_do_rcv) will send Reset */ 603 /* Caller (dccp_v4_do_rcv) will send Reset */
604 dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; 604 dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;
605 return 1; 605 return 1;
606 } else if (sk->sk_state == DCCP_CLOSED) {
607 dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;
608 return 1;
606 } 609 }
607 610
608 if (sk->sk_state != DCCP_REQUESTING && sk->sk_state != DCCP_RESPOND) { 611 /* Step 6: Check sequence numbers (omitted in LISTEN/REQUEST state) */
609 if (dccp_check_seqno(sk, skb)) 612 if (sk->sk_state != DCCP_REQUESTING && dccp_check_seqno(sk, skb))
610 goto discard; 613 goto discard;
611
612 /*
613 * Step 8: Process options and mark acknowledgeable
614 */
615 if (dccp_parse_options(sk, NULL, skb))
616 return 1;
617 614
618 dccp_handle_ackvec_processing(sk, skb); 615 /*
619 dccp_deliver_input_to_ccids(sk, skb); 616 * Step 7: Check for unexpected packet types
617 * If (S.is_server and P.type == Response)
618 * or (S.is_client and P.type == Request)
619 * or (S.state == RESPOND and P.type == Data),
620 * Send Sync packet acknowledging P.seqno
621 * Drop packet and return
622 */
623 if ((dp->dccps_role != DCCP_ROLE_CLIENT &&
624 dh->dccph_type == DCCP_PKT_RESPONSE) ||
625 (dp->dccps_role == DCCP_ROLE_CLIENT &&
626 dh->dccph_type == DCCP_PKT_REQUEST) ||
627 (sk->sk_state == DCCP_RESPOND && dh->dccph_type == DCCP_PKT_DATA)) {
628 dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC);
629 goto discard;
620 } 630 }
621 631
632 /* Step 8: Process options */
633 if (dccp_parse_options(sk, NULL, skb))
634 return 1;
635
622 /* 636 /*
623 * Step 9: Process Reset 637 * Step 9: Process Reset
624 * If P.type == Reset, 638 * If P.type == Reset,
@@ -626,41 +640,21 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
626 * S.state := TIMEWAIT 640 * S.state := TIMEWAIT
627 * Set TIMEWAIT timer 641 * Set TIMEWAIT timer
628 * Drop packet and return 642 * Drop packet and return
629 */ 643 */
630 if (dh->dccph_type == DCCP_PKT_RESET) { 644 if (dh->dccph_type == DCCP_PKT_RESET) {
631 dccp_rcv_reset(sk, skb); 645 dccp_rcv_reset(sk, skb);
632 return 0; 646 return 0;
633 /* 647 } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) { /* Step 13 */
634 * Step 7: Check for unexpected packet types
635 * If (S.is_server and P.type == Response)
636 * or (S.is_client and P.type == Request)
637 * or (S.state == RESPOND and P.type == Data),
638 * Send Sync packet acknowledging P.seqno
639 * Drop packet and return
640 */
641 } else if ((dp->dccps_role != DCCP_ROLE_CLIENT &&
642 dh->dccph_type == DCCP_PKT_RESPONSE) ||
643 (dp->dccps_role == DCCP_ROLE_CLIENT &&
644 dh->dccph_type == DCCP_PKT_REQUEST) ||
645 (sk->sk_state == DCCP_RESPOND &&
646 dh->dccph_type == DCCP_PKT_DATA)) {
647 dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC);
648 goto discard;
649 } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) {
650 if (dccp_rcv_closereq(sk, skb)) 648 if (dccp_rcv_closereq(sk, skb))
651 return 0; 649 return 0;
652 goto discard; 650 goto discard;
653 } else if (dh->dccph_type == DCCP_PKT_CLOSE) { 651 } else if (dh->dccph_type == DCCP_PKT_CLOSE) { /* Step 14 */
654 if (dccp_rcv_close(sk, skb)) 652 if (dccp_rcv_close(sk, skb))
655 return 0; 653 return 0;
656 goto discard; 654 goto discard;
657 } 655 }
658 656
659 switch (sk->sk_state) { 657 switch (sk->sk_state) {
660 case DCCP_CLOSED:
661 dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;
662 return 1;
663
664 case DCCP_REQUESTING: 658 case DCCP_REQUESTING:
665 queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len); 659 queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len);
666 if (queued >= 0) 660 if (queued >= 0)
@@ -669,8 +663,12 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
669 __kfree_skb(skb); 663 __kfree_skb(skb);
670 return 0; 664 return 0;
671 665
672 case DCCP_RESPOND:
673 case DCCP_PARTOPEN: 666 case DCCP_PARTOPEN:
667 /* Step 8: if using Ack Vectors, mark packet acknowledgeable */
668 dccp_handle_ackvec_processing(sk, skb);
669 dccp_deliver_input_to_ccids(sk, skb);
670 /* fall through */
671 case DCCP_RESPOND:
674 queued = dccp_rcv_respond_partopen_state_process(sk, skb, 672 queued = dccp_rcv_respond_partopen_state_process(sk, skb,
675 dh, len); 673 dh, len);
676 break; 674 break;