render / rpms / libvirt

Forked from rpms/libvirt 10 months ago
Clone
7a3408
From b80365f3a798bfc245d3db7d7586d2e82b38f68e Mon Sep 17 00:00:00 2001
7a3408
Message-Id: <b80365f3a798bfc245d3db7d7586d2e82b38f68e@dist-git>
7a3408
From: Michal Privoznik <mprivozn@redhat.com>
7a3408
Date: Fri, 14 Aug 2015 16:06:32 +0200
7a3408
Subject: [PATCH] bridge_driver: Introduce networkBandwidthUpdate
7a3408
7a3408
https://bugzilla.redhat.com/show_bug.cgi?id=1252473
7a3408
7a3408
So, if a domain vNIC's bandwidth has been successfully set, it's
7a3408
possible that because @floor is set on network's bridge, this
7a3408
part may need updating too. And that's exactly what this function
7a3408
does. While the previous commit introduced a function to check if
7a3408
@floor can be satisfied, this does all the hard work. In general,
7a3408
there may be three, well four possibilities:
7a3408
7a3408
  1) No change in @floor value (either it remain unset, or its
7a3408
  value hasn't changed)
7a3408
7a3408
  2) The @floor value has changed from a non-zero to a non-zero
7a3408
  value
7a3408
7a3408
  3) New @floor is to be set
7a3408
7a3408
  4) Old @floor must be cleared out
7a3408
7a3408
The difference between 2), 3) and 4) is, that while in 2) the QoS
7a3408
tree on the network's bridge already has a special class for the
7a3408
vNIC, in 3) the class must be created from scratch. In 4) it must
7a3408
be removed. Fortunately, we have helpers for all three
7a3408
interesting cases.
7a3408
7a3408
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
7a3408
(cherry picked from commit 812932bea2c703d4031f947096f8efaf21b662bf)
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 | 163 ++++++++++++++++++++++++++++++++++++--------
7a3408
 src/network/bridge_driver.h |  11 +++
7a3408
 2 files changed, 145 insertions(+), 29 deletions(-)
7a3408
7a3408
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
7a3408
index 04602ed..666078c 100644
7a3408
--- a/src/network/bridge_driver.c
7a3408
+++ b/src/network/bridge_driver.c
7a3408
@@ -4794,38 +4794,17 @@ networkNextClassID(virNetworkObjPtr net)
7a3408
     return ret;
7a3408
 }
7a3408
 
7a3408
+
7a3408
 static int
7a3408
-networkPlugBandwidth(virNetworkObjPtr net,
7a3408
-                     virDomainNetDefPtr iface)
7a3408
+networkPlugBandwidthImpl(virNetworkObjPtr net,
7a3408
+                         virDomainNetDefPtr iface,
7a3408
+                         virNetDevBandwidthPtr ifaceBand,
7a3408
+                         unsigned long long new_rate)
7a3408
 {
7a3408
     virNetworkDriverStatePtr driver = networkGetDriver();
7a3408
-    int ret = -1;
7a3408
-    int plug_ret;
7a3408
-    unsigned long long new_rate = 0;
7a3408
     ssize_t class_id = 0;
7a3408
-    char ifmac[VIR_MAC_STRING_BUFLEN];
7a3408
-    virNetDevBandwidthPtr ifaceBand = virDomainNetGetActualBandwidth(iface);
7a3408
-
7a3408
-    if ((plug_ret = networkCheckBandwidth(net, ifaceBand, NULL,
7a3408
-                                          iface->mac, &new_rate)) < 0) {
7a3408
-        /* helper reported error */
7a3408
-        goto cleanup;
7a3408
-    }
7a3408
-
7a3408
-    if (plug_ret > 0) {
7a3408
-        /* no QoS needs to be set; claim success */
7a3408
-        ret = 0;
7a3408
-        goto cleanup;
7a3408
-    }
7a3408
-
7a3408
-    virMacAddrFormat(&iface->mac, ifmac);
7a3408
-    if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK ||
7a3408
-        !iface->data.network.actual) {
7a3408
-        virReportError(VIR_ERR_INTERNAL_ERROR,
7a3408
-                       _("Cannot set bandwidth on interface '%s' of type %d"),
7a3408
-                       ifmac, iface->type);
7a3408
-        goto cleanup;
7a3408
-    }
7a3408
+    int plug_ret;
7a3408
+    int ret = -1;
7a3408
 
