4 Commits

3 changed files with 54 additions and 12 deletions

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
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
the host side of the tap; SMB tolerates it, SSH does not. The package installs a udev rule that
turns the offloads off on every libvirt tap as it appears, and `vm-native-setup` says so if it is
missing.
the host side of the tap; SMB tolerates it, SSH does not. This holds for both `igb` and `e1000e`.
The package installs a udev rule that turns the offloads off on every libvirt tap as it appears,
and `vm-native-setup` says so if it is missing.
## 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
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
virtiofs for host files: it is a virtio device the scanner names, and its shared memory backing
blocks transparent hugepages for the whole guest. Share over SMB on the e1000e link instead.
applies. The NIC stays `igb`, so the network survives the driver removal in the next step: Windows
has an in-box driver for the Intel 82576 it emulates. Do not use virtiofs for host files: it is a
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

View File

@@ -8,7 +8,7 @@
# vfio-native-qemu QEMU 11.1.1 with the platform-identity patches, in /opt
pkgname=vfio-native
pkgver=1.1.1
pkgver=1.3.0
pkgrel=1
pkgdesc="Present a libvirt guest as a self-consistent physical machine, and tune it"
arch=('any')
@@ -48,7 +48,7 @@ package() {
# this coexists with whatever hook the host already has.
install -Dm755 scripts/libvirt-hook-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 \
"${pkgdir}/usr/lib/udev/rules.d/99-vfio-native-vnet-offload.rules"
}

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):
return 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='([^']*)'[^/]*/>",
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)
if "<serial>" not in d:
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"<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"<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":
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
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 " sudo install -Dm644 $SELF/scripts/99-vfio-native-vnet-offload.rules /etc/udev/rules.d/ && sudo udevadm control --reload-rules"
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" = performance ] || echo "host governor is '$gov' - run: sudo cpupower frequency-set -g performance"