Since 0.9.4 release libvirt supports setting some QoS attributes on virtual
bridges and/or virtual interfaces. Average and peak rate, namely. It lacks
minimal guaranteed bandwidth aka 'floor' attribute, though. This patch set
tries to fill that hole. However, there are some things you want to know before
diving into individual patches:
1) Hierarchical shaping
The whole magic hidden in here: Classes [1] can have multiple children and form
a tree. A class can borrow unused bandwidth from other sibling classes up
to its 'ceil'. This is done in kernel, though. Classes does not share any info
among interfaces. Therefore we need to group traffic from domain interfaces
so it goes over one point (a bridge). It is now obvious why this functionality
is limited to VIR_DOMAIN_NET_TYPE_NETWORK only as the other bridged network
type (VIR_DOMAIN_NET_TYPE_BRIDGE:) is meant to be not managed or touched
by libvirt at all.
This patches build that tree of classes. On network startup, a root class
with one child class are created. This child is supposed to be catchment for
all interfaces which will ever be plugged and don't have any 'floor'.
Once we have network prepared, an interface may be plugged in. That means
on a domain startup, as we create virtual devices for a domain and plug
them into a bridge, we can create separate class for created interface
(if it is needed = has 'floor' set). Class are distinguished by u_int16
identifier which:
- needs to be unique among one bridge, obviously
- we want to keep, and pass on interface unplugging
2) Network status file
Because of the class ID I am mentioning above, I found myself in need of
saving next free class ID among with network, so it survives daemon reboots.
That's what 5th patch does actually.
On interface plug event an unique class ID is taken and on successful
QoS set it is stored into an interface. Having said that, domain status
XML was extended to keep pair <interface alias; class id>
3) Tying interface traffic with class
is done via filter [2]. Filters direct packets into a classes during which
packet undergoes examination. Such filter is caller classifier. For example,
filter classify packets based on their marks, src/dest ip address, port, etc.
And here comes another magic trick. But not so nice as the first one.
Libvirt does not know anything about guest (interface) ip address(es).
The only thing that libvirt knows for sure is MAC address. But for some reason,
filters refuse to use ebtables marks even if iptables marks works well.
Filters, however does not support classifying by MAC address. Well, not directly.
u32 filter can match any part of a packet at any offset. Offset 0 is
start of IP header. And offsets can be negative :)
1:
http://tldp.org/HOWTO/Traffic-Control-HOWTO/components.html#c-class
2:
http://tldp.org/HOWTO/Traffic-Control-HOWTO/components.html#c-filter
Michal Privoznik (6):
bandwidth: add new 'floor' attribute
bandwidth: Create hierarchical shaping classes
bandwidth: Create (un)plug functions
bandwidth: Create network (un)plug functions
network: Create status files
domain: Keep assigned class_id in domstatus XML
daemon/libvirtd.c | 3 +
docs/formatdomain.html.in | 21 +++-
docs/schemas/networkcommon.rng | 5 +
po/POTFILES.in | 1 +
src/conf/domain_conf.c | 10 +-
src/conf/domain_conf.h | 1 +
src/conf/netdev_bandwidth_conf.c | 81 +++++++++++---
src/conf/netdev_bandwidth_conf.h | 3 +-
src/conf/network_conf.c | 220 ++++++++++++++++++++++++++++++++------
src/conf/network_conf.h | 9 ++
src/libvirt_network.syms | 2 +
src/libvirt_private.syms | 2 +
src/lxc/lxc_driver.c | 3 +-
src/network/bridge_driver.c | 109 +++++++++++++++++--
src/network/bridge_driver.h | 7 ++
src/qemu/qemu_command.c | 20 +++-
src/qemu/qemu_domain.c | 66 +++++++++++-
src/qemu/qemu_process.c | 12 ++
src/util/virnetdevbandwidth.c | 205 ++++++++++++++++++++++++++++++++++--
src/util/virnetdevbandwidth.h | 19 +++-
src/util/virnetdevmacvlan.c | 2 +-
21 files changed, 710 insertions(+), 91 deletions(-)
--
1.7.3.4