aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2011-07-03 11:49:16 -0400
committerGerrit Renker <gerrit@erg.abdn.ac.uk>2011-07-04 14:36:33 -0400
commitc0c2015056d7bd69f3554208271407e7e2ee69e5 (patch)
tree8144a35fcb508fe6e9a24442ceb013ad9dda2bad /net
parent31fcb99d9958bdf04e84224e202f69e6cdac893b (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 may consume resources) now comes after step 7. 2. Sequence number checks are omitted if in state LISTEN/REQUEST, due to the note underneath the table in RFC 4340, 7.5.3. As a result, 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. 3. 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. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Diffstat (limited to 'net')
-rw-r--r--net/dccp/input.c61
1 files changed, 30 insertions, 31 deletions
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 4222e7a654b0..51d5fe5fffba 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -619,20 +619,31 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
619 return 1; 619 return 1;
620 } 620 }
621 621
622 if (sk->sk_state != DCCP_REQUESTING && sk->sk_state != DCCP_RESPOND) { 622 /* Step 6: Check sequence numbers (omitted in LISTEN/REQUEST state) */
623 if (dccp_check_seqno(sk, skb)) 623 if (sk->sk_state != DCCP_REQUESTING && dccp_check_seqno(sk, skb))
624 goto discard; 624 goto discard;
625
626 /*
627 * Step 8: Process options and mark acknowledgeable
628 */
629 if (dccp_parse_options(sk, NULL, skb))
630 return 1;
631 625
632 dccp_handle_ackvec_processing(sk, skb); 626 /*
633 dccp_deliver_input_to_ccids(sk, skb); 627 * Step 7: Check for unexpected packet types
628 * If (S.is_server and P.type == Response)
629 * or (S.is_client and P.type == Request)
630 * or (S.state == RESPOND and P.type == Data),
631 * Send Sync packet acknowledging P.seqno
632 * Drop packet and return
633 */
634 if ((dp->dccps_role != DCCP_ROLE_CLIENT &&
635 dh->dccph_type == DCCP_PKT_RESPONSE) ||
636 (dp->dccps_role == DCCP_ROLE_CLIENT &&
637 dh->dccph_type == DCCP_PKT_REQUEST) ||
638 (sk->sk_state == DCCP_RESPOND && dh->dccph_type == DCCP_PKT_DATA)) {
639 dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC);
640 goto discard;
634 } 641 }
635 642
643 /* Step 8: Process options */
644 if (dccp_parse_options(sk, NULL, skb))
645 return 1;
646
636 /* 647 /*
637 * Step 9: Process Reset 648 * Step 9: Process Reset
638 * If P.type == Reset, 649 * If P.type == Reset,
@@ -640,31 +651,15 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
640 * S.state := TIMEWAIT 651 * S.state := TIMEWAIT
641 * Set TIMEWAIT timer 652 * Set TIMEWAIT timer
642 * Drop packet and return 653 * Drop packet and return
643 */ 654 */
644 if (dh->dccph_type == DCCP_PKT_RESET) { 655 if (dh->dccph_type == DCCP_PKT_RESET) {
645 dccp_rcv_reset(sk, skb); 656 dccp_rcv_reset(sk, skb);
646 return 0; 657 return 0;
647 /* 658 } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) { /* Step 13 */
648 * Step 7: Check for unexpected packet types
649 * If (S.is_server and P.type == Response)
650 * or (S.is_client and P.type == Request)
651 * or (S.state == RESPOND and P.type == Data),
652 * Send Sync packet acknowledging P.seqno
653 * Drop packet and return
654 */
655 } else if ((dp->dccps_role != DCCP_ROLE_CLIENT &&
656 dh->dccph_type == DCCP_PKT_RESPONSE) ||
657 (dp->dccps_role == DCCP_ROLE_CLIENT &&
658 dh->dccph_type == DCCP_PKT_REQUEST) ||
659 (sk->sk_state == DCCP_RESPOND &&
660 dh->dccph_type == DCCP_PKT_DATA)) {
661 dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC);
662 goto discard;
663 } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) {
664 if (dccp_rcv_closereq(sk, skb)) 659 if (dccp_rcv_closereq(sk, skb))
665 return 0; 660 return 0;
666 goto discard; 661 goto discard;
667 } else if (dh->dccph_type == DCCP_PKT_CLOSE) { 662 } else if (dh->dccph_type == DCCP_PKT_CLOSE) { /* Step 14 */
668 if (dccp_rcv_close(sk, skb)) 663 if (dccp_rcv_close(sk, skb))
669 return 0; 664 return 0;
670 goto discard; 665 goto discard;
@@ -679,8 +674,12 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
679 __kfree_skb(skb); 674 __kfree_skb(skb);
680 return 0; 675 return 0;
681 676
682 case DCCP_RESPOND:
683 case DCCP_PARTOPEN: 677 case DCCP_PARTOPEN:
678 /* Step 8: if using Ack Vectors, mark packet acknowledgeable */
679 dccp_handle_ackvec_processing(sk, skb);
680 dccp_deliver_input_to_ccids(sk, skb);
681 /* fall through */
682 case DCCP_RESPOND:
684 queued = dccp_rcv_respond_partopen_state_process(sk, skb, 683 queued = dccp_rcv_respond_partopen_state_process(sk, skb,
685 dh, len); 684 dh, len);
686 break; 685 break;