[CRIU] [PATCH 07/14] soccr/tcp: Fill actual connection info using the library

Pavel Emelyanov xemul at virtuozzo.com
Mon Apr 18 06:04:47 PDT 2016


This just moves the code from criu/sk-tcp.c into soccr/.

Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
 criu/sk-tcp.c | 122 ++++++++--------------------------------------------------
 soccr/soccr.c |  91 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 106 insertions(+), 107 deletions(-)

diff --git a/criu/sk-tcp.c b/criu/sk-tcp.c
index c512ad1..bc64e89 100644
--- a/criu/sk-tcp.c
+++ b/criu/sk-tcp.c
@@ -1,6 +1,4 @@
 #include <netinet/tcp.h>
-#include <sys/ioctl.h>
-#include <linux/sockios.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <sys/mman.h>
@@ -29,11 +27,6 @@
 #include "protobuf.h"
 #include "images/tcp-stream.pb-c.h"
 
-#ifndef SIOCOUTQNSD
-/* MAO - Define SIOCOUTQNSD ioctl if we don't have it */
-#define SIOCOUTQNSD     0x894B
-#endif
-
 #ifndef CONFIG_HAS_TCP_REPAIR
 /*
  * It's been reported that both tcp_repair_opt
@@ -77,48 +70,6 @@ static int tcp_repair_on(int fd)
 	return ret;
 }
 
-static int refresh_inet_sk(struct inet_sk_desc *sk, struct tcp_info *ti)
-{
-	int size;
-
-	if (dump_opt(sk->rfd, SOL_TCP, TCP_INFO, ti)) {
-		pr_perror("Failed to obtain TCP_INFO");
-		return -1;
-	}
-
-	switch (ti->tcpi_state) {
-	case TCP_ESTABLISHED:
-	case TCP_CLOSE:
-		break;
-	default:
-		pr_err("Unknown state %d\n", sk->state);
-		return -1;
-	}
-
-	if (ioctl(sk->rfd, SIOCOUTQ, &size) == -1) {
-		pr_perror("Unable to get size of snd queue");
-		return -1;
-	}
-
-	sk->wqlen = size;
-
-	if (ioctl(sk->rfd, SIOCOUTQNSD, &size) == -1) {
-		pr_perror("Unable to get size of unsent data");
-		return -1;
-	}
-
-	sk->uwqlen = size;
-
-	if (ioctl(sk->rfd, SIOCINQ, &size) == -1) {
-		pr_perror("Unable to get size of recv queue");
-		return -1;
-	}
-
-	sk->rqlen = size;
-
-	return 0;
-}
-
 static int tcp_repair_establised(int fd, struct inet_sk_desc *sk)
 {
 	int ret;
@@ -267,52 +218,10 @@ err_recv:
 	goto err_buf;
 }
 
-static int tcp_stream_get_options(int sk, struct tcp_info *ti, TcpStreamEntry *tse)
-{
-	int ret;
-	socklen_t auxl;
-	int val;
-
-	auxl = sizeof(tse->mss_clamp);
-	ret = getsockopt(sk, SOL_TCP, TCP_MAXSEG, &tse->mss_clamp, &auxl);
-	if (ret < 0)
-		goto err_sopt;
-
-	tse->opt_mask = ti->tcpi_options;
-	if (ti->tcpi_options & TCPI_OPT_WSCALE) {
-		tse->snd_wscale = ti->tcpi_snd_wscale;
-		tse->rcv_wscale = ti->tcpi_rcv_wscale;
-		tse->has_rcv_wscale = true;
-	}
-
-	if (ti->tcpi_options & TCPI_OPT_TIMESTAMPS) {
-		auxl = sizeof(val);
-		ret = getsockopt(sk, SOL_TCP, TCP_TIMESTAMP, &val, &auxl);
-		if (ret < 0)
-			goto err_sopt;
-
-		tse->has_timestamp = true;
-		tse->timestamp = val;
-	}
-
-	pr_info("\toptions: mss_clamp %x wscale %x tstamp %d sack %d\n",
-			(int)tse->mss_clamp,
-			ti->tcpi_options & TCPI_OPT_WSCALE ? (int)tse->snd_wscale : -1,
-			ti->tcpi_options & TCPI_OPT_TIMESTAMPS ? 1 : 0,
-			ti->tcpi_options & TCPI_OPT_SACK ? 1 : 0);
-
-	return 0;
-
-err_sopt:
-	pr_perror("\tsockopt failed");
-	return -1;
-}
-
 static int dump_tcp_conn_state(struct inet_sk_desc *sk)
 {
 	struct libsoccr_sk *socr = sk->priv;
 	int ret, aux;
-	struct tcp_info ti;
 	struct cr_img *img;
 	TcpStreamEntry tse = TCP_STREAM_ENTRY__INIT;
 	char *in_buf, *out_buf;
@@ -327,16 +236,27 @@ static int dump_tcp_conn_state(struct inet_sk_desc *sk)
 		goto err_r;
 	}
 
-	ret = refresh_inet_sk(sk, &ti);
-	if (ret < 0)
-		goto err_r;
+	tse.inq_len = data.inq_len;
+	tse.outq_len = data.outq_len;
+	tse.unsq_len = data.unsq_len;
+	tse.has_unsq_len = true;
+	tse.mss_clamp = data.mss_clamp;
+	tse.opt_mask = data.opt_mask;
+	if (tse.opt_mask & TCPI_OPT_WSCALE) {
+		tse.snd_wscale = data.snd_wscale;
+		tse.rcv_wscale = data.rcv_wscale;
+		tse.has_rcv_wscale = true;
+	}
+	if (tse.opt_mask & TCPI_OPT_TIMESTAMPS) {
+		tse.timestamp = data.timestamp;
+		tse.has_timestamp = true;
+	}
 
 	/*
 	 * Read queue
 	 */
 
 	pr_info("Reading inq for socket\n");
