public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: Stefano Brivio <sbrivio@redhat.com>
To: passt-dev@passt.top
Subject: [PATCH 1/4] passt, tap: Daemonise once socket is ready without waiting for connection
Date: Fri, 28 Jan 2022 19:34:06 +0100	[thread overview]
Message-ID: <20220128183409.3407795-2-sbrivio@redhat.com> (raw)
In-Reply-To: <20220128183409.3407795-1-sbrivio@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 6174 bytes --]

The existing behaviour is not really practical: an automated agent in
charge of starting both qemu and passt would need to fork itself to
start passt, because passt won't fork to background until qemu
connects, and the agent needs to unblock to start qemu.

Instead of waiting for a connection to daemonise, do it right away as
soon as a socket is available: that can be considered an initialised
state already.

Signed-off-by: Stefano Brivio <sbrivio(a)redhat.com>
---
 passt.c |  6 ++++--
 tap.c   | 62 +++++++++++++++++++++++++++++++++++++++++----------------
 tap.h   |  2 +-
 tcp.c   |  2 +-
 4 files changed, 51 insertions(+), 21 deletions(-)

diff --git a/passt.c b/passt.c
index 3c9fb90..a8bb88e 100644
--- a/passt.c
+++ b/passt.c
@@ -345,6 +345,7 @@ int main(int argc, char **argv)
 	}
 	sock_probe_mem(&c);
 
+	c.fd_tap = c.fd_tap_listen = -1;
 	tap_sock_init(&c);
 
 	clock_gettime(CLOCK_MONOTONIC, &now);
@@ -387,9 +388,10 @@ loop:
 
 	for (i = 0; i < nfds; i++) {
 		union epoll_ref ref = *((union epoll_ref *)&events[i].data.u64);
+		int fd = events[i].data.fd;
 
-		if (events[i].data.fd == c.fd_tap)
-			tap_handler(&c, events[i].events, &now);
+		if (fd == c.fd_tap || fd == c.fd_tap_listen)
+			tap_handler(&c, fd, events[i].events, &now);
 		else
 			sock_handler(&c, ref, events[i].events, &now);
 	}
diff --git a/tap.c b/tap.c
index 2bf6f71..34a5705 100644
--- a/tap.c
+++ b/tap.c
@@ -769,7 +769,7 @@ restart:
 }
 
 /**
- * tap_sock_init_unix() - Create and bind AF_UNIX socket, wait for connection
+ * tap_sock_init_unix() - Create and bind AF_UNIX socket, listen for connection
  * @c:		Execution context
  *
  * #syscalls:passt unlink|unlinkat
@@ -777,19 +777,21 @@ restart:
 static void tap_sock_init_unix(struct ctx *c)
 {
 	int fd = socket(AF_UNIX, SOCK_STREAM, 0), ex;
+	struct epoll_event ev = { 0 };
 	struct sockaddr_un addr = {
 		.sun_family = AF_UNIX,
 	};
-	int i, ret, v = INT_MAX / 2;
+	int i, ret;
 
-	if (c->fd_tap_listen)
+	if (c->fd_tap_listen != -1) {
+		epoll_ctl(c->epollfd, EPOLL_CTL_DEL, c->fd_tap_listen, &ev);
 		close(c->fd_tap_listen);
+	}
 
 	if (fd < 0) {
 		perror("UNIX socket");
 		exit(EXIT_FAILURE);
 	}
-	c->fd_tap_listen = fd;
 
 	for (i = 1; i < UNIX_SOCK_MAX; i++) {
 		char *path = addr.sun_path;
@@ -836,6 +838,10 @@ static void tap_sock_init_unix(struct ctx *c)
 
 	listen(fd, 0);
 
+	ev.data.fd = c->fd_tap_listen = fd;
+	ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
+	epoll_ctl(c->epollfd, EPOLL_CTL_ADD, c->fd_tap_listen, &ev);
+
 	info("You can now start qrap:");
 	info("    ./qrap 5 kvm ... -net socket,fd=5 -net nic,model=virtio");
 	info("or directly qemu, patched with:");
@@ -843,14 +849,32 @@ static void tap_sock_init_unix(struct ctx *c)
 	info("as follows:");
 	info("    kvm ... -net socket,connect=%s -net nic,model=virtio",
 	     addr.sun_path);
+}
 
-	c->fd_tap = accept(fd, NULL, NULL);
+/**
+ * tap_sock_accept_unix() - Accept connection on listening socket
+ * @c:		Execution context
+ */
+static void tap_sock_accept_unix(struct ctx *c)
+{
+	struct epoll_event ev = { 0 };
+	int v = INT_MAX / 2;
+
+	c->fd_tap = accept(c->fd_tap_listen, NULL, NULL);
+
+	epoll_ctl(c->epollfd, EPOLL_CTL_DEL, c->fd_tap_listen, &ev);
+	close(c->fd_tap_listen);
+	c->fd_tap_listen = -1;
 
 	if (!c->low_rmem)
 		setsockopt(c->fd_tap, SOL_SOCKET, SO_RCVBUF, &v, sizeof(v));
 
 	if (!c->low_wmem)
 		setsockopt(c->fd_tap, SOL_SOCKET, SO_SNDBUF, &v, sizeof(v));
+
+	ev.data.fd = c->fd_tap;
+	ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
+	epoll_ctl(c->epollfd, EPOLL_CTL_ADD, c->fd_tap, &ev);
 }
 
 static int tun_ns_fd = -1;
