public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
* [PATCH] treewide: Sandbox qrap
@ 2026-07-18  7:42 Stefano Brivio
  0 siblings, 0 replies; only message 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] only message in thread

only message in thread, other threads:[~2026-07-18  7:42 UTC | newest]

Thread overview: (only message) (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

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