public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
* [PATCH] treewide: Sandbox qrap
@ 2026-07-18  7:42 Stefano Brivio
  2026-07-19  4:03 ` David Gibson
  0 siblings, 1 reply; 2+ messages in thread
From: Stefano Brivio @ 2026-07-18  7:42 UTC (permalink / raw)
  To: passt-dev; +Cc: David Gibson, Andrea Bolognani

No sunsetting or rightsizing for you, qrap: dig, bury, and cover.

Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
---
 .gitignore                    |   1 -
 Makefile                      |  11 +-
 README.md                     |   4 -
 contrib/fedora/passt.spec     |   2 -
 doc/demo.sh                   |  12 +-
 doc/passt_overview.excalidraw |  29 ---
 hooks/pre-push                |   2 +-
 passt.1                       | 235 ++++++++++---------
 qrap.1                        |  77 ------
 qrap.c                        | 429 ----------------------------------
 tap.c                         |   2 -
 test/distro/opensuse          |   2 +-
 12 files changed, 127 insertions(+), 679 deletions(-)
 delete mode 100644 qrap.1
 delete mode 100644 qrap.c

diff --git a/.gitignore b/.gitignore
index 3e40d9f..71420b6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,7 +5,6 @@
 /pasta.avx2
 /passt-repair
 /pesto
-/qrap
 /pasta.1
 /seccomp.h
 /seccomp_pesto.h
diff --git a/Makefile b/Makefile
index 5757aef..77474d6 100644
--- a/Makefile
+++ b/Makefile
@@ -39,13 +39,12 @@ PASST_SRCS = arch.c arp.c bitmap.c checksum.c conf.c dhcp.c dhcpv6.c \
 	parse.c passt.c pasta.c pcap.c pif.c repair.c serialise.c tap.c tcp.c \
 	tcp_buf.c tcp_splice.c tcp_vu.c udp.c udp_flow.c udp_vu.c util.c \
 	vhost_user.c virtio.c vu_common.c
-QRAP_SRCS = qrap.c
 PASST_REPAIR_SRCS = passt-repair.c
 PESTO_SRCS = pesto.c bitmap.c fwd_rule.c inany.c ip.c lineread.c parse.c \
 	serialise.c
-SRCS = $(PASST_SRCS) $(QRAP_SRCS) $(PASST_REPAIR_SRCS) $(PESTO_SRCS)
+SRCS = $(PASST_SRCS) $(PASST_REPAIR_SRCS) $(PESTO_SRCS)
 
-MANPAGES = passt.1 pasta.1 pesto.1 qrap.1 passt-repair.1
+MANPAGES = passt.1 pasta.1 pesto.1 passt-repair.1
 
 PASST_HEADERS = arch.h arp.h bitmap.h checksum.h conf.h dhcp.h dhcpv6.h \
 	epoll_ctl.h flow.h fwd.h fwd_rule.h flow_table.h icmp.h icmp_flow.h \
@@ -54,7 +53,6 @@ PASST_HEADERS = arch.h arp.h bitmap.h checksum.h conf.h dhcp.h dhcpv6.h \
 	serialise.h siphash.h tap.h tcp.h tcp_buf.h tcp_conn.h tcp_internal.h \
 	tcp_splice.h tcp_vu.h udp.h udp_flow.h udp_internal.h udp_vu.h util.h \
 	vhost_user.h virtio.h vu_common.h
-QRAP_HEADERS = arp.h ip.h passt.h util.h
 PASST_REPAIR_HEADERS = linux_dep.h
 PESTO_HEADERS = bitmap.h common.h fwd_rule.h inany.h ip.h log.h parse.h \
 	pesto.h serialise.h
@@ -76,7 +74,7 @@ docdir		?= $(datarootdir)/doc/passt
 mandir		?= $(datarootdir)/man
 man1dir		?= $(mandir)/man1
 
-BASEBIN := passt qrap passt-repair pesto
+BASEBIN := passt passt-repair pesto
 ifeq ($(TARGET_ARCH),x86_64)
 BASEBIN += passt.avx2
 endif
@@ -112,9 +110,6 @@ passt.avx2: $(PASST_SRCS) $(PASST_HEADERS) seccomp.h
 pasta.avx2 pasta.1 pasta: pasta%: passt%
 	ln -sf $< $@
 
-qrap: BASE_CPPFLAGS += -DARCH=\"$(TARGET_ARCH)\"
-qrap: $(QRAP_SRCS) $(QRAP_HEADERS)
-
 passt-repair: $(PASST_REPAIR_SRCS) $(PASST_REPAIR_HEADERS) seccomp_repair.h
 
 pesto: BASE_CPPFLAGS += -DPESTO
diff --git a/README.md b/README.md
index 8fdc0a3..43caf49 100644
--- a/README.md
+++ b/README.md
@@ -376,10 +376,6 @@ speeding up local connections, and usually requiring NAT. _pasta_:
 _passt_ exchanges packets with _qemu_ via UNIX domain socket, using the `socket`
 back-end in qemu. This is supported since qemu 7.2.
 
-For older versions, the [qrap](/passt/tree/qrap.c) wrapper can be used to
-connect to a UNIX domain socket and to start qemu, which can now use the file
-descriptor that's already opened.
-
 This approach, compared to using a _tap_ device, doesn't require any security
 capabilities, as we don't need to create any interface.
 
diff --git a/contrib/fedora/passt.spec b/contrib/fedora/passt.spec
index 34838af..6c7530a 100644
--- a/contrib/fedora/passt.spec
+++ b/contrib/fedora/passt.spec
@@ -118,12 +118,10 @@ fi
 %doc %{_docdir}/%{name}/demo.sh
 %{_bindir}/passt
 %{_bindir}/pasta
-%{_bindir}/qrap
 %{_bindir}/passt-repair
 %{_bindir}/pesto
 %{_mandir}/man1/passt.1*
 %{_mandir}/man1/pasta.1*
-%{_mandir}/man1/qrap.1*
 %{_mandir}/man1/passt-repair.1*
 %{_mandir}/man1/pesto.1*
 %ifarch x86_64
diff --git a/doc/demo.sh b/doc/demo.sh
index 6b0917c..b56669f 100755
--- a/doc/demo.sh
+++ b/doc/demo.sh
@@ -177,7 +177,7 @@ into_ns() {
 	next
 	[ "${KEY}" = "s" ] && ${SHELL}
 
-	cmd passt -P "${DEMO_DIR}/passt.pid"
+	cmd passt -P "${DEMO_DIR}/passt.pid" -s "${DEMO_DIR}/passt.socket"
 	echo
 	echo "...passt is running."
 	next
@@ -198,15 +198,12 @@ into_ns() {
 		echo "can download and use mbuto (https://mbuto.sh/) to build a"
 		echo "basic initramfs image. Otherwise, press 's' to skip this"
 		echo "step, and start an existing virtual machine yourself."
-		echo "You'll need to use the qrap(1) wrapper, with qemu options"
-		echo "as reported above."
 
 		next
 	else
 		echo "This script doesn't know, yet, how to run a virtual"
 		echo "machine on your architecture (${__arch}). Please start an"
-		echo "existing virtual machine yourself, using the qrap(1)"
-		echo "wrapper, with qemu options as reported above."
+		echo "existing virtual machine yourself."
 		echo
 	fi
 
@@ -225,12 +222,13 @@ into_ns() {
 	next
 
 	# shellcheck disable=SC2086
-	cmd qrap 5 ${__qemu_arch}					    \
+	cmd ${__qemu_arch}						    \
 		-smp "$(nproc)" -m 1024					    \
 		-nographic -serial stdio -nodefaults -no-reboot -vga none   \
 		-initrd "${DEMO_DIR}/demo.img"				    \
 		-kernel "/boot/vmlinuz-$(uname -r)" -append "console=ttyS0" \
-		-net socket,fd=5 -net nic,model=virtio || :
+		-device virtio-net-pci,netdev=s				    \
+		-netdev stream,id=s,server=off,addr.type=unix,addr.path="${DEMO_DIR}/passt.socket" || :
 }
 
 STTY_BACKUP="$(stty -g)"
diff --git a/doc/passt_overview.excalidraw b/doc/passt_overview.excalidraw
index 790728e..3217b3f 100644
--- a/doc/passt_overview.excalidraw
+++ b/doc/passt_overview.excalidraw
@@ -3595,35 +3595,6 @@
       "baseline": 17,
       "textAlign": "left",
       "verticalAlign": "top"
-    },
-    {
-      "type": "text",
-      "version": 1448,
-      "versionNonce": 1345391945,
-      "isDeleted": false,
-      "id": "c-esZiuHSm3wnTRlmIJZk",
-      "fillStyle": "hachure",
-      "strokeWidth": 1,
-      "strokeStyle": "dotted",
-      "roughness": 1,
-      "opacity": 100,
-      "angle": 4.969352159599495,
-      "x": 816.7081559166961,
-      "y": 215.74807066759342,
-      "strokeColor": "#2b8a3e",
-      "backgroundColor": "transparent",
-      "width": 211,
-      "height": 23,
-      "seed": 939668423,
-      "groupIds": [],
-      "strokeSharpness": "round",
-      "boundElementIds": [],
-      "fontSize": 20,
-      "fontFamily": 1,
-      "text": "(currently \"qrap\" wrapper)",
-      "baseline": 17,
-      "textAlign": "left",
-      "verticalAlign": "top"
     }
   ],
   "appState": {
diff --git a/hooks/pre-push b/hooks/pre-push
index 3e2d15f..8eebdbc 100755
--- a/hooks/pre-push
+++ b/hooks/pre-push
@@ -54,7 +54,7 @@ done
 cd ..
 
 make pkgs
-scp passt passt.avx2 passt.1 qrap qrap.1	"${USER_HOST}:${BIN}"
+scp passt passt.avx2 passt.1			"${USER_HOST}:${BIN}"
 scp pasta pasta.avx2 pasta.1			"${USER_HOST}:${BIN}"
 scp passt-repair passt-repair.1			"${USER_HOST}:${BIN}"
 scp pesto pesto.1				"${USER_HOST}:${BIN}"
diff --git a/passt.1 b/passt.1
index 995590a..53e072a 100644
--- a/passt.1
+++ b/passt.1
@@ -580,8 +580,7 @@ Default is \fBnone\fR for \fBpasst\fR and \fBauto\fR for \fBpasta\fR.
 
 .TP
 .BR \-s ", " \-\-socket-path ", " \-\-socket " " \fIpath
-Path for UNIX domain socket used by \fBqemu\fR(1) or \fBqrap\fR(1) to connect to
-\fBpasst\fR.
+Path for UNIX domain socket used by \fBqemu\fR(1) to connect to \fBpasst\fR.
 Default is to probe a free socket, not accepting connections, starting from
 \fI/tmp/passt_1.socket\fR to \fI/tmp/passt_64.socket\fR.
 
@@ -762,129 +761,132 @@ forwards loopback traffic between namespaces.
 .RS
 .nf
 $ iperf3 -s -D
-$ ./pasta
-Outbound interface: eth0, namespace interface: eth0
-ARP:
-    address: 28:16:ad:39:a9:ea
-DHCP:
-    assign: 192.168.1.118
-    mask: 255.255.255.0
-    router: 192.168.1.1
-NDP/DHCPv6:
-    assign: 2a02:6d40:3ca5:2001:b81d:fa4a:8cdd:cf17
-    router: fe80::62e3:27ff:fe33:2b01
-#
-# dhclient -4 --no-pid
-# dhclient -6 --no-pid
+
+$ pasta --config-net
+
 # ip address show
 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
     inet 127.0.0.1/8 scope host lo
        valid_lft forever preferred_lft forever
-    inet6 ::1/128 scope host 
+    inet6 ::1/128 scope host proto kernel_lo 
        valid_lft forever preferred_lft forever
-2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc pfifo_fast state UNKNOWN group default qlen 1000
-    link/ether 5e:90:02:eb:b0:2a brd ff:ff:ff:ff:ff:ff
-    inet 192.168.1.118/24 brd 192.168.1.255 scope global eth0
+2: enp9s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc fq_codel state UNKNOWN group default qlen 1000
+    link/ether be:16:49:5a:65:dc brd ff:ff:ff:ff:ff:ff
+    inet 88.198.0.164/27 brd 88.198.0.191 scope global noprefixroute enp9s0
        valid_lft forever preferred_lft forever
-    inet6 2a02:6d40:3ca5:2001:b81d:fa4a:8cdd:cf17/128 scope global 
+    inet6 2a01:4f8:222:904::2/64 scope global nodad 
        valid_lft forever preferred_lft forever
-    inet6 2a02:6d40:3ca5:2001:5c90:2ff:feeb:b02a/64 scope global dynamic mngtmpaddr 
-       valid_lft 3591sec preferred_lft 3591sec
-    inet6 fe80::5c90:2ff:feeb:b02a/64 scope link 
+    inet6 fe80::bc16:49ff:fe5a:65dc/64 scope link nodad proto kernel_ll 
        valid_lft forever preferred_lft forever
+
 # ip route show
-default via 192.168.1.1 dev eth0 
-192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.118 
+default via 88.198.0.161 dev enp9s0 proto dhcp metric 1002 
+88.198.0.160/27 dev enp9s0 proto dhcp scope link metric 1002 
+
 # ip -6 route show
-2a02:6d40:3ca5:2001:b81d:fa4a:8cdd:cf17 dev eth0 proto kernel metric 256 pref medium
-2a02:6d40:3ca5:2001::/64 dev eth0 proto kernel metric 256 expires 3584sec pref medium
-fe80::/64 dev eth0 proto kernel metric 256 pref medium
-default via fe80::62e3:27ff:fe33:2b01 dev eth0 proto ra metric 1024 expires 3584sec pref medium
+2a01:4f8:222:904::/64 dev enp9s0 proto kernel metric 256 pref medium
+fe80::/64 dev enp9s0 proto kernel metric 256 pref medium
+default via fe80::1 dev enp9s0 metric 1024 onlink pref medium
+
 # iperf3 -c 127.0.0.1 -t1
 Connecting to host 127.0.0.1, port 5201
-[  5] local 127.0.0.1 port 51938 connected to 127.0.0.1 port 5201
+[  5] local 127.0.0.1 port 59112 connected to 127.0.0.1 port 5201
 [ ID] Interval           Transfer     Bitrate         Retr  Cwnd
-[  5]   0.00-1.00   sec  4.46 GBytes  38.3 Gbits/sec    0   3.93 MBytes       
+[  5]   0.00-1.00   sec  3.89 GBytes  33.4 Gbits/sec    0   2.62 MBytes       
 - - - - - - - - - - - - - - - - - - - - - - - - -
 [ ID] Interval           Transfer     Bitrate         Retr
-[  5]   0.00-1.00   sec  4.46 GBytes  38.3 Gbits/sec    0             sender
-[  5]   0.00-1.41   sec  4.45 GBytes  27.1 Gbits/sec                  receiver
+[  5]   0.00-1.00   sec  3.89 GBytes  33.4 Gbits/sec    0             sender
+[  5]   0.00-1.00   sec  3.89 GBytes  33.4 Gbits/sec                  receiver
 
 iperf Done.
+
 # iperf3 -c ::1 -t1
 Connecting to host ::1, port 5201
-[  5] local ::1 port 50108 connected to ::1 port 5201
+[  5] local ::1 port 49138 connected to ::1 port 5201
 [ ID] Interval           Transfer     Bitrate         Retr  Cwnd
-[  5]   0.00-1.00   sec  4.35 GBytes  37.4 Gbits/sec    0   4.99 MBytes       
+[  5]   0.00-1.00   sec  4.32 GBytes  37.0 Gbits/sec    0   1.06 MBytes       
 - - - - - - - - - - - - - - - - - - - - - - - - -
 [ ID] Interval           Transfer     Bitrate         Retr
-[  5]   0.00-1.00   sec  4.35 GBytes  37.4 Gbits/sec    0             sender
-[  5]   0.00-1.41   sec  4.35 GBytes  26.4 Gbits/sec                  receiver
+[  5]   0.00-1.00   sec  4.32 GBytes  37.0 Gbits/sec    0             sender
+[  5]   0.00-1.00   sec  4.32 GBytes  37.0 Gbits/sec                  receiver
 
 iperf Done.
-# ping -c1 -4 spaghetti.pizza
-PING spaghetti.pizza (172.67.192.217) 56(84) bytes of data.
-64 bytes from 172.67.192.217: icmp_seq=1 ttl=255 time=37.3 ms
+
+# ping -nc1 -4 spaghetti.pizza
+PING spaghetti.pizza (5.161.47.86) 56(84) bytes of data.
+64 bytes from 5.161.47.86: icmp_seq=1 ttl=255 time=99.4 ms
 
 --- spaghetti.pizza ping statistics ---
 1 packets transmitted, 1 received, 0% packet loss, time 0ms
-# ping -c1 -6 spaghetti.pizza
-PING spaghetti.pizza(2606:4700:3034::6815:147a (2606:4700:3034::6815:147a)) 56 data bytes
-64 bytes from 2606:4700:3034::6815:147a: icmp_seq=1 ttl=255 time=35.6 ms
+rtt min/avg/max/mdev = 99.433/99.433/99.433/0.000 ms
+# ping -nc1 -6 spaghetti.pizza
+PING spaghetti.pizza (2a01:4f8:1c1e:d6f1::1) 56 data bytes
+64 bytes from 2a01:4f8:1c1e:d6f1::1: icmp_seq=1 ttl=255 time=3.11 ms
 
 --- spaghetti.pizza ping statistics ---
 1 packets transmitted, 1 received, 0% packet loss, time 0ms
-rtt min/avg/max/mdev = 35.605/35.605/35.605/0.000 ms
-# logout
-$
-
-.RE
+rtt min/avg/max/mdev = 3.110/3.110/3.110/0.000 ms
 .fi
+.RE
 
 .BR "Connect an existing user and network namespace"
 .RS
 .nf
 $ unshare -rUn
-# echo $$
-2446678
 
+# echo $$
+1295969
 .fi
-.BR "	[From another terminal]"
+
+.BR "[From another terminal]"
 .nf
-$ ./pasta 2446678
-Outbound interface: eth0, namespace interface: eth0
-ARP:
-    address: 28:16:ad:39:a9:ea
+$ pasta --config-net 1295969
+Template interface: enp9s0 (IPv4), enp9s0 (IPv6)
+Namespace interface: enp9s0
+MAC:
+    host: 9a:55:9a:55:9a:55
+    NAT to host 127.0.0.1: 88.198.0.161
 DHCP:
-    assign: 192.168.1.118
-    mask: 255.255.255.0
-    router: 192.168.1.1
+    assign: 88.198.0.164
+    mask: 255.255.255.224
+    router: 88.198.0.161
+DNS:
+    185.12.64.1
+    185.12.64.2
+    NAT to host ::1: fe80::1
 NDP/DHCPv6:
-    assign: 2a02:6d40:3ca5:2001:b81d:fa4a:8cdd:cf17
-    router: fe80::62e3:27ff:fe33:2b01
-
+    assign: 2a01:4f8:222:904::2
+    router: fe80::1
+    our link-local: fe80::1
+Inbound forwarding rules (HOST):
+    TCP [*]:1-32767  =>  1-32767  (best effort) (auto-scan)
+    TCP [*]:61000-65535  =>  61000-65535  (best effort) (auto-scan)
+    UDP [*]:1-32767  =>  1-32767  (best effort) (auto-scan)
+    UDP [*]:61000-65535  =>  61000-65535  (best effort) (auto-scan)
+Outbound forwarding rules (SPLICE):
+    TCP [*]%lo:1-32767  =>  1-32767  (best effort) (auto-scan)
+    TCP [*]%lo:61000-65535  =>  61000-65535  (best effort) (auto-scan)
+    UDP [*]%lo:1-32767  =>  1-32767  (best effort) (auto-scan)
+    UDP [*]%lo:61000-65535  =>  61000-65535  (best effort) (auto-scan)
 .fi
-.BR "	[Back to the original terminal]"
+
+.BR "[Back to the original terminal]"
 .nf
-# dhclient -4 --no-pid
-# dhclient -6 --no-pid
 # ip address show
 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
     inet 127.0.0.1/8 scope host lo
        valid_lft forever preferred_lft forever
-    inet6 ::1/128 scope host 
+    inet6 ::1/128 scope host proto kernel_lo 
        valid_lft forever preferred_lft forever
-2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc pfifo_fast state UNKNOWN group default qlen 1000
-    link/ether fa:c1:2a:27:92:a9 brd ff:ff:ff:ff:ff:ff
-    inet 192.168.1.118/24 brd 192.168.1.255 scope global eth0
+2: enp9s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc fq_codel state UNKNOWN group default qlen 1000
+    link/ether 9a:44:5e:54:d3:2c brd ff:ff:ff:ff:ff:ff
+    inet 88.198.0.164/27 brd 88.198.0.191 scope global noprefixroute enp9s0
        valid_lft forever preferred_lft forever
-    inet6 2a02:6d40:3ca5:2001:b81d:fa4a:8cdd:cf17/128 scope global 
+    inet6 2a01:4f8:222:904::2/64 scope global nodad 
        valid_lft forever preferred_lft forever
-    inet6 2a02:6d40:3ca5:2001:f8c1:2aff:fe27:92a9/64 scope global dynamic mngtmpaddr 
-       valid_lft 3594sec preferred_lft 3594sec
-    inet6 fe80::f8c1:2aff:fe27:92a9/64 scope link 
+    inet6 fe80::9844:5eff:fe54:d32c/64 scope link nodad proto kernel_ll 
        valid_lft forever preferred_lft forever
 .fi
 .RE
@@ -893,72 +895,69 @@ NDP/DHCPv6:
 .BR "Start and connect a guest with basic port forwarding"
 .RS
 .nf
-$ ./passt -f -t 2222:22
-Outbound interface: eth0
-ARP:
-    address: 28:16:ad:39:a9:ea
+$ passt -f -t 2222:22
+UNIX domain socket bound at /tmp/passt_1.socket
+No IPv6 nameserver available for NDP/DHCPv6
+Template interface: enp9s0 (IPv4), enp9s0 (IPv6)
+MAC:
+    host: 9a:55:9a:55:9a:55
+    NAT to host 127.0.0.1: 88.198.0.161
 DHCP:
-    assign: 192.168.1.118
-    mask: 255.255.255.0
-    router: 192.168.1.1
-        search:
-            redhat.com
+    assign: 88.198.0.164
+    mask: 255.255.255.224
+    router: 88.198.0.161
+DNS:
+    185.12.64.1
+    185.12.64.2
+    NAT to host ::1: fe80::1
 NDP/DHCPv6:
-    assign: 2a02:6d40:3ca5:2001:b81d:fa4a:8cdd:cf17
-    router: fe80::62e3:27ff:fe33:2b01
-        search:
-            redhat.com
-UNIX domain socket bound at /tmp/passt_1.socket
-
-You can now start qrap:
-    ./qrap 5 qemu-system-x86_64 ... -net socket,fd=5 -net nic,model=virtio
-or directly qemu, patched with:
-    qemu/0001-net-Allow-also-UNIX-domain-sockets-to-be-used-as-net.patch
-as follows:
-    qemu-system-x86_64 ... -net socket,connect=/tmp/passt_1.socket -net nic,model=virtio
-
+    assign: 2a01:4f8:222:904::2
+    router: fe80::1
+    our link-local: fe80::1
+Inbound forwarding rules (HOST):
+    TCP [*]:2222  =>  22 
+
+You can now start qemu (>= 7.2, with commit 13c6be96618c):
+    kvm ... -device virtio-net-pci,netdev=s -netdev stream,id=s,server=off,addr.type=unix,addr.path=/tmp/passt_1.socket
 .fi
-.BR "	[From another terminal]"
-.nf
-$ ./qrap 5 qemu-system-x86_64 test.qcow2 -m 1024 -display none -nodefaults -nographic -net socket,fd=5 -net nic,model=virtio
-Connected to /tmp/passt_1.socket
 
-.fi
-.BR "	[Back to the original terminal]"
+.BR "[From another terminal]"
 .nf
-passt: DHCP: ack to request
-passt:     from 52:54:00:12:34:56
-passt: NDP: received NS, sending NA
-passt: NDP: received RS, sending RA
-passt: DHCPv6: received SOLICIT, sending ADVERTISE
-passt: NDP: received NS, sending NA
-passt: DHCPv6: received REQUEST/RENEW/CONFIRM, sending REPLY
-passt: NDP: received NS, sending NA
+$ qemu-system-x86_64 -m 128 test.qcow2 -display none -nodefaults -nographic -device virtio-net-pci,netdev=s -netdev stream,id=s,server=off,addr.type=unix,addr.path=/tmp/passt_1.socket
+.fi
 
+.BR "[Back to the original terminal]"
+.nf
+accepted connection from PID 1301736
+New guest MAC address observed: 52:54:00:12:34:56
+DHCP: offer to discover
+    from 52:54:00:12:34:56
+DHCP: ack to request
+    from 52:54:00:12:34:56
+NDP: received RS, sending RA
 .fi
-.BR "	[From yet another terminal]"
+
+.BR "[From yet another terminal]"
 .nf
 $ ssh -p 2222 root@localhost
 root@localhost's password: 
 .fi
-.BR "	[...]"
+.BR "[...]"
 .nf
 # ip address show
-1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
+1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
     inet 127.0.0.1/8 scope host lo
        valid_lft forever preferred_lft forever
     inet6 ::1/128 scope host 
        valid_lft forever preferred_lft forever
-2: ens2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc pfifo_fast state UP group default qlen 1000
+2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
     link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
-    inet 192.168.1.118/24 brd 192.168.1.255 scope global noprefixroute ens2
+    inet 88.198.0.164/27 scope global eth0
        valid_lft forever preferred_lft forever
-    inet6 2a02:6d40:3ca5:2001:b81d:fa4a:8cdd:cf17/128 scope global noprefixroute 
+    inet6 2a01:4f8:222:904:5054:ff:fe12:3456/64 scope global dynamic flags 100 
        valid_lft forever preferred_lft forever
-    inet6 2a02:6d40:3ca5:2001:b019:9ae2:a2fe:e6b4/64 scope global dynamic noprefixroute 
-       valid_lft 3588sec preferred_lft 3588sec
-    inet6 fe80::1f98:d09f:9309:9e77/64 scope link noprefixroute 
+    inet6 fe80::5054:ff:fe12:3456/64 scope link 
        valid_lft forever preferred_lft forever
 .fi
 .RE
diff --git a/qrap.1 b/qrap.1
deleted file mode 100644
index 98cc877..0000000
--- a/qrap.1
+++ /dev/null
@@ -1,77 +0,0 @@
-.\" SPDX-License-Identifier: GPL-2.0-or-later
-.\" Copyright (c) 2020-2021 Red Hat GmbH
-.\" Author: Stefano Brivio <sbrivio@redhat.com>
-.TH qrap 1
-
-.SH NAME
-.B qrap
-\- temporary qemu wrapper connecting UNIX domain socket to file descriptor
-
-.SH SYNOPSIS
-.B qrap
-[\fIFDNUM\fR \fIQEMU_CMD\fR] [\fIQEMU_ARG\fR]...
-.SH DESCRIPTION
-\fBqrap\fR is a wrapper, designed specifically for usage with \fBqemu\fR(1) and
-\fBpasst\fR(1), connecting a UNIX domain socket to a file descriptor, and
-running \fBqemu\fR(1) with given arguments.
-
-A running instance of \fBpasst\fR(1) is probed checking for UNIX domain sockets,
-answering a dummy ARP request, with names starting from
-\fI/tmp/passt_1.socket\fR up to \fI/tmp/passt_64.socket\fR.
-
-If first and second arguments are not a socket number and a command, that is,
-respectively, \fIFDNUM\fR and \fIQEMU_CMD\fR, \fBqrap\fR will try to locate a
-qemu executable in \fBPATH\fR and patch the command line to specify a network
-device and a \fInetdev\fR back-end for usage with \fBpasst\fR(1).
-
-If \fBqrap\fR patches the command line, it will remove any potentially
-conflicting network device, that is, any \fI-netdev\fR or \fI-net\fR option, or
-any \fI-device\fR option with argument starting with \fIvirtio-net-pci,\fR,
-\fIvirtio-net-ccw,\fR, \fIe1000,\fR, \fIe1000e,\fR, or \fIrtl8139,\fR.
-
-.SH EXAMPLES
-
-.BR "Start qemu explicitly passing its command name and a socket number"
-.RS
-.nf
-$ ./qrap 5 kvm test.qcow2 -m 1024 -display none -nodefaults -nographic -net socket,fd=5 -net nic,model=virtio
-.fi
-.RE
-
-.BR "Start qemu without command name and socket number, patching arguments"
-.RS
-.nf
-$ ./qrap test.qcow2 -m 1024 -display none -nodefaults -nographic
-.fi
-.RE
-
-.SH NOTES
-
-This wrapper is temporary: qemu commit 13c6be96618c ("net: stream: add unix
-socket") introduces native AF_UNIX socket support, and it should be included in
-qemu starting from the 7.2 release. It will be around for a little bit longer to
-give users enough time to switch.
-
-.SH AUTHOR
-
-Stefano Brivio <sbrivio@redhat.com>
-
-.SH REPORTING BUGS
-
-No public bug tracker is available at this time. For the moment being, report
-issues to Stefano Brivio <sbrivio@redhat.com>.
-
-.SH COPYRIGHT
-
-Copyright (c) 2020-2021 Red Hat GmbH.
-
-\fBqrap\fR is free software: you can redistribute is and/or modify it under the
-terms of the GNU General Public License as published by the Free Software
-Foundation, either version 2 of the License, or (at your option) any later
-version. 
-
-.SH SEE ALSO
-
-\fBqemu\fR(1), \fBpasst\fR(1).
-
-High-level documentation is available at https://passt.top/passt/about/.
diff --git a/qrap.c b/qrap.c
deleted file mode 100644
index d596706..0000000
--- a/qrap.c
+++ /dev/null
@@ -1,429 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-/* PASST - Plug A Simple Socket Transport
- *
- * qrap.c - qemu wrapper connecting UNIX domain socket to file descriptor
- *
- * Copyright (c) 2020-2021 Red Hat GmbH
- * Author: Stefano Brivio <sbrivio@redhat.com>
- *
- * TODO: Drop this implementation once qemu commit 13c6be96618c ("net: stream:
- * add unix socket") is included in a release (7.2), and once we can reasonably
- * assume existing users switched to it.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <errno.h>
-#include <linux/limits.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <net/if_arp.h>
-#include <netinet/in.h>
-#include <netinet/ip6.h>
-#include <netinet/if_ether.h>
-#include <time.h>
-
-#include <linux/icmpv6.h>
-
-#include "util.h"
-#include "ip.h"
-#include "passt.h"
-#include "arp.h"
-
-static char *qemu_names[] = {
-	"kvm",
-	"qemu-kvm",
-#ifdef ARCH
-	( "qemu-system-" ARCH ),
-#endif
-	"/usr/libexec/qemu-kvm",
-	NULL,
-};
-
-/**
- * struct drop_arg - Drop matching arguments on command line
- * @name:	Option name
- * @val:	Substring in option value, NULL matches any value
- */
-static const struct drop_arg {
-	char *name;
-	char *val;
-} drop_args[] = {
-	{ "-netdev",	NULL },
-	{ "-net",	NULL },
-	{ "-device",	"virtio-net-pci," },
-	{ "-device",	"{\"driver\":\"virtio-net-pci\"," },
-	{ "-device",	"virtio-net-ccw," },
-	{ "-device",	"{\"driver\":\"virtio-net-ccw\"," },
-	{ "-device",	"e1000," },
-	{ "-device",	"{\"driver\":\"e1000\"," },
-	{ "-device",	"e1000e," },
-	{ "-device",	"{\"driver\":\"e1000e\"," },
-	{ "-device",	"rtl8139," },
-	{ "-device",	"{\"driver\":\"rtl8139\"," },
-	{ 0 },
-};
-
-/**
- * struct pci_dev - PCI devices to add on command line depending on machine name
- * @mach:		Machine name
- * @name:		Device ("-device") name to insert
- * @template:		Prefix for device specification (first part of address)
- * @template_post:	Suffix for device specification (last part of address)
- * @template_json:		Device prefix for when JSON is used
- * @template_json_post:	Device suffix for when JSON is used
- * @base:		Base used for PCI addresses
- * @first:		First usable PCI address
- * @last:		Last usable PCI address
- */
-static const struct pci_dev {
-	char *mach;
-	char *name;
-	char *template;
-	char *template_post;
-	char *template_json;
-	char *template_json_post;
-	int base;
-	int first;
-	int last;
-} pci_devs[] = {
-	{
-		"pc-q35", "virtio-net-pci",
-		"bus=pci.", ",addr=0x0",
-		"\"bus\":\"pci.", ",\"addr\":\"0x0\"",
-		10, 3, /* 2: hotplug bus */ 31
-	},
-	{
-		"pc-", "virtio-net-pci",
-		"bus=pci.0,addr=0x", "",
-		"\"bus\":\"pci.0\",\"addr\":\"0x", "",
-		16, 2, /* 1: ISA bridge */ 31
-	},
-	{
-		"s390-ccw", "virtio-net-ccw",
-		"devno=fe.0.", "",
-		"\"devno\":\"fe.0.", "",
-		16, 1, 16
-	},
-	{ 0 },
-};
-
-#define DEFAULT_FD	5
-
-/**
- * usage() - Print usage and exit
- * @name:	Executable name
- */
-void usage(const char *name)
-{
-	fprintf(stderr, "Usage: %s [FDNUM QEMU_CMD] [QEMU_ARG]...\n", name);
-	fprintf(stderr, "\n");
-	fprintf(stderr, "If first and second arguments aren't a socket number\n"
-			"and a path, %s will try to locate a qemu binary\n"
-			"and directly patch the command line\n", name);
-
-	exit(EXIT_FAILURE);
-}
-
-/**
- * main() - Entry point and main loop
- * @argc:	Argument count
- * @argv:	File descriptor number, then qemu with arguments
- *
- * Return: 0 once interrupted, non-zero on failure
- */
-int main(int argc, char **argv)
-{
-	int i, s, qemu_argc = 0, addr_map = 0, has_dev = 0, has_json = 0, retry_on_reset, rc;
-	struct timeval tv = { .tv_sec = 0, .tv_usec = (long)(500 * 1000) };
-	char *qemu_argv[ARG_MAX], dev_str[ARG_MAX];
-	struct sockaddr_un addr = {
-		.sun_family = AF_UNIX,
-	};
-	const struct pci_dev *dev = NULL;
-	long fd;
-	struct {
-		uint32_t vnet_len4;
-		struct ethhdr eh4;
-		struct arphdr ah;
-		struct arpmsg am;
-
-		uint32_t vnet_len6;
-		struct ethhdr eh6;
-		struct ipv6hdr ip6hr;
-		struct icmp6hdr ihr;
-		struct in6_addr target;
-	} __attribute__((__packed__)) probe = {
-		.vnet_len4 = htonl(42),
-		{
-			.h_dest   = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
-			.h_source = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
-			.h_proto  = htons(ETH_P_ARP),
-		},
-		{	.ar_hrd = htons(ARPHRD_ETHER),
-			.ar_pro = htons(ETH_P_IP),
-			.ar_hln = ETH_ALEN,
-			.ar_pln = 4,
-			.ar_op  = htons(ARPOP_REQUEST),
-		},
-		{
-			.sha = { 0 }, .sip = { 0 }, .tha = { 0 }, .tip = { 0 },
-		},
-		.vnet_len6 = htonl(78),
-		{
-			.h_dest   = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
-			.h_source = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
-			.h_proto  = htons(ETH_P_IPV6),
-		},
-		{
-			.version = 6,
-			.payload_len = htons(24),
-			.nexthdr = IPPROTO_ICMPV6,
-			.hop_limit = 255,
-			.saddr = IN6ADDR_LOOPBACK_INIT,
-			.daddr = IN6ADDR_ANY_INIT,
-		},
-		{
-			.icmp6_type = 135,
-			.icmp6_code = 0,
-		},
-		IN6ADDR_ANY_INIT,
-	};
-	char probe_r;
-
-	if (argc >= 3) {
-		const char *path = getenv("PATH");
-		errno = 0;
-		fd = strtol(argv[1], NULL, 0);
-		if (fd >= 3 && fd < INT_MAX && !errno && path) {
-			char env_path[ARG_MAX + 1], *p, command[ARG_MAX];
-
-			strncpy(env_path, path, ARG_MAX);
-			/* cppcheck-suppress strtokCalled */
-			p = strtok(env_path, ":");
-			while (p) {
-				snprintf(command, ARG_MAX, "%s/%s", p, argv[2]);
-				if (!access(command, X_OK))
-					goto valid_args;
-
-				/* cppcheck-suppress strtokCalled */
-				p = strtok(NULL, ":");
-			}
-		}
-	}
-
-	fd = DEFAULT_FD;
-
-	for (i = 1; i < argc - 1; i++) {
-		if (strcmp(argv[i], "-machine"))
-			continue;
-
-		for (dev = pci_devs; dev->mach; dev++) {
-			if (strstr(argv[i + 1], dev->mach) == argv[i + 1])
-				break;
-		}
-	}
-
-	if (!dev || !dev->mach)
-		dev = pci_devs;
-
-	for (qemu_argc = 1, i = 1; i < argc; i++) {
-		const struct drop_arg *a;
-
-		for (a = drop_args; a->name; a++) {
-			if (!strcmp(argv[i], a->name)) {
-				if (!a->val)
-					break;
-
-				if (i + 1 < argc &&
-				    strstr(argv[i + 1], a->val) == argv[i + 1])
-					break;
-			}
-		}
-		if (a->name) {
-			i++;
-			continue;
-		}
-
-		if (!strcmp(argv[i], "-device") && i + 1 < argc) {
-			const char *template = NULL;
-			const char *p;
-
-			has_dev = 1;
-
-			if ((p = strstr(argv[i + 1], dev->template))) {
-				template = dev->template;
-			} else if ((p = strstr(argv[i + 1], dev->template_json))) {
-				template = dev->template_json;
-				has_json = 1;
-			}
-
-			if (template) {
-				long n;
-
-				n = strtol(p + strlen(template), NULL, dev->base);
-				if (!errno)
-					addr_map |= (1 << n);
-			}
-		}
-
-		qemu_argv[qemu_argc++] = argv[i];
-	}
-
-	for (i = dev->first; i < dev->last; i++) {
-		if (!(addr_map & (1 << i)))
-			break;
-	}
-	if (i == dev->last) {
-		fprintf(stderr, "Couldn't find free address for device\n");
-		usage(argv[0]);
-	}
-
-	if (has_dev) {
-		qemu_argv[qemu_argc++] = "-device";
-		if (!has_json) {
-			if (dev->base == 16) {
-				snprintf(dev_str, ARG_MAX,
-				         "%s,%s%x%s,netdev=hostnet0,x-txburst=4096",
-				         dev->name, dev->template, i, dev->template_post);
-			} else if (dev->base == 10) {
-				snprintf(dev_str, ARG_MAX,
-				         "%s,%s%d%s,netdev=hostnet0,x-txburst=4096",
-				         dev->name, dev->template, i, dev->template_post);
-			}
-		} else {
-			if (dev->base == 16) {
-				snprintf(dev_str, ARG_MAX,
-				         "{\"driver\":\"%s\",%s%x\"%s,\"netdev\":\"hostnet0\",\"x-txburst\":4096}",
-				         dev->name, dev->template_json, i, dev->template_json_post);
-			} else if (dev->base == 10) {
-				snprintf(dev_str, ARG_MAX,
-				         "{\"driver\":\"%s\",%s%d\"%s,\"netdev\":\"hostnet0\",\"x-txburst\":4096}",
-				         dev->name, dev->template_json, i, dev->template_json_post);
-			}
-		}
-		qemu_argv[qemu_argc++] = dev_str;
-	}
-
-	qemu_argv[qemu_argc++] = "-netdev";
-	if (!has_json) {
-		qemu_argv[qemu_argc++] = "socket,fd=" STR(DEFAULT_FD) ",id=hostnet0";
-	} else {
-		qemu_argv[qemu_argc++] = "{\"type\":\"socket\",\"fd\":\"" STR(DEFAULT_FD) "\",\"id\":\"hostnet0\"}";
-	}
-	qemu_argv[qemu_argc] = NULL;
-
-valid_args:
-	for (i = 1; i < UNIX_SOCK_MAX; i++) {
-		retry_on_reset = 50;
-
-retry:
-		s = socket(AF_UNIX, SOCK_STREAM, 0);
-		if (s < 0) {
-			perror("socket");
-			exit(EXIT_FAILURE);
-		}
-
-		if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)))
-			perror("setsockopt SO_RCVTIMEO");
-		if (setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)))
-			perror("setsockopt SO_SNDTIMEO");
-
-		snprintf(addr.sun_path, UNIX_PATH_MAX, UNIX_SOCK_PATH, i);
-
-		errno = 0;
-
-		if (connect(s, (const struct sockaddr *)&addr, sizeof(addr))) {
-			rc = errno;
-			perror("connect");
-		} else if (send(s, &probe, sizeof(probe), 0) != sizeof(probe)) {
-			rc = errno;
-			perror("send");
-		} else if (recv(s, &probe_r, 1, MSG_PEEK) <= 0) {
-			rc = errno;
-			perror("recv");
-		} else {
-			break;
-		}
-
-		/* FIXME: in a KubeVirt environment, libvirtd invokes qrap three
-		 * times in a strict sequence when a virtual machine needs to
-		 * be started, namely, when:
-		 * - the domain XML is saved
-		 * - the domain is started (for "probing")
-		 * - the virtual machine is started for real
-		 * and it often happens that the qemu process is still running
-		 * when qrap is invoked again, so passt will refuse the new
-		 * connection because the previous one is still active. This
-		 * overlap seems to be anywhere between 0 and 3ms.
-		 *
-		 * If we get a connection reset, retry a few times, to allow for
-		 * the previous qemu instance to terminate and, in turn, for the
-		 * connection to passt to be closed.
-		 *
-		 * This should be fixed in libvirt instead. It probably makes
-		 * sense to check this behaviour once native libvirt support is
-		 * there, and this implies native qemu support too, so at that
-		 * point qrap will have no reason to exist anymore -- that is,
-		 * this FIXME will probably remain until the tool itself is
-		 * obsoleted.
-		 */
-		if (retry_on_reset && rc == ECONNRESET) {
-			retry_on_reset--;
-			/* cppcheck-suppress usleepCalled */
-			usleep(50 * 1000);
-			goto retry;
-		}
-
-		fprintf(stderr, "Probe of %s failed\n", addr.sun_path);
-
-		close(s);
-	}
-
-	if (i == UNIX_SOCK_MAX) {
-		perror("connect");
-		exit(EXIT_FAILURE);
-	}
-
-	tv.tv_usec = 0;
-	if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)))
-		perror("setsockopt, SO_RCVTIMEO reset");
-	if (setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)))
-		perror("setsockopt, SO_SNDTIMEO reset");
-
-	fprintf(stderr, "Connected to %s\n", addr.sun_path);
-
-	if (dup2(s, (int)fd) < 0) {
-		perror("dup");
-		exit(EXIT_FAILURE);
-	}
-
-	close(s);
-
-	if (qemu_argc) {
-		char **name;
-
-		for (name = qemu_names; *name; name++) {
-			qemu_argv[0] = *name;
-			execvp(*name, qemu_argv);
-			if (errno != ENOENT) {
-				perror("execvp");
-				usage(argv[0]);
-			}
-		}
-		if (errno == ENOENT)
-			fprintf(stderr, "Couldn't find qemu command\n");
-	} else {
-		execvp(argv[2], argv + 2);
-	}
-
-	perror("execvp");
-
-	return EXIT_FAILURE;
-}
diff --git a/tap.c b/tap.c
index cf87591..dfa66c7 100644
--- a/tap.c
+++ b/tap.c
@@ -1377,8 +1377,6 @@ static void tap_backend_show_hints(const struct ctx *c)
 		info("\nYou can now start qemu (>= 7.2, with commit 13c6be96618c):");
 		info("    kvm ... -device virtio-net-pci,netdev=s -netdev stream,id=s,server=off,addr.type=unix,addr.path=%s",
 		     c->sock_path);
-		info("or qrap, for earlier qemu versions:");
-		info("    ./qrap 5 kvm ... -net socket,fd=5 -net nic,model=virtio");
 		break;
 	case MODE_VU:
 		info("You can start qemu with:");
diff --git a/test/distro/opensuse b/test/distro/opensuse
index eab722b..9ceb0bd 100644
--- a/test/distro/opensuse
+++ b/test/distro/opensuse
@@ -39,7 +39,7 @@ hostb	./passt -s __STATEDIR__/passt.socket -P __PIDFILE__ &
 sleep	1
 host	echo
 hout	DNS6 sed -n 's/^nameserver \([^:]*:\)\([^%]*\).*/\1\2/p' /etc/resolv.conf | head -1
-hout	GUEST_FILES ls -1 *.c *.h *.sh passt.1 qrap.1 Makefile README.md | tr '\n' ' '; echo
+hout	GUEST_FILES ls -1 *.c *.h *.sh passt.1 Makefile README.md | tr '\n' ' '; echo
 
 
 test	OpenSUSE Leap 15.1
-- 
2.43.0


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] treewide: Sandbox qrap
  2026-07-18  7:42 [PATCH] treewide: Sandbox qrap Stefano Brivio
@ 2026-07-19  4:03 ` David Gibson
  0 siblings, 0 replies; 2+ messages in thread
