[libvirt] [PATCH-RFC-V2] qemu: Add network bandwidth setting for ethernet interfaces

Anirban Chakraborty abchak at juniper.net
Wed Oct 8 04:35:47 UTC 2014



On 10/6/14, 3:43 AM, "Michal Privoznik" <mprivozn at redhat.com> wrote:

>On 18.09.2014 01:33, Anirban Chakraborty wrote:
>> V2:
>> Consolidate calls to virNetDevBandwidthSet
>> Clear bandwidth settings when the interface is detached or domain
>>destroyed
>>
>> V1:
>> 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      |  7 +++++++
>>   src/lxc/lxc_process.c       | 27 ++++++++++++++-------------
>>   src/qemu/qemu_command.c     |  9 ++++-----
>>   src/qemu/qemu_driver.c      | 21 +++++++++++++++++++++
>>   src/qemu/qemu_hotplug.c     | 13 +++++++++++++
>>   src/util/virnetdevmacvlan.c | 10 ----------
>>   src/util/virnetdevmacvlan.h |  1 -
>>   7 files changed, 59 insertions(+), 29 deletions(-)
>>
>> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
>> index 640a4c5..3c950f1 100644
>> --- a/src/conf/domain_conf.h
>> +++ b/src/conf/domain_conf.h
>> @@ -829,6 +829,13 @@ typedef enum {
>>       VIR_DOMAIN_NET_TYPE_LAST
>>   } virDomainNetType;
>>
>> +/* check bandwidth configuration for a network interface */
>> +#define NETDEVIF_SUPPORT_BANDWIDTH(type) \
>> +   ((type == VIR_DOMAIN_NET_TYPE_ETHERNET || \
>> +     type == VIR_DOMAIN_NET_TYPE_NETWORK  || \
>> +     type == VIR_DOMAIN_NET_TYPE_BRIDGE   || \
>> +     type == VIR_DOMAIN_NET_TYPE_DIRECT) ? true : false)
>> +
>
>I'd rather turn this into a function (possibly inline function).

Will do.

