4 Commits
3 changed files with 54 additions and 12 deletions
+33 -7
View File
@@ -75,11 +75,11 @@ Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
Put your public key in `C:\ProgramData\ssh\administrators_authorized_keys` for an Administrator Put your public key in `C:\ProgramData\ssh\administrators_authorized_keys` for an Administrator
account. `vm-native-verify` uses that key. account. `vm-native-verify` uses that key.
SSH into the guest fails with `Corrupted MAC on input` until the host has the e1000e offload rule SSH into the guest fails with `Corrupted MAC on input` until the host has the NIC offload rule
from the `vfio-native` package. The emulated NIC's TX offloads corrupt integrity-checked traffic on from the `vfio-native` package. The emulated NIC's TX offloads corrupt integrity-checked traffic on
the host side of the tap; SMB tolerates it, SSH does not. The package installs a udev rule that the host side of the tap; SMB tolerates it, SSH does not. This holds for both `igb` and `e1000e`.
turns the offloads off on every libvirt tap as it appears, and `vm-native-setup` says so if it is The package installs a udev rule that turns the offloads off on every libvirt tap as it appears,
missing. and `vm-native-setup` says so if it is missing.
## 3. Make the NVMe driver boot-critical ## 3. Make the NVMe driver boot-critical
@@ -127,9 +127,35 @@ Two things it asks or warns about:
Before the first boot, if the host has less free memory than the guest's RAM, free and compact Before the first boot, if the host has less free memory than the guest's RAM, free and compact
it so the guest lands on transparent hugepages; `vm-native-setup` prints the two commands when it it so the guest lands on transparent hugepages; `vm-native-setup` prints the two commands when it
applies. The NIC stays `e1000e`, so the network survives the driver removal in the next step. Do not use applies. The NIC stays `igb`, so the network survives the driver removal in the next step: Windows
virtiofs for host files: it is a virtio device the scanner names, and its shared memory backing has an in-box driver for the Intel 82576 it emulates. Do not use virtiofs for host files: it is a
blocks transparent hugepages for the whole guest. Share over SMB on the e1000e link instead. virtio device the scanner names, and its shared memory backing blocks transparent hugepages for the
whole guest. Share over SMB on the `igb` link instead.
### Jumbo frames
`vm-native-setup` puts `<mtu size='9000'/>` on the guest interface. The emulated NIC is packet-rate
bound rather than bandwidth bound, so larger frames cut the per-packet cost the guest pays on
receive - the direction that matters when you read files off an SMB share. Measured on igb, host to
guest: 2922 Mbit/s at 1500, 14232 Mbit/s at 9000, byte-for-byte identical either way.
Both ends have to agree or the frames are simply dropped. The libvirt network needs it too:
```
virsh net-edit default # add <mtu size='9000'/>
virsh net-destroy default && virsh net-start default
```
and in the guest, set the adapter's *Jumbo Packet* to 9014 and the interface MTU to 9000:
```powershell
$n = (Get-NetAdapter -Physical | Where-Object Status -eq 'Up').Name
Set-NetAdapterAdvancedProperty -Name $n -RegistryKeyword "*JumboPacket" -RegistryValue 9014
Set-NetIPInterface -InterfaceAlias $n -NlMtu 9000
```
Check `Get-NetIPInterface` afterwards: setting *Jumbo Packet* alone leaves the IP MTU at 1500 and
you get none of the benefit.
## 5. Remove the virtio drivers and the agents ## 5. Remove the virtio drivers and the agents
+2 -2
View File
@@ -8,7 +8,7 @@
# vfio-native-qemu QEMU 11.1.1 with the platform-identity patches, in /opt # vfio-native-qemu QEMU 11.1.1 with the platform-identity patches, in /opt
pkgname=vfio-native pkgname=vfio-native
pkgver=1.1.1 pkgver=1.3.0
pkgrel=1 pkgrel=1
pkgdesc="Present a libvirt guest as a self-consistent physical machine, and tune it" pkgdesc="Present a libvirt guest as a self-consistent physical machine, and tune it"
arch=('any') arch=('any')
@@ -48,7 +48,7 @@ package() {
# this coexists with whatever hook the host already has. # this coexists with whatever hook the host already has.
install -Dm755 scripts/libvirt-hook-cpu-isolation.sh \ install -Dm755 scripts/libvirt-hook-cpu-isolation.sh \
"${pkgdir}/etc/libvirt/hooks/qemu.d/10-cpu-isolation.sh" "${pkgdir}/etc/libvirt/hooks/qemu.d/10-cpu-isolation.sh"
# e1000e offloads corrupt integrity-checked traffic on libvirt taps; host-wide by nature # emulated NIC offloads corrupt integrity-checked traffic on libvirt taps; host-wide by nature
install -Dm644 scripts/99-vfio-native-vnet-offload.rules \ install -Dm644 scripts/99-vfio-native-vnet-offload.rules \
"${pkgdir}/usr/lib/udev/rules.d/99-vfio-native-vnet-offload.rules" "${pkgdir}/usr/lib/udev/rules.d/99-vfio-native-vnet-offload.rules"
} }
+19 -3
View File
@@ -637,8 +637,11 @@ if conformant and E["CONVERT"] == "1":
if "device='disk'" not in d or ("bus='nvme'" in d and "<serial>" in d): if "device='disk'" not in d or ("bus='nvme'" in d and "<serial>" in d):
return d return d
d = re.sub(r"<target dev='([^']*)' bus='(virtio|sata|scsi)'/>", r"<target dev='\1' bus='nvme'/>", d) d = re.sub(r"<target dev='([^']*)' bus='(virtio|sata|scsi)'/>", r"<target dev='\1' bus='nvme'/>", d)
# cache='none' is O_DIRECT: on btrfs the guest can change a page while the
# write is in flight, so the stored checksum never matches and later reads
# fail with EIO. Buffered writes hand the filesystem a stable page.
d = re.sub(r"<driver name='qemu' type='([^']*)'[^/]*/>", d = re.sub(r"<driver name='qemu' type='([^']*)'[^/]*/>",
r"<driver name='qemu' type='\1' cache='none' io='native' discard='unmap'/>", d) r"<driver name='qemu' type='\1' cache='writeback' io='threads' discard='unmap'/>", d)
d = re.sub(r"\s*<address type='(pci|drive)'[^/]*/>", "", d) d = re.sub(r"\s*<address type='(pci|drive)'[^/]*/>", "", d)
if "<serial>" not in d: if "<serial>" not in d:
serial = E["NVME_SERIAL"] if n[0] == 0 else E["NVME_SERIAL"][:-1] + "0123456789ABCDEF"[n[0] % 16] serial = E["NVME_SERIAL"] if n[0] == 0 else E["NVME_SERIAL"][:-1] + "0123456789ABCDEF"[n[0] % 16]
@@ -658,7 +661,11 @@ if conformant and E["CONVERT"] == "1":
s = re.sub(r"\s*<input type='[^']*' bus='virtio'/>", "", s) s = re.sub(r"\s*<input type='[^']*' bus='virtio'/>", "", s)
s = re.sub(r"<memballoon model='virtio'>.*?</memballoon>", "<memballoon model='none'/>", s, flags=re.S) s = re.sub(r"<memballoon model='virtio'>.*?</memballoon>", "<memballoon model='none'/>", s, flags=re.S)
s = re.sub(r"<memballoon model='virtio'/>", "<memballoon model='none'/>", s) s = re.sub(r"<memballoon model='virtio'/>", "<memballoon model='none'/>", s)
s = re.sub(r"<model type='virtio'/>(\s*<driver [^/]*/>)?", "<model type='e1000e'/>", s) # jumbo frames are the single biggest win on the host<->guest link: the emulated
# NIC is packet-rate bound, so 9000-byte frames cut the per-packet cost the guest
# pays on receive. Measured 2922 -> 14232 Mbit/s inbound on igb, byte-exact clean.
s = re.sub(r"<model type='virtio'/>(\s*<driver [^/]*/>)?",
"<model type='igb'/>\n <mtu size='9000'/>", s)
if prof == "full": if prof == "full":
s = re.sub(r"<video>.*?</video>", "<video>\n <model type='none'/>\n </video>", s, flags=re.S) s = re.sub(r"<video>.*?</video>", "<video>\n <model type='none'/>\n </video>", s, flags=re.S)
@@ -824,10 +831,19 @@ if [ "$PROFILE" = full ]; then
fi fi
if [ ! -e /usr/lib/udev/rules.d/99-vfio-native-vnet-offload.rules ] && [ ! -e /etc/udev/rules.d/99-vfio-native-vnet-offload.rules ]; then if [ ! -e /usr/lib/udev/rules.d/99-vfio-native-vnet-offload.rules ] && [ ! -e /etc/udev/rules.d/99-vfio-native-vnet-offload.rules ]; then
echo "NOTE: the e1000e offload udev rule is not installed. SSH into the guest will fail with" echo "NOTE: the NIC offload udev rule is not installed. SSH into the guest will fail with"
echo " 'Corrupted MAC on input' until it is:" echo " 'Corrupted MAC on input' until it is:"
echo " sudo install -Dm644 $SELF/scripts/99-vfio-native-vnet-offload.rules /etc/udev/rules.d/ && sudo udevadm control --reload-rules" echo " sudo install -Dm644 $SELF/scripts/99-vfio-native-vnet-offload.rules /etc/udev/rules.d/ && sudo udevadm control --reload-rules"
fi fi
NET=$("${C[@]}" dumpxml "$DOM" 2>/dev/null | sed -n "s/.*<source network='\([^']*\)'.*/\1/p" | head -1)
NETMTU=$([ -n "$NET" ] && "${C[@]}" net-dumpxml --inactive "$NET" 2>/dev/null | sed -n "s/.*<mtu size='\([0-9]*\)'.*/\1/p")
if [ -n "$NET" ] && [ "${NETMTU:-1500}" -lt 9000 ]; then
echo "NOTE: the guest interface asks for MTU 9000 but libvirt network '$NET' is at ${NETMTU:-1500}."
echo " Jumbo needs both ends; inbound throughput is ~5x with it. Add <mtu size='9000'/> to"
echo " the network and restart it: virsh net-edit $NET && virsh net-destroy $NET && virsh net-start $NET"
echo " Then in the guest: set the NIC's Jumbo Packet to 9014 and the interface MTU to 9000."
fi
gov=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null || echo unknown) gov=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null || echo unknown)
[ "$gov" = performance ] || echo "host governor is '$gov' - run: sudo cpupower frequency-set -g performance" [ "$gov" = performance ] || echo "host governor is '$gov' - run: sudo cpupower frequency-set -g performance"