[CRIU] [PATCH 12/21] tcp: allow to dump intermediate closing states
Andrei Vagin
avagin at openvz.org
Mon Nov 28 11:27:47 PST 2016
From: Andrei Vagin <avagin at virtuozzo.com>
soccr already knows how to restore this sockets.
CRIU has to ...:
* unlock all packets with the SOCCR_MARK mark
* request half-closed socket via socket_diag
* transpit src and dst addresses to libsoccr
Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
criu/net.c | 3 +++
criu/netfilter.c | 4 +++-
criu/sk-inet.c | 21 +++++++++++++--------
criu/sk-tcp.c | 10 ++++++++--
criu/sockets.c | 10 ++++++++--
images/tcp-stream.proto | 2 ++
6 files changed, 37 insertions(+), 13 deletions(-)
diff --git a/criu/net.c b/criu/net.c
index 329c97c..2b3f13b 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -15,6 +15,8 @@
#include <linux/sockios.h>
#include <libnl3/netlink/msg.h>
+#include "../soccr/soccr.h"
+
#include "imgset.h"
#include "namespaces.h"
#include "net.h"
@@ -1764,6 +1766,7 @@ int network_lock_internal()
":CRIU - [0:0]\n"
"-I INPUT -j CRIU\n"
"-I OUTPUT -j CRIU\n"
+ "-A CRIU -m mark --mark " __stringify(SOCCR_MARK) " -j ACCEPT\n"
"-A CRIU -j DROP\n"
"COMMIT\n";
int ret = 0, nsret;
diff --git a/criu/netfilter.c b/criu/netfilter.c
index 1896365..5942eb0 100644
--- a/criu/netfilter.c
+++ b/criu/netfilter.c
@@ -5,6 +5,8 @@
#include <sys/wait.h>
#include <stdlib.h>
+#include "../soccr/soccr.h"
+
#include "util.h"
#include "common/list.h"
#include "files.h"
@@ -21,7 +23,7 @@ static char buf[512];
*/
#define NF_CONN_CMD "%s %s -t filter %s %s --protocol tcp " \
- "--source %s --sport %d --destination %s --dport %d -j DROP"
+ "-m mark ! --mark " __stringify(SOCCR_MARK) " --source %s --sport %d --destination %s --dport %d -j DROP"
static char iptable_cmd_ipv4[] = "iptables";
static char iptable_cmd_ipv6[] = "ip6tables";
diff --git a/criu/sk-inet.c b/criu/sk-inet.c
index b7ae0c5..6fafa26 100644
--- a/criu/sk-inet.c
+++ b/criu/sk-inet.c
@@ -115,13 +115,13 @@ static int can_dump_inet_sk(const struct inet_sk_desc *sk)
{
BUG_ON((sk->sd.family != AF_INET) && (sk->sd.family != AF_INET6));
- if (sk->shutdown) {
- pr_err("Can't dump shutdown inet socket %x\n",
- sk->sd.ino);
- return 0;
- }
-
if (sk->type == SOCK_DGRAM) {
+ if (sk->shutdown) {
+ pr_err("Can't dump shutdown inet socket %x\n",
+ sk->sd.ino);
+ return 0;
+ }
+
if (sk->wqlen != 0) {
pr_err("Can't dump corked dgram socket %x\n",
sk->sd.ino);
@@ -163,6 +163,11 @@ static int can_dump_inet_sk(const struct inet_sk_desc *sk)
}
break;
case TCP_ESTABLISHED:
+ case TCP_FIN_WAIT2:
+ case TCP_FIN_WAIT1:
+ case TCP_CLOSE_WAIT:
+ case TCP_LAST_ACK:
+ case TCP_CLOSING:
if (!opts.tcp_established_ok) {
pr_err("Connected TCP socket, consider using --%s option.\n",
SK_EST_PARAM);
@@ -483,7 +488,7 @@ static struct file_desc_ops inet_desc_ops = {
static inline int tcp_connection(InetSkEntry *ie)
{
- return (ie->proto == IPPROTO_TCP) && (ie->state == TCP_ESTABLISHED);
+ return (ie->proto == IPPROTO_TCP && ie->dst_port);
}
static int collect_one_inetsk(void *o, ProtobufCMessage *base, struct cr_img *i)
@@ -661,7 +666,7 @@ static int open_inet_sk(struct file_desc *d)
mutex_unlock(&ii->port->reuseaddr_lock);
}
- if (ie->state == TCP_ESTABLISHED &&
+ if (ie->dst_port &&
inet_connect(sk, ii))
goto err;
done:
diff --git a/criu/sk-tcp.c b/criu/sk-tcp.c
index bfe26c1..2637d83 100644
--- a/criu/sk-tcp.c
+++ b/criu/sk-tcp.c
@@ -142,6 +142,11 @@ static int dump_tcp_conn_state(struct inet_sk_desc *sk)
tse.has_unsq_len = true;
tse.mss_clamp = data.mss_clamp;
tse.opt_mask = data.opt_mask;
+
+ tse.has_cr_flags = true;
+ if (data.flags & SOCCR_FLAGS_ACKED_FIN)
+ tse.cr_flags |= SOCCR_FLAGS_ACKED_FIN;
+
if (tse.opt_mask & TCPI_OPT_WSCALE) {
tse.snd_wscale = data.snd_wscale;
tse.rcv_wscale = data.rcv_wscale;
@@ -226,7 +231,7 @@ err_r:
int dump_one_tcp(int fd, struct inet_sk_desc *sk)
{
- if (sk->state != TCP_ESTABLISHED)
+ if (sk->dst_port == 0)
return 0;
pr_info("Dumping TCP connection\n");
@@ -303,7 +308,7 @@ static int restore_tcp_conn_state(int sk, struct libsoccr_sk *socr, struct inet_
goto err_c;
}
- data.state = TCP_ESTABLISHED;
+ data.state = ii->ie->state;;
data.inq_len = tse->inq_len;
data.inq_seq = tse->inq_seq;
data.outq_len = tse->outq_len;
@@ -311,6 +316,7 @@ static int restore_tcp_conn_state(int sk, struct libsoccr_sk *socr, struct inet_
data.unsq_len = tse->unsq_len;
data.mss_clamp = tse->mss_clamp;
data.opt_mask = tse->opt_mask;
+ data.flags |= tse->cr_flags; /* SOCCR_FLAGS_ACKED_FIN */
if (tse->opt_mask & TCPI_OPT_WSCALE) {
if (!tse->has_rcv_wscale) {
pr_err("No rcv wscale in the image\n");
diff --git a/criu/sockets.c b/criu/sockets.c
index b5c03fd..51927bf 100644
--- a/criu/sockets.c
+++ b/criu/sockets.c
@@ -645,7 +645,10 @@ int collect_sockets(struct ns_id *ns)
req.r.i.sdiag_protocol = IPPROTO_TCP;
req.r.i.idiag_ext = 0;
/* Only listening and established sockets supported yet */
- req.r.i.idiag_states = (1 << TCP_LISTEN) | (1 << TCP_ESTABLISHED);
+ req.r.i.idiag_states = (1 << TCP_LISTEN) | (1 << TCP_ESTABLISHED) |
+ (1 << TCP_FIN_WAIT1) | (1 << TCP_FIN_WAIT2) |
+ (1 << TCP_CLOSE_WAIT) | (1 << TCP_LAST_ACK) |
+ (1 << TCP_CLOSING);
tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, &req.r.i);
if (tmp)
err = tmp;
@@ -673,7 +676,10 @@ int collect_sockets(struct ns_id *ns)
req.r.i.sdiag_protocol = IPPROTO_TCP;
req.r.i.idiag_ext = 0;
/* Only listening sockets supported yet */
- req.r.i.idiag_states = (1 << TCP_LISTEN) | (1 << TCP_ESTABLISHED);
+ req.r.i.idiag_states = (1 << TCP_LISTEN) | (1 << TCP_ESTABLISHED) |
+ (1 << TCP_FIN_WAIT1) | (1 << TCP_FIN_WAIT2) |
+ (1 << TCP_CLOSE_WAIT) | (1 << TCP_LAST_ACK) |
+ (1 << TCP_CLOSING);
tmp = do_collect_req(nl, &req, sizeof(req), inet_receive_one, &req.r.i);
if (tmp)
err = tmp;
diff --git a/images/tcp-stream.proto b/images/tcp-stream.proto
index 1740783..3515c3c 100644
--- a/images/tcp-stream.proto
+++ b/images/tcp-stream.proto
@@ -24,4 +24,6 @@ message tcp_stream_entry {
optional uint32 max_window = 15;
optional uint32 rcv_wnd = 16;
optional uint32 rcv_wup = 17;
+
+ optional uint32 cr_flags = 18;
}
--
2.7.4
More information about the CRIU
mailing list