KVM, video virtio, Debian 8 guest, host with Intel HD 4000 – install a 4.9 kernel on the guest for optimal 2D graphics performance !

Some time ago I wrote a post about the use of new virtio video driver for a KVM guest with a Debian 8 operative system. See:
KVM, video QXL und video virtio – Video-Auflösung des Gnome-Desktops eines Debian 8-Gastystems einstellen
The KVM host at that time was a PC with a native Nvidia graphics card. In my post I was very positive about the 2D-performance results of the spice/virtio combination for the KVM guest graphics.

Two days ago I had to perform the installation of a Debian 8 KVM guest - this time, however, the host was a laptop with an Optimus system: The internal graphics card of the i7-3632QM CPU was/is an Intel HD Graphics 4000. (The laptop has an additional Nvidia GT645 M, which can be used via Bumblebee.) Under normal conditions the Intel HD graphics (with the i915 kernel module) has sufficient power to support 2D and 3D accelerated GUIs. In my case the laptop ran on Opensuse Leap 42.2, qemu-kvm was of version 2.9, libvirt of version 3.3 (installed from the "virtualization"-repository: http://download.opensuse.org/repositories/Virtualization/openSUSE_Leap_42.2/). But this time I got a bit disappointed.

Disappointing 2D-graphics performance of the Debian8 KVM guest with kernel 3.6, with spice/QXL and spice/virtio

I experienced two problematic points with the Debian 8 guest and its original 3.6 kernel:

  • The performance with the Spice/QXL-graphics of the KVM guest was not at all convincing - especially not with GTK-applications (neither on a KDE or Gnome 3 GUI of the guest) at and above guest graphics resolutions 1400x900. I saw tearing of windows during fast movements across the spice terminal screen. Especially disappointing was the performance of Firefox ESR: Sluggish reactions of all kinds of window contents and slow reactions to scrolling of complicated web site contents - especially of running videos. But the QXL driver at least gave me the choice of many, many guest resolutions up to the maximum resolution of the host.
  • The performance was only slightly better with the new "virtio" driver. But the choice of guest resolutions was very limited with a maximum of 1280x768px.

Update to the latest kernel on the Debian 8 guest

I then read on some Internet websites that the virtio graphics driver on qemu/kvm requires a kernel later than version 4.x on the guest system, too. So why not try? The installation of newer kernels on Debian 8 is possible by adding the "backports" repository to apt's configuration. We have to a add a line

deb http://mirror.one.com/debian/ jessie-backports main contrib non-free

to /etc/apt/sources.list on the Debian system. The we execute

apt-get update

and

apt-get install -t jessie-backports linux-image-amd64

to get the latest kernel installed. In my case this is a SMP kernel of version 4.9.18. Up to now this kernel lead to no conflicts or problems with any of the installed software on the Debian 8 guest.

Results of the updated guest with kernel 4.9

The graphical performance of the Debian guest with spice/virtio combination, however, changed dramatically to the better! Actually, the overall 2D-performance is now really convincing - even on the relatively weak Intel HD 4000. The tear free moving of window frames of all kinds of Qt- or Gtk3-applications across the spice terminal is just one point. The other is that the performance impression of e.g. Firefox ESR on the virtualized guest is almost not distinguishable from Firefox on the host's KDE interface. Below you see 2 FF windows on the Gnome GUI of the Debian 8 KVM guest plus a QGit window. One FF window plays a video.

And in addition I now get all resolutions I could wish for:

I love KVM! Even on laptops!

KVM/qemu, libvirt, virt-manager – persistent names for virtual network interfaces of guest systems

Whilst experimenting with KVM guests and netfilter iptables, I cloned some guest systems. The virtual network interfaces of the different guests (old ones and cloned ones) were created with reference to a "virtual network" - a "host only network" in my case. The corresponding bridge was defined via virt-manager.

I found that one cannot always rely on a persistent "N"-number in the name "vnetN" of the interface devices of my virtual guests throughout cloning, further system changes and a reboot. I am not quite sure whether there is also an impact of systemd/udev - as I installed a new version of systemd during my experiments, too. Whatever exact reason: There are obviously conditions under which the name of a previously defined virtual NIC device of a specific guest may change due to a vnet-renumbering.

In my case one of the guests originally had gotten a virtual NIC (tun device) with a defined MAC and a name of "vnet3". Later on (after cloning and other system changes) the guest's virtual NIC with the same MAC got a device name "vnet6" - although I had not touched its configuration. That the MAC was kept up is not surprising as it resides in the XML-definition file created for the guest when I configured it with the help of virt-manager.

Such a change of the name of an Ethernet interface may of course become a disaster for the application of NETFILTER rules - especially for IPTABLES rules which directly refer to device names via the "--physdev" option. Your precious firewall rules may become worthless after a renaming of your virtual NIC.

I had to search a while to find an information on how to make the names created by libvirt for tun interfaces of KVM/qemu guests persistent. Stupid me! I should have looked into the libvirt Wiki in the first place:
http://libvirt.org/formatdomain.html#elementsNICSVirtual
http://libvirt.org/formatdomain.html#elementsNICSTargetOverride

The trick is to place an additional tag inside the tag for the interface definition in the guest's XML file. And to follow a naming rule ...

In my case I used virsh (virsh edit kali3) to edit the configuration file "kali3.xml" og a guest named "kali3". You find the guest configuration files in the directory "/etc/libvirt/qemu/" of your Linux host. In the editor I navigated to the relevant interface definition - see the last one in the list below - which I changed :

 
    <interface type='bridge'>
      <mac address='52:54:00:22:cf:63'/>
      <source bridge='virbr_vmw'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
    <interface type='network'>
      <mac address='52:54:00:96:db:01'/>
      <source network='kali2'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/>
    </interface>
    <interface type='network'>
      <mac address='52:54:00:b2:7c:1f'/>
      <source network='virbr6'/>
      <target dev='vk61'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x0b' function='0x0'/>
    </interface>

 
You see some interface definitions there. All interface definitions include a MAC definition. The MACs were statistically created and assigned when I added the virtual NICs to the guests' configuration via virt-manager. None of the first definitions contains anything that resembles a device name definition. However, the interesting supplement can be found in the last interface definition:

<target dev='vk61'/>

The "target" tag allows for the definition of a persistent device name (here: vk61). Note that the documentation says that the name chosen must NOT start with "vnet".

To apply the changes save the modified configuration files for your guests and restart the libvirtd service :

systemctl restart libvirtd.service

I hope this helps other people who need persistent names of the device interfaces of their KVM guests!

KVM – Anlegen eines privaten, isolierten Netzwerks mit virt-manager

Im vorhergehenden Artikel dieses Blogs
Opensuse – manuelles Anlegen von Bridge to LAN Devices (br0, br1, …) für KVM Hosts
hatte ich 2 Arten der Anbindung eines KVM-Gastsystems an die physikalische Umwelt des KVM-Hostes diskutiert. Ich hatte angemerkt, dass es unter KVM/libvirt neben einem direkten Bridging zu einer physikalischen Host-NIC natürlich auch die Möglichkeit gibt, KVM-Gäste an ein sog. "Host-Only-Network" [HON] anzubinden. Intern wird dieses Netzwerk durch eine virtuelle Bridge repräsentiert. Soll man aus dem HON heraus mit der physikalischen Umwelt (LAN) kommunizieren, muss man auf dem KVM-Host Routing zwischen einer bereitgestellten virtuellen Host-NIC der Bridge zu einer physikalischen NIC des Hostes ermöglichen. Letztere leitet die Pakete dann ins LAN.

Unterlässt man das Routing (und/oder filtert man Pakete aus dem HON) auf dem Host, so befinden sich Gastsystem und Host in einem isolierten virtuellen Netz, aus dem nach außen ohne weitere Vorkehrungen nicht kommuniziert werden kann. Dem isolierten Netz können natürlich weitere Gäste beitreten.

Wegen der Nachfrage einer Leserin, zeige ich nachfolgend kurz die Anlage eines virtuellen Host-Only-Netzwerks unter KVM mittels "virt-manager". Ich setze voraus, dass der "libvirtd"-Daemon läuft.

Man ruft als root "virt-manager" auf und geht im Übersichtsfenster auf "Edit >> Connection Details" und dort auf den Reiter "Virtual Networks". Dort findet man unter der Übersichtsliste zu bereits vorhandenen Netzwerken, einen Button mit einem "+" Symbol zum Anlegen eines neuen Netzwerks. Ich zeige nachfolgend die Dialogsequenz:

new_network_1

new_network_2

new_network_3

new_network_4

new_network_5

Die Bridge und eine zugehörige Host-NIC tauchen dann auch in der Liste der vorhandenen Netzwerk-Devices auf. Unter Opensuse zeigt das Komamndo "wicked show all" dann etwa ein virbr-Device (virtual bridge - im Beispiel ein "virbr2"):

virbr2          device-unconfigured
      link:     #73, state device-up, mtu 1500
      type:     bridge
      addr:     ipv4 192.168.120.1/24

virbr2-nic      device-unconfigured
      link:     #74, state down, mtu 1500, master virbr2
      type:     tap, hwaddr 52:54:00:c9:bd:24

 
Das neue Netzwerk findet sich dann auch in Form einer XML-Netzwerk-Konfigurations-Datei unter "/etc/libvirt/qemu/networks/host2.xml" wieder:

<!--
WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
OVERWRITTEN AND LOST. Changes to this xml configuration should be made using:
  virsh net-edit host2
or other application using the libvirt API.
-->

<network>
  <name>host2</name>
  <uuid>f47c2d04-b1d6-48bf-a6dc-a643d28b38d3</uuid>
  <bridge name='virbr2' stp='on' delay='0'/>
  <mac address='52:54:00:c9:bd:24'/>
  <domain name='host2'/>
  <ip address='192.168.120.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.120.128' end='192.168.120.254'/>
    </dhcp>
  </ip>
</network>

 
Will man eine solche Host-Only-Bridge von einem KVM-Gast aus nutzen, so muss man für diesen Gast ein entsprechendes "Netzwerk"-Device (NIC) anlegen, das der Bridge zugeordnet wird. "virt-manager" bietet auch hierfür entsprechende grafische Dialoge an. Ich gehe davon aus, dass eine virtuelle Maschine (z.B. namens "kali2") bereits existiert. Man öffnet deren Konfigurations-Oberfläche durch Doppelklick auf den entsprechenden Eintrag in der Liste aller KVM-Instanzen unter "virt-manager". Im sich öffnenden Fenster klickt man weiter auf den Button mit dem "i"-Symbol:

new_network_6

Danach taucht das Device auch in der XML-Konfigurationsdatei für den Gast auf - in meinem Beispiel etwa für einen Kali-Gast mit der Datei "/etc/libvirt/qemu/kali.xml" - ich zeige nur den relevanten Ausschnitt:

    <interface type='network'>
      <mac address='52:54:00:0d:3c:8b'/>
      <source network='host2'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x0d' function='0x0'/>
    </interface>

 
Danach muss man den Gast neu starten und in ihm natürlich das neu aufgetauchte Netzwerk-Interface manuell konfigurieren - falls man nicht auf DHCP setzt und/oder besondere Einstellungen benötigt. Man merke sich hierzu die MAC-Adresse, um bei mehreren NICs nicht den Überblick zu verlieren! Man achte auch auf das Default-Gateway, wenn Routing über den Host gewünscht ist.

Achtung: Das neue virtuelle Netzwerk des Gastes ist mit "ifconfig", "ip" oder "wicked" Kommandos erst als ein "vnetN"-Device sichtbar, wenn der Gast gestartet und aktiv ist. Das "N" steht dabei für eine fortlaufende Nummer, die vom System (libvirt) vergeben wird. Z.B. taucht unter "wicked show all" dann ggf. ein Device "vnet3" auf:

virbr2          device-unconfigured
      link:     #73, state device-up, mtu 1500
      type:     bridge
      addr:     ipv4 192.168.120.1/24

virbr2-nic      device-unconfigured
      link:     #74, state down, mtu 1500, master virbr2
      type:     tap, hwaddr 52:54:00:c9:bd:24
...
...
vnet3           device-unconfigured
      link:     #17, state up, mtu 1500, master virbr2
      type:     tap, hwaddr fe:54:00:0d:3c:8b

 
Man beachte, dass sowohl die Host-Nic, als auch das Device des Gastes "tap"-Devices sind. Allg. Infos zu tap-devices finden sich hier:
https://www.kernel.org/doc/Documentation/networking/tuntap.txt
https://de.wikipedia.org/wiki/TUN/TAP

Hinweise für Leser, die die Konfiguration lieber manuell und über die Kommandozeile durchführen mögen

Wie man eine virtuelle Bridge auf dem KVM-Host mittels des "brctl"-Kommandos einrichtet, benennt und wie man ihr "tap"-Devices zuordnet, habe ich im Prinzip bereits früher am Beispiel einer direkten Bridge zu einem physikalischen Device beschrieben:
Opensuse – manuelles Anlegen von Bridge to LAN Devices (br0, br1, …) für KVM Hosts
Siehe aber auch hier:
http://www.linux-kvm.org/page/Networking#Configuring_Guest_Networking - Abschnitt (Private Network)

"tap"-Devices kann man manuell und temporär über das Kommando "tunctl" auf dem Host erzeugen.
Siehe etwa :
http://unix.stackexchange.com/questions/86720/can-i-create-a-virtual-ethernet-interface-named-eth0
http://serverfault.com/questions/347895/creating-tun-tap-devices-on-linux
http://www.naturalborncoder.com/virtualization/2014/10/17/understanding-tun-tap-interfaces/
http://blog.elastocloud.org/2015/07/qemukvm-bridged-network-with-tap.html

Die Zuordnung von "tap"-Devices zu einer virtuellen Linux-Bridge erfolgt über das "brctl addif"-Kommando. Nun fehlt also nur noch eine Methode, um einmal erzeugte "tap"-Devices in die Konfiguration eines Gastes einzubinden.

Ich kenne einige Leute, die starten ihre virtuellen Maschinen lieber eigenhändig und über Scripts statt über virt-manager. Dann kann die Netzwerk-Konfiguration des Gastsystems in Form passender Optionsparameter des Kommandos "qemu-system-x86_64" (mit weiteren Optionen für KVM-Unterstützung; s.u.) oder des Kommandos "qemu-kvm" zum Starten eines KVM-Gastes geschehen. Eine Übersicht über diese Möglichkeit findet man hier:
http://qemu-buch.de/de/index.php?title=QEMU-KVM-Buch/_Netzwerkoptionen/_Virtuelle_Netzwerke_konfigurieren
In abgekürzter Form auch hier :
https://bbs.archlinux.org/viewtopic.php?pid=1148335#p1148335
https://bbs.archlinux.org/viewtopic.php?pid=1424044#p1424044

Eine weitere Alternative ist hier beschrieben (s. den Abschnitt zu "Private Networking"):
http://www.linux-kvm.org/page/Networking#Configuring_Guest_Networking

Übrigens: "qemu-kvm" ist auf aktuellen Linux-Systemen meist nur ein kleines Shell-Script-Kommando, dass "qemu-system-x86_64" mit KVM-Hardware-Unterstützungsoptionen aufruft! Siehe zum Unterschied zw. "qemu-system-x86_64" und "qemu-kvm" etwa
http://www.linux-kvm.com/content/qemu-kvm-or-qemu-system-x8664%EF%BC%9F).
Die Optionen des "qemu-kvm"-Kommandos sind z.B. hier beschrieben:
https://www.suse.com/documentation/sles11/book_kvm/data/cha_qemu_running_gen_opts.html
Eine Zusammenfassung zu tap-Devices und verschiedenen Bridging-Varianten gibt auch
https://www.suse.com/documentation/sles11/book_kvm/data/cha_qemu_running_networking.html

Will man die Tools von "libvirt/virt-manager" zum Starten der virtuellen Maschine benutzen, dann kann die "manuelle" Definition von virtuellen NICs für einen KVM-Gastes aber auch mittels des "virsh edit"-Kommandos zur Manipulation des XML-Files für die Gastkonfiguration durchgeführt werden.
Siehe:
http://serverfault.com/questions/665440/set-up-network-interfaces-in-ubuntu-for-kvm-virtual-machine

In einigen Situationen kann es auch erforderlich sein, den Gast im laufenden Betrieb um ein Netzwerkinterface zu einem neu definierten virtuellen Netz zu erweitern. Informationen hierzu findet man hier:
http://www.linuxwave.info/2014/12/hot-attach-and-hot-detach-network.html
https://kashyapc.fedorapeople.org/virt/add-network-card-in-guest.txt