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 Hooray! Reviewed-by: David Gibson > --- > .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: 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: 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: 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: 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: 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: 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: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 > +1: lo: 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: mtu 65520 qdisc pfifo_fast state UP group default qlen 1000 > +2: eth0: 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 > -.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 > - > -.SH REPORTING BUGS > - > -No public bug tracker is available at this time. For the moment being, report > -issues to Stefano Brivio . > - > -.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 > - * > - * 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 > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > -#include > - > -#include > - > -#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