[libvirt] [PATCH] network: Add bandwidth support to ethernet interface

Anirban Chakraborty abchak at juniper.net
Wed Oct 29 23:56:41 UTC 2014


Ethernet interfaces in libvirt currently do not support bandwidth setting.
For example, following xml file for an interface will not apply these
settings to corresponding qdiscs.

    <interface type="ethernet">
      <mac address="02:36:1d:18:2a:e4"/>
      <model type="virtio"/>
      <script path=""/>
      <target dev="tap361d182a-e4"/>
      <bandwidth>
        <inbound average="984" peak="1024" burst="64"/>
        <outbound average="2000" peak="2048" burst="128"/>
      </bandwidth>
    </interface>

Signed-off-by: Anirban Chakraborty <abchak at juniper.net>
---
 src/conf/domain_conf.h      | 21 +++++++++++++++++++++
 src/lxc/lxc_driver.c        |  3 +++
 src/lxc/lxc_process.c       | 18 +++++++++---------
 src/qemu/qemu_command.c     | 25 +++++++++++++++++++------
 src/qemu/qemu_command.h     |  2 ++
 src/qemu/qemu_driver.c      |  3 +++
 src/qemu/qemu_hotplug.c     | 12 ++++++++++++
 src/qemu/qemu_process.c     |  3 +++
 src/util/virnetdevmacvlan.c | 10 ----------
 src/util/virnetdevmacvlan.h |  1 -
 10 files changed, 72 insertions(+), 26 deletions(-)

diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 9908d88..40e85d9 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2848,4 +2848,25 @@ int virDomainObjSetMetadata(virDomainObjPtr vm,
 bool virDomainDefNeedsPlacementAdvice(virDomainDefPtr def)
     ATTRIBUTE_NONNULL(1);

+static inline bool virNetDevSupportBandwidth(virDomainNetType type)
+{
+    switch (type) {
+    case VIR_DOMAIN_NET_TYPE_BRIDGE:
+    case VIR_DOMAIN_NET_TYPE_NETWORK:
+    case VIR_DOMAIN_NET_TYPE_DIRECT:
+    case VIR_DOMAIN_NET_TYPE_ETHERNET:
+        return true;
+    case VIR_DOMAIN_NET_TYPE_USER:
+    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
+    case VIR_DOMAIN_NET_TYPE_SERVER:
+    case VIR_DOMAIN_NET_TYPE_CLIENT:
+    case VIR_DOMAIN_NET_TYPE_MCAST:
+    case VIR_DOMAIN_NET_TYPE_INTERNAL:
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+    case VIR_DOMAIN_NET_TYPE_LAST:
+        break;
+    }
+    return false;
+}
+
 #endif /* __DOMAIN_CONF_H */
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 979382b..8a21af4 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -72,6 +72,7 @@
 #include "viraccessapicheck.h"
 #include "viraccessapichecklxc.h"
 #include "virhostdev.h"
+#include "qemu/qemu_command.h"

 #define VIR_FROM_THIS VIR_FROM_LXC

@@ -4634,6 +4635,8 @@ lxcDomainDetachDeviceNetLive(virDomainObjPtr vm,

     detach = vm->def->nets[detachidx];

+    qemuDomainClearNetBandwidth(vm);
+
     switch (virDomainNetGetActualType(detach)) {
     case VIR_DOMAIN_NET_TYPE_BRIDGE:
     case VIR_DOMAIN_NET_TYPE_NETWORK:
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index ed30c37..3192011 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -274,11 +274,6 @@ char *virLXCProcessSetupInterfaceBridged(virConnectPtr conn,
     if (virNetDevSetOnline(parentVeth, true) < 0)
         goto cleanup;

-    if (virNetDevBandwidthSet(net->ifname,
-                              virDomainNetGetActualBandwidth(net),
-                              false) < 0)
-        goto cleanup;
-
     if (net->filter &&
         virDomainConfNWFilterInstantiate(conn, vm->uuid, net) < 0)
         goto cleanup;
@@ -300,6 +295,7 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn,
     virNetDevBandwidthPtr bw;
     virNetDevVPortProfilePtr prof;
     virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
+    const char *linkdev = virDomainNetGetActualDirectDev(net);

     /* XXX how todo bandwidth controls ?
      * Since the 'net-ifname' is about to be moved to a different
@@ -329,14 +325,13 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn,

     if (virNetDevMacVLanCreateWithVPortProfile(
             net->ifname, &net->mac,
-            virDomainNetGetActualDirectDev(net),
+            linkdev,
             virDomainNetGetActualDirectMode(net),
             false, def->uuid,
-            virDomainNetGetActualVirtPortProfile(net),
+            prof,
             &res_ifname,
             VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
-            cfg->stateDir,
-            virDomainNetGetActualBandwidth(net), 0) < 0)
+            cfg->stateDir, 0) < 0)
         goto cleanup;

     ret = res_ifname;
@@ -450,6 +445,11 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
             goto cleanup;
         }

+        /* set network bandwidth */
+        if (virNetDevBandwidthSet(def->nets[i]->ifname,
+                virDomainNetGetActualBandwidth(def->nets[i]), false) < 0)
+           goto cleanup;
+
         (*veths)[(*nveths)-1] = veth;

         /* Make sure all net definitions will have a name in the container */
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 2e5af4f..7922672 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -191,7 +191,6 @@ qemuPhysIfaceConnect(virDomainDefPtr def,
         virDomainNetGetActualVirtPortProfile(net),
         &res_ifname,
         vmop, cfg->stateDir,
-        virDomainNetGetActualBandwidth(net),
         macvlan_create_flags);
     if (rc >= 0) {
         virDomainAuditNetDevice(def, net, res_ifname, true);
@@ -371,11 +370,6 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
                                   &net->mac) < 0)
         goto cleanup;

-    if (virNetDevBandwidthSet(net->ifname,
-                              virDomainNetGetActualBandwidth(net),
-                              false) < 0)
-        goto cleanup;
-
     if (net->filter &&
         virDomainConfNWFilterInstantiate(conn, def->uuid, net) < 0) {
         goto cleanup;
@@ -7427,6 +7421,13 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
             goto cleanup;
     }

+    /* Set Bandwidth */
+    if (virNetDevSupportBandwidth(actualType) &&
+           virNetDevBandwidthSet(net->ifname,
+           virDomainNetGetActualBandwidth(net),
+           false) < 0)
+        goto cleanup;
+
     if ((actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
          actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
          actualType == VIR_DOMAIN_NET_TYPE_ETHERNET ||
@@ -12463,3 +12464,15 @@ virDomainDefPtr qemuParseCommandLinePid(virCapsPtr qemuCaps,
     virStringFreeList(progenv);
     return def;
 }
+
+void qemuDomainClearNetBandwidth(virDomainObjPtr vm)
+{
+    size_t i;
+    virDomainNetType type;
+
+    for (i = 0; i < vm->def->nnets; i++) {
+        type = virDomainNetGetActualType(vm->def->nets[i]);
+        if (virNetDevSupportBandwidth(type))
+            virNetDevBandwidthClear(vm->def->nets[i]->ifname);
+    }
+}
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index aa40c9e..7963a91 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -277,4 +277,6 @@ int qemuCheckDiskConfig(virDomainDiskDefPtr disk);

 bool
 qemuCheckFips(void);
+
+void qemuDomainClearNetBandwidth(virDomainObjPtr vm);
 #endif /* __QEMU_COMMAND_H__*/
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 2eaf77d..6ef1132 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2196,6 +2196,9 @@ qemuDomainDestroyFlags(virDomainPtr dom,
     if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0)
         goto cleanup;

+    /* Clear network bandwidth */
+    qemuDomainClearNetBandwidth(vm);
+
     qemuDomainSetFakeReboot(driver, vm, false);


diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 33241fb..9eb125f 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -50,6 +50,7 @@
 #include "virstring.h"
 #include "virtime.h"
 #include "storage/storage_driver.h"
+#include "domain_conf.h"

 #define VIR_FROM_THIS VIR_FROM_QEMU

@@ -948,6 +949,12 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
             goto cleanup;
     }

+    /* Set Bandwidth */
+    if (virNetDevSupportBandwidth(actualType) &&
+            virNetDevBandwidthSet(net->ifname,
+            virDomainNetGetActualBandwidth(net), false) < 0)
+        goto cleanup;
+
     for (i = 0; i < tapfdSize; i++) {
         if (virSecurityManagerSetTapFDLabel(driver->securityManager,
                                             vm->def, tapfd[i]) < 0)
@@ -3536,6 +3543,11 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver,
             goto cleanup;
     }

+    if (virNetDevSupportBandwidth(virDomainNetGetActualType(detach)) &&
+            virNetDevBandwidthClear(detach->ifname) < 0)
+        VIR_WARN("cannot clear bandwidth setting for device : %s",
+                       detach->ifname);
+
     qemuDomainMarkDeviceForRemoval(vm, &detach->info);

     qemuDomainObjEnterMonitor(driver, vm);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index ef258cf..21448a5 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4825,6 +4825,9 @@ void qemuProcessStop(virQEMUDriverPtr driver,
                       virStrerror(errno, ebuf, sizeof(ebuf)));
     }

+    /* Clear network bandwidth */
+    qemuDomainClearNetBandwidth(vm);
+
     virDomainConfVMNWFilterTeardown(vm);

     if (cfg->macFilter) {
diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c
index c83341c..956a96b 100644
--- a/src/util/virnetdevmacvlan.c
+++ b/src/util/virnetdevmacvlan.c
@@ -811,7 +811,6 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname,
                                            char **res_ifname,
                                            virNetDevVPortProfileOp vmOp,
                                            char *stateDir,
-                                           virNetDevBandwidthPtr bandwidth,
                                            unsigned int flags)
 {
     const char *type = (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) ?
@@ -925,14 +924,6 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *tgifname,
         rc = 0;
     }

-    if (virNetDevBandwidthSet(cr_ifname, bandwidth, false) < 0) {
-        if (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP)
-            VIR_FORCE_CLOSE(rc); /* sets rc to -1 */
-        else
-            rc = -1;
-        goto disassociate_exit;
-    }
-
     if (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_CREATE ||
         vmOp == VIR_NETDEV_VPORT_PROFILE_OP_RESTORE) {
         /* Only directly register upon a create or restore (restarting
@@ -1076,7 +1067,6 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *ifname ATTRIBUTE_UNUSED,
                                            char **res_ifname ATTRIBUTE_UNUSED,
                                            virNetDevVPortProfileOp vmop ATTRIBUTE_UNUSED,
                                            char *stateDir ATTRIBUTE_UNUSED,
-                                           virNetDevBandwidthPtr bandwidth ATTRIBUTE_UNUSED,
                                            unsigned int flags)
 {
     virCheckFlags(0, -1);
diff --git a/src/util/virnetdevmacvlan.h b/src/util/virnetdevmacvlan.h
index 41aa4e2..f08d32b 100644
--- a/src/util/virnetdevmacvlan.h
+++ b/src/util/virnetdevmacvlan.h
@@ -68,7 +68,6 @@ int virNetDevMacVLanCreateWithVPortProfile(const char *ifname,
                                            char **res_ifname,
                                            virNetDevVPortProfileOp vmop,
                                            char *stateDir,
-                                           virNetDevBandwidthPtr bandwidth,
                                            unsigned int flags)
     ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(6)
     ATTRIBUTE_NONNULL(8) ATTRIBUTE_NONNULL(10) ATTRIBUTE_RETURN_CHECK;
-- 
1.8.2.3




More information about the libvir-list mailing list