mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 06:05:27 +00:00
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.
This commit is contained in:
parent
5c77d18b1b
commit
fe957f0a6f
@ -129,6 +129,8 @@
|
||||
numbers, The units for <code>average</code> and <code>peak</code> attributes
|
||||
are kilobytes per second, and for the <code>burst</code> just kilobytes.
|
||||
The rate is shared equally within domains connected to the network.
|
||||
Moreover, <code>bandwidth</code> element can be included in
|
||||
<code>portgroup</code> element.
|
||||
<span class="since">Since 0.9.4</span>
|
||||
</p>
|
||||
|
||||
|
@ -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, " </actual>\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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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, " </portgroup>\n");
|
||||
}
|
||||
|
||||
|
@ -123,6 +123,7 @@ struct _virPortGroupDef {
|
||||
char *name;
|
||||
bool isDefault;
|
||||
virVirtualPortProfileParamsPtr virtPortProfile;
|
||||
virBandwidthPtr bandwidth;
|
||||
};
|
||||
|
||||
typedef struct _virNetworkDef virNetworkDef;
|
||||
|
@ -337,6 +337,7 @@ virDomainLoadAllConfigs;
|
||||
virDomainMemballoonModelTypeFromString;
|
||||
virDomainMemballoonModelTypeToString;
|
||||
virDomainNetDefFree;
|
||||
virDomainNetGetActualBandwidth;
|
||||
virDomainNetGetActualBridgeName;
|
||||
virDomainNetGetActualDirectDev;
|
||||
virDomainNetGetActualDirectMode;
|
||||
@ -710,6 +711,7 @@ nlComm;
|
||||
|
||||
|
||||
# network.h
|
||||
virBandwidthCopy;
|
||||
virBandwidthDefFormat;
|
||||
virBandwidthDefFree;
|
||||
virBandwidthDefParseNode;
|
||||
|
@ -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;
|
||||
|
||||
/* <forward type='bridge|private|vepa|passthrough'> 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).
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user