@@ -885,6 +909,8 @@ static int tap_ns_tun(void *arg)
  */
 static void tap_sock_init_tun(struct ctx *c)
 {
+	struct epoll_event ev = { 0 };
+
 	NS_CALL(tap_ns_tun, c);
 	if (tun_ns_fd == -1) {
 		err("Failed to open tun socket in namespace");
@@ -896,6 +922,10 @@ static void tap_sock_init_tun(struct ctx *c)
 	pcap_init(c, c->pasta_netns_fd);
 
 	c->fd_tap = tun_ns_fd;
+
+	ev.data.fd = c->fd_tap;
+	ev.events = EPOLLIN | EPOLLRDHUP;
+	epoll_ctl(c->epollfd, EPOLL_CTL_ADD, c->fd_tap, &ev);
 }
 
 /**
@@ -904,33 +934,31 @@ static void tap_sock_init_tun(struct ctx *c)
  */
 void tap_sock_init(struct ctx *c)
 {
-	struct epoll_event ev = { 0 };
-
-	if (c->fd_tap) {
+	if (c->fd_tap != -1) {
 		epoll_ctl(c->epollfd, EPOLL_CTL_DEL, c->fd_tap, NULL);
 		close(c->fd_tap);
 	}
 
-	if (c->mode == MODE_PASST) {
+	if (c->mode == MODE_PASST)
 		tap_sock_init_unix(c);
-		ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
-	} else {
+	else
 		tap_sock_init_tun(c);
-		ev.events = EPOLLIN | EPOLLRDHUP;
-	}
-
-	ev.data.fd = c->fd_tap;
-	epoll_ctl(c->epollfd, EPOLL_CTL_ADD, c->fd_tap, &ev);
 }
 
 /**
  * tap_handler() - Packet handler for AF_UNIX or tuntap file descriptor
  * @c:		Execution context
+ * @fd:		File descriptor where event occurred
  * @events:	epoll events
  * @now:	Current timestamp
  */
-void tap_handler(struct ctx *c, uint32_t events, struct timespec *now)
+void tap_handler(struct ctx *c, int fd, uint32_t events, struct timespec *now)
 {
+	if (fd == c->fd_tap_listen && events == EPOLLIN) {
+		tap_sock_accept_unix(c);
+		return;
+	}
+
 	if (events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR))
 		goto fail;
 
diff --git a/tap.h b/tap.h
index c437f5f..8942fcf 100644
--- a/tap.h
+++ b/tap.h
@@ -6,5 +6,5 @@
 void tap_ip_send(struct ctx *c, struct in6_addr *src, uint8_t proto,
 		 char *in, size_t len, uint32_t flow);
 int tap_send(struct ctx *c, void *data, size_t len, int vnet_pre);
-void tap_handler(struct ctx *c, uint32_t events, struct timespec *now);
+void tap_handler(struct ctx *c, int fd, uint32_t events, struct timespec *now);
 void tap_sock_init(struct ctx *c);
diff --git a/tcp.c b/tcp.c
index 01f09e9..7122898 100644
--- a/tcp.c
+++ b/tcp.c
@@ -2319,7 +2319,7 @@ recvmsg:
 				if (errno == EAGAIN || errno == EWOULDBLOCK)
 					return 0;
 
-				tap_handler(c, EPOLLERR, now);
+				tap_handler(c, c->fd_tap, EPOLLERR, now);
 			}
 
 			i--;
-- 
@@ -2319,7 +2319,7 @@ recvmsg:
 				if (errno == EAGAIN || errno == EWOULDBLOCK)
 					return 0;
 
-				tap_handler(c, EPOLLERR, now);
+				tap_handler(c, c->fd_tap, EPOLLERR, now);
 			}
 
 			i--;
-- 
2.33.0


  reply	other threads:[~2022-01-28 18:34 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-28 18:34 [PATCH 0/4] Proof-of-concept for Kata Containers integration Stefano Brivio
2022-01-28 18:34 ` Stefano Brivio [this message]
2022-01-28 18:34 ` [PATCH 2/4] qemu: Rebase patch for UNIX domain socket support to latest upstream Stefano Brivio
2022-01-28 18:34 ` [PATCH 3/4] libvirt, qemu: Move patches to new directory, contrib Stefano Brivio
2022-01-28 18:34 ` [PATCH 4/4] contrib: Introduce PoC for Kata Containers with user-mode networking Stefano Brivio

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220128183409.3407795-2-sbrivio@redhat.com \
    --to=sbrivio@redhat.com \
    --cc=passt-dev@passt.top \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).