aboutgitcodebugslistschat
diff options
context:
space:
mode:
-rw-r--r--passt.c7
-rw-r--r--qemu/0001-net-Allow-also-UNIX-domain-sockets-to-be-used-as-net.patch176
-rw-r--r--qemu/0002-net-Don-t-ignore-EINVAL-on-netdev-socket-connection.patch31
3 files changed, 213 insertions, 1 deletions
diff --git a/passt.c b/passt.c
index 98576a6..6bc040a 100644
--- a/passt.c
+++ b/passt.c
@@ -562,7 +562,12 @@ listen:
listen(fd_unix, 1);
fprintf(stderr,
"You can now start qrap:\n\t"
- "./qrap 5 kvm ... -net socket,fd=5 -net nic,model=virtio\n\n");
+ "./qrap 5 kvm ... -net socket,fd=5 -net nic,model=virtio\n"
+ "or directly qemu, patched with:\n\t"
+ "qemu/0001-net-Allow-also-UNIX-domain-sockets-to-be-used-as-net.patch\n"
+ "as follows:\n\t"
+ "kvm ... -net socket,connect="
+ UNIX_SOCK_PATH " -net nic,model=virtio\n\n");
c.fd_unix = accept(fd_unix, NULL, NULL);
ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP | EPOLLERR | EPOLLHUP;
diff --git a/qemu/0001-net-Allow-also-UNIX-domain-sockets-to-be-used-as-net.patch b/qemu/0001-net-Allow-also-UNIX-domain-sockets-to-be-used-as-net.patch
new file mode 100644
index 0000000..ef00526
--- /dev/null
+++ b/qemu/0001-net-Allow-also-UNIX-domain-sockets-to-be-used-as-net.patch
@@ -0,0 +1,176 @@
+From 8876676bbdb108f51c372d1347dec1382078d702 Mon Sep 17 00:00:00 2001
+From: Stefano Brivio <sbrivio@redhat.com>
+Date: Wed, 17 Mar 2021 10:33:22 +0100
+Subject: [PATCH 1/2] net: Allow also UNIX domain sockets to be used as -netdev
+ socket
+
+It has lower overhead compared to TCP, doesn't need a free port
+and the adaptation is trivial.
+
+Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
+---
+ net/socket.c | 93 +++++++++++++++++++++++++++++++++++++++++--------
+ qemu-options.hx | 12 +++----
+ 2 files changed, 84 insertions(+), 21 deletions(-)
+
+diff --git a/net/socket.c b/net/socket.c
+index c0de10c0c0..9d06953983 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -528,27 +528,62 @@ static int net_socket_listen_init(NetClientState *peer,
+ {
+ NetClientState *nc;
+ NetSocketState *s;
+- struct sockaddr_in saddr;
+- int fd, ret;
++ struct sockaddr_storage saddr;
++ struct sockaddr_in *saddr_in = (struct sockaddr_in *)&saddr;
++ struct sockaddr_un *saddr_un = (struct sockaddr_un *)&saddr;
++ size_t saddr_size;
++ int fd, ret, pf;
+ NetdevSocketOptions *stored;
+
+- if (parse_host_port(&saddr, host_str, errp) < 0) {
+- return -1;
++#ifndef WIN32
++ if (strchr(host_str, ':')) {
++#endif
++ if (parse_host_port(saddr_in, host_str, errp) < 0)
++ return -1;
++
++ pf = PF_INET;
++ saddr_size = sizeof(*saddr_in);
++#ifndef WIN32
++ } else {
++ struct stat sb;
++
++ if (stat(host_str, &sb) == -1) {
++ error_setg_errno(errp, errno, "can't stat socket path");
++ return -1;
++ }
++
++ if ((sb.st_mode & S_IFMT) != S_IFSOCK) {
++ error_setg_errno(errp, errno, "path provided is not a socket");
++ return -1;
++ }
++
++ saddr_un->sun_family = PF_UNIX;
++ strncpy(saddr_un->sun_path, host_str, sizeof(saddr_un->sun_path));
++
++ pf = PF_UNIX;
++ saddr_size = sizeof(*saddr_un);
+ }
++#endif /* !WIN32 */
+
+- fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
++ fd = qemu_socket(pf, SOCK_STREAM, 0);
+ if (fd < 0) {
+ error_setg_errno(errp, errno, "can't create stream socket");
+ return -1;
+ }
+ qemu_set_nonblock(fd);
+
+- socket_set_fast_reuse(fd);
++ if (pf == PF_INET)
++ socket_set_fast_reuse(fd);
+
+- ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
++ ret = bind(fd, (struct sockaddr *)&saddr, saddr_size);
+ if (ret < 0) {
+- error_setg_errno(errp, errno, "can't bind ip=%s to socket",
+- inet_ntoa(saddr.sin_addr));
++ if (pf == PF_INET)
++ error_setg_errno(errp, errno, "can't bind ip=%s to socket",
++ inet_ntoa(saddr_in->sin_addr));
++ else if (pf == PF_UNIX)
++ error_setg_errno(errp, errno, "can't create socket with path: %s",
++ host_str);
++
+ closesocket(fd);
+ return -1;
+ }
+@@ -586,15 +621,43 @@ static int net_socket_connect_init(NetClientState *peer,
+ Error **errp)
+ {
+ NetSocketState *s;
+- int fd, connected, ret;
+- struct sockaddr_in saddr;
++ int fd, connected, ret, pf;
++ struct sockaddr_storage saddr;
++ size_t saddr_size;
+ NetdevSocketOptions *stored;
+
+- if (parse_host_port(&saddr, host_str, errp) < 0) {
+- return -1;
++#ifndef WIN32
++ if (strchr(host_str, ':')) {
++#endif
++ if (parse_host_port((struct sockaddr_in *)&saddr, host_str, errp) < 0)
++ return -1;
++
++ pf = PF_INET;
++ saddr_size = sizeof(struct sockaddr_in);
++#ifndef WIN32
++ } else {
++ struct sockaddr_un *saddr_un = (struct sockaddr_un *)&saddr;
++ struct stat sb;
++
++ if (stat(host_str, &sb) == -1) {
++ error_setg_errno(errp, errno, "can't stat socket path");
++ return -1;
++ }
++
++ if ((sb.st_mode & S_IFMT) != S_IFSOCK) {
++ error_setg_errno(errp, errno, "provided path is not a socket");
++ return -1;
++ }
++
++ saddr_un->sun_family = PF_UNIX;
++ strncpy(saddr_un->sun_path, host_str, sizeof(saddr_un->sun_path));
++
++ pf = PF_UNIX;
++ saddr_size = sizeof(struct sockaddr_un);
+ }
++#endif /* !WIN32 */
+
+- fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
++ fd = qemu_socket(pf, SOCK_STREAM, 0);
+ if (fd < 0) {
+ error_setg_errno(errp, errno, "can't create stream socket");
+ return -1;
+@@ -603,7 +666,7 @@ static int net_socket_connect_init(NetClientState *peer,
+
+ connected = 0;
+ for(;;) {
+- ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
++ ret = connect(fd, (struct sockaddr *)&saddr, saddr_size);
+ if (ret < 0) {
+ if (errno == EINTR || errno == EWOULDBLOCK) {
+ /* continue */
+diff --git a/qemu-options.hx b/qemu-options.hx
+index fe83ea09b2..b41351a54e 100644
+--- a/qemu-options.hx
++++ b/qemu-options.hx
+@@ -2836,13 +2836,13 @@ SRST
+ #connect a TAP device to bridge qemubr0
+ |qemu_system| linux.img -netdev bridge,br=qemubr0,id=n1 -device virtio-net,netdev=n1
+
+-``-netdev socket,id=id[,fd=h][,listen=[host]:port][,connect=host:port]``
++``-netdev socket,id=id[,fd=h][,listen=[host]:port|path][,connect=host:port|path]``
+ This host network backend can be used to connect the guest's network
+- to another QEMU virtual machine using a TCP socket connection. If
+- ``listen`` is specified, QEMU waits for incoming connections on port
+- (host is optional). ``connect`` is used to connect to another QEMU
+- instance using the ``listen`` option. ``fd``\ =h specifies an
+- already opened TCP socket.
++ to another QEMU virtual machine using a TCP or a UNIX domain socket
++ connection. If ``listen`` is specified, QEMU waits for incoming
++ connections on port (host is optional), or on path. ``connect`` is used
++ to connect to another QEMU instance using the ``listen`` option.
++ ``fd``\ =h specifies an already opened TCP or UNIX domain socket.
+
+ Example:
+
+--
+2.28.0
+
diff --git a/qemu/0002-net-Don-t-ignore-EINVAL-on-netdev-socket-connection.patch b/qemu/0002-net-Don-t-ignore-EINVAL-on-netdev-socket-connection.patch
new file mode 100644
index 0000000..0e2caa8
--- /dev/null
+++ b/qemu/0002-net-Don-t-ignore-EINVAL-on-netdev-socket-connection.patch
@@ -0,0 +1,31 @@
+From f4c9af4041754209eaad4f98041466b6f5e54902 Mon Sep 17 00:00:00 2001
+From: Stefano Brivio <sbrivio@redhat.com>
+Date: Wed, 17 Mar 2021 10:35:32 +0100
+Subject: [PATCH 2/2] net: Don't ignore EINVAL on netdev socket connection
+
+Other errors are treated as failure by net_socket_connect_init(),
+but if connect() returns EINVAL, we'll fail silently. Remove the
+related exception.
+
+Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
+---
+ net/socket.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/net/socket.c b/net/socket.c
+index 9d06953983..a7c10ea2b2 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -671,8 +671,7 @@ static int net_socket_connect_init(NetClientState *peer,
+ if (errno == EINTR || errno == EWOULDBLOCK) {
+ /* continue */
+ } else if (errno == EINPROGRESS ||
+- errno == EALREADY ||
+- errno == EINVAL) {
++ errno == EALREADY) {
+ break;
+ } else {
+ error_setg_errno(errp, errno, "can't connect socket");
+--
+2.28.0
+