|
|
7a3408 |
From 3e1dd6eacd48107e7646c8346bca73e280692542 Mon Sep 17 00:00:00 2001
|
|
|
7a3408 |
Message-Id: <3e1dd6eacd48107e7646c8346bca73e280692542@dist-git>
|
|
|
7a3408 |
From: Michal Privoznik <mprivozn@redhat.com>
|
|
|
7a3408 |
Date: Fri, 14 Aug 2015 16:06:31 +0200
|
|
|
7a3408 |
Subject: [PATCH] bridge_driver: Introduce networkBandwidthChangeAllowed
|
|
|
7a3408 |
|
|
|
7a3408 |
https://bugzilla.redhat.com/show_bug.cgi?id=1252473
|
|
|
7a3408 |
|
|
|
7a3408 |
When a domain vNIC's bandwidth is to be changed (at runtime) it is
|
|
|
7a3408 |
possible that guaranteed minimal bandwidth (@floor) will change too.
|
|
|
7a3408 |
Well, so far it is, because we still don't have an implementation that
|
|
|
7a3408 |
allows setting it dynamically, so it's effectively erased on:
|
|
|
7a3408 |
|
|
|
7a3408 |
#virsh domiftune $dom vnet0 --inbound 0
|
|
|
7a3408 |
|
|
|
7a3408 |
However, that's slightly unfortunate. We do some checks on domain
|
|
|
7a3408 |
startup to see if @floor can be guaranteed. We ought do the same if
|
|
|
7a3408 |
QoS is changed at runtime.
|
|
|
7a3408 |
|
|
|
7a3408 |
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
7a3408 |
(cherry picked from commit 41a1531de54476310572f694c0b9cb9c63d4191d)
|
|
|
7a3408 |
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
7a3408 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
7a3408 |
---
|
|
|
7a3408 |
src/network/bridge_driver.c | 78 ++++++++++++++++++++++++++++++++++++++++++---
|
|
|
7a3408 |
src/network/bridge_driver.h | 12 +++++++
|
|
|
7a3408 |
2 files changed, 86 insertions(+), 4 deletions(-)
|
|
|
7a3408 |
|
|
|
7a3408 |
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
|
|
|
7a3408 |
index 17fc430..04602ed 100644
|
|
|
7a3408 |
--- a/src/network/bridge_driver.c
|
|
|
7a3408 |
+++ b/src/network/bridge_driver.c
|
|
|
7a3408 |
@@ -4686,9 +4686,18 @@ networkGetNetworkAddress(const char *netname, char **netaddr)
|
|
|
7a3408 |
* networkCheckBandwidth:
|
|
|
7a3408 |
* @net: network QoS
|
|
|
7a3408 |
* @ifaceBand: interface QoS (may be NULL if no QoS)
|
|
|
7a3408 |
+ * @oldBandwidth: new interface QoS (may be NULL if no QoS)
|
|
|
7a3408 |
* @ifaceMac: interface MAC (used in error messages for identification)
|
|
|
7a3408 |
* @new_rate: new rate for non guaranteed class
|
|
|
7a3408 |
*
|
|
|
7a3408 |
+ * Function checks if @ifaceBand can be satisfied on @net. However, sometimes it
|
|
|
7a3408 |
+ * may happen that the interface that @ifaceBand corresponds to is already
|
|
|
7a3408 |
+ * plugged into the @net and the bandwidth is to be updated. In that case we
|
|
|
7a3408 |
+ * need to check if new bandwidth can be satisfied. If that's the case
|
|
|
7a3408 |
+ * @ifaceBand should point to new bandwidth settings and @oldBandwidth to
|
|
|
7a3408 |
+ * current ones. If you want to suppress this functionality just pass
|
|
|
7a3408 |
+ * @oldBandwidth == NULL.
|
|
|
7a3408 |
+ *
|
|
|
7a3408 |
* Returns: -1 if plugging would overcommit network QoS
|
|
|
7a3408 |
* 0 if plugging is safe (@new_rate updated)
|
|
|
7a3408 |
* 1 if no QoS is set (@new_rate untouched)
|
|
|
7a3408 |
@@ -4696,6 +4705,7 @@ networkGetNetworkAddress(const char *netname, char **netaddr)
|
|
|
7a3408 |
static int
|
|
|
7a3408 |
networkCheckBandwidth(virNetworkObjPtr net,
|
|
|
7a3408 |
virNetDevBandwidthPtr ifaceBand,
|
|
|
7a3408 |
+ virNetDevBandwidthPtr oldBandwidth,
|
|
|
7a3408 |
virMacAddr ifaceMac,
|
|
|
7a3408 |
unsigned long long *new_rate)
|
|
|
7a3408 |
{
|
|
|
7a3408 |
@@ -4716,14 +4726,18 @@ networkCheckBandwidth(virNetworkObjPtr net,
|
|
|
7a3408 |
return -1;
|
|
|
7a3408 |
}
|
|
|
7a3408 |
|
|
|
7a3408 |
- if (!ifaceBand || !ifaceBand->in || !ifaceBand->in->floor ||
|
|
|
7a3408 |
+ if (((!ifaceBand || !ifaceBand->in || !ifaceBand->in->floor) &&
|
|
|
7a3408 |
+ (!oldBandwidth || !oldBandwidth->in || !oldBandwidth->in->floor)) ||
|
|
|
7a3408 |
!netBand || !netBand->in) {
|
|
|
7a3408 |
/* no QoS required, claim success */
|
|
|
7a3408 |
return 1;
|
|
|
7a3408 |
}
|
|
|
7a3408 |
|
|
|
7a3408 |
tmp_new_rate = netBand->in->average;
|
|
|
7a3408 |
- tmp_floor_sum += ifaceBand->in->floor;
|
|
|
7a3408 |
+ if (oldBandwidth && oldBandwidth->in)
|
|
|
7a3408 |
+ tmp_floor_sum -= oldBandwidth->in->floor;
|
|
|
7a3408 |
+ if (ifaceBand && ifaceBand->in)
|
|
|
7a3408 |
+ tmp_floor_sum += ifaceBand->in->floor;
|
|
|
7a3408 |
|
|
|
7a3408 |
/* check against peak */
|
|
|
7a3408 |
if (netBand->in->peak) {
|
|
|
7a3408 |
@@ -4749,7 +4763,8 @@ networkCheckBandwidth(virNetworkObjPtr net,
|
|
|
7a3408 |
goto cleanup;
|
|
|
7a3408 |
}
|
|
|
7a3408 |
|
|
|
7a3408 |
- *new_rate = tmp_new_rate;
|
|
|
7a3408 |
+ if (new_rate)
|
|
|
7a3408 |
+ *new_rate = tmp_new_rate;
|
|
|
7a3408 |
ret = 0;
|
|
|
7a3408 |
|
|
|
7a3408 |
cleanup:
|
|
|
7a3408 |
@@ -4791,7 +4806,7 @@ networkPlugBandwidth(virNetworkObjPtr net,
|
|
|
7a3408 |
char ifmac[VIR_MAC_STRING_BUFLEN];
|
|
|
7a3408 |
virNetDevBandwidthPtr ifaceBand = virDomainNetGetActualBandwidth(iface);
|
|
|
7a3408 |
|
|
|
7a3408 |
- if ((plug_ret = networkCheckBandwidth(net, ifaceBand,
|
|
|
7a3408 |
+ if ((plug_ret = networkCheckBandwidth(net, ifaceBand, NULL,
|
|
|
7a3408 |
iface->mac, &new_rate)) < 0) {
|
|
|
7a3408 |
/* helper reported error */
|
|
|
7a3408 |
goto cleanup;
|
|
|
7a3408 |
@@ -4917,3 +4932,58 @@ networkNetworkObjTaint(virNetworkObjPtr net,
|
|
|
7a3408 |
virNetworkTaintTypeToString(taint));
|
|
|
7a3408 |
}
|
|
|
7a3408 |
}
|
|
|
7a3408 |
+
|
|
|
7a3408 |
+
|
|
|
7a3408 |
+static bool
|
|
|
7a3408 |
+networkBandwidthGenericChecks(virDomainNetDefPtr iface,
|
|
|
7a3408 |
+ virNetDevBandwidthPtr newBandwidth)
|
|
|
7a3408 |
+{
|
|
|
7a3408 |
+ virNetDevBandwidthPtr ifaceBand = virDomainNetGetActualBandwidth(iface);
|
|
|
7a3408 |
+ unsigned long long old_floor, new_floor;
|
|
|
7a3408 |
+
|
|
|
7a3408 |
+ if (virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_NETWORK) {
|
|
|
7a3408 |
+ /* This is not an interface that's plugged into a network.
|
|
|
7a3408 |
+ * We don't care. Thus from our POV bandwidth change is allowed. */
|
|
|
7a3408 |
+ return false;
|
|
|
7a3408 |
+ }
|
|
|
7a3408 |
+
|
|
|
7a3408 |
+ old_floor = new_floor = 0;
|
|
|
7a3408 |
+
|
|
|
7a3408 |
+ if (ifaceBand && ifaceBand->in)
|
|
|
7a3408 |
+ old_floor = ifaceBand->in->floor;
|
|
|
7a3408 |
+ if (newBandwidth && newBandwidth->in)
|
|
|
7a3408 |
+ new_floor = newBandwidth->in->floor;
|
|
|
7a3408 |
+
|
|
|
7a3408 |
+ return new_floor != old_floor;
|
|
|
7a3408 |
+}
|
|
|
7a3408 |
+
|
|
|
7a3408 |
+
|
|
|
7a3408 |
+bool
|
|
|
7a3408 |
+networkBandwidthChangeAllowed(virDomainNetDefPtr iface,
|
|
|
7a3408 |
+ virNetDevBandwidthPtr newBandwidth)
|
|
|
7a3408 |
+{
|
|
|
7a3408 |
+ virNetworkDriverStatePtr driver = networkGetDriver();
|
|
|
7a3408 |
+ virNetworkObjPtr network = NULL;
|
|
|
7a3408 |
+ virNetDevBandwidthPtr ifaceBand = virDomainNetGetActualBandwidth(iface);
|
|
|
7a3408 |
+ bool ret = false;
|
|
|
7a3408 |
+
|
|
|
7a3408 |
+ if (!networkBandwidthGenericChecks(iface, newBandwidth))
|
|
|
7a3408 |
+ return true;
|
|
|
7a3408 |
+
|
|
|
7a3408 |
+ network = virNetworkObjFindByName(driver->networks, iface->data.network.name);
|
|
|
7a3408 |
+ if (!network) {
|
|
|
7a3408 |
+ virReportError(VIR_ERR_NO_NETWORK,
|
|
|
7a3408 |
+ _("no network with matching name '%s'"),
|
|
|
7a3408 |
+ iface->data.network.name);
|
|
|
7a3408 |
+ return false;
|
|
|
7a3408 |
+ }
|
|
|
7a3408 |
+
|
|
|
7a3408 |
+ if (networkCheckBandwidth(network, newBandwidth, ifaceBand, iface->mac, NULL) < 0)
|
|
|
7a3408 |
+ goto cleanup;
|
|
|
7a3408 |
+
|
|
|
7a3408 |
+ ret = true;
|
|
|
7a3408 |
+
|
|
|
7a3408 |
+ cleanup:
|
|
|
7a3408 |
+ virNetworkObjEndAPI(&network);
|
|
|
7a3408 |
+ return ret;
|
|
|
7a3408 |
+}
|
|
|
7a3408 |
diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h
|
|
|
7a3408 |
index 513ccf7..cce9237 100644
|
|
|
7a3408 |
--- a/src/network/bridge_driver.h
|
|
|
7a3408 |
+++ b/src/network/bridge_driver.h
|
|
|
7a3408 |
@@ -52,6 +52,11 @@ int networkDnsmasqConfContents(virNetworkObjPtr network,
|
|
|
7a3408 |
char **configstr,
|
|
|
7a3408 |
dnsmasqContext *dctx,
|
|
|
7a3408 |
dnsmasqCapsPtr caps);
|
|
|
7a3408 |
+
|
|
|
7a3408 |
+bool networkBandwidthChangeAllowed(virDomainNetDefPtr iface,
|
|
|
7a3408 |
+ virNetDevBandwidthPtr newBandwidth)
|
|
|
7a3408 |
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
|
|
7a3408 |
+
|
|
|
7a3408 |
# else
|
|
|
7a3408 |
/* Define no-op replacements that don't drag in any link dependencies. */
|
|
|
7a3408 |
# define networkAllocateActualDevice(dom, iface) 0
|
|
|
7a3408 |
@@ -73,6 +78,13 @@ networkReleaseActualDevice(virDomainDefPtr dom ATTRIBUTE_UNUSED,
|
|
|
7a3408 |
return 0;
|
|
|
7a3408 |
}
|
|
|
7a3408 |
|
|
|
7a3408 |
+static inline bool
|
|
|
7a3408 |
+networkBandwidthChangeAllowed(virDomainNetDefPtr iface ATTRIBUTE_UNUSED,
|
|
|
7a3408 |
+ virNetDevBandwidthPtr newBandwidth ATTRIBUTE_UNUSED)
|
|
|
7a3408 |
+{
|
|
|
7a3408 |
+ return true;
|
|
|
7a3408 |
+}
|
|
|
7a3408 |
+
|
|
|
7a3408 |
# endif
|
|
|
7a3408 |
|
|
|
7a3408 |
typedef char *(*networkDnsmasqLeaseFileNameFunc)(const char *netname);
|
|
|
7a3408 |
--
|
|
|
7a3408 |
2.5.0
|
|
|
7a3408 |
|