DCCP protocol discussions
 help / color / mirror / Atom feed
From: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
To: dccp@vger.kernel.org
Subject: Re: [PATCH 3/10]: Dedicated auxiliary states to support
Date: Sun, 30 Sep 2007 14:06:07 +0000	[thread overview]
Message-ID: <20070930140607.GT23546@ghostprotocols.net> (raw)
In-Reply-To: <200707121523.40095@strip-the-willow>

Em Thu, Jul 12, 2007 at 03:23:39PM +0100, Gerrit Renker escreveu:
> [DCCP]: Dedicated auxiliary states to support passive-close
> 
> This adds two auxiliary states to deal with passive closes:
>   * PASSIVE_1 (reached from OPEN via reception of Close) and
>   * PASSIVE_2 (reached from OPEN via reception of CloseReq)


Perhaps we should rename PASSIVE_1 (magic number) to PASSIVE_CLOSEREQ
and PASSIVE_2 to PASSIVE_CLOSE, and also CLOSEREQ to ACTIVE_CLOSEREQ?

I'll defer these patches till we get some more discussion. There are
many more unrelated patches to work on after all :)

- Arnaldo

> to the internal state machine.
> 
> The PASSIVE_1 and PASSIVE_2 states represent the two ways a passive-close
> can happen in DCCP.  The addition of these states is not merely to
> increase clarity. These states are required by the implementation to
> allow a receiver to process unread data before acknowledging the received
> connection-termination-request (i.e. the Close/CloseReq).
> 
> Fix:
> ----
>  This patch uses the PASSIVE_1 and PASSIVE_2 states to explicitly refer to
>  passive-closing states and to protect against external wipeout of internal
>  receive queues. The macroscopic behaviour is compatible with RFC 4340, but
>  without the auxiliary states, buggy, absurd and abnormal behaviour of the
>  socket API will continue. Which is to say, without auxiliary states it does
>  not work.
> 
>  As a consequence, the count of DCCP_STATE_MASK has been increased, to account
>  for the number of new states. 
> 
> 
> Implementation Note:
> --------------------
>  To keep compatibility with sk_stream_wait_connect():
>  * DCCP_CLOSING continues to map into TCP_CLOSING (since this state can be
>    either passive- or active-close)
>  * DCCP_CLOSEREQ maps into TCP_FIN_WAIT1 (since it is always active-close)
> 
>  It is tempting to keep the clever merge of the CLOSEREQ and CLOSING states.
>  However, with the number of possible state transitions, this would require:
> 
>  * quite a number of `if' statements to distinguish all predecessors of
>    the CLOSING state (server/client, active/passive, server timewait yes/no);
> 
>  * two different branches from the CLOSING state:
>    - to TIMEWAIT if it is not an active server-close without keeping timewait state
>    - to CLOSED otherwise (and requiring to receive a Close instead of a Reset).
>  
>  In light of this, I think it is cleaner to implement separate CLOSEREQ and CLOSING
>  states (this is done by the subsequent patches).
> 
> Further documentation is on http://www.erg.abdn.ac.uk/users/gerrit/dccp/docs/closing_states/
> 
> 
>                     Why this is necessary [can be removed]
>                     --------------------------------------
> 
>  The two states are not mentioned in the DCCP specification [RFC 4340, 8.4].
>  In fact, RFC 4340 is silent about passive-close. In a nutshell, suppose that
>  the CLOSE_WAIT and LAST_ACK states were removed from TCP, i.e. a FIN triggers
>  direct transition from ESTABLISHED to CLOSED - similar problem. 
>  The detailed account is as follows.
> 
>  The first problem lies in using inet_stream_connect():
> 
>  An absurd case arises if we let the protocol machinery, not the application,
>  go through the states. If the protocol machinery allows to proceed to DCCP_CLOSED
>  (which corresponds to TCP_CLOSE), connect() returns with -ECONNABORTED, even if
>  there was data in the receive queue. 
> 
>  Therefore, if we want to keep the useful abstraction of inet_stream_connect(), we
>  need to make sure that a passive close can not lead to DCCP_CLOSE via the protocol
>  machinery alone. 
> 
>  The second problem is also related to entering DCCP_CLOSED too early: 
> 
>  Even if connect() were fixed, if a passive-close can directly trigger a state 
>  transition from OPEN to DCCP_CLOSED, the receiver may not be able to read data
>  from its input queue. The reason is that the input queue has already been wiped, 
>  DCCP_CLOSED state has been entered, while the SOCK_DONE flag has not yet been set.
>  Consequently, any subsequent call to dccp_recvmsg terminates in -ENOTCONN, 
>  and this despite of a potentially full receive queue.
> 
> 
> Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
> ---
>  include/linux/dccp.h |   22 +++++++++++++++++++++-
>  net/dccp/proto.c     |    3 +++
>  2 files changed, 24 insertions(+), 1 deletion(-)
> 
> --- a/include/linux/dccp.h
> +++ b/include/linux/dccp.h
> @@ -230,16 +230,35 @@ enum dccp_state {
>  	DCCP_REQUESTING	= TCP_SYN_SENT,
>  	DCCP_LISTEN	= TCP_LISTEN,
>  	DCCP_RESPOND	= TCP_SYN_RECV,
> +	/*
> +	 *			Close states:
> +	 *
> +	 * CLOSEREQ is active-server close only.
> +	 * CLOSING can have three different meanings [RFC 4340, 8.3]:
> +	 *  a. Client has performed active-close, sent a Close to peer from
> +	 *     state OPEN or PARTOPEN, waiting for the final Reset
> +	 *     (in this case, SOCK_DONE = 1).
> +	 *  b. Client performs passive-Close, by receiving an CloseReq in OPEN
> +	 *     or PARTOPEN state. It sends a Close and waits for final Reset
> +	 *     (in this case, SOCK_DONE = 0).
> +	 *  c. Server decides to hold TIMEWAIT state & performs an active-close.
> +	 * To avoid erasing receive queues too early, the transitional states
> +	 * PASSIVE_1 (from OPEN => CLOSED) and PASSIVE_2 (from (PART)OPEN to
> +	 * CLOSING, corresponds to (b) above) are used.
> +	 */
> +	DCCP_CLOSEREQ	= TCP_FIN_WAIT1,
>  	DCCP_CLOSING	= TCP_CLOSING,
>  	DCCP_TIME_WAIT	= TCP_TIME_WAIT,
>  	DCCP_CLOSED	= TCP_CLOSE,
>  	/* Everything below here is specific to DCCP only */
>  	DCCP_INTRINSICS = TCP_MAX_STATES,
>  	DCCP_PARTOPEN,
> +	DCCP_PASSIVE_1,		/* any node receiving a Close  */
> +	DCCP_PASSIVE_2,		/* client receiving a CloseReq */
>  	DCCP_MAX_STATES
>  };
>  
> -#define DCCP_STATE_MASK 0xf
> +#define DCCP_STATE_MASK 0x1f
>  #define DCCP_ACTION_FIN (1<<7)
>  
>  enum {
> @@ -247,6 +266,7 @@ enum {
>  	DCCPF_REQUESTING = TCPF_SYN_SENT,
>  	DCCPF_LISTEN	 = TCPF_LISTEN,
>  	DCCPF_RESPOND	 = TCPF_SYN_RECV,
> +	DCCPF_CLOSEREQ	 = TCPF_FIN_WAIT1,
>  	DCCPF_CLOSING	 = TCPF_CLOSING,
>  	DCCPF_TIME_WAIT	 = TCPF_TIME_WAIT,
>  	DCCPF_CLOSED	 = TCPF_CLOSE,
> --- a/net/dccp/proto.c
> +++ b/net/dccp/proto.c
> @@ -139,6 +139,9 @@ const char *dccp_state_name(const int st
>  	[DCCP_LISTEN]	  = "LISTEN",
>  	[DCCP_RESPOND]	  = "RESPOND",
>  	[DCCP_CLOSING]	  = "CLOSING",
> +	[DCCP_CLOSEREQ]	  = "CLOSEREQ",
> +	[DCCP_PASSIVE_1]  = "PASSIVE_1",
> +	[DCCP_PASSIVE_2]  = "PASSIVE_2",
>  	[DCCP_TIME_WAIT]  = "TIME_WAIT",
>  	[DCCP_CLOSED]	  = "CLOSED",
>  	};
> -
> To unsubscribe from this list: send the line "unsubscribe dccp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

  parent reply	other threads:[~2007-09-30 14:06 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-07-12 14:23 [PATCH 3/10]: Dedicated auxiliary states to support passive-close Gerrit Renker
2007-09-06  4:24 ` Ian McDonald
2007-09-30 14:06 ` Arnaldo Carvalho de Melo [this message]
2007-10-01 10:54 ` Gerrit Renker
2007-10-21  1:35 ` Ian McDonald

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070930140607.GT23546@ghostprotocols.net \
    --to=acme@ghostprotocols.net \
    --cc=dccp@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox