[CRIU] [PATCH] tcp: add ability to restore closing states (v2)
Andrey Vagin
avagin at openvz.org
Mon Apr 7 04:03:14 PDT 2014
Here are TCP_FIN_WAIT{1,2}, TCP_WAIT_STOP, TCP_CLOSING, TCP_LAST_ACK,
TCP_TIME_WAIT.
v2: We decide to not use control message for repairing a fin packets in
queues. Because it looks quite tricky. Alexey suggested to restore each
state separately and in this case setsockopt looks more logical.
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
include/net/tcp.h | 1 +
include/uapi/linux/tcp.h | 1 +
net/ipv4/tcp.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++
net/ipv4/tcp_input.c | 2 +-
4 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 743acce..016fdb4 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -562,6 +562,7 @@ void tcp_cwnd_application_limited(struct sock *sk);
void tcp_resume_early_retransmit(struct sock *sk);
void tcp_rearm_rto(struct sock *sk);
void tcp_reset(struct sock *sk);
+void tcp_fin(struct sock *sk);
/* tcp_timer.c */
void tcp_init_xmit_timers(struct sock *);
diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
index 377f1e5..4f6b3de 100644
--- a/include/uapi/linux/tcp.h
+++ b/include/uapi/linux/tcp.h
@@ -112,6 +112,7 @@ enum {
#define TCP_FASTOPEN 23 /* Enable FastOpen on listeners */
#define TCP_TIMESTAMP 24
#define TCP_NOTSENT_LOWAT 25 /* limit number of unsent bytes in write queue */
+#define TCP_REPAIR_STATE 26 /* Current state of this connection */
struct tcp_repair_opt {
__u32 opt_code;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 964e3f8..393d769 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2431,6 +2431,58 @@ static int tcp_repair_options_est(struct tcp_sock *tp,
return 0;
}
+static int tcp_repair_state(struct sock *sk, int state)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+
+ if (sk->sk_state != TCP_ESTABLISHED)
+ return -EINVAL;
+
+ switch (state) {
+ case TCP_ESTABLISHED:
+ break;
+
+ case TCP_FIN_WAIT2:
+ if (tp->snd_una != tp->write_seq)
+ return -EINVAL;
+ tcp_set_state(sk, TCP_FIN_WAIT2);
+ break;
+
+ case TCP_TIME_WAIT:
+ if (tp->snd_una != tp->write_seq)
+ return -EINVAL;
+ tcp_time_wait(sk, TCP_TIME_WAIT, 0);
+ break;
+
+ case TCP_CLOSE_WAIT:
+ tcp_set_state(sk, TCP_CLOSE_WAIT);
+ break;
+
+ case TCP_LAST_ACK:
+ case TCP_FIN_WAIT1:
+ case TCP_CLOSING:
+ tcp_set_state(sk, state);
+ tcp_send_fin(sk);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if ((1 << sk->sk_state) & (TCPF_FIN_WAIT1 |
+ TCPF_FIN_WAIT2 |
+ TCPF_CLOSING |
+ TCPF_LAST_ACK))
+ sk->sk_shutdown |= SEND_SHUTDOWN;
+
+ if ((1 << sk->sk_state) & (TCPF_CLOSE_WAIT |
+ TCPF_CLOSING |
+ TCPF_LAST_ACK))
+ sk->sk_shutdown |= RCV_SHUTDOWN;
+
+ return 0;
+}
+
/*
* Socket option code for TCP.
*/
@@ -2568,6 +2620,13 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
err = -EPERM;
break;
+ case TCP_REPAIR_STATE:
+ if (tp->repair)
+ err = tcp_repair_state(sk, val);
+ else
+ err = -EINVAL;
+ break;
+
case TCP_CORK:
/* When set indicates to always queue non-full frames.
* Later the user clears this option and we transmit
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index eeaac39..352480c 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3820,7 +3820,7 @@ void tcp_reset(struct sock *sk)
*
* If we are in FINWAIT-2, a received FIN moves us to TIME-WAIT.
*/
-static void tcp_fin(struct sock *sk)
+void tcp_fin(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
const struct dst_entry *dst;
--
1.8.5.3
More information about the CRIU
mailing list