1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-06 08:58:35 +03:00

bridge_driver: Introduce networkBandwidthChangeAllowed

When a domain vNIC's bandwidth is to be changed (at runtime) it is
possible that guaranteed minimal bandwidth (@floor) will change too.
Well, so far it is, because we still don't have an implementation that
allows setting it dynamically, so it's effectively erased on:

    #virsh domiftune $dom vnet0 --inbound 0

However, that's slightly unfortunate. We do some checks on domain
startup to see if @floor can be guaranteed. We ought do the same if
QoS is changed at runtime.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Michal Privoznik 2015-07-31 17:02:10 +02:00
parent 45090449c4
commit 41a1531de5
2 changed files with 86 additions and 4 deletions

View File

@ -4686,9 +4686,18 @@ networkGetNetworkAddress(const char *netname, char **netaddr)
* networkCheckBandwidth: * networkCheckBandwidth:
* @net: network QoS * @net: network QoS
* @ifaceBand: interface QoS (may be NULL if no QoS) * @ifaceBand: interface QoS (may be NULL if no QoS)
* @oldBandwidth: new interface QoS (may be NULL if no QoS)
* @ifaceMac: interface MAC (used in error messages for identification) * @ifaceMac: interface MAC (used in error messages for identification)
* @new_rate: new rate for non guaranteed class * @new_rate: new rate for non guaranteed class
* *
* Function checks if @ifaceBand can be satisfied on @net. However, sometimes it
* may happen that the interface that @ifaceBand corresponds to is already
* plugged into the @net and the bandwidth is to be updated. In that case we
* need to check if new bandwidth can be satisfied. If that's the case
* @ifaceBand should point to new bandwidth settings and @oldBandwidth to
* current ones. If you want to suppress this functionality just pass
* @oldBandwidth == NULL.
*
* Returns: -1 if plugging would overcommit network QoS * Returns: -1 if plugging would overcommit network QoS
* 0 if plugging is safe (@new_rate updated) * 0 if plugging is safe (@new_rate updated)
* 1 if no QoS is set (@new_rate untouched) * 1 if no QoS is set (@new_rate untouched)
@ -4696,6 +4705,7 @@ networkGetNetworkAddress(const char *netname, char **netaddr)
static int static int
networkCheckBandwidth(virNetworkObjPtr net, networkCheckBandwidth(virNetworkObjPtr net,
virNetDevBandwidthPtr ifaceBand, virNetDevBandwidthPtr ifaceBand,
virNetDevBandwidthPtr oldBandwidth,
virMacAddr ifaceMac, virMacAddr ifaceMac,
unsigned long long *new_rate) unsigned long long *new_rate)
{ {
@ -4716,14 +4726,18 @@ networkCheckBandwidth(virNetworkObjPtr net,
return -1; return -1;
} }
if (!ifaceBand || !ifaceBand->in || !ifaceBand->in->floor || if (((!ifaceBand || !ifaceBand->in || !ifaceBand->in->floor) &&
(!oldBandwidth || !oldBandwidth->in || !oldBandwidth->in->floor)) ||
!netBand || !netBand->in) { !netBand || !netBand->in) {
/* no QoS required, claim success */ /* no QoS required, claim success */
return 1; return 1;
} }
tmp_new_rate = netBand->in->average; tmp_new_rate = netBand->in->average;
tmp_floor_sum += ifaceBand->in->floor; if (oldBandwidth && oldBandwidth->in)
tmp_floor_sum -= oldBandwidth->in->floor;
if (ifaceBand && ifaceBand->in)
tmp_floor_sum += ifaceBand->in->floor;
/* check against peak */ /* check against peak */
if (netBand->in->peak) { if (netBand->in->peak) {
@ -4749,7 +4763,8 @@ networkCheckBandwidth(virNetworkObjPtr net,
goto cleanup; goto cleanup;
} }
*new_rate = tmp_new_rate; if (new_rate)
*new_rate = tmp_new_rate;
ret = 0; ret = 0;
cleanup: cleanup:
@ -4791,7 +4806,7 @@ networkPlugBandwidth(virNetworkObjPtr net,
char ifmac[VIR_MAC_STRING_BUFLEN]; char ifmac[VIR_MAC_STRING_BUFLEN];
virNetDevBandwidthPtr ifaceBand = virDomainNetGetActualBandwidth(iface); virNetDevBandwidthPtr ifaceBand = virDomainNetGetActualBandwidth(iface);
if ((plug_ret = networkCheckBandwidth(net, ifaceBand, if ((plug_ret = networkCheckBandwidth(net, ifaceBand, NULL,
iface->mac, &new_rate)) < 0) { iface->mac, &new_rate)) < 0) {
/* helper reported error */ /* helper reported error */
goto cleanup; goto cleanup;
@ -4917,3 +4932,58 @@ networkNetworkObjTaint(virNetworkObjPtr net,
virNetworkTaintTypeToString(taint)); virNetworkTaintTypeToString(taint));
} }
} }
static bool
networkBandwidthGenericChecks(virDomainNetDefPtr iface,
virNetDevBandwidthPtr newBandwidth)
{
virNetDevBandwidthPtr ifaceBand = virDomainNetGetActualBandwidth(iface);
unsigned long long old_floor, new_floor;
if (virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_NETWORK) {
/* This is not an interface that's plugged into a network.
* We don't care. Thus from our POV bandwidth change is allowed. */
return false;
}
old_floor = new_floor = 0;
if (ifaceBand && ifaceBand->in)
old_floor = ifaceBand->in->floor;
if (newBandwidth && newBandwidth->in)
new_floor = newBandwidth->in->floor;
return new_floor != old_floor;
}
bool
networkBandwidthChangeAllowed(virDomainNetDefPtr iface,
virNetDevBandwidthPtr newBandwidth)
{
virNetworkDriverStatePtr driver = networkGetDriver();
virNetworkObjPtr network = NULL;
virNetDevBandwidthPtr ifaceBand = virDomainNetGetActualBandwidth(iface);
bool ret = false;
if (!networkBandwidthGenericChecks(iface, newBandwidth))
return true;
network = virNetworkObjFindByName(driver->networks, iface->data.network.name);
if (!network) {
virReportError(VIR_ERR_NO_NETWORK,
_("no network with matching name '%s'"),
iface->data.network.name);
return false;
}
if (networkCheckBandwidth(network, newBandwidth, ifaceBand, iface->mac, NULL) < 0)
goto cleanup;
ret = true;
cleanup:
virNetworkObjEndAPI(&network);
return ret;
}

View File

@ -52,6 +52,11 @@ int networkDnsmasqConfContents(virNetworkObjPtr network,
char **configstr, char **configstr,
dnsmasqContext *dctx, dnsmasqContext *dctx,
dnsmasqCapsPtr caps); dnsmasqCapsPtr caps);
bool networkBandwidthChangeAllowed(virDomainNetDefPtr iface,
virNetDevBandwidthPtr newBandwidth)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
# else # else
/* Define no-op replacements that don't drag in any link dependencies. */ /* Define no-op replacements that don't drag in any link dependencies. */
# define networkAllocateActualDevice(dom, iface) 0 # define networkAllocateActualDevice(dom, iface) 0
@ -73,6 +78,13 @@ networkReleaseActualDevice(virDomainDefPtr dom ATTRIBUTE_UNUSED,
return 0; return 0;
} }
static inline bool
networkBandwidthChangeAllowed(virDomainNetDefPtr iface ATTRIBUTE_UNUSED,
virNetDevBandwidthPtr newBandwidth ATTRIBUTE_UNUSED)
{
return true;
}
# endif # endif
typedef char *(*networkDnsmasqLeaseFileNameFunc)(const char *netname); typedef char *(*networkDnsmasqLeaseFileNameFunc)(const char *netname);