[libvirt] [PATCH v6] network: Add network bandwidth support to ethernet interfaces

Anirban Chakraborty abchak at juniper.net
Tue Nov 18 23:55:48 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/netdev_bandwidth_conf.c | 14 ++++++++++-
 src/conf/netdev_bandwidth_conf.h | 25 +++++++++++++++++++
 src/libvirt_private.syms         |  1 +
 src/lxc/lxc_driver.c             |  8 +++++++
 src/lxc/lxc_process.c            | 52 +++++++++++++++++++++++-----------------
 src/qemu/qemu_command.c          | 16 ++++++++-----
 src/qemu/qemu_hotplug.c          | 12 ++++++++++
 src/qemu/qemu_process.c          |  4 ++++
 src/util/virnetdevmacvlan.c      | 10 --------
 src/util/virnetdevmacvlan.h      |  1 -
 10 files changed, 103 insertions(+), 40 deletions(-)

diff --git a/src/conf/netdev_bandwidth_conf.c b/src/conf/netdev_bandwidth_conf.c
index 2e5b564..63a39e3 100644
--- a/src/conf/netdev_bandwidth_conf.c
+++ b/src/conf/netdev_bandwidth_conf.c
@@ -25,7 +25,6 @@
 #include "netdev_bandwidth_conf.h"
 #include "virerror.h"
 #include "viralloc.h"
-#include "domain_conf.h"
 #include "virstring.h"

 #define VIR_FROM_THIS VIR_FROM_NONE
@@ -269,3 +268,16 @@ virNetDevBandwidthFormat(virNetDevBandwidthPtr def, virBufferPtr buf)
  cleanup:
     return ret;
 }
+
+void
+virDomainClearNetBandwidth(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/conf/netdev_bandwidth_conf.h b/src/conf/netdev_bandwidth_conf.h
index 23aaaf3..60dacc6 100644
--- a/src/conf/netdev_bandwidth_conf.h
+++ b/src/conf/netdev_bandwidth_conf.h
@@ -27,6 +27,7 @@
 # include "virnetdevbandwidth.h"
 # include "virbuffer.h"
 # include "virxml.h"
+# include "domain_conf.h"

 virNetDevBandwidthPtr virNetDevBandwidthParse(xmlNodePtr node,
                                               int net_type)
@@ -35,4 +36,28 @@ int virNetDevBandwidthFormat(virNetDevBandwidthPtr def,
                              virBufferPtr buf)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);

+void virDomainClearNetBandwidth(virDomainObjPtr vm)
+    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 /* __VIR_NETDEV_BANDWIDTH_CONF_H__ */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0864618..1c0cfb1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -509,6 +509,7 @@ virInterfaceRemove;
 # conf/netdev_bandwidth_conf.h
 virNetDevBandwidthFormat;
 virNetDevBandwidthParse;
+virDomainClearNetBandwidth;


 # conf/netdev_vlan_conf.h
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index cf2a3c8..e9e0da3 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 "netdev_bandwidth_conf.h"

 #define VIR_FROM_THIS VIR_FROM_LXC

@@ -4213,6 +4214,11 @@ lxcDomainAttachDeviceNetLive(virConnectPtr conn,
                        _("Network device type is not supported"));
         goto cleanup;
     }
