[05/11] tcp: allow to dump intermediate closing states

Submitted by Andrei Vagin on Nov. 11, 2016, 7:10 a.m.

Details

Message ID 1478848211-23802-6-git-send-email-avagin@openvz.org
State Superseded
Series "tcp: add support of half closed tcp sockets"
Headers show

Commit Message

Andrei Vagin Nov. 11, 2016, 7:10 a.m.
From: Andrei Vagin <avagin@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@virtuozzo.com>
---
 criu/net.c       |  3 +++
 criu/netfilter.c |  4 +++-
 criu/sk-inet.c   | 21 +++++++++++++--------
 criu/sk-tcp.c    | 13 +++++++++++--
 criu/sockets.c   | 10 ++++++++--
 5 files changed, 38 insertions(+), 13 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/net.c b/criu/net.c
index 6e4cfea..546ebdd 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"
@@ -1763,6 +1765,7 @@  static 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 2ba331e..d9c3df1 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 5807ed2..b1779a6 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);
@@ -488,7 +493,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)
@@ -666,7 +671,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 a702abc..e790bba 100644
--- a/criu/sk-tcp.c
+++ b/criu/sk-tcp.c
@@ -224,7 +224,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");
@@ -301,7 +301,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;
@@ -336,6 +336,15 @@  static int restore_tcp_conn_state(int sk, struct libsoccr_sk *socr, struct inet_
 		data.rcv_wup = tse->rcv_wup;
 	}
 
+	if (kdat.has_tcp_half_closed) {
+		data.flags |= SOCCR_FLAGS_ADDR;
+		data.family = ii->ie->family;
+		data.src_port = ii->ie->src_port;
+		data.dst_port = ii->ie->dst_port;
+		memcpy(data.src_addr, ii->ie->src_addr, sizeof(data.src_addr));
+		memcpy(data.dst_addr, ii->ie->dst_addr, sizeof(data.dst_addr));
+	}
+
 	(void)data;
 
 	if (libsoccr_set_sk_data_unbound(socr, &data, sizeof(data)))
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;