[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