[CRIU] [PATCH 4/4] soccr: Move src/dst address from _data

Pavel Emelyanov xemul at virtuozzo.com
Wed Dec 14 01:41:45 PST 2016


Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
 criu/sk-tcp.c |  8 +++++--
 soccr/soccr.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++-------------
 soccr/soccr.h | 19 ++++++++++++---
 3 files changed, 81 insertions(+), 21 deletions(-)

diff --git a/criu/sk-tcp.c b/criu/sk-tcp.c
index bfc5cb9..6f04bdb 100644
--- a/criu/sk-tcp.c
+++ b/criu/sk-tcp.c
@@ -285,6 +285,7 @@ static int restore_tcp_conn_state(int sk, struct libsoccr_sk *socr, struct inet_
 	struct cr_img *img;
 	TcpStreamEntry *tse;
 	struct libsoccr_sk_data data = {};
+	union libsoccr_addr sa_src, sa_dst;
 
 	pr_info("Restoring TCP connection id %x ino %x\n", ii->ie->id, ii->ie->ino);
 
@@ -335,15 +336,18 @@ static int restore_tcp_conn_state(int sk, struct libsoccr_sk *socr, struct inet_
 		data.rcv_wup = tse->rcv_wup;
 	}
 
-	if (restore_sockaddr(&data.src_addr,
+	if (restore_sockaddr(&sa_src,
 				ii->ie->family, ii->ie->src_port,
 				ii->ie->src_addr, 0) < 0)
 		goto err_c;
-	if (restore_sockaddr(&data.dst_addr,
+	if (restore_sockaddr(&sa_dst,
 				ii->ie->family, ii->ie->dst_port,
 				ii->ie->dst_addr, 0) < 0)
 		goto err_c;
 
+	libsoccr_set_addr(socr, 1, &sa_src, 0);
+	libsoccr_set_addr(socr, 0, &sa_dst, 0);
+
 	/*
 	 * O_NONBLOCK has to be set before libsoccr_restore(),
 	 * it is required to restore syn-sent sockets.
diff --git a/soccr/soccr.c b/soccr/soccr.c
index 11ac28c..ebd0374 100644
--- a/soccr/soccr.c
+++ b/soccr/soccr.c
@@ -107,10 +107,14 @@ struct libsoccr_sk {
 	unsigned flags;
 	char *recv_queue;
 	char *send_queue;
+	union libsoccr_addr *src_addr;
+	union libsoccr_addr *dst_addr;
 };
 
 #define SK_FLAG_FREE_RQ		0x1
 #define SK_FLAG_FREE_SQ		0x2
+#define SK_FLAG_FREE_SA		0x4
+#define SK_FLAG_FREE_DA		0x8
 
 struct libsoccr_sk *libsoccr_pause(int fd)
 {
@@ -128,6 +132,8 @@ struct libsoccr_sk *libsoccr_pause(int fd)
 	ret->flags = 0;
 	ret->recv_queue = NULL;
 	ret->send_queue = NULL;
+	ret->src_addr = NULL;
+	ret->dst_addr = NULL;
 	ret->fd = fd;
 	return ret;
 }
@@ -139,6 +145,10 @@ void libsoccr_resume(struct libsoccr_sk *sk)
 		free(sk->recv_queue);
 	if (sk->flags & SK_FLAG_FREE_SQ)
 		free(sk->send_queue);
+	if (sk->flags & SK_FLAG_FREE_SA)
+		free(sk->src_addr);
+	if (sk->flags & SK_FLAG_FREE_DA)
+		free(sk->dst_addr);
 	free(sk);
 }
 
@@ -389,6 +399,16 @@ char *libsoccr_get_queue_bytes(struct libsoccr_sk *sk, int queue_id, unsigned fl
 	return ret;
 }
 
+#define GET_SA_FLAGS	(SOCCR_MEM_EXCL)
+union libsoccr_addr *libsoccr_get_addr(struct libsoccr_sk *sk, int self, unsigned flags)
+{
+	if (flags & ~GET_SA_FLAGS)
+		return NULL;
+
+	/* FIXME -- implemeted in CRIU, makes sence to have it here too */
+	return NULL;
+}
+
 static int set_queue_seq(struct libsoccr_sk *sk, int queue, __u32 seq)
 {
 	logd("\tSetting %d queue seq to %u\n", queue, seq);
@@ -421,6 +441,9 @@ static int libsoccr_set_sk_data_noq(struct libsoccr_sk *sk,
 	if (!data || data_size < SOCR_DATA_MIN_SIZE)
 		return -1;
 
+	if (!sk->dst_addr || !sk->src_addr)
+		return -1;
+
 	mstate = 1 << data->state;
 
 	if (data->state == TCP_LISTEN)
@@ -444,15 +467,15 @@ static int libsoccr_set_sk_data_noq(struct libsoccr_sk *sk,
 	if (set_queue_seq(sk, TCP_SEND_QUEUE, seq))
 		return -3;
 
-	if (data->dst_addr.sa.sa_family == AF_INET)
-		addr_size = sizeof(data->dst_addr.v4);
+	if (sk->dst_addr->sa.sa_family == AF_INET)
+		addr_size = sizeof(sk->dst_addr->v4);
 	else
-		addr_size = sizeof(data->dst_addr.v6);
+		addr_size = sizeof(sk->dst_addr->v6);
 
 	if (data->state == TCP_SYN_SENT && tcp_repair_off(sk->fd))
 		return -1;
 
-	if (connect(sk->fd, &data->dst_addr.sa, addr_size) == -1 &&
+	if (connect(sk->fd, &sk->dst_addr->sa, addr_size) == -1 &&
 						errno != EINPROGRESS) {
 		loge("Can't connect inet socket back\n");
 		return -1;
@@ -508,7 +531,8 @@ static int libsoccr_set_sk_data_noq(struct libsoccr_sk *sk,
 	return 0;
 }
 
-static int send_fin(struct libsoccr_sk_data *data, unsigned data_size, uint8_t flags)
+static int send_fin(struct libsoccr_sk *sk, struct libsoccr_sk_data *data,
+		unsigned data_size, uint8_t flags)
 {
 	int ret, exit_code = -1;
 	char errbuf[LIBNET_ERRBUF_SIZE];
@@ -516,7 +540,7 @@ static int send_fin(struct libsoccr_sk_data *data, unsigned data_size, uint8_t f
 	int libnet_type;
 	libnet_t *l;
 
-	if (data->dst_addr.sa.sa_family == AF_INET6)
+	if (sk->dst_addr->sa.sa_family == AF_INET6)
 		libnet_type = LIBNET_RAW6;
 	else
 		libnet_type = LIBNET_RAW4;
@@ -532,8 +556,8 @@ static int send_fin(struct libsoccr_sk_data *data, unsigned data_size, uint8_t f
 		goto err;
 
 	ret = libnet_build_tcp(
-		ntohs(data->dst_addr.v4.sin_port),		/* source port */
-		ntohs(data->src_addr.v4.sin_port),		/* destination port */
+		ntohs(sk->dst_addr->v4.sin_port),		/* source port */
+		ntohs(sk->src_addr->v4.sin_port),		/* destination port */
 		data->inq_seq,			/* sequence number */
 		data->outq_seq - data->outq_len,	/* acknowledgement num */
 		flags,				/* control flags */
@@ -550,11 +574,11 @@ static int send_fin(struct libsoccr_sk_data *data, unsigned data_size, uint8_t f
 		goto err;
 	}
 
-	if (data->dst_addr.sa.sa_family == AF_INET6) {
+	if (sk->dst_addr->sa.sa_family == AF_INET6) {
 		struct libnet_in6_addr src, dst;
 
-		memcpy(&dst, &data->dst_addr.v6.sin6_addr, sizeof(dst));
-		memcpy(&src, &data->src_addr.v6.sin6_addr, sizeof(src));
+		memcpy(&dst, &sk->dst_addr->v6.sin6_addr, sizeof(dst));
+		memcpy(&src, &sk->src_addr->v6.sin6_addr, sizeof(src));
 
 		ret = libnet_build_ipv6(
 			0, 0,
@@ -567,7 +591,7 @@ static int send_fin(struct libsoccr_sk_data *data, unsigned data_size, uint8_t f
 			0,		/* payload size */
 			l,		/* libnet handle */
 			0);		/* libnet id */
-	} else if (data->dst_addr.sa.sa_family == AF_INET)
+	} else if (sk->dst_addr->sa.sa_family == AF_INET)
 		ret = libnet_build_ipv4(
 			LIBNET_IPV4_H + LIBNET_TCP_H + 20,	/* length */
 			0,			/* TOS */
@@ -576,8 +600,8 @@ static int send_fin(struct libsoccr_sk_data *data, unsigned data_size, uint8_t f
 			64,			/* TTL */
 			IPPROTO_TCP,		/* protocol */
 			0,			/* checksum */
-			data->dst_addr.v4.sin_addr.s_addr,	/* source IP */
-			data->src_addr.v4.sin_addr.s_addr,	/* destination IP */
+			sk->dst_addr->v4.sin_addr.s_addr,	/* source IP */
+			sk->src_addr->v4.sin_addr.s_addr,	/* destination IP */
 			NULL,			/* payload */
 			0,			/* payload size */
 			l,			/* libnet handle */
@@ -680,7 +704,7 @@ int libsoccr_restore(struct libsoccr_sk *sk,
 
 	/* Send a fin packet to the socket to restore it in a receive queue. */
 	if (mstate & (RCVQ_FIRST_FIN | RCVQ_SECOND_FIN))
-		if (send_fin(data, data_size, TH_ACK | TH_FIN) < 0)
+		if (send_fin(sk, data, data_size, TH_ACK | TH_FIN) < 0)
 			return -1;
 
 	if (mstate & SNDQ_SECOND_FIN)
@@ -691,7 +715,7 @@ int libsoccr_restore(struct libsoccr_sk *sk,
 
 	if (mstate & SNDQ_FIN_ACKED) {
 		data->outq_seq++;
-		if (send_fin(data, data_size, TH_ACK) < 0)
+		if (send_fin(sk, data, data_size, TH_ACK) < 0)
 			return -1;
 	}
 
@@ -827,3 +851,22 @@ int libsoccr_set_queue_bytes(struct libsoccr_sk *sk, int queue_id, char *bytes,
 
 	return -1;
 }
+
+#define SET_SA_FLAGS	(SOCCR_MEM_EXCL)
+int libsoccr_set_addr(struct libsoccr_sk *sk, int self, union libsoccr_addr *addr, unsigned flags)
+{
+	if (flags & ~SET_SA_FLAGS)
+		return -1;
+
+	if (self) {
+		sk->src_addr = addr;
+		if (flags & SOCCR_MEM_EXCL)
+			sk->flags |= SK_FLAG_FREE_SA;
+	} else {
+		sk->dst_addr = addr;
+		if (flags & SOCCR_MEM_EXCL)
+			sk->flags |= SK_FLAG_FREE_DA;
+	}
+
+	return 0;
+}
diff --git a/soccr/soccr.h b/soccr/soccr.h
index cd73271..f46116a 100644
--- a/soccr/soccr.h
+++ b/soccr/soccr.h
@@ -90,9 +90,6 @@ struct libsoccr_sk_data {
 	__u32	max_window;
 	__u32	rcv_wnd;
 	__u32	rcv_wup;
-
-	union libsoccr_addr src_addr;
-	union libsoccr_addr dst_addr;
 };
 
 /*
@@ -184,6 +181,13 @@ int libsoccr_save(struct libsoccr_sk *sk, struct libsoccr_sk_data *data, unsigne
 char *libsoccr_get_queue_bytes(struct libsoccr_sk *sk, int queue_id, unsigned flags);
 
 /*
+ * Returns filled libsoccr_addr for a socket. This value is also required
+ * on restore, but addresses may be obtained from somewhere else, these
+ * are just common sockaddr-s.
+ */
+union libsoccr_addr *libsoccr_get_addr(struct libsoccr_sk *sk, int self, unsigned flags);
+
+/*
  * RESTORING calls
  *
  * The restoring of a socket is like below
@@ -195,6 +199,8 @@ char *libsoccr_get_queue_bytes(struct libsoccr_sk *sk, int queue_id, unsigned fl
  * 	h = libsoccr_pause(sk)
  * 	libsoccr_set_queue_bytes(h, TCP_SEND_QUEUE, outq);
  * 	libsoccr_set_queue_bytes(h, TCP_RECV_QUEUE, inq);
+ * 	libsoccr_set_addr(h, 1, src_addr);
+ * 	libsoccr_set_addr(h, 0, dst_addr);
  * 	libsoccr_restore(h, &data, sizeof(data))
  *
  * 	libsoccr_resume(h)
@@ -211,6 +217,13 @@ char *libsoccr_get_queue_bytes(struct libsoccr_sk *sk, int queue_id, unsigned fl
 int libsoccr_set_queue_bytes(struct libsoccr_sk *sk, int queue_id, char *bytes, unsigned flags);
 
 /*
+ * Set a pointer on the libsoccr_addr for src/dst.
+ * If flags have SOCCR_MEM_EXCL, the buffer is stolen by the library and is 
+ * fre()-ed after libsoccr_resume().
+ */
+int libsoccr_set_addr(struct libsoccr_sk *sk, int self, union libsoccr_addr *, unsigned flags);
+
+/*
  * Performs restore actions on bind()-ed socket
  */
 int libsoccr_restore(struct libsoccr_sk *sk, struct libsoccr_sk_data *data, unsigned data_size);
-- 
2.5.0



More information about the CRIU mailing list