aboutgitcodebugslistschat
diff options
context:
space:
mode:
-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--;