aboutgitcodebugslistschat
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2022-01-26 16:39:33 +0100
committerStefano Brivio <sbrivio@redhat.com>2022-01-28 18:51:50 +0100
commit34e642923538a05ac21d7e7495da23fb0da56c5f (patch)
tree7bf87c1259114dd95d05302d9fdc9aa985edbab7
parentb1f5688495665269fb17732a3c7fb91c709e61b6 (diff)
downloadpasst-34e642923538a05ac21d7e7495da23fb0da56c5f.tar
passt-34e642923538a05ac21d7e7495da23fb0da56c5f.tar.gz
passt-34e642923538a05ac21d7e7495da23fb0da56c5f.tar.bz2
passt-34e642923538a05ac21d7e7495da23fb0da56c5f.tar.lz
passt-34e642923538a05ac21d7e7495da23fb0da56c5f.tar.xz
passt-34e642923538a05ac21d7e7495da23fb0da56c5f.tar.zst
passt-34e642923538a05ac21d7e7495da23fb0da56c5f.zip
passt, tap: Daemonise once socket is ready without waiting for connection
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@redhat.com>
-rw-r--r--passt.c6
-rw-r--r--tap.c62
-rw-r--r--tap.h2
-rw-r--r--tcp.c2
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--;