7a3408
     /* generate new class_id */
7a3408
     if ((class_id = networkNextClassID(net)) < 0) {
7a3408
@@ -4861,6 +4840,46 @@ networkPlugBandwidth(virNetworkObjPtr net,
7a3408
                  net->def->bridge);
7a3408
 
7a3408
     ret = 0;
7a3408
+ cleanup:
7a3408
+    return ret;
7a3408
+}
7a3408
+
7a3408
+
7a3408
+static int
7a3408
+networkPlugBandwidth(virNetworkObjPtr net,
7a3408
+                     virDomainNetDefPtr iface)
7a3408
+{
7a3408
+    int ret = -1;
7a3408
+    int plug_ret;
7a3408
+    unsigned long long new_rate = 0;
7a3408
+    char ifmac[VIR_MAC_STRING_BUFLEN];
7a3408
+    virNetDevBandwidthPtr ifaceBand = virDomainNetGetActualBandwidth(iface);
7a3408
+
7a3408
+    if ((plug_ret = networkCheckBandwidth(net, ifaceBand, NULL,
7a3408
+                                          iface->mac, &new_rate)) < 0) {
7a3408
+        /* helper reported error */
7a3408
+        goto cleanup;
7a3408
+    }
7a3408
+
7a3408
+    if (plug_ret > 0) {
7a3408
+        /* no QoS needs to be set; claim success */
7a3408
+        ret = 0;
7a3408
+        goto cleanup;
7a3408
+    }
7a3408
+
7a3408
+    virMacAddrFormat(&iface->mac, ifmac);
7a3408
+    if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK ||
7a3408
+        !iface->data.network.actual) {
7a3408
+        virReportError(VIR_ERR_INTERNAL_ERROR,
7a3408
+                       _("Cannot set bandwidth on interface '%s' of type %d"),
7a3408
+                       ifmac, iface->type);
7a3408
+        goto cleanup;
7a3408
+    }
7a3408
+
7a3408
+    if (networkPlugBandwidthImpl(net, iface, ifaceBand, new_rate) < 0)
7a3408
+        goto cleanup;
7a3408
+
7a3408
+    ret = 0;
7a3408
 
7a3408
  cleanup:
7a3408
     return ret;
7a3408
@@ -4938,15 +4957,19 @@ static bool
7a3408
 networkBandwidthGenericChecks(virDomainNetDefPtr iface,
7a3408
                               virNetDevBandwidthPtr newBandwidth)