-	tse.inq_len = sk->rqlen;
 	ret = tcp_stream_get_queue(sk->rfd, TCP_RECV_QUEUE,
 			&tse.inq_seq, tse.inq_len, &in_buf);
 	if (ret < 0)
@@ -347,24 +267,12 @@ static int dump_tcp_conn_state(struct inet_sk_desc *sk)
 	 */
 
 	pr_info("Reading outq for socket\n");
-	tse.outq_len = sk->wqlen;
-	tse.unsq_len = sk->uwqlen;
-	tse.has_unsq_len = true;
 	ret = tcp_stream_get_queue(sk->rfd, TCP_SEND_QUEUE,
 			&tse.outq_seq, tse.outq_len, &out_buf);
 	if (ret < 0)
 		goto err_out;
 
 	/*
-	 * Initial options
-	 */
-
-	pr_info("Reading options for socket\n");
-	ret = tcp_stream_get_options(sk->rfd, &ti, &tse);
-	if (ret < 0)
-		goto err_opt;
-
-	/*
 	 * TCP socket options
 	 */
 
diff --git a/soccr/soccr.c b/soccr/soccr.c
index c858452..13dc317 100644
--- a/soccr/soccr.c
+++ b/soccr/soccr.c
@@ -1,8 +1,15 @@
 #include <netinet/tcp.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/ioctl.h>
+#include <linux/sockios.h>
 #include "soccr.h"
 
+#ifndef SIOCOUTQNSD
+/* MAO - Define SIOCOUTQNSD ioctl if we don't have it */
+#define SIOCOUTQNSD     0x894B
+#endif
+
 static void (*log)(unsigned int loglevel, const char *format, ...)
 	__attribute__ ((__format__ (__printf__, 2, 3)));
 static unsigned int log_level = 0;
@@ -63,6 +70,82 @@ void libsoccr_resume(struct libsoccr_sk *sk)
 	free(sk);
 }
 
+static int refresh_sk(struct libsoccr_sk *sk, struct libsoccr_sk_data *data, struct tcp_info *ti)
+{
+	int size;
+	socklen_t olen = sizeof(*ti);
+
+	if (getsockopt(sk->fd, SOL_TCP, TCP_INFO, ti, &olen) || olen != sizeof(*ti)) {
+		loge("Failed to obtain TCP_INFO");
+		return -1;
+	}
+
+	switch (ti->tcpi_state) {
+	case TCP_ESTABLISHED:
+	case TCP_CLOSE:
+		break;
+	default:
+		loge("Unknown state %d\n", ti->tcpi_state);
+		return -1;
+	}
+
+	if (ioctl(sk->fd, SIOCOUTQ, &size) == -1) {
+		loge("Unable to get size of snd queue");
+		return -1;
+	}
+
+	data->outq_len = size;
+
+	if (ioctl(sk->fd, SIOCOUTQNSD, &size) == -1) {
+		loge("Unable to get size of unsent data");
+		return -1;
+	}
+
+	data->unsq_len = size;
+
+	if (ioctl(sk->fd, SIOCINQ, &size) == -1) {
+		loge("Unable to get size of recv queue");
+		return -1;
+	}
+
+	data->inq_len = size;
+
+	return 0;
+}
+
+static int get_stream_options(struct libsoccr_sk *sk, struct libsoccr_sk_data *data, struct tcp_info *ti)
+{
+	int ret;
+	socklen_t auxl;
+	int val;
+
+	auxl = sizeof(data->mss_clamp);
+	ret = getsockopt(sk->fd, SOL_TCP, TCP_MAXSEG, &data->mss_clamp, &auxl);
+	if (ret < 0)
+		goto err_sopt;
+
+	data->opt_mask = ti->tcpi_options;
+	if (ti->tcpi_options & TCPI_OPT_WSCALE) {
+		data->snd_wscale = ti->tcpi_snd_wscale;
+		data->rcv_wscale = ti->tcpi_rcv_wscale;
+	}
+
+	if (ti->tcpi_options & TCPI_OPT_TIMESTAMPS) {
+		auxl = sizeof(val);
+		ret = getsockopt(sk->fd, SOL_TCP, TCP_TIMESTAMP, &val, &auxl);
+		if (ret < 0)
+			goto err_sopt;
+
+		data->timestamp = val;
+	}
+
+	return 0;
+
+err_sopt:
+	loge("\tsockopt failed");
+	return -1;
+}
+
 /*
  * This is how much data we've had in the initial libsoccr
  */
@@ -70,10 +153,18 @@ void libsoccr_resume(struct libsoccr_sk *sk)
 
 int libsoccr_get_sk_data(struct libsoccr_sk *sk, struct libsoccr_sk_data *data, unsigned data_size)
 {
+	struct tcp_info ti;
+
 	if (!data || data_size < SOCR_DATA_MIN_SIZE)
 		return -1;
 
 	memset(data, 0, data_size);
 
+	if (refresh_sk(sk, data, &ti))
+		return -2;
+
+	if (get_stream_options(sk, data, &ti))
+		return -3;
+
 	return sizeof(struct libsoccr_sk_data);
 }
-- 
2.5.0



More information about the CRIU mailing list