@@ -30,9 +30,14 @@ cost twice over.
3030it relocates the ceiling rather than removing
3131it: packets now arrive faster than a single guest receive queue can drain, and
3232the drops reappear at a higher rate. More queue pairs is what removes them,
33- which is why both are defaults: vhost everywhere, and a queue count that follows
34- the VM's vCPU count. The knob you are more likely to reach for is the other
35- direction — see [ Choosing a queue count] ( #choosing-a-queue-count ) .
33+ which is why enabling vhost also enables a queue count that follows the VM's
34+ vCPU count — the two travel together.
35+
36+ vhost is ** off by default** and enabled per node (or per VM). Two things make
37+ it an opt-in rather than a default: turning it on changes the virtio-net device
38+ of every bridge/macvtap VM on its next boot, and it requires ` /dev/vhost-net `
39+ to be accessible to the account QEMU runs under, which the VMM cannot verify on
40+ the operator's behalf — see [ Enabling vhost on a node] ( #enabling-vhost-on-a-node ) .
3641
3742## Configuration
3843
@@ -47,22 +52,24 @@ bridge = "dstack-br0"
4752vhost = true
4853```
4954
50- Queue pairs are not a node setting. They default to the VM's vCPU count, capped
51- at 16, because the useful number follows the VM rather than the host — the guest
52- driver uses at most one queue pair per vCPU. A deployment overrides that per VM,
53- up to ` max_net_queues ` .
55+ Queue pairs are not a node setting. With vhost on they default to the VM's vCPU
56+ count, capped at 16, because the useful number follows the VM rather than the
57+ host — the guest driver uses at most one queue pair per vCPU. A deployment
58+ overrides that per VM, up to ` max_net_queues ` .
5459
5560Raising ` max_net_queues ` above 16 widens what a deployment may ask for without
5661moving the default's cap, so a larger VM never silently acquires a worse
5762default. Lowering it below 16 does lower the default too, because a node that
5863refuses a request for four queue pairs should not hand out sixteen by itself.
5964The hard ceiling from any source is 64.
6065
61- Turning vhost off also turns the multiqueue default off. Without vhost the QEMU
62- main loop drains every queue on one thread, so extra queues buy little while
63- still costing a netd interface, more MSI-X vectors, and a changed guest device.
64- An explicit queue count is still honoured without vhost, since that combination
65- is a deliberate request rather than a default.
66+ Without vhost the default is a single queue pair. The QEMU main loop drains
67+ every queue on one thread, so extra queues buy little while still costing a
68+ netd interface, more MSI-X vectors, and a changed guest device. An explicit
69+ queue count is still honoured without vhost, since that combination is a
70+ deliberate request rather than a default. The two defaults travelling together
71+ also means a node that never sets ` vhost ` keeps building the device its VMs
72+ have always had.
6673
6774A VM overrides either value at deploy time, and ` UpdateVm ` changes them
6875afterwards — the new values apply from the VM's next boot:
@@ -128,6 +135,31 @@ vhost state are not part of it, so retuning a NIC does not change app identity
128135or require an on-chain update. Adding or removing a NIC does: the NIC count
129136changes the guest's ACPI tables and therefore RTMR0.
130137
138+ ## Enabling vhost on a node
139+
140+ Setting ` vhost = true ` in ` [cvm.networking] ` is a node-wide behaviour change:
141+ every bridge or macvtap VM that has not pinned its own data plane gets a
142+ different virtio-net device on its next boot — ` vhost=on ` , ` mq=on ` with
143+ vCPU-scaled queue pairs, and the matching MSI-X vector count. The device is not
144+ measured, so attestation and app identity are unaffected. Before flipping it:
145+
146+ 1 . ** Verify ` /dev/vhost-net ` is accessible to the account QEMU runs under.**
147+ It is ` root:kvm 0660 ` on Debian-family hosts, where adding the account to
148+ the ` kvm ` group suffices, and ` root:root 0600 ` on several others. If the
149+ account lacks access, QEMU exits at launch and every affected VM stops
150+ restarting. The VMM warns at startup when its own access fails, but it
151+ cannot refuse on that basis — QEMU need not share its credentials.
152+
153+ 2 . ** Restart ` netd ` before or together with the VMM.** Multiqueue bridge NICs
154+ are prepared by ` netd ` , and the VMM checks that ` netd ` echoes the queue
155+ count it built. An older ` netd ` fails that check; the launch is rolled back
156+ and fails with the reason in the VMM log, but the VM does not start until
157+ ` netd ` is upgraded.
158+
159+ 3 . ** Roll back by setting ` vhost = false ` .** The node value reaches every VM
160+ that did not pin ` vhost ` explicitly, from its next boot; a VM that pinned
161+ ` vhost = true ` keeps it until updated.
162+
131163## What each mode supports
132164
133165| Mode | netdev | vhost | queues > 1 |
@@ -144,8 +176,8 @@ vhost switches bridge mode to a `tap` netdev driven by the same setuid
144176no compiled-in default path for the ` tap ` netdev, so the VMM probes the known
145177distribution locations; set ` cvm.qemu_bridge_helper ` if yours is elsewhere. If
146178no helper is found the NIC falls back to the non-vhost ` bridge ` netdev with a
147- warning, because vhost is a default and a default must not stop a node from
148- booting VMs .
179+ warning, because a node-wide setting must not stop a node from booting VMs
180+ that never asked for it .
149181
150182The helper returns exactly one descriptor, which is why more than one queue
151183pair in bridge mode is created by ` netd ` instead: it adds a persistent
@@ -224,10 +256,11 @@ the same calculation, against the node configuration and manifest as they stand
224256now, rather than the ones a finished boot ran under.
225257
226258If that account lacks access, QEMU exits at startup and the VM never boots. The
227- VMM does not pre-check this: QEMU need not share the VMM's credentials, so
228- refusing a launch on the VMM's own access would block deployments the host can
229- run. It only warns when the device node is missing outright, which is a fact
230- about the host rather than about either account.
259+ VMM does not refuse a launch over this: QEMU need not share the VMM's
260+ credentials, so a refusal based on the VMM's own access would block deployments
261+ the host can run. It warns instead — when the device node is missing outright,
262+ and when the VMM's own open is denied, since QEMU usually does share its
263+ account.
231264
232265vhost-net works normally in a TDX guest: the virtio rings and buffers live in
233266shared, unencrypted memory precisely so a host-side backend can reach them.
0 commit comments