7a3408
 {
7a3408
-    virNetDevBandwidthPtr ifaceBand = virDomainNetGetActualBandwidth(iface);
7a3408
+    virNetDevBandwidthPtr ifaceBand;
7a3408
     unsigned long long old_floor, new_floor;
7a3408
 
7a3408
+    if (!iface && !newBandwidth)
7a3408
+        return false;
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
+    ifaceBand = virDomainNetGetActualBandwidth(iface);
7a3408
     old_floor = new_floor = 0;
7a3408
 
7a3408
     if (ifaceBand && ifaceBand->in)
7a3408
@@ -4987,3 +5010,85 @@ networkBandwidthChangeAllowed(virDomainNetDefPtr iface,
7a3408
     virNetworkObjEndAPI(&network);
7a3408
     return ret;
7a3408
 }
7a3408
+
7a3408
+
7a3408
+int
7a3408
+networkBandwidthUpdate(virDomainNetDefPtr iface,
7a3408
+                       virNetDevBandwidthPtr newBandwidth)
7a3408
+{
7a3408
+    virNetworkDriverStatePtr driver = networkGetDriver();
7a3408
+    virNetworkObjPtr network = NULL;
7a3408
+    virNetDevBandwidthPtr ifaceBand = virDomainNetGetActualBandwidth(iface);
7a3408
+    unsigned long long new_rate = 0;
7a3408
+    int plug_ret;
7a3408
+    int ret = -1;
7a3408
+
7a3408
+    if (!networkBandwidthGenericChecks(iface, newBandwidth))
7a3408
+        return 0;
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 ret;
7a3408
+    }
7a3408
+
7a3408
+    if ((plug_ret = networkCheckBandwidth(network, newBandwidth, ifaceBand,
7a3408
+                                          iface->mac, &new_rate)) < 0) {
7a3408
+        /* helper reported error */
7a3408
+        goto cleanup;
7a3408
+    }
7a3408
+
7a3408
+    if (plug_ret > 0) {
7a3408
+        /* no QoS needs to be set; claim success */
7a3408
+        ret = 0;
7a3408
+        goto cleanup;
7a3408
+    }
7a3408
+
7a3408
+    /* Okay, there are three possible scenarios: */
7a3408
+
7a3408
+    if (ifaceBand->in && ifaceBand->in->floor &&
7a3408
+        newBandwidth->in && newBandwidth->in->floor) {
7a3408
+        /* Either we just need to update @floor .. */
7a3408
+
7a3408
+        if (virNetDevBandwidthUpdateRate(network->def->bridge,
7a3408
+                                         iface->data.network.actual->class_id,
7a3408
+                                         network->def->bandwidth,
7a3408
+                                         newBandwidth->in->floor) < 0)
7a3408
+            goto cleanup;
7a3408
+
7a3408
+        network->floor_sum -= ifaceBand->in->floor;
7a3408
+        network->floor_sum += newBandwidth->in->floor;
7a3408
+        new_rate -= network->floor_sum;
7a3408
+
7a3408
+        if (virNetDevBandwidthUpdateRate(network->def->bridge, 2,
7a3408
+                                         network->def->bandwidth, new_rate) < 0 ||
7a3408
+            virNetworkSaveStatus(driver->stateDir, network) < 0) {
7a3408
+            /* Ouch, rollback */
7a3408
+            network->floor_sum -= newBandwidth->in->floor;
7a3408
+            network->floor_sum += ifaceBand->in->floor;
7a3408
+
7a3408
+            ignore_value(virNetDevBandwidthUpdateRate(network->def->bridge,
7a3408
+                                                      iface->data.network.actual->class_id,
7a3408
+                                                      network->def->bandwidth,
7a3408
+                                                      ifaceBand->in->floor));
7a3408
+            goto cleanup;
7a3408
+        }
7a3408
+    } else if (newBandwidth->in && newBandwidth->in->floor) {
7a3408
+        /* .. or we need to plug in new .. */
7a3408
+
7a3408
+        if (networkPlugBandwidthImpl(network, iface, newBandwidth, new_rate) < 0)
7a3408
+            goto cleanup;
7a3408
+    } else {
7a3408
+        /* .. or unplug old. */
7a3408
+
7a3408
+        if (networkUnplugBandwidth(network, iface) < 0)
7a3408
+            goto cleanup;
7a3408
+    }
7a3408
+
7a3408
+    ret = 0;
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 cce9237..7db2c90 100644
7a3408
--- a/src/network/bridge_driver.h
7a3408
+++ b/src/network/bridge_driver.h
7a3408
@@ -57,6 +57,10 @@ bool networkBandwidthChangeAllowed(virDomainNetDefPtr iface,
7a3408
                                    virNetDevBandwidthPtr newBandwidth)
7a3408
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
7a3408
 
7a3408
+int networkBandwidthUpdate(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
@@ -85,6 +89,13 @@ networkBandwidthChangeAllowed(virDomainNetDefPtr iface ATTRIBUTE_UNUSED,
7a3408
     return true;
7a3408
 }
7a3408
 
7a3408
+static inline int
7a3408
+networkBandwidthUpdate(virDomainNetDefPtr iface ATTRIBUTE_UNUSED,
7a3408
+                       virNetDevBandwidthPtr newBandwidth ATTRIBUTE_UNUSED)
7a3408
+{
7a3408
+    return 0;
7a3408
+}
7a3408
+
7a3408
 # endif
7a3408
 
7a3408
 typedef char *(*networkDnsmasqLeaseFileNameFunc)(const char *netname);
7a3408
-- 
7a3408
2.5.0
7a3408