KVM guest virtual network configuration using Open vSwitch

Open vSwitch (OVS) is a production-quality, multilayer-virtual switch. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (for example, NetFlow, sFlow, IPFIX, RSPAN, CLI, LACP, and 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V. See the full feature list on the Open vSwitch website.1

To use Open vSwitch, the service must be enabled and started using the following commands:

[root@kvmhost ~]# systemctl enable openvswitch.service 
[root@kvmhost ~]# systemctl start openvswitch.service

Enablement and starting need only be done once and will persist across KVM host restarts.

To create an Open vSwitch bridge use:

[root@kvmhost ~]# ovs-vsctl add-br <bridge-name>

In typical configurations, the bridge is directly attached to a dedicated network interface in the KVM host. When this is done, the bridge and the attached KVM guests are restricted to using only that host interface.

If multiple KVM host interfaces are available, it may be more desirable to allow the KVM guest/software bridge to be able to direct network traffic to any network interface in the KVM host. In this case the software bridge is not attached or bound to any specific host interface. Instead, it is more desirable to let the TCP/IP stack in the KVM host handle the routing of outbound traffic to the appropriate interface based on the destination IP or subnet. This method of network traffic steering is referred to here as IP routing.

To enable IP routing to direct inbound traffic correctly to the bridge, two more items must be configured.

First, the KVM host must be configured to allow inbound network traffic to be forwarded to the bridge. Ensure the following system setting is enabled:

[root@kvmhost ~]# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1; 

If a value of 0 is returned, IP forward is disabled. Use the following command to manually enable it:

[root@kvmhost ~]# sysctl -w net.ipv4.ip_forward
net.ipv4.ip_forward = 1;

This enables IP forwarding until the system is rebooted. To make this setting persist, it needs to be added to the /etc/sysctl.conf file. Add or change the net.ipv4.ip_forward line in your /etc/sysctl.conf file to net.ipv4.ip_forward=1.

The second configuration change needed for the bridge to receive inbound traffic is to assign an IP address. IP routing relies on the content of the kernel's IP routing table to determine to which interface network traffic should be directed. An IP address and subnet entry is required to add the necessary rule(s) to the kernel's IP routing table to enable the KVM host to determine the network interface to which to deliver the inbound packet.

A software bridge can assume different roles. At a minimum a bridge controls traffic flow between devices that are attached to the bridge. However, a bridge can also behave as a standard network interface. To behave as a network interface the bridge must be configured with an IP address and subnet. With its IP address and subnet assigned, the bridge interface is added to the kernel's IP routing table and then can be the source or destination for IP routing. For the desired behavior, our bridge was configured as a network interface.

To assign the appropriate IP addresses and subnet, the following command was used:

[root@kvmhost ~]# ifconfig <bridge-name> <ip-address> netmask <net-mask> txqueuelen <value>

This command was added to the /etc/rc.d/rc.local file as a quick way to persistently configure the bridge at each reboot. An alternative approach would require creating an ifcfg-<bridge-name> script in /etc/sysconfig/network-scripts.

To configure a KVM guest interface to use an Open vSwitch bridge, the XML stanza to define the KVM guest's interface in the guest's libvirt XML configuration file should include the following:

<interface type="bridge">
  <mac address=”11:22:33:44:55:66”>
  <source bridge="bridge-name"/>
  <virtualport type='openvswitch'/>
  <model type="virtio"/>
  <driver name="vhost"/> 
</interface>

Replace the values for mac address and source bridge to match your configuration.

For the KVM guest interface to connect to a bridge, use <interface type="bridge"> and specify the name of the bridge using <source bridge="bridge-name">.

For better performance throughput and latency, it is recommended that KVM guests use the newer vhost-net driver, rather than the older paravirtualizated virtio-net driver, by specifying the keyword <driver name="vhost"/> in the guest's libvirt configuration file. Vhost-net uses an in-kernel guest networking performance enhancement that moves network packets between the guest and the host system using the Linux® kernel rather than QEMU. This avoids context switches from the kernel to user space to improve overall performance.

When using an Open vSwitch bridge, it is required to not only specify the bridge by name (<source bridge="bridge-name">) but to also specify <virtualport type="openvswitch".

The MAC address field is optional; if it is omitted, the libvirt daemon will generate a unique address.

After the changes have been saved in the KVM guest's libvirt xml configuration file, the libvirt daemon needs to be informed, using the following commands:

[root@kvmhost ~]# virsh undefine <kvm-guest-name> 
[root@kvmhost ~]# virsh define <kvm-guest-libvirt-xml-file>

And lastly, remember to restart the KVM guest for the changes to take effect.