This a basic implemantation to support the net_cls feature of
cgroups. It adds the setting of a net_cls.classid value to the
existing cgroups setup in the qemu driver.
The classid is specified in the qemu.conf file.
This enables the use of the tc utility to manage traffic from/to
vitual machines
based on the setting combination of classid and network interface.
Signed-off-by: D.Herrendoerfer <d.herrendoerfer [at] herrendoerfer
[dot] name >
src/libvirt_private.syms | 1 +
src/qemu/qemu.conf | 6 +++++-
src/qemu/qemu_conf.c | 7 ++++++-
src/qemu/qemu_conf.h | 1 +
src/qemu/qemu_driver.c | 12 ++++++++++++
src/util/cgroup.c | 18 +++++++++++++++++-
src/util/cgroup.h | 3 +++
7 files changed, 45 insertions(+), 3 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index f251c94..771911e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -80,6 +80,7 @@ virCgroupSetFreezerState;
virCgroupSetMemory;
virCgroupSetMemoryHardLimit;
virCgroupSetMemorySoftLimit;
+virCgroupSetNetworkClassID;
virCgroupSetSwapHardLimit;
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index f4f965e..591d8dc 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -157,7 +157,7 @@
# can be mounted in different locations. libvirt will detect
# where they are located.
#
-# cgroup_controllers = [ "cpu", "devices", "memory" ]
+# cgroup_controllers = [ "cpu", "devices", "memory",
"net_cls" ]
# This is the basic set of devices allowed / required by
# all virtual machines.
@@ -175,6 +175,10 @@
# "/dev/rtc", "/dev/hpet", "/dev/net/tun",
#]
+# This is the default classid that will be assigned
+# to all virtual machines.
+# cgroup_net_cls_classid = 4096
+
# The default format for Qemu/KVM guest save images is raw; that is,
the
# memory from the domain is dumped out directly to a file. If you
have
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 7cd0603..46ac040 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -326,7 +326,8 @@ int qemudLoadDriverConfig(struct qemud_driver
*driver,
driver->cgroupControllers =
(1 << VIR_CGROUP_CONTROLLER_CPU) |
(1 << VIR_CGROUP_CONTROLLER_DEVICES) |
- (1 << VIR_CGROUP_CONTROLLER_MEMORY);
+ (1 << VIR_CGROUP_CONTROLLER_MEMORY) |
+ (1 << VIR_CGROUP_CONTROLLER_NETWORK);
}
for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
if (driver->cgroupControllers & (1 << i)) {
@@ -364,6 +365,10 @@ int qemudLoadDriverConfig(struct qemud_driver
*driver,
driver->cgroupDeviceACL[i] = NULL;
}
+ p = virConfGetValue (conf, "cgroup_net_cls_classid");
+ CHECK_TYPE ("cgroup_net_cls_classid", VIR_CONF_LONG);
+ if (p) driver->cgroupNetClsClassid = p->l;
+
p = virConfGetValue (conf, "save_image_format");
CHECK_TYPE ("save_image_format", VIR_CONF_STRING);
if (p && p->str) {
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index aba64d6..961c6cd 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -119,6 +119,7 @@ struct qemud_driver {
virCgroupPtr cgroup;
int cgroupControllers;
char **cgroupDeviceACL;
+ int cgroupNetClsClassid;
virDomainObjList domains;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 1a7c1ad..42448b5 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -186,6 +186,8 @@ static int qemudVMFiltersInstantiate(virConnectPtr
conn,
static struct qemud_driver *qemu_driver = NULL;
+#include "interface.h"
+
static void *qemuDomainObjPrivateAlloc(void)
{
@@ -3597,6 +3599,16 @@ static int qemuSetupCgroup(struct qemud_driver
*driver,
vm->def->name);
}
+ if (qemuCgroupControllerActive(driver,
VIR_CGROUP_CONTROLLER_NETWORK)) {
+
+ if (driver->cgroupNetClsClassid != 0) {
+ rc = virCgroupSetNetworkClassID(cgroup, driver-
cgroupNetClsClassid);
+ if (rc != 0) {
+ VIR_WARN("Cannot set net_cls.classid for: %s",
+ vm->def->name);
+ }
+ }
+ }
done:
virCgroupFree(&cgroup);
return 0;
diff --git a/src/util/cgroup.c b/src/util/cgroup.c
index 2758a8f..a2ed0ed 100644
--- a/src/util/cgroup.c
+++ b/src/util/cgroup.c
@@ -37,7 +37,7 @@
VIR_ENUM_IMPL(virCgroupController, VIR_CGROUP_CONTROLLER_LAST,
"cpu", "cpuacct", "cpuset",
"memory", "devices",
- "freezer");
+ "freezer", "net_cls");
struct virCgroupController {
int type;
@@ -851,6 +851,22 @@ int virCgroupForDomain(virCgroupPtr driver
ATTRIBUTE_UNUSED,
#endif
/**
+ * virCgroupSetNetworkClassID:
+ *
+ * @group: The cgroup to change memory for
+ * @classid: The classID number
+ *
+ * Returns: 0 on success
+ */
+int virCgroupSetNetworkClassID(virCgroupPtr group, unsigned long
classid)
+{
+ return virCgroupSetValueU64(group,
+ VIR_CGROUP_CONTROLLER_NETWORK,
+ "net_cls.classid",
+ classid);
+}
+
+/**
* virCgroupSetMemory:
*
* @group: The cgroup to change memory for
diff --git a/src/util/cgroup.h b/src/util/cgroup.h
index 9e1c61f..9626e82 100644
--- a/src/util/cgroup.h
+++ b/src/util/cgroup.h
@@ -22,6 +22,7 @@ enum {
VIR_CGROUP_CONTROLLER_MEMORY,
VIR_CGROUP_CONTROLLER_DEVICES,
VIR_CGROUP_CONTROLLER_FREEZER,
+ VIR_CGROUP_CONTROLLER_NETWORK,
VIR_CGROUP_CONTROLLER_LAST
};
@@ -40,6 +41,8 @@ int virCgroupForDomain(virCgroupPtr driver,
int virCgroupAddTask(virCgroupPtr group, pid_t pid);
+int virCgroupSetNetworkClassID(virCgroupPtr group, unsigned long
classid);
+
int virCgroupSetMemory(virCgroupPtr group, unsigned long kb);
int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb);