[v2,07/15] sk-queue: Allow to dump a skb sender

Submitted by Kirill Tkhai on May 27, 2016, 1:06 p.m.

Details

Message ID 146435440856.31234.14409258406024489940.stgit@pro
State Rejected
Series "Support for packet's msg_name in receive queue of promiscous DGRAM sockets"
Headers show

Commit Message

Kirill Tkhai May 27, 2016, 1:06 p.m.
Add a possibility to dump a packet sender using a method get_sender,
passed by caller.

If there is the only sender of all pending socket's packets, its inode
is returned as result in (*sender_ino). Otherwise, 0 is there (inode 0
can't exist in real world).

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 criu/include/sk-queue.h |    4 +++-
 criu/sk-queue.c         |   53 +++++++++++++++++++++++++++++++++++++++--------
 criu/sk-unix.c          |    4 +++-
 3 files changed, 50 insertions(+), 11 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/include/sk-queue.h b/criu/include/sk-queue.h
index e0a47af..93498e3 100644
--- a/criu/include/sk-queue.h
+++ b/criu/include/sk-queue.h
@@ -1,8 +1,10 @@ 
 #ifndef __CR_SK_QUEUE_H__
 #define __CR_SK_QUEUE_H__
 
+#define SK_NONAME_SENDER	(~0ULL)
+
 extern struct collect_image_info sk_queues_cinfo;
-extern int dump_sk_queue(int sock_fd, int sock_id);
+extern int dump_sk_queue(int sock_fd, int sock_id, u32 (*get_sender)(const char *, int), u64 *sender_ino);
 extern int restore_sk_queue(int fd, unsigned int peer_id);
 
 #endif /* __CR_SK_QUEUE_H__ */
diff --git a/criu/sk-queue.c b/criu/sk-queue.c
index 50854d7..fa3407b 100644
--- a/criu/sk-queue.c
+++ b/criu/sk-queue.c
@@ -59,12 +59,16 @@  struct collect_image_info sk_queues_cinfo = {
 	.collect = collect_one_packet,
 };
 
-int dump_sk_queue(int sock_fd, int sock_id)
+/* Currently known the longest possible sender name thru all socket types */
+#define MAX_MSG_NAME_LEN	(sizeof (struct sockaddr_un))
+
+int dump_sk_queue(int sock_fd, int sock_id, u32 (*get_sender)(const char *, int), u64 *sender_ino)
 {
-	SkPacketEntry pe = SK_PACKET_ENTRY__INIT;
-	int ret, size, orig_peek_off;
-	void *data;
+	int ret, size, orig_peek_off, first = 1;
+	bool only_sender = true;
+	void *data, *mem;
 	socklen_t tmp;
+	u64 next;
 
 	/*
 	 * Save original peek offset.
@@ -87,16 +91,22 @@  int dump_sk_queue(int sock_fd, int sock_id)
 		return ret;
 	}
 
+	if (get_sender)
+		size += MAX_MSG_NAME_LEN;
+
 	/* Note: 32 bytes will be used by kernel for protocol header. */
 	size -= 32;
 
 	/*
 	 * Allocate data for a stream.
 	 */
-	data = xmalloc(size);
-	if (!data)
+	mem = data = xmalloc(size);
+	if (!mem)
 		return -1;
 
+	if (get_sender)
+		data += MAX_MSG_NAME_LEN;
+
 	/*
 	 * Enable peek offset incrementation.
 	 */
@@ -106,9 +116,8 @@  int dump_sk_queue(int sock_fd, int sock_id)
 		goto err_brk;
 	}
 
-	pe.id_for = sock_id;
-
 	while (1) {
+		SkPacketEntry pe = SK_PACKET_ENTRY__INIT;
 		struct iovec iov = {
 			.iov_base	= data,
 			.iov_len	= size,
@@ -118,6 +127,12 @@  int dump_sk_queue(int sock_fd, int sock_id)
 			.msg_iovlen	= 1,
 		};
 
+		if (get_sender) {
+			msg.msg_name	= mem;
+			msg.msg_namelen	= MAX_MSG_NAME_LEN;
+		}
+
+		pe.id_for = sock_id;
 		ret = pe.length = recvmsg(sock_fd, &msg, MSG_DONTWAIT | MSG_PEEK);
 		if (!ret)
 			/*
@@ -141,6 +156,25 @@  int dump_sk_queue(int sock_fd, int sock_id)
 			goto err_set_sock;
 		}
 
+		if (get_sender) {
+			next = get_sender(msg.msg_name, msg.msg_namelen);
+			if (next) {
+				pe.has_sender_ino = true;
+				pe.sender_ino = next;
+			} else
+				next = SK_NONAME_SENDER;
+
+			if (only_sender) {
+				if (first)
+					*sender_ino = next;
+				else if (*sender_ino != next)
+					only_sender = false;
+			}
+
+			if (!only_sender)
+				*sender_ino = 0;
+		}
+
 		ret = pb_write_one(img_from_set(glob_imgset, CR_FD_SK_QUEUES), &pe, PB_SK_QUEUES);
 		if (ret < 0) {
 			ret = -EIO;
@@ -152,6 +186,7 @@  int dump_sk_queue(int sock_fd, int sock_id)
 			ret = -EIO;
 			goto err_set_sock;
 		}
+		first = 0;
 	}
 	ret = 0;
 
@@ -164,7 +199,7 @@  int dump_sk_queue(int sock_fd, int sock_id)
 		ret = -1;
 	}
 err_brk:
-	xfree(data);
+	xfree(mem);
 	return ret;
 }
 
diff --git a/criu/sk-unix.c b/criu/sk-unix.c
index 58aba82..d2342ff 100644
--- a/criu/sk-unix.c
+++ b/criu/sk-unix.c
@@ -52,6 +52,8 @@ 
 #define USK_SERVICE	(1 << 1)
 #define USK_CALLBACK	(1 << 2)
 #define USK_INHERIT	(1 << 3)
+#define USK_EMPTY_Q	(1 << 4)
+#define USK_NONAME_SND	(1 << 5)
 
 typedef struct {
 	char			*dir;
@@ -462,7 +464,7 @@  static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
 	 */
 	if (sk->rqlen != 0 && !(sk->type == SOCK_STREAM &&
 				sk->state == TCP_LISTEN))
-		if (dump_sk_queue(lfd, id))
+		if (dump_sk_queue(lfd, id, NULL, NULL))
 			goto err;
 
 	pr_info("Dumping unix socket at %d\n", p->fd);

Comments

Pavel Emelyanov May 30, 2016, 11:45 a.m.
On 05/27/2016 04:06 PM, Kirill Tkhai wrote:
> Add a possibility to dump a packet sender using a method get_sender,
> passed by caller.
> 
> If there is the only sender of all pending socket's packets, its inode
> is returned as result in (*sender_ino). Otherwise, 0 is there (inode 0
> can't exist in real world).

And what does this set do in case of a socket with several senders in queue?


> @@ -52,6 +52,8 @@
>  #define USK_SERVICE	(1 << 1)
>  #define USK_CALLBACK	(1 << 2)
>  #define USK_INHERIT	(1 << 3)
> +#define USK_EMPTY_Q	(1 << 4)

Why is this bit needed?

> +#define USK_NONAME_SND	(1 << 5)
>  
>  typedef struct {
>  	char			*dir;
Kirill Tkhai May 30, 2016, 12:36 p.m.
On 30.05.2016 14:45, Pavel Emelyanov wrote:
> On 05/27/2016 04:06 PM, Kirill Tkhai wrote:
>> Add a possibility to dump a packet sender using a method get_sender,
>> passed by caller.
>>
>> If there is the only sender of all pending socket's packets, its inode
>> is returned as result in (*sender_ino). Otherwise, 0 is there (inode 0
>> can't exist in real world).
> 
> And what does this set do in case of a socket with several senders in queue?

If there are several senders in queue, get_sender method return 0,
so we dump this socket as has_sender_ino == false, and use this information
on restore.
 
>> @@ -52,6 +52,8 @@
>>  #define USK_SERVICE	(1 << 1)
>>  #define USK_CALLBACK	(1 << 2)
>>  #define USK_INHERIT	(1 << 3)
>> +#define USK_EMPTY_Q	(1 << 4)
> 
> Why is this bit needed?

Empty queue is one of likely cases. This just should speed-up restore stage.
 
>> +#define USK_NONAME_SND	(1 << 5)
>>  
>>  typedef struct {
>>  	char			*dir;
>