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