From: David Gibson @ 2026-07-19  4:03 UTC (permalink / raw)
  To: Stefano Brivio; +Cc: passt-dev, Andrea Bolognani

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

On Sat, Jul 18, 2026 at 09:42:25AM +0200, Stefano Brivio wrote:
> No sunsetting or rightsizing for you, qrap: dig, bury, and cover.
> 
> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>

Hooray!

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

> ---
>  .gitignore                    |   1 -
>  Makefile                      |  11 +-
>  README.md                     |   4 -
>  contrib/fedora/passt.spec     |   2 -
>  doc/demo.sh                   |  12 +-
>  doc/passt_overview.excalidraw |  29 ---
>  hooks/pre-push                |   2 +-
>  passt.1                       | 235 ++++++++++---------
>  qrap.1                        |  77 ------
>  qrap.c                        | 429 ----------------------------------
>  tap.c                         |   2 -
>  test/distro/opensuse          |   2 +-
>  12 files changed, 127 insertions(+), 679 deletions(-)
>  delete mode 100644 qrap.1
>  delete mode 100644 qrap.c
> 
> diff --git a/.gitignore b/.gitignore
> index 3e40d9f..71420b6 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -5,7 +5,6 @@
>  /pasta.avx2
>  /passt-repair
>  /pesto
> -/qrap
>  /pasta.1
>  /seccomp.h
>  /seccomp_pesto.h
> diff --git a/Makefile b/Makefile
> index 5757aef..77474d6 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -39,13 +39,12 @@ PASST_SRCS = arch.c arp.c bitmap.c checksum.c conf.c dhcp.c dhcpv6.c \
>  	parse.c passt.c pasta.c pcap.c pif.c repair.c serialise.c tap.c tcp.c \
>  	tcp_buf.c tcp_splice.c tcp_vu.c udp.c udp_flow.c udp_vu.c util.c \
>  	vhost_user.c virtio.c vu_common.c
> -QRAP_SRCS = qrap.c
>  PASST_REPAIR_SRCS = passt-repair.c
>  PESTO_SRCS = pesto.c bitmap.c fwd_rule.c inany.c ip.c lineread.c parse.c \
>  	serialise.c
> -SRCS = $(PASST_SRCS) $(QRAP_SRCS) $(PASST_REPAIR_SRCS) $(PESTO_SRCS)
> +SRCS = $(PASST_SRCS) $(PASST_REPAIR_SRCS) $(PESTO_SRCS)
>  
> -MANPAGES = passt.1 pasta.1 pesto.1 qrap.1 passt-repair.1
> +MANPAGES = passt.1 pasta.1 pesto.1 passt-repair.1
>  
>  PASST_HEADERS = arch.h arp.h bitmap.h checksum.h conf.h dhcp.h dhcpv6.h \
>  	epoll_ctl.h flow.h fwd.h fwd_rule.h flow_table.h icmp.h icmp_flow.h \
> @@ -54,7 +53,6 @@ PASST_HEADERS = arch.h arp.h bitmap.h checksum.h conf.h dhcp.h dhcpv6.h \
>  	serialise.h siphash.h tap.h tcp.h tcp_buf.h tcp_conn.h tcp_internal.h \
>  	tcp_splice.h tcp_vu.h udp.h udp_flow.h udp_internal.h udp_vu.h util.h \
>  	vhost_user.h virtio.h vu_common.h
> -QRAP_HEADERS = arp.h ip.h passt.h util.h
>  PASST_REPAIR_HEADERS = linux_dep.h
>  PESTO_HEADERS = bitmap.h common.h fwd_rule.h inany.h ip.h log.h parse.h \
>  	pesto.h serialise.h
> @@ -76,7 +74,7 @@ docdir		?= $(datarootdir)/doc/passt
>  mandir		?= $(datarootdir)/man
>  man1dir		?= $(mandir)/man1
>  
> -BASEBIN := passt qrap passt-repair pesto
> +BASEBIN := passt passt-repair pesto
>  ifeq ($(TARGET_ARCH),x86_64)
>  BASEBIN += passt.avx2
>  endif
> @@ -112,9 +110,6 @@ passt.avx2: $(PASST_SRCS) $(PASST_HEADERS) seccomp.h
>  pasta.avx2 pasta.1 pasta: pasta%: passt%
>  	ln -sf $< $@
>  
> -qrap: BASE_CPPFLAGS += -DARCH=\"$(TARGET_ARCH)\"
> -qrap: $(QRAP_SRCS) $(QRAP_HEADERS)
> -
>  passt-repair: $(PASST_REPAIR_SRCS) $(PASST_REPAIR_HEADERS) seccomp_repair.h
>  
>  pesto: BASE_CPPFLAGS += -DPESTO
> diff --git a/README.md b/README.md
> index 8fdc0a3..43caf49 100644
> --- a/README.md
> +++ b/README.md
> @@ -376,10 +376,6 @@ speeding up local connections, and usually requiring NAT. _pasta_:
>  _passt_ exchanges packets with _qemu_ via UNIX domain socket, using the `socket`
>  back-end in qemu. This is supported since qemu 7.2.
>  
> -For older versions, the [qrap](/passt/tree/qrap.c) wrapper can be used to
> -connect to a UNIX domain socket and to start qemu, which can now use the file
> -descriptor that's already opened.
> -
>  This approach, compared to using a _tap_ device, doesn't require any security
>  capabilities, as we don't need to create any interface.
>  
> diff --git a/contrib/fedora/passt.spec b/contrib/fedora/passt.spec
> index 34838af..6c7530a 100644
> --- a/contrib/fedora/passt.spec
> +++ b/contrib/fedora/passt.spec
> @@ -118,12 +118,10 @@ fi
>  %doc %{_docdir}/%{name}/demo.sh
>  %{_bindir}/passt
>  %{_bindir}/pasta
> -%{_bindir}/qrap
>  %{_bindir}/passt-repair
>  %{_bindir}/pesto
>  %{_mandir}/man1/passt.1*
>  %{_mandir}/man1/pasta.1*
> -%{_mandir}/man1/qrap.1*
>  %{_mandir}/man1/passt-repair.1*
>  %{_mandir}/man1/pesto.1*
>  %ifarch x86_64
> diff --git a/doc/demo.sh b/doc/demo.sh
> index 6b0917c..b56669f 100755
> --- a/doc/demo.sh
> +++ b/doc/demo.sh
> @@ -177,7 +177,7 @@ into_ns() {
>  	next
>  	[ "${KEY}" = "s" ] && ${SHELL}
>  
> -	cmd passt -P "${DEMO_DIR}/passt.pid"
> +	cmd passt -P "${DEMO_DIR}/passt.pid" -s "${DEMO_DIR}/passt.socket"
>  	echo
>  	echo "...passt is running."
>  	next
> @@ -198,15 +198,12 @@ into_ns() {
>  		echo "can download and use mbuto (https://mbuto.sh/) to build a"
>  		echo "basic initramfs image. Otherwise, press 's' to skip this"
>  		echo "step, and start an existing virtual machine yourself."
> -		echo "You'll need to use the qrap(1) wrapper, with qemu options"
> -		echo "as reported above."
>  
>  		next
>  	else
>  		echo "This script doesn't know, yet, how to run a virtual"
>  		echo "machine on your architecture (${__arch}). Please start an"
> -		echo "existing virtual machine yourself, using the qrap(1)"
> -		echo "wrapper, with qemu options as reported above."
> +		echo "existing virtual machine yourself."
>  		echo
>  	fi
>  
> @@ -225,12 +222,13 @@ into_ns() {
>  	next
>  
>  	# shellcheck disable=SC2086
> -	cmd qrap 5 ${__qemu_arch}					    \
> +	cmd ${__qemu_arch}						    \
>  		-smp "$(nproc)" -m 1024					    \
>  		-nographic -serial stdio -nodefaults -no-reboot -vga none   \
>  		-initrd "${DEMO_DIR}/demo.img"				    \
>  		-kernel "/boot/vmlinuz-$(uname -r)" -append "console=ttyS0" \
> -		-net socket,fd=5 -net nic,model=virtio || :
> +		-device virtio-net-pci,netdev=s				    \
> +		-netdev stream,id=s,server=off,addr.type=unix,addr.path="${DEMO_DIR}/passt.socket" || :
>  }
>  
>  STTY_BACKUP="$(stty -g)"
> diff --git a/doc/passt_overview.excalidraw b/doc/passt_overview.excalidraw
> index 790728e..3217b3f 100644
> --- a/doc/passt_overview.excalidraw
> +++ b/doc/passt_overview.excalidraw
> @@ -3595,35 +3595,6 @@
>        "baseline": 17,
>        "textAlign": "left",
>        "verticalAlign": "top"
> -    },
> -    {
> -      "type": "text",
> -      "version": 1448,
> -      "versionNonce": 1345391945,
> -      "isDeleted": false,
> -      "id": "c-esZiuHSm3wnTRlmIJZk",
> -      "fillStyle": "hachure",
> -      "strokeWidth": 1,
> -      "strokeStyle": "dotted",
> -      "roughness": 1,
> -      "opacity": 100,
> -      "angle": 4.969352159599495,
> -      "x": 816.7081559166961,
> -      "y": 215.74807066759342,
> -      "strokeColor": "#2b8a3e",
> -      "backgroundColor": "transparent",
> -      "width": 211,
> -      "height": 23,
> -      "seed": 939668423,
> -      "groupIds": [],
> -      "strokeSharpness": "round",
> -      "boundElementIds": [],
> -      "fontSize": 20,
> -      "fontFamily": 1,
> -      "text": "(currently \"qrap\" wrapper)",
> -      "baseline": 17,
> -      "textAlign": "left",
> -      "verticalAlign": "top"
>      }
>    ],
>    "appState": {
> diff --git a/hooks/pre-push b/hooks/pre-push
> index 3e2d15f..8eebdbc 100755
> --- a/hooks/pre-push
> +++ b/hooks/pre-push
> @@ -54,7 +54,7 @@ done
>  cd ..
>  
>  make pkgs
> -scp passt passt.avx2 passt.1 qrap qrap.1	"${USER_HOST}:${BIN}"
> +scp passt passt.avx2 passt.1			"${USER_HOST}:${BIN}"
>  scp pasta pasta.avx2 pasta.1			"${USER_HOST}:${BIN}"
>  scp passt-repair passt-repair.1			"${USER_HOST}:${BIN}"
>  scp pesto pesto.1				"${USER_HOST}:${BIN}"
> diff --git a/passt.1 b/passt.1
> index 995590a..53e072a 100644
> --- a/passt.1
> +++ b/passt.1
> @@ -580,8 +580,7 @@ Default is \fBnone\fR for \fBpasst\fR and \fBauto\fR for \fBpasta\fR.
>  
>  .TP
>  .BR \-s ", " \-\-socket-path ", " \-\-socket " " \fIpath
> -Path for UNIX domain socket used by \fBqemu\fR(1) or \fBqrap\fR(1) to connect to
> -\fBpasst\fR.
> +Path for UNIX domain socket used by \fBqemu\fR(1) to connect to \fBpasst\fR.
>  Default is to probe a free socket, not accepting connections, starting from
>  \fI/tmp/passt_1.socket\fR to \fI/tmp/passt_64.socket\fR.
>  
> @@ -762,129 +761,132 @@ forwards loopback traffic between namespaces.
>  .RS
>  .nf
>  $ iperf3 -s -D
> -$ ./pasta
> -Outbound interface: eth0, namespace interface: eth0
> -ARP:
> -    address: 28:16:ad:39:a9:ea
> -DHCP:
> -    assign: 192.168.1.118
> -    mask: 255.255.255.0
> -    router: 192.168.1.1
> -NDP/DHCPv6:
> -    assign: 2a02:6d40:3ca5:2001:b81d:fa4a:8cdd:cf17
> -    router: fe80::62e3:27ff:fe33:2b01
> -#
> -# dhclient -4 --no-pid
> -# dhclient -6 --no-pid
> +
> +$ pasta --config-net
> +
>  # ip address show
>  1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
>      link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
>      inet 127.0.0.1/8 scope host lo
>         valid_lft forever preferred_lft forever
> -    inet6 ::1/128 scope host 
> +    inet6 ::1/128 scope host proto kernel_lo 
>         valid_lft forever preferred_lft forever
> -2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc pfifo_fast state UNKNOWN group default qlen 1000
> -    link/ether 5e:90:02:eb:b0:2a brd ff:ff:ff:ff:ff:ff
> -    inet 192.168.1.118/24 brd 192.168.1.255 scope global eth0
> +2: enp9s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc fq_codel state UNKNOWN group default qlen 1000
> +    link/ether be:16:49:5a:65:dc brd ff:ff:ff:ff:ff:ff
> +    inet 88.198.0.164/27 brd 88.198.0.191 scope global noprefixroute enp9s0
>         valid_lft forever preferred_lft forever
> -    inet6 2a02:6d40:3ca5:2001:b81d:fa4a:8cdd:cf17/128 scope global 
> +    inet6 2a01:4f8:222:904::2/64 scope global nodad 
>         valid_lft forever preferred_lft forever
> -    inet6 2a02:6d40:3ca5:2001:5c90:2ff:feeb:b02a/64 scope global dynamic mngtmpaddr 
> -       valid_lft 3591sec preferred_lft 3591sec
> -    inet6 fe80::5c90:2ff:feeb:b02a/64 scope link 
> +    inet6 fe80::bc16:49ff:fe5a:65dc/64 scope link nodad proto kernel_ll 
>         valid_lft forever preferred_lft forever
> +
>  # ip route show
> -default via 192.168.1.1 dev eth0 
> -192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.118 
> +default via 88.198.0.161 dev enp9s0 proto dhcp metric 1002 
> +88.198.0.160/27 dev enp9s0 proto dhcp scope link metric 1002 
> +
>  # ip -6 route show
> -2a02:6d40:3ca5:2001:b81d:fa4a:8cdd:cf17 dev eth0 proto kernel metric 256 pref medium
> -2a02:6d40:3ca5:2001::/64 dev eth0 proto kernel metric 256 expires 3584sec pref medium
> -fe80::/64 dev eth0 proto kernel metric 256 pref medium
> -default via fe80::62e3:27ff:fe33:2b01 dev eth0 proto ra metric 1024 expires 3584sec pref medium
> +2a01:4f8:222:904::/64 dev enp9s0 proto kernel metric 256 pref medium
> +fe80::/64 dev enp9s0 proto kernel metric 256 pref medium
> +default via fe80::1 dev enp9s0 metric 1024 onlink pref medium
> +
>  # iperf3 -c 127.0.0.1 -t1
>  Connecting to host 127.0.0.1, port 5201
> -[  5] local 127.0.0.1 port 51938 connected to 127.0.0.1 port 5201
> +[  5] local 127.0.0.1 port 59112 connected to 127.0.0.1 port 5201
>  [ ID] Interval           Transfer     Bitrate         Retr  Cwnd
> -[  5]   0.00-1.00   sec  4.46 GBytes  38.3 Gbits/sec    0   3.93 MBytes       
> +[  5]   0.00-1.00   sec  3.89 GBytes  33.4 Gbits/sec    0   2.62 MBytes       
>  - - - - - - - - - - - - - - - - - - - - - - - - -
>  [ ID] Interval           Transfer     Bitrate         Retr
> -[  5]   0.00-1.00   sec  4.46 GBytes  38.3 Gbits/sec    0             sender
> -[  5]   0.00-1.41   sec  4.45 GBytes  27.1 Gbits/sec                  receiver
> +[  5]   0.00-1.00   sec  3.89 GBytes  33.4 Gbits/sec    0             sender
> +[  5]   0.00-1.00   sec  3.89 GBytes  33.4 Gbits/sec                  receiver
>  
>  iperf Done.
> +
>  # iperf3 -c ::1 -t1
>  Connecting to host ::1, port 5201
> -[  5] local ::1 port 50108 connected to ::1 port 5201
> +[  5] local ::1 port 49138 connected to ::1 port 5201
>  [ ID] Interval           Transfer     Bitrate         Retr  Cwnd
> -[  5]   0.00-1.00   sec  4.35 GBytes  37.4 Gbits/sec    0   4.99 MBytes       
> +[  5]   0.00-1.00   sec  4.32 GBytes  37.0 Gbits/sec    0   1.06 MBytes       
>  - - - - - - - - - - - - - - - - - - - - - - - - -
>  [ ID] Interval           Transfer     Bitrate         Retr
> -[  5]   0.00-1.00   sec  4.35 GBytes  37.4 Gbits/sec    0             sender
> -[  5]   0.00-1.41   sec  4.35 GBytes  26.4 Gbits/sec                  receiver
> +[  5]   0.00-1.00   sec  4.32 GBytes  37.0 Gbits/sec    0             sender
> +[  5]   0.00-1.00   sec  4.32 GBytes  37.0 Gbits/sec                  receiver
>  
>  iperf Done.
> -# ping -c1 -4 spaghetti.pizza
> -PING spaghetti.pizza (172.67.192.217) 56(84) bytes of data.
> -64 bytes from 172.67.192.217: icmp_seq=1 ttl=255 time=37.3 ms
> +
> +# ping -nc1 -4 spaghetti.pizza
> +PING spaghetti.pizza (5.161.47.86) 56(84) bytes of data.
> +64 bytes from 5.161.47.86: icmp_seq=1 ttl=255 time=99.4 ms
>  
>  --- spaghetti.pizza ping statistics ---
>  1 packets transmitted, 1 received, 0% packet loss, time 0ms
> -# ping -c1 -6 spaghetti.pizza
> -PING spaghetti.pizza(2606:4700:3034::6815:147a (2606:4700:3034::6815:147a)) 56 data bytes
> -64 bytes from 2606:4700:3034::6815:147a: icmp_seq=1 ttl=255 time=35.6 ms
> +rtt min/avg/max/mdev = 99.433/99.433/99.433/0.000 ms
> +# ping -nc1 -6 spaghetti.pizza
> +PING spaghetti.pizza (2a01:4f8:1c1e:d6f1::1) 56 data bytes
> +64 bytes from 2a01:4f8:1c1e:d6f1::1: icmp_seq=1 ttl=255 time=3.11 ms
>  
>  --- spaghetti.pizza ping statistics ---
>  1 packets transmitted, 1 received, 0% packet loss, time 0ms
> -rtt min/avg/max/mdev = 35.605/35.605/35.605/0.000 ms
> -# logout
> -$
> -
> -.RE
> +rtt min/avg/max/mdev = 3.110/3.110/3.110/0.000 ms
>  .fi
> +.RE
>  
>  .BR "Connect an existing user and network namespace"
>  .RS
>  .nf
>  $ unshare -rUn
> -# echo $$
> -2446678
>  
> +# echo $$
> +1295969
>  .fi
> -.BR "	[From another terminal]"
> +
> +.BR "[From another terminal]"
>  .nf
> -$ ./pasta 2446678
> -Outbound interface: eth0, namespace interface: eth0
> -ARP:
> -    address: 28:16:ad:39:a9:ea
> +$ pasta --config-net 1295969
> +Template interface: enp9s0 (IPv4), enp9s0 (IPv6)
> +Namespace interface: enp9s0
> +MAC:
> +    host: 9a:55:9a:55:9a:55
> +    NAT to host 127.0.0.1: 88.198.0.161
>  DHCP:
> -    assign: 192.168.1.118
> -    mask: 255.255.255.0
> -    router: 192.168.1.1
> +    assign: 88.198.0.164
> +    mask: 255.255.255.224
> +    router: 88.198.0.161
> +DNS:
> +    185.12.64.1
> +    185.12.64.2
> +    NAT to host ::1: fe80::1
>  NDP/DHCPv6:
> -    assign: 2a02:6d40:3ca5:2001:b81d:fa4a:8cdd:cf17
> -    router: fe80::62e3:27ff:fe33:2b01
> -
> +    assign: 2a01:4f8:222:904::2
> +    router: fe80::1
> +    our link-local: fe80::1
> +Inbound forwarding rules (HOST):
> +    TCP [*]:1-32767  =>  1-32767  (best effort) (auto-scan)
> +    TCP [*]:61000-65535  =>  61000-65535  (best effort) (auto-scan)
> +    UDP [*]:1-32767  =>  1-32767  (best effort) (auto-scan)
> +    UDP [*]:61000-65535  =>  61000-65535  (best effort) (auto-scan)
> +Outbound forwarding rules (SPLICE):
> +    TCP [*]%lo:1-32767  =>  1-32767  (best effort) (auto-scan)
> +    TCP [*]%lo:61000-65535  =>  61000-65535  (best effort) (auto-scan)
> +    UDP [*]%lo:1-32767  =>  1-32767  (best effort) (auto-scan)
> +    UDP [*]%lo:61000-65535  =>  61000-65535  (best effort) (auto-scan)
>  .fi
> -.BR "	[Back to the original terminal]"
> +
> +.BR "[Back to the original terminal]"
>  .nf
> -# dhclient -4 --no-pid
> -# dhclient -6 --no-pid
>  # ip address show
>  1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
>      link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
>      inet 127.0.0.1/8 scope host lo
>         valid_lft forever preferred_lft forever
> -    inet6 ::1/128 scope host 
> +    inet6 ::1/128 scope host proto kernel_lo 
>         valid_lft forever preferred_lft forever
> -2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc pfifo_fast state UNKNOWN group default qlen 1000
> -    link/ether fa:c1:2a:27:92:a9 brd ff:ff:ff:ff:ff:ff
> -    inet 192.168.1.118/24 brd 192.168.1.255 scope global eth0
> +2: enp9s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc fq_codel state UNKNOWN group default qlen 1000
> +    link/ether 9a:44:5e:54:d3:2c brd ff:ff:ff:ff:ff:ff
> +    inet 88.198.0.164/27 brd 88.198.0.191 scope global noprefixroute enp9s0
>         valid_lft forever preferred_lft forever
> -    inet6 2a02:6d40:3ca5:2001:b81d:fa4a:8cdd:cf17/128 scope global 
> +    inet6 2a01:4f8:222:904::2/64 scope global nodad 
>         valid_lft forever preferred_lft forever
> -    inet6 2a02:6d40:3ca5:2001:f8c1:2aff:fe27:92a9/64 scope global dynamic mngtmpaddr 
> -       valid_lft 3594sec preferred_lft 3594sec
> -    inet6 fe80::f8c1:2aff:fe27:92a9/64 scope link 
> +    inet6 fe80::9844:5eff:fe54:d32c/64 scope link nodad proto kernel_ll 
>         valid_lft forever preferred_lft forever
>  .fi
>  .RE
> @@ -893,72 +895,69 @@ NDP/DHCPv6:
>  .BR "Start and connect a guest with basic port forwarding"
>  .RS
>  .nf
> -$ ./passt -f -t 2222:22
> -Outbound interface: eth0
> -ARP:
> -    address: 28:16:ad:39:a9:ea
> +$ passt -f -t 2222:22
> +UNIX domain socket bound at /tmp/passt_1.socket
> +No IPv6 nameserver available for NDP/DHCPv6
> +Template interface: enp9s0 (IPv4), enp9s0 (IPv6)
> +MAC:
> +    host: 9a:55:9a:55:9a:55
> +    NAT to host 127.0.0.1: 88.198.0.161
>  DHCP:
> -    assign: 192.168.1.118
> -    mask: 255.255.255.0
> -    router: 192.168.1.1
> -        search:
> -            redhat.com
> +    assign: 88.198.0.164
> +    mask: 255.255.255.224
> +    router: 88.198.0.161
> +DNS:
> +    185.12.64.1
> +    185.12.64.2
> +    NAT to host ::1: fe80::1
>  NDP/DHCPv6:
> -    assign: 2a02:6d40:3ca5:2001:b81d:fa4a:8cdd:cf17
> -    router: fe80::62e3:27ff:fe33:2b01
> -        search:
> -            redhat.com
> -UNIX domain socket bound at /tmp/passt_1.socket
> -
> -You can now start qrap:
> -    ./qrap 5 qemu-system-x86_64 ... -net socket,fd=5 -net nic,model=virtio
> -or directly qemu, patched with:
> -    qemu/0001-net-Allow-also-UNIX-domain-sockets-to-be-used-as-net.patch
> -as follows:
> -    qemu-system-x86_64 ... -net socket,connect=/tmp/passt_1.socket -net nic,model=virtio
> -
> +    assign: 2a01:4f8:222:904::2
> +    router: fe80::1
> +    our link-local: fe80::1
> +Inbound forwarding rules (HOST):
> +    TCP [*]:2222  =>  22 
> +
> +You can now start qemu (>= 7.2, with commit 13c6be96618c):
> +    kvm ... -device virtio-net-pci,netdev=s -netdev stream,id=s,server=off,addr.type=unix,addr.path=/tmp/passt_1.socket
>  .fi
> -.BR "	[From another terminal]"
> -.nf
> -$ ./qrap 5 qemu-system-x86_64 test.qcow2 -m 1024 -display none -nodefaults -nographic -net socket,fd=5 -net nic,model=virtio
> -Connected to /tmp/passt_1.socket
>  
> -.fi
> -.BR "	[Back to the original terminal]"
> +.BR "[From another terminal]"
>  .nf
> -passt: DHCP: ack to request
> -passt:     from 52:54:00:12:34:56
> -passt: NDP: received NS, sending NA
> -passt: NDP: received RS, sending RA
> -passt: DHCPv6: received SOLICIT, sending ADVERTISE
> -passt: NDP: received NS, sending NA
> -passt: DHCPv6: received REQUEST/RENEW/CONFIRM, sending REPLY
> -passt: NDP: received NS, sending NA
> +$ qemu-system-x86_64 -m 128 test.qcow2 -display none -nodefaults -nographic -device virtio-net-pci,netdev=s -netdev stream,id=s,server=off,addr.type=unix,addr.path=/tmp/passt_1.socket
> +.fi
>  
> +.BR "[Back to the original terminal]"
> +.nf
> +accepted connection from PID 1301736
> +New guest MAC address observed: 52:54:00:12:34:56
> +DHCP: offer to discover
> +    from 52:54:00:12:34:56
> +DHCP: ack to request
> +    from 52:54:00:12:34:56
> +NDP: received RS, sending RA
>  .fi
> -.BR "	[From yet another terminal]"
> +
> +.BR "[From yet another terminal]"
>  .nf
>  $ ssh -p 2222 root@localhost
>  root@localhost's password: 
>  .fi
> -.BR "	[...]"
> +.BR "[...]"
>  .nf
>  # ip address show
> -1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
> +1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
>      link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
>      inet 127.0.0.1/8 scope host lo
>         valid_lft forever preferred_lft forever
>      inet6 ::1/128 scope host 
>         valid_lft forever preferred_lft forever
> -2: ens2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc pfifo_fast state UP group default qlen 1000
> +2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
>      link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
> -    inet 192.168.1.118/24 brd 192.168.1.255 scope global noprefixroute ens2
> +    inet 88.198.0.164/27 scope global eth0
>         valid_lft forever preferred_lft forever
> -    inet6 2a02:6d40:3ca5:2001:b81d:fa4a:8cdd:cf17/128 scope global noprefixroute 
> +    inet6 2a01:4f8:222:904:5054:ff:fe12:3456/64 scope global dynamic flags 100 
>         valid_lft forever preferred_lft forever
> -    inet6 2a02:6d40:3ca5:2001:b019:9ae2:a2fe:e6b4/64 scope global dynamic noprefixroute 
> -       valid_lft 3588sec preferred_lft 3588sec
> -    inet6 fe80::1f98:d09f:9309:9e77/64 scope link noprefixroute 
> +    inet6 fe80::5054:ff:fe12:3456/64 scope link 
>         valid_lft forever preferred_lft forever
>  .fi
>  .RE
> diff --git a/qrap.1 b/qrap.1
> deleted file mode 100644
> index 98cc877..0000000
> --- a/qrap.1
> +++ /dev/null
> @@ -1,77 +0,0 @@
> -.\" SPDX-License-Identifier: GPL-2.0-or-later
> -.\" Copyright (c) 2020-2021 Red Hat GmbH
> -.\" Author: Stefano Brivio <sbrivio@redhat.com>
> -.TH qrap 1
> -
> -.SH NAME
> -.B qrap
> -\- temporary qemu wrapper connecting UNIX domain socket to file descriptor
> -
> -.SH SYNOPSIS
> -.B qrap
> -[\fIFDNUM\fR \fIQEMU_CMD\fR] [\fIQEMU_ARG\fR]...
> -.SH DESCRIPTION
> -\fBqrap\fR is a wrapper, designed specifically for usage with \fBqemu\fR(1) and
> -\fBpasst\fR(1), connecting a UNIX domain socket to a file descriptor, and
> -running \fBqemu\fR(1) with given arguments.
> -
> -A running instance of \fBpasst\fR(1) is probed checking for UNIX domain sockets,
> -answering a dummy ARP request, with names starting from
> -\fI/tmp/passt_1.socket\fR up to \fI/tmp/passt_64.socket\fR.
> -
> -If first and second arguments are not a socket number and a command, that is,
> -respectively, \fIFDNUM\fR and \fIQEMU_CMD\fR, \fBqrap\fR will try to locate a
> -qemu executable in \fBPATH\fR and patch the command line to specify a network
> -device and a \fInetdev\fR back-end for usage with \fBpasst\fR(1).
> -
> -If \fBqrap\fR patches the command line, it will remove any potentially
> -conflicting network device, that is, any \fI-netdev\fR or \fI-net\fR option, or
> -any \fI-device\fR option with argument starting with \fIvirtio-net-pci,\fR,
> -\fIvirtio-net-ccw,\fR, \fIe1000,\fR, \fIe1000e,\fR, or \fIrtl8139,\fR.
> -
> -.SH EXAMPLES
> -
> -.BR "Start qemu explicitly passing its command name and a socket number"
> -.RS
> -.nf
> -$ ./qrap 5 kvm test.qcow2 -m 1024 -display none -nodefaults -nographic -net socket,fd=5 -net nic,model=virtio
> -.fi
> -.RE
> -
> -.BR "Start qemu without command name and socket number, patching arguments"
> -.RS
> -.nf
> -$ ./qrap test.qcow2 -m 1024 -display none -nodefaults -nographic
> -.fi
> -.RE
> -
> -.SH NOTES
> -
> -This wrapper is temporary: qemu commit 13c6be96618c ("net: stream: add unix
> -socket") introduces native AF_UNIX socket support, and it should be included in
> -qemu starting from the 7.2 release. It will be around for a little bit longer to
> -give users enough time to switch.
> -
> -.SH AUTHOR
> -
> -Stefano Brivio <sbrivio@redhat.com>
> -
> -.SH REPORTING BUGS
> -
> -No public bug tracker is available at this time. For the moment being, report
> -issues to Stefano Brivio <sbrivio@redhat.com>.
> -
> -.SH COPYRIGHT
> -
> -Copyright (c) 2020-2021 Red Hat GmbH.
> -
> -\fBqrap\fR is free software: you can redistribute is and/or modify it under the
> -terms of the GNU General Public License as published by the Free Software
> -Foundation, either version 2 of the License, or (at your option) any later
> -version. 
> -
> -.SH SEE ALSO
> -
> -\fBqemu\fR(1), \fBpasst\fR(1).
> -
> -High-level documentation is available at https://passt.top/passt/about/.
> diff --git a/qrap.c b/qrap.c
> deleted file mode 100644
> index d596706..0000000
> --- a/qrap.c
> +++ /dev/null
> @@ -1,429 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-or-later
> -
> -/* PASST - Plug A Simple Socket Transport
> - *
> - * qrap.c - qemu wrapper connecting UNIX domain socket to file descriptor
> - *
> - * Copyright (c) 2020-2021 Red Hat GmbH
> - * Author: Stefano Brivio <sbrivio@redhat.com>
> - *
> - * TODO: Drop this implementation once qemu commit 13c6be96618c ("net: stream:
> - * add unix socket") is included in a release (7.2), and once we can reasonably
> - * assume existing users switched to it.
> - */
> -
> -#include <stdio.h>
> -#include <stdint.h>
> -#include <stdlib.h>
> -#include <string.h>
> -#include <unistd.h>
> -#include <sys/types.h>
> -#include <sys/socket.h>
> -#include <errno.h>
> -#include <linux/limits.h>
> -#include <limits.h>
> -#include <fcntl.h>
> -#include <net/if_arp.h>
> -#include <netinet/in.h>
> -#include <netinet/ip6.h>
> -#include <netinet/if_ether.h>
> -#include <time.h>
> -
> -#include <linux/icmpv6.h>
> -
> -#include "util.h"
> -#include "ip.h"
> -#include "passt.h"
> -#include "arp.h"
> -
> -static char *qemu_names[] = {
> -	"kvm",
> -	"qemu-kvm",
> -#ifdef ARCH
> -	( "qemu-system-" ARCH ),
> -#endif
> -	"/usr/libexec/qemu-kvm",
> -	NULL,
> -};
> -
> -/**
> - * struct drop_arg - Drop matching arguments on command line
> - * @name:	Option name
> - * @val:	Substring in option value, NULL matches any value
> - */
> -static const struct drop_arg {
> -	char *name;
> -	char *val;
> -} drop_args[] = {
> -	{ "-netdev",	NULL },
> -	{ "-net",	NULL },
> -	{ "-device",	"virtio-net-pci," },
> -	{ "-device",	"{\"driver\":\"virtio-net-pci\"," },
> -	{ "-device",	"virtio-net-ccw," },
> -	{ "-device",	"{\"driver\":\"virtio-net-ccw\"," },
> -	{ "-device",	"e1000," },
> -	{ "-device",	"{\"driver\":\"e1000\"," },
> -	{ "-device",	"e1000e," },
> -	{ "-device",	"{\"driver\":\"e1000e\"," },
> -	{ "-device",	"rtl8139," },
> -	{ "-device",	"{\"driver\":\"rtl8139\"," },
> -	{ 0 },
> -};
> -
> -/**
> - * struct pci_dev - PCI devices to add on command line depending on machine name
> - * @mach:		Machine name
> - * @name:		Device ("-device") name to insert
> - * @template:		Prefix for device specification (first part of address)
> - * @template_post:	Suffix for device specification (last part of address)
> - * @template_json:		Device prefix for when JSON is used
> - * @template_json_post:	Device suffix for when JSON is used
> - * @base:		Base used for PCI addresses
> - * @first:		First usable PCI address
> - * @last:		Last usable PCI address
> - */
> -static const struct pci_dev {
> -	char *mach;
> -	char *name;
> -	char *template;
> -	char *template_post;
> -	char *template_json;
> -	char *template_json_post;
> -	int base;
> -	int first;
> -	int last;
> -} pci_devs[] = {
> -	{
> -		"pc-q35", "virtio-net-pci",
> -		"bus=pci.", ",addr=0x0",
> -		"\"bus\":\"pci.", ",\"addr\":\"0x0\"",
> -		10, 3, /* 2: hotplug bus */ 31
> -	},
> -	{
> -		"pc-", "virtio-net-pci",
> -		"bus=pci.0,addr=0x", "",
> -		"\"bus\":\"pci.0\",\"addr\":\"0x", "",
> -		16, 2, /* 1: ISA bridge */ 31
> -	},
> -	{
> -		"s390-ccw", "virtio-net-ccw",
> -		"devno=fe.0.", "",
> -		"\"devno\":\"fe.0.", "",
> -		16, 1, 16
> -	},
> -	{ 0 },
> -};
> -
> -#define DEFAULT_FD	5
> -
> -/**
> - * usage() - Print usage and exit
> - * @name:	Executable name
> - */
> -void usage(const char *name)
> -{
> -	fprintf(stderr, "Usage: %s [FDNUM QEMU_CMD] [QEMU_ARG]...\n", name);
> -	fprintf(stderr, "\n");
> -	fprintf(stderr, "If first and second arguments aren't a socket number\n"
> -			"and a path, %s will try to locate a qemu binary\n"
> -			"and directly patch the command line\n", name);
> -
> -	exit(EXIT_FAILURE);
> -}
> -
> -/**
> - * main() - Entry point and main loop
> - * @argc:	Argument count
> - * @argv:	File descriptor number, then qemu with arguments
> - *
> - * Return: 0 once interrupted, non-zero on failure
> - */
> -int main(int argc, char **argv)
> -{
> -	int i, s, qemu_argc = 0, addr_map = 0, has_dev = 0, has_json = 0, retry_on_reset, rc;
> -	struct timeval tv = { .tv_sec = 0, .tv_usec = (long)(500 * 1000) };
> -	char *qemu_argv[ARG_MAX], dev_str[ARG_MAX];
> -	struct sockaddr_un addr = {
> -		.sun_family = AF_UNIX,
> -	};
> -	const struct pci_dev *dev = NULL;
> -	long fd;
> -	struct {
> -		uint32_t vnet_len4;
> -		struct ethhdr eh4;
> -		struct arphdr ah;
> -		struct arpmsg am;
> -
> -		uint32_t vnet_len6;
> -		struct ethhdr eh6;
> -		struct ipv6hdr ip6hr;
> -		struct icmp6hdr ihr;
> -		struct in6_addr target;
> -	} __attribute__((__packed__)) probe = {
> -		.vnet_len4 = htonl(42),
> -		{
> -			.h_dest   = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
> -			.h_source = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
> -			.h_proto  = htons(ETH_P_ARP),
> -		},
> -		{	.ar_hrd = htons(ARPHRD_ETHER),
> -			.ar_pro = htons(ETH_P_IP),
> -			.ar_hln = ETH_ALEN,
> -			.ar_pln = 4,
> -			.ar_op  = htons(ARPOP_REQUEST),
> -		},
> -		{
> -			.sha = { 0 }, .sip = { 0 }, .tha = { 0 }, .tip = { 0 },
> -		},
> -		.vnet_len6 = htonl(78),
> -		{
> -			.h_dest   = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
> -			.h_source = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
> -			.h_proto  = htons(ETH_P_IPV6),
> -		},
> -		{
> -			.version = 6,
> -			.payload_len = htons(24),
> -			.nexthdr = IPPROTO_ICMPV6,
> -			.hop_limit = 255,
> -			.saddr = IN6ADDR_LOOPBACK_INIT,
> -			.daddr = IN6ADDR_ANY_INIT,
> -		},
> -		{
> -			.icmp6_type = 135,
> -			.icmp6_code = 0,
> -		},
> -		IN6ADDR_ANY_INIT,
> -	};
> -	char probe_r;
> -
> -	if (argc >= 3) {
> -		const char *path = getenv("PATH");
> -		errno = 0;
> -		fd = strtol(argv[1], NULL, 0);
> -		if (fd >= 3 && fd < INT_MAX && !errno && path) {
> -			char env_path[ARG_MAX + 1], *p, command[ARG_MAX];
> -
> -			strncpy(env_path, path, ARG_MAX);
> -			/* cppcheck-suppress strtokCalled */
> -			p = strtok(env_path, ":");
> -			while (p) {
> -				snprintf(command, ARG_MAX, "%s/%s", p, argv[2]);
> -				if (!access(command, X_OK))
> -					goto valid_args;
> -
> -				/* cppcheck-suppress strtokCalled */
> -				p = strtok(NULL, ":");
> -			}
> -		}
> -	}
> -
> -	fd = DEFAULT_FD;
> -
> -	for (i = 1; i < argc - 1; i++) {
> -		if (strcmp(argv[i], "-machine"))
> -			continue;
> -
> -		for (dev = pci_devs; dev->mach; dev++) {
> -			if (strstr(argv[i + 1], dev->mach) == argv[i + 1])
> -				break;
> -		}
> -	}
> -
> -	if (!dev || !dev->mach)
> -		dev = pci_devs;
> -
> -	for (qemu_argc = 1, i = 1; i < argc; i++) {
> -		const struct drop_arg *a;
> -
> -		for (a = drop_args; a->name; a++) {
> -			if (!strcmp(argv[i], a->name)) {
> -				if (!a->val)
> -					break;
> -
> -				if (i + 1 < argc &&
> -				    strstr(argv[i + 1], a->val) == argv[i + 1])
> -					break;
> -			}
> -		}
> -		if (a->name) {
> -			i++;
> -			continue;
> -		}
> -
> -		if (!strcmp(argv[i], "-device") && i + 1 < argc) {
> -			const char *template = NULL;
> -			const char *p;
> -
> -			has_dev = 1;
> -
> -			if ((p = strstr(argv[i + 1], dev->template))) {
> -				template = dev->template;
> -			} else if ((p = strstr(argv[i + 1], dev->template_json))) {
> -				template = dev->template_json;
> -				has_json = 1;
> -			}
> -
> -			if (template) {
> -				long n;
> -
> -				n = strtol(p + strlen(template), NULL, dev->base);
> -				if (!errno)
> -					addr_map |= (1 << n);
> -			}
> -		}
> -
> -		qemu_argv[qemu_argc++] = argv[i];
> -	}
> -
> -	for (i = dev->first; i < dev->last; i++) {
> -		if (!(addr_map & (1 << i)))
> -			break;
> -	}
> -	if (i == dev->last) {
> -		fprintf(stderr, "Couldn't find free address for device\n");
> -		usage(argv[0]);
> -	}
> -
> -	if (has_dev) {
> -		qemu_argv[qemu_argc++] = "-device";
> -		if (!has_json) {
> -			if (dev->base == 16) {
> -				snprintf(dev_str, ARG_MAX,
> -				         "%s,%s%x%s,netdev=hostnet0,x-txburst=4096",
> -				         dev->name, dev->template, i, dev->template_post);
> -			} else if (dev->base == 10) {
> -				snprintf(dev_str, ARG_MAX,
> -				         "%s,%s%d%s,netdev=hostnet0,x-txburst=4096",
> -				         dev->name, dev->template, i, dev->template_post);
> -			}
> -		} else {
> -			if (dev->base == 16) {
> -				snprintf(dev_str, ARG_MAX,
> -				         "{\"driver\":\"%s\",%s%x\"%s,\"netdev\":\"hostnet0\",\"x-txburst\":4096}",
> -				         dev->name, dev->template_json, i, dev->template_json_post);
> -			} else if (dev->base == 10) {
> -				snprintf(dev_str, ARG_MAX,
> -				         "{\"driver\":\"%s\",%s%d\"%s,\"netdev\":\"hostnet0\",\"x-txburst\":4096}",
> -				         dev->name, dev->template_json, i, dev->template_json_post);
> -			}
> -		}
> -		qemu_argv[qemu_argc++] = dev_str;
> -	}
> -
> -	qemu_argv[qemu_argc++] = "-netdev";
> -	if (!has_json) {
> -		qemu_argv[qemu_argc++] = "socket,fd=" STR(DEFAULT_FD) ",id=hostnet0";
> -	} else {
> -		qemu_argv[qemu_argc++] = "{\"type\":\"socket\",\"fd\":\"" STR(DEFAULT_FD) "\",\"id\":\"hostnet0\"}";
> -	}
> -	qemu_argv[qemu_argc] = NULL;
> -
> -valid_args:
> -	for (i = 1; i < UNIX_SOCK_MAX; i++) {
> -		retry_on_reset = 50;
> -
> -retry:
> -		s = socket(AF_UNIX, SOCK_STREAM, 0);
> -		if (s < 0) {
> -			perror("socket");
> -			exit(EXIT_FAILURE);
> -		}
> -
> -		if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)))
> -			perror("setsockopt SO_RCVTIMEO");
> -		if (setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)))
> -			perror("setsockopt SO_SNDTIMEO");
> -
> -		snprintf(addr.sun_path, UNIX_PATH_MAX, UNIX_SOCK_PATH, i);
> -
> -		errno = 0;
> -
> -		if (connect(s, (const struct sockaddr *)&addr, sizeof(addr))) {
> -			rc = errno;
> -			perror("connect");
> -		} else if (send(s, &probe, sizeof(probe), 0) != sizeof(probe)) {
> -			rc = errno;
> -			perror("send");
> -		} else if (recv(s, &probe_r, 1, MSG_PEEK) <= 0) {
> -			rc = errno;
> -			perror("recv");
> -		} else {
> -			break;
> -		}
> -
> -		/* FIXME: in a KubeVirt environment, libvirtd invokes qrap three
> -		 * times in a strict sequence when a virtual machine needs to
> -		 * be started, namely, when:
> -		 * - the domain XML is saved
> -		 * - the domain is started (for "probing")
> -		 * - the virtual machine is started for real
> -		 * and it often happens that the qemu process is still running
> -		 * when qrap is invoked again, so passt will refuse the new
> -		 * connection because the previous one is still active. This
> -		 * overlap seems to be anywhere between 0 and 3ms.
> -		 *
> -		 * If we get a connection reset, retry a few times, to allow for
> -		 * the previous qemu instance to terminate and, in turn, for the
> -		 * connection to passt to be closed.
> -		 *
> -		 * This should be fixed in libvirt instead. It probably makes
> -		 * sense to check this behaviour once native libvirt support is
> -		 * there, and this implies native qemu support too, so at that
> -		 * point qrap will have no reason to exist anymore -- that is,
> -		 * this FIXME will probably remain until the tool itself is
> -		 * obsoleted.
> -		 */
> -		if (retry_on_reset && rc == ECONNRESET) {
> -			retry_on_reset--;
> -			/* cppcheck-suppress usleepCalled */
> -			usleep(50 * 1000);
> -			goto retry;
> -		}
> -
> -		fprintf(stderr, "Probe of %s failed\n", addr.sun_path);
> -
> -		close(s);
> -	}
> -
> -	if (i == UNIX_SOCK_MAX) {
> -		perror("connect");
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	tv.tv_usec = 0;
> -	if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)))
> -		perror("setsockopt, SO_RCVTIMEO reset");
> -	if (setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)))
> -		perror("setsockopt, SO_SNDTIMEO reset");
> -
> -	fprintf(stderr, "Connected to %s\n", addr.sun_path);
> -
> -	if (dup2(s, (int)fd) < 0) {
> -		perror("dup");
> -		exit(EXIT_FAILURE);
> -	}
> -
> -	close(s);
> -
> -	if (qemu_argc) {
> -		char **name;
> -
> -		for (name = qemu_names; *name; name++) {
> -			qemu_argv[0] = *name;
> -			execvp(*name, qemu_argv);
> -			if (errno != ENOENT) {
> -				perror("execvp");
> -				usage(argv[0]);
> -			}
> -		}
> -		if (errno == ENOENT)
> -			fprintf(stderr, "Couldn't find qemu command\n");
> -	} else {
> -		execvp(argv[2], argv + 2);
> -	}
> -
> -	perror("execvp");
> -
> -	return EXIT_FAILURE;
> -}
> diff --git a/tap.c b/tap.c
> index cf87591..dfa66c7 100644
> --- a/tap.c
> +++ b/tap.c
> @@ -1377,8 +1377,6 @@ static void tap_backend_show_hints(const struct ctx *c)
>  		info("\nYou can now start qemu (>= 7.2, with commit 13c6be96618c):");
>  		info("    kvm ... -device virtio-net-pci,netdev=s -netdev stream,id=s,server=off,addr.type=unix,addr.path=%s",
>  		     c->sock_path);
> -		info("or qrap, for earlier qemu versions:");
> -		info("    ./qrap 5 kvm ... -net socket,fd=5 -net nic,model=virtio");
>  		break;
>  	case MODE_VU:
>  		info("You can start qemu with:");
> diff --git a/test/distro/opensuse b/test/distro/opensuse
> index eab722b..9ceb0bd 100644
> --- a/test/distro/opensuse
> +++ b/test/distro/opensuse
> @@ -39,7 +39,7 @@ hostb	./passt -s __STATEDIR__/passt.socket -P __PIDFILE__ &
>  sleep	1
>  host	echo
>  hout	DNS6 sed -n 's/^nameserver \([^:]*:\)\([^%]*\).*/\1\2/p' /etc/resolv.conf | head -1
> -hout	GUEST_FILES ls -1 *.c *.h *.sh passt.1 qrap.1 Makefile README.md | tr '\n' ' '; echo
> +hout	GUEST_FILES ls -1 *.c *.h *.sh passt.1 Makefile README.md | tr '\n' ' '; echo
>  
>  
>  test	OpenSUSE Leap 15.1
> -- 
> 2.43.0
> 

-- 
David Gibson (he or they)	| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you, not the other way
				| around.
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-07-19  4:21 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-18  7:42 [PATCH] treewide: Sandbox qrap Stefano Brivio
2026-07-19  4:03 ` David Gibson

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).