+    /* set network bandwidth */
+    if (virNetDevSupportBandwidth(actualType) &&
+        virNetDevBandwidthSet(net->ifname,
+        virDomainNetGetActualBandwidth(net), false) < 0)
+        goto cleanup;

     if (virNetDevSetNamespace(veth, priv->initpid) < 0) {
         virDomainAuditNet(vm, NULL, net, "attach", false);
@@ -4644,6 +4650,8 @@ lxcDomainDetachDeviceNetLive(virDomainObjPtr vm,

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

+    virDomainClearNetBandwidth(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 37ddbbc..5bbd696 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -51,6 +51,7 @@
 #include "viratomic.h"
 #include "virprocess.h"
 #include "virsystemd.h"
+#include "netdev_bandwidth_conf.h"

 #define VIR_FROM_THIS VIR_FROM_LXC

@@ -274,11 +275,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 +296,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 +326,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;
@@ -368,6 +364,8 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
     int ret = -1;
     size_t i;
     size_t niface = 0;
+    virDomainNetDefPtr net;
+    virDomainNetType type;

     for (i = 0; i < def->nnets; i++) {
         char *veth = NULL;
@@ -375,13 +373,15 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
          * network's pool of devices, or resolve bridge device name
          * to the one defined in the network definition.
          */
-        if (networkAllocateActualDevice(def, def->nets[i]) < 0)
+        net = def->nets[i];
+        if (networkAllocateActualDevice(def, net) < 0)
             goto cleanup;

         if (VIR_EXPAND_N(*veths, *nveths, 1) < 0)
             goto cleanup;

-        switch (virDomainNetGetActualType(def->nets[i])) {
+        type = virDomainNetGetActualType(net);
+        switch (type) {
         case VIR_DOMAIN_NET_TYPE_NETWORK: {
             virNetworkPtr network;
             char *brname = NULL;
@@ -389,7 +389,7 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
             virErrorPtr errobj;

             if (!(network = virNetworkLookupByName(conn,
-                                                   def->nets[i]->data.network.name)))
+                                                   net->data.network.name)))
                 goto cleanup;
             if (!(brname = virNetworkGetBridgeName(network)))
                fail = true;
@@ -405,7 +405,7 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,

             if (!(veth = virLXCProcessSetupInterfaceBridged(conn,
                                                             def,
-                                                            def->nets[i],
+                                                            net,
                                                             brname))) {
                 VIR_FREE(brname);
                 goto cleanup;
@@ -414,7 +414,7 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
             break;
         }
         case VIR_DOMAIN_NET_TYPE_BRIDGE: {
-            const char *brname = virDomainNetGetActualBridgeName(def->nets[i]);
+            const char *brname = virDomainNetGetActualBridgeName(net);
             if (!brname) {
                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                _("No bridge name specified"));
@@ -422,7 +422,7 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
             }
             if (!(veth = virLXCProcessSetupInterfaceBridged(conn,
                                                             def,
-                                                            def->nets[i],
+                                                            net,
                                                             brname)))
                 goto cleanup;
         }   break;
@@ -430,31 +430,39 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
         case VIR_DOMAIN_NET_TYPE_DIRECT:
             if (!(veth = virLXCProcessSetupInterfaceDirect(conn,
                                                            def,
-                                                           def->nets[i])))
+                                                           net)))
                 goto cleanup;
             break;

-        case VIR_DOMAIN_NET_TYPE_USER:
         case VIR_DOMAIN_NET_TYPE_ETHERNET:
+            break;
+
+        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_LAST:
+        case VIR_DOMAIN_NET_TYPE_HOSTDEV:
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("Unsupported network type %s"),
-                           virDomainNetTypeToString(
-                               virDomainNetGetActualType(def->nets[i])
-                               ));
+                           virDomainNetTypeToString(type));
             goto cleanup;
+
         }

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

         /* Make sure all net definitions will have a name in the container */
-        if (!def->nets[i]->ifname_guest) {
-            if (virAsprintf(&def->nets[i]->ifname_guest, "eth%zu", niface) < 0)
+        if (!net->ifname_guest) {
+            if (virAsprintf(&net->ifname_guest, "eth%zu", niface) < 0)
                 return -1;
             niface++;
         }
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 1399ce4..8025ff6 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -43,6 +43,7 @@
 #include "domain_addr.h"
 #include "domain_audit.h"
 #include "domain_conf.h"
+#include "netdev_bandwidth_conf.h"
 #include "snapshot_conf.h"
 #include "storage_conf.h"
 #include "secret_conf.h"
@@ -192,7 +193,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);
@@ -372,11 +372,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;
@@ -7501,6 +7496,15 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
             goto cleanup;
     }

+    /* Set Bandwidth */
+    if (net->ifname && strlen(net->ifname)) {
+        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 ||
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index b9a0cee..3e7b7da 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -31,6 +31,7 @@
 #include "qemu_command.h"
 #include "qemu_hostdev.h"
 #include "domain_audit.h"
+#include "netdev_bandwidth_conf.h"
 #include "domain_nwfilter.h"
 #include "virlog.h"
 #include "datatypes.h"
@@ -947,6 +948,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)
@@ -3545,6 +3552,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 7518138..b782984 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -69,6 +69,7 @@
 #include "storage/storage_driver.h"
 #include "configmake.h"
 #include "nwfilter_conf.h"
+#include "netdev_bandwidth_conf.h"

 #define VIR_FROM_THIS VIR_FROM_QEMU

@@ -4843,6 +4844,9 @@ void qemuProcessStop(virQEMUDriverPtr driver,
                       virStrerror(errno, ebuf, sizeof(ebuf)));
     }

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

     if (cfg->macFilter) {
diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c
index 89e221d..2ff24b1 100644
--- a/src/util/virnetdevmacvlan.c
+++ b/src/util/virnetdevmacvlan.c
@@ -810,7 +810,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) ?
@@ -923,14 +922,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
@@ -1073,7 +1064,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.9.1




More information about the libvir-list mailing list