render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
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