From fe957f0a6fe7cca46f2b36e8e38daf1c34438a3d Mon Sep 17 00:00:00 2001
From: Michal Privoznik
Date: Tue, 26 Jul 2011 14:42:37 +0200
Subject: [PATCH] bandwidth: Integrate bandwidth into portgroups
Every DomainNetDef has a bandwidth, as does every portgroup.
Whenever a DomainNetDef of type NETWORK is about to be used, a call is
made to networkAllocateActualDevice(). This function chooses the "best"
bandwidth object and places it in the DomainActualNetDef.
From that point on, whenever some code needs to use the bandwidth data
for the interface, it's retrieved with virDomainNetGetActualBandwidth(),
which will always return the "best" info as determined in the
previous step.
---
docs/formatnetwork.html.in | 2 ++
src/conf/domain_conf.c | 22 ++++++++++++++
src/conf/domain_conf.h | 3 ++
src/conf/network_conf.c | 10 +++++++
src/conf/network_conf.h | 1 +
src/libvirt_private.syms | 2 ++
src/network/bridge_driver.c | 19 ++++++++++--
src/qemu/qemu_command.c | 6 ++--
src/util/network.c | 58 +++++++++++++++++++++++++++++++++++++
src/util/network.h | 2 ++
10 files changed, 121 insertions(+), 4 deletions(-)
diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index f0ff703269..ddfa77cb92 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -129,6 +129,8 @@
numbers, The units for average
and peak
attributes
are kilobytes per second, and for the burst
just kilobytes.
The rate is shared equally within domains connected to the network.
+ Moreover, bandwidth
element can be included in
+ portgroup
element.
Since 0.9.4
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 072c970e7d..f99294cc1c 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -753,6 +753,8 @@ virDomainActualNetDefFree(virDomainActualNetDefPtr def)
break;
}
+ virBandwidthDefFree(def->bandwidth);
+
VIR_FREE(def);
}
@@ -2621,6 +2623,7 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
virDomainActualNetDefPtr actual = NULL;
int ret = -1;
xmlNodePtr save_ctxt = ctxt->node;
+ xmlNodePtr bandwidth_node = NULL;
char *type = NULL;
char *mode = NULL;
@@ -2677,6 +2680,11 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
}
}
+ bandwidth_node = virXPathNode("./bandwidth", ctxt);
+ if (bandwidth_node &&
+ !(actual->bandwidth = virBandwidthDefParseNode(bandwidth_node)))
+ goto error;
+
*def = actual;
actual = NULL;
ret = 0;
@@ -8713,6 +8721,10 @@ virDomainActualNetDefFormat(virBufferPtr buf,
default:
break;
}
+
+ if (virBandwidthDefFormat(buf, def->bandwidth, " ") < 0)
+ goto error;
+
virBufferAddLit(buf, " \n");
ret = 0;
@@ -11383,3 +11395,13 @@ virDomainNetGetActualDirectVirtPortProfile(virDomainNetDefPtr iface)
return NULL;
return iface->data.network.actual->data.direct.virtPortProfile;
}
+
+virBandwidthPtr
+virDomainNetGetActualBandwidth(virDomainNetDefPtr iface)
+{
+ if ((iface->type == VIR_DOMAIN_NET_TYPE_NETWORK) &&
+ iface->data.network.actual && iface->data.network.actual->bandwidth) {
+ return iface->data.network.actual->bandwidth;
+ }
+ return iface->bandwidth;
+}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 212f0c5f0f..715d99572e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -362,6 +362,7 @@ struct _virDomainActualNetDef {
virVirtualPortProfileParamsPtr virtPortProfile;
} direct;
} data;
+ virBandwidthPtr bandwidth;
};
/* Stores the virtual network interface configuration */
@@ -1490,6 +1491,8 @@ char *virDomainNetGetActualDirectDev(virDomainNetDefPtr iface);
int virDomainNetGetActualDirectMode(virDomainNetDefPtr iface);
virVirtualPortProfileParamsPtr
virDomainNetGetActualDirectVirtPortProfile(virDomainNetDefPtr iface);
+virBandwidthPtr
+virDomainNetGetActualBandwidth(virDomainNetDefPtr iface);
int virDomainControllerInsert(virDomainDefPtr def,
virDomainControllerDefPtr controller);
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 1ef80dc01d..6714c209a7 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -92,6 +92,8 @@ virPortGroupDefClear(virPortGroupDefPtr def)
{
VIR_FREE(def->name);
VIR_FREE(def->virtPortProfile);
+ virBandwidthDefFree(def->bandwidth);
+ def->bandwidth = NULL;
}
static void
@@ -771,6 +773,7 @@ virNetworkPortGroupParseXML(virPortGroupDefPtr def,
xmlNodePtr save;
xmlNodePtr virtPortNode;
+ xmlNodePtr bandwidth_node;
char *isDefault = NULL;
int result = -1;
@@ -790,6 +793,12 @@ virNetworkPortGroupParseXML(virPortGroupDefPtr def,
goto error;
}
+ bandwidth_node = virXPathNode("./bandwidth", ctxt);
+ if (bandwidth_node &&
+ !(def->bandwidth = virBandwidthDefParseNode(bandwidth_node))) {
+ goto error;
+ }
+
result = 0;
error:
if (result < 0) {
@@ -1257,6 +1266,7 @@ virPortGroupDefFormat(virBufferPtr buf,
}
virBufferAddLit(buf, ">\n");
virVirtualPortProfileFormat(buf, def->virtPortProfile, " ");
+ virBandwidthDefFormat(buf, def->bandwidth, " ");
virBufferAddLit(buf, " \n");
}
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 6d0845e36c..869085e0bd 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -123,6 +123,7 @@ struct _virPortGroupDef {
char *name;
bool isDefault;
virVirtualPortProfileParamsPtr virtPortProfile;
+ virBandwidthPtr bandwidth;
};
typedef struct _virNetworkDef virNetworkDef;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 853ee628f1..a40610093c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -337,6 +337,7 @@ virDomainLoadAllConfigs;
virDomainMemballoonModelTypeFromString;
virDomainMemballoonModelTypeToString;
virDomainNetDefFree;
+virDomainNetGetActualBandwidth;
virDomainNetGetActualBridgeName;
virDomainNetGetActualDirectDev;
virDomainNetGetActualDirectMode;
@@ -710,6 +711,7 @@ nlComm;
# network.h
+virBandwidthCopy;
virBandwidthDefFormat;
virBandwidthDefFree;
virBandwidthDefParseNode;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index b1c6b12bf3..b8c6c97507 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -2811,6 +2811,7 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
(netdef->forwardType == VIR_NETWORK_FORWARD_VEPA) ||
(netdef->forwardType == VIR_NETWORK_FORWARD_PASSTHROUGH)) {
virVirtualPortProfileParamsPtr virtport = NULL;
+ virPortGroupDefPtr portgroup = NULL;
/* are all
* VIR_DOMAIN_NET_TYPE_DIRECT.
@@ -2839,11 +2840,10 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
}
/* Find the most specific virtportprofile and copy it */
+ portgroup = virPortGroupFindByName(netdef, iface->data.network.portgroup);
if (iface->data.network.virtPortProfile) {
virtport = iface->data.network.virtPortProfile;
} else {
- virPortGroupDefPtr portgroup
- = virPortGroupFindByName(netdef, iface->data.network.portgroup);
if (portgroup)
virtport = portgroup->virtPortProfile;
else
@@ -2859,6 +2859,21 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
*/
*iface->data.network.actual->data.direct.virtPortProfile = *virtport;
}
+
+ /* Find the most specific bandwidth config and copy it */
+ if (iface->bandwidth) {
+ if (virBandwidthCopy(&iface->data.network.actual->bandwidth,
+ iface->bandwidth) < 0) {
+ goto cleanup;
+ }
+ } else {
+ if (portgroup &&
+ virBandwidthCopy(&iface->data.network.actual->bandwidth,
+ portgroup->bandwidth) < 0) {
+ goto cleanup;
+ }
+ }
+
/* If there is only a single device, just return it (caller will detect
* any error if exclusive use is required but could not be acquired).
*/
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index f8fd4eee9a..35d6b1e021 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -132,7 +132,8 @@ qemuPhysIfaceConnect(virDomainDefPtr def,
vnet_hdr, def->uuid,
virDomainNetGetActualDirectVirtPortProfile(net),
&res_ifname,
- vmop, driver->stateDir, net->bandwidth);
+ vmop, driver->stateDir,
+ virDomainNetGetActualBandwidth(net));
if (rc >= 0) {
virDomainAuditNetDevice(def, net, res_ifname, true);
VIR_FREE(net->ifname);
@@ -299,7 +300,8 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
}
if (tapfd >= 0 &&
- virBandwidthEnable(net->bandwidth, net->ifname) < 0) {
+ virBandwidthEnable(virDomainNetGetActualBandwidth(net),
+ net->ifname) < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot set bandwidth limits on %s"),
net->ifname);
diff --git a/src/util/network.c b/src/util/network.c
index 5561012ada..6fcdab2bba 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -1263,3 +1263,61 @@ cleanup:
virCommandFree(cmd);
return ret;
}
+
+/*
+ * virBandwidthCopy:
+ * @dest: destination
+ * @src: source
+ *
+ * Returns -1 on OOM error (which gets reported),
+ * 0 otherwise.
+ */
+int
+virBandwidthCopy(virBandwidthPtr *dest,
+ const virBandwidthPtr src)
+{
+ int ret = -1;
+
+ if (!dest) {
+ virSocketError(VIR_ERR_INVALID_ARG, "%s",
+ _("invalid argument supplied"));
+ return -1;
+ }
+
+ *dest = NULL;
+ if (!src) {
+ /* nothing to be copied */
+ return 0;
+ }
+
+ if (VIR_ALLOC(*dest) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (src->in) {
+ if (VIR_ALLOC((*dest)->in) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ memcpy((*dest)->in, src->in, sizeof(*src->in));
+ }
+
+ if (src->out) {
+ if (VIR_ALLOC((*dest)->out) < 0) {
+ virReportOOMError();
+ VIR_FREE((*dest)->in);
+ goto cleanup;
+ }
+ memcpy((*dest)->out, src->out, sizeof(*src->out));
+ }
+
+ ret = 0;
+
+cleanup:
+ if (ret < 0) {
+ virBandwidthDefFree(*dest);
+ *dest = NULL;
+ }
+ return ret;
+}
diff --git a/src/util/network.h b/src/util/network.h
index 139f6ccb8b..6ceaa6d5b9 100644
--- a/src/util/network.h
+++ b/src/util/network.h
@@ -158,4 +158,6 @@ int virBandwidthDefFormat(virBufferPtr buf,
int virBandwidthEnable(virBandwidthPtr bandwidth, const char *iface);
int virBandwidthDisable(const char *iface, bool may_fail);
+int virBandwidthCopy(virBandwidthPtr *dest, const virBandwidthPtr src);
+
#endif /* __VIR_NETWORK_H__ */