diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-12-08 04:16:27 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-08 04:16:27 -0500 |
commit | 991d927c8652b2ab51bd8eef2b773bb2c77d457b (patch) | |
tree | b21cab0ebe4b9f93a2c57b6dc6cd2f38ec828301 /net | |
parent | 192b27ff35bad4cf76cc4239419e9f805935e4f8 (diff) |
dccp: Integration of dynamic feature activation - part 3 (client side)
This integrates feature-activation in the client:
1. When dccp_parse_options() fails, the reset code is already set; request_sent\
_state_process() currently overrides this with `Packet Error', which is not
intended - changed to use the reset code supplied by dccp_parse_options().
2. When feature negotiation fails, the socket should be marked as not usable,
so that the application is notified that an error occurred. This is achieved
by a new label 'unable_to_proceed': generating an error code of `Aborted',
setting the socket state to CLOSED, returning with ECOMM in sk_err.
3. Avoids parsing the Ack twice in Respond state by not doing option processing
again in dccp_rcv_respond_partopen_state_process (as option processing has
already been done on the request_sock in dccp_check_req).
Since this addresses congestion-control initialisation, a corresponding
FIXME has been removed.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/dccp/input.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/net/dccp/input.c b/net/dccp/input.c index 3070015edc75..0672b7e1763e 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c | |||
@@ -421,8 +421,13 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, | |||
421 | goto out_invalid_packet; | 421 | goto out_invalid_packet; |
422 | } | 422 | } |
423 | 423 | ||
424 | /* | ||
425 | * If option processing (Step 8) failed, return 1 here so that | ||
426 | * dccp_v4_do_rcv() sends a Reset. The Reset code depends on | ||
427 | * the option type and is set in dccp_parse_options(). | ||
428 | */ | ||
424 | if (dccp_parse_options(sk, NULL, skb)) | 429 | if (dccp_parse_options(sk, NULL, skb)) |
425 | goto out_invalid_packet; | 430 | return 1; |
426 | 431 | ||
427 | /* Obtain usec RTT sample from SYN exchange (used by CCID 3) */ | 432 | /* Obtain usec RTT sample from SYN exchange (used by CCID 3) */ |
428 | if (likely(dp->dccps_options_received.dccpor_timestamp_echo)) | 433 | if (likely(dp->dccps_options_received.dccpor_timestamp_echo)) |
@@ -475,6 +480,15 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, | |||
475 | */ | 480 | */ |
476 | dccp_set_state(sk, DCCP_PARTOPEN); | 481 | dccp_set_state(sk, DCCP_PARTOPEN); |
477 | 482 | ||
483 | /* | ||
484 | * If feature negotiation was successful, activate features now; | ||
485 | * an activation failure means that this host could not activate | ||
486 | * one ore more features (e.g. insufficient memory), which would | ||
487 | * leave at least one feature in an undefined state. | ||
488 | */ | ||
489 | if (dccp_feat_activate_values(sk, &dp->dccps_featneg)) | ||
490 | goto unable_to_proceed; | ||
491 | |||
478 | /* Make sure socket is routed, for correct metrics. */ | 492 | /* Make sure socket is routed, for correct metrics. */ |
479 | icsk->icsk_af_ops->rebuild_header(sk); | 493 | icsk->icsk_af_ops->rebuild_header(sk); |
480 | 494 | ||
@@ -509,6 +523,16 @@ out_invalid_packet: | |||
509 | /* dccp_v4_do_rcv will send a reset */ | 523 | /* dccp_v4_do_rcv will send a reset */ |
510 | DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR; | 524 | DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR; |
511 | return 1; | 525 | return 1; |
526 | |||
527 | unable_to_proceed: | ||
528 | DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_ABORTED; | ||
529 | /* | ||
530 | * We mark this socket as no longer usable, so that the loop in | ||
531 | * dccp_sendmsg() terminates and the application gets notified. | ||
532 | */ | ||
533 | dccp_set_state(sk, DCCP_CLOSED); | ||
534 | sk->sk_err = ECOMM; | ||
535 | return 1; | ||
512 | } | 536 | } |
513 | 537 | ||
514 | static int dccp_rcv_respond_partopen_state_process(struct sock *sk, | 538 | static int dccp_rcv_respond_partopen_state_process(struct sock *sk, |
@@ -600,7 +624,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
600 | return 1; | 624 | return 1; |
601 | } | 625 | } |
602 | 626 | ||
603 | if (sk->sk_state != DCCP_REQUESTING) { | 627 | if (sk->sk_state != DCCP_REQUESTING && sk->sk_state != DCCP_RESPOND) { |
604 | if (dccp_check_seqno(sk, skb)) | 628 | if (dccp_check_seqno(sk, skb)) |
605 | goto discard; | 629 | goto discard; |
606 | 630 | ||
@@ -665,8 +689,6 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
665 | return 1; | 689 | return 1; |
666 | 690 | ||
667 | case DCCP_REQUESTING: | 691 | case DCCP_REQUESTING: |
668 | /* FIXME: do congestion control initialization */ | ||
669 | |||
670 | queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len); | 692 | queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len); |
671 | if (queued >= 0) | 693 | if (queued >= 0) |
672 | return queued; | 694 | return queued; |