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__ */