Limiting VM network speed

From ISPWiki
Jump to: navigation, search
Hierarchy: VMmanager KVM -> VIRTUAL MACHINES

Using limits in VMmanager

For limiting data transfer speed for virtual machines, Vmmanager uses libvirt.

You can set or change a limit while creating/editing the virtual machine in the "Load limit" section



VMmanager add the following records into the virtual machine's XML

<domain type='kvm'>
   <interface type='network'>
       <inbound average='12000'/>   Incomming traffic in KiB\s
       <outbound average='12000'/>  Outgoing traffic in KiB\s

You can set the limit with the command

virsh edit <vps name>

After you modified the XML, restart the VPS to apply the changes

virsh destroy <vps name> && virsh start <vps name>

Note that once the virtual machine is modified again in VMmanager, the panel will change the XML into its own and your settings will be lost.


libvirt uses the packet tc from iproute2 for traffic shaping

Components of Linux Traffic Control

Queues (qdisc). The qdisc is the major building block on which all of Linux traffic control is built, and is also called a queuing discipline. A queue that may have child elements is given the primary number called "handle" and uses an additional number for enumeration of classes, for example: "10:"

Classes (class). Classes are very flexible and can always contain either multiple children classes or a single child qdisc ('classid'). The identifier is not related to the parent classes, but to the parent queue.

Filter (filter). The simplest role of the filter is to classify packets. Filters can be attached either to qdiscs or to classes, however the enqueued packet always enters the root qdisc first and then the packet may be directed to any subclasses, where the packet may undergo further classification. Filters have the identifier consisting of three parts required for search in filters hierarchy.

All the limits are set on the virtual machine's interface. Let's take vnet3 as an example

Limiting incoming traffic

Following are the commands that libvirt uses for limiting incoming traffic.


root@vm:~# tc qdisc add dev vnet3 root handle 1: htb default 1

The HTB queue is the most intuitive replacement of CBQ queue in Linux. Both CBQ and HTB help to control outgoing bandwidth. They enable to divide the physical bandwidth into several. In both cases you can specify how to distribute bandwidth and define from which bandwidth the packet will be sent to a physical device. Unlike CBQ, HTB distribute traffic based on the Token Bucket Filter, which does not depend on characteristics of the network interface and bandwidth.

default 1 - means that filtered packets will be included into class 1:1


root@vm:~# tc class add dev vnet3 parent 1: classid 1:1 htb rate 96000Kbit

class 1:1 - sets limit to 96000Kbit\s


root@vm:~# tc filter add dev vnet3 parent 1: handle 1 protocol ip fw flowid 1:1

libvirt set limit for traffic marked as 1 to be redirected to class 1:1. You can set mark 1 in iptables like that:

iptables -A PREROUTING -t mangle -i vnet3 -j MARK --set-mark 1

In that case the mark is not required because the whole traffic is redirected to class 1:1

Limiting outgoing traffic

Following are the commands that libvirt uses for limiting outgoing traffic.


root@vm:~# tc qdisc add dev vnet3 ingress

ingress - is a classless queue, that uses only a filter


root@vm:~# tc filter add dev vnet3 parent ffff: protocol ip u32 match ip src police rate 12mbps burst 12m mtu 64kb drop flowid :1

Old versions of libvirt contained the error. Mtu equaled burst leading to packets lose, and actual data transfer speed differed from the specified value.