diff options
author | Arnaldo Carvalho de Melo <acme@mandriva.com> | 2005-08-23 21:50:06 -0700 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 16:04:31 -0700 |
commit | 7ad07e7cf343181002c10c39d3f57a88e4903d4f (patch) | |
tree | c22067f3f443faebdcd3403fa8ce7c5c89662c60 /net/dccp/proto.c | |
parent | 58e45131dc269eff0983c6d44494f9e687686900 (diff) | |
download | linux-7ad07e7cf343181002c10c39d3f57a88e4903d4f.tar.bz2 |
[DCCP]: Implement the CLOSING timer
So that we retransmit CLOSE/CLOSEREQ packets till they elicit an
answer or we hit a timeout.
Most of the machinery uses TCP approaches, this code has to be
polished & audited, but this is better than we had before.
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp/proto.c')
-rw-r--r-- | net/dccp/proto.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 8b613c3017c5..a3f8a8095f81 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -402,12 +402,15 @@ void dccp_close(struct sock *sk, long timeout) /* Check zero linger _after_ checking for unread data. */ sk->sk_prot->disconnect(sk, 0); } else if (dccp_close_state(sk)) { - dccp_send_close(sk); + dccp_send_close(sk, 1); } sk_stream_wait_close(sk, timeout); adjudge_to_death: + /* + * It is the last release_sock in its life. It will remove backlog. + */ release_sock(sk); /* * Now socket is owned by kernel and we acquire BH lock @@ -419,11 +422,26 @@ adjudge_to_death: sock_hold(sk); sock_orphan(sk); - - if (sk->sk_state != DCCP_CLOSED) + + /* + * The last release_sock may have processed the CLOSE or RESET + * packet moving sock to CLOSED state, if not we have to fire + * the CLOSE/CLOSEREQ retransmission timer, see "8.3. Termination" + * in draft-ietf-dccp-spec-11. -acme + */ + if (sk->sk_state == DCCP_CLOSING) { + /* FIXME: should start at 2 * RTT */ + /* Timer for repeating the CLOSE/CLOSEREQ until an answer. */ + inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, + inet_csk(sk)->icsk_rto, + DCCP_RTO_MAX); +#if 0 + /* Yeah, we should use sk->sk_prot->orphan_count, etc */ dccp_set_state(sk, DCCP_CLOSED); +#endif + } - atomic_inc(&dccp_orphan_count); + atomic_inc(sk->sk_prot->orphan_count); if (sk->sk_state == DCCP_CLOSED) inet_csk_destroy_sock(sk); |