>
>>   /* the backend driver used for virtio interfaces */
>>   typedef enum {
>>       VIR_DOMAIN_NET_BACKEND_TYPE_DEFAULT, /* prefer kernel, fall back
>>to user */
>> diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
>> index ed30c37..5ef91e8 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;
>> -
>
>Well, the virLXCProcessSetupInterfaceBridged is used elsewhere in the
>code too. For instance after this patch the QoS is not applied on
>interfaces hotplugged into an LXC container.

Thanks for pointing it out. I am taking care of it in my next patch.

>
>>       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,16 +325,15 @@ 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)
>> +            0) < 0)
>>           goto cleanup;
>> -
>>       ret = res_ifname;
>>
>>    cleanup:
>> @@ -368,6 +363,7 @@ static int
>>virLXCProcessSetupInterfaces(virConnectPtr conn,
>>       int ret = -1;
>>       size_t i;
>>       size_t niface = 0;
>> +    int actualType;
>>
>>       for (i = 0; i < def->nnets; i++) {
>>           char *veth = NULL;
>> @@ -381,7 +377,8 @@ static int
>>virLXCProcessSetupInterfaces(virConnectPtr conn,
>>           if (VIR_EXPAND_N(*veths, *nveths, 1) < 0)
>>               goto cleanup;
>>
>> -        switch (virDomainNetGetActualType(def->nets[i])) {
>> +        actualType = virDomainNetGetActualType(def->nets[i]);
>> +        switch (actualType) {
>>           case VIR_DOMAIN_NET_TYPE_NETWORK: {
>>               virNetworkPtr network;
>>               char *brname = NULL;
>> @@ -444,11 +441,15 @@ static int
>>virLXCProcessSetupInterfaces(virConnectPtr conn,
>>           case VIR_DOMAIN_NET_TYPE_LAST:
>>               virReportError(VIR_ERR_INTERNAL_ERROR,
>>                              _("Unsupported network type %s"),
>> -                           virDomainNetTypeToString(
>> -                               virDomainNetGetActualType(def->nets[i])
>> -                               ));
>> +                           virDomainNetTypeToString(actualType));
>>               goto cleanup;
>>           }
>> +        /* set network bandwidth */
>> +        if (NETDEVIF_SUPPORT_BANDWIDTH(actualType) &&
>>virNetDevBandwidthSet(
>> +                def->nets[i]->ifname, virDomainNetGetActualBandwidth(
>> +                def->nets[i]),
>> +                false) < 0)
>
>I must say this formatting looks very strange to me in libvirt
>connotations.
Yeah, this was not right, for some reason it escaped my attention.

>
>> +           goto cleanup;
>>
>>           (*veths)[(*nveths)-1] = veth;
>>
>> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
>> index f2e6e5a..404c51b 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,10 +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) {
>> @@ -7313,6 +7308,10 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
>>           if (tapfd[0] < 0)
>>               goto cleanup;
>>       }
>> +    /* Set bandwidth  */
>> +    if (NETDEVIF_SUPPORT_BANDWIDTH(actualType) &&
>>virNetDevBandwidthSet(
>> +            net->ifname, virDomainNetGetActualBandwidth(net), false) <
>>0)
>> +        goto cleanup;
>>
>>       if ((actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
>>            actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
>> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
>> index 5fd89a3..f5a5cbe 100644
>> --- a/src/qemu/qemu_driver.c
>> +++ b/src/qemu/qemu_driver.c
>> @@ -186,6 +186,9 @@ qemuVMFilterRebuild(virDomainObjListIterator iter,
>>void *data)
>>       return virDomainObjListForEach(qemu_driver->domains, iter, data);
>>   }
>>
>> +static void
>> +qemuDomainClearNetBandwidth(virDomainObjPtr vm);
>> +
>>   static virNWFilterCallbackDriver qemuCallbackDriver = {
>>       .name = QEMU_DRIVER_NAME,
>>       .vmFilterRebuild = qemuVMFilterRebuild,
>> @@ -2196,6 +2199,9 @@ qemuDomainDestroyFlags(virDomainPtr dom,
>>       if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0)
>>           goto cleanup;
>>
>> +    /* Clear network bandwidth settings */
>> +    qemuDomainClearNetBandwidth(vm);
>> +
>
>
>No. This clears QoS only if the destroy API is called. However, domain
>may terminate by other means where the QoS should be cleared too, e.g.
>'sudo poweroff' caled from within the domain. So this call needs to go
>into qemuProcessStop.

Got it, thanks for catching it.

>
>>       qemuDomainSetFakeReboot(driver, vm, false);
>>
>>
>> @@ -17952,6 +17958,21 @@ qemuConnectGetAllDomainStats(virConnectPtr
>>conn,
>>       return ret;
>>   }
>>
>> +/* Clear the bandwidth setting of all the network interfaces of a vm */
>> +static void
>> +qemuDomainClearNetBandwidth(virDomainObjPtr vm)
>> +{
>> +    size_t i;
>> +    int actualType;
>> +
>> +    for (i = 0; i < vm->def->nnets; i++) {
>> +        virDomainNetDefPtr net = vm->def->nets[i];
>> +        actualType = virDomainNetGetActualType(net);
>> +        if (NETDEVIF_SUPPORT_BANDWIDTH(actualType))
>> +            virNetDevBandwidthClear(net->ifname);
>> +    }
>> +}
>> +
>
>Okay. Previously QoS was set on TAP devices only. So there was no need
>to call  virNetDevBandwidthClear as the TAP devices were removed with
>qemu process tearing down. However, this clears just qemu domains and
>left LXC containers uncleared.

I¹ll take care of it in my next patch. Thanks.

Anirban





More information about the libvir-list mailing list