[libvirt] [PATCH 3/9] bridge_driver: Introduce networkBandwidthChangeAllowed

John Ferlan jferlan at redhat.com
Mon Aug 10 21:46:34 UTC 2015



On 08/03/2015 02:39 AM, Michal Privoznik wrote:
> When a domain vNIC's bandwidth is to be changed (at runtime) it is
> possible that guaranteed minimal bandwidth (@floor) will change too.
> Well, so far it is, because we still don't have an implementation that
> allows setting it dynamically, so it's effectively erased on:
> 
>     #virsh domiftune $dom vnet0 --inbound 0
> 
> However, that's slightly unfortunate. We do some checks on domain
> startup to see if @floor can be guaranteed. We ought do the same if
> QoS is changed at runtime.
> 
> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
> ---
>  src/network/bridge_driver.c | 72 +++++++++++++++++++++++++++++++++++++++++++--
>  src/network/bridge_driver.h | 12 ++++++++
>  2 files changed, 82 insertions(+), 2 deletions(-)
> 
> diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
> index 17fc430..fa60ba4 100644
> --- a/src/network/bridge_driver.c
> +++ b/src/network/bridge_driver.c
> @@ -4686,9 +4686,18 @@ networkGetNetworkAddress(const char *netname, char **netaddr)
>   * networkCheckBandwidth:
>   * @net: network QoS
>   * @ifaceBand: interface QoS (may be NULL if no QoS)
> + * @oldBandwidth: new interface QoS (may be NULL if no QoS)
>   * @ifaceMac: interface MAC (used in error messages for identification)
>   * @new_rate: new rate for non guaranteed class
>   *
> + * Function checks if @ifaceBand can be satisfied on @net. However, sometimes it
> + * may happen that the interface that @ifaceBand corresponds to is already
> + * plugged into the @net and the bandwidth is to be updated. In that case we
> + * need to check if new bandwidth can be satisfied. If that's the case
> + * @ifaceBand should point to new bandwidth settings and @oldBandwidth to
> + * current ones. If you want to suppress this functionality just pass
> + * @oldBandwidth == NULL.
> + *
>   * Returns: -1 if plugging would overcommit network QoS
>   *           0 if plugging is safe (@new_rate updated)
>   *           1 if no QoS is set (@new_rate untouched)

new_rate is unchanged if passed as NULL too

Part of me says - who cares - just set it and let the caller decide -
both paths will "always have" that extra "if" check now... and it only
ever matters if plugging is safe.

I'm OK keeping as is - so I'll ACK and let you decide. At the very least
point out that new_rate can be NULL in the comments. I'm guessing that
if the caller that has it NULL had a value, then there'd be a warning
about an unused variable...

John
> @@ -4696,6 +4705,7 @@ networkGetNetworkAddress(const char *netname, char **netaddr)
>  static int
>  networkCheckBandwidth(virNetworkObjPtr net,
>                        virNetDevBandwidthPtr ifaceBand,
> +                      virNetDevBandwidthPtr oldBandwidth,
>                        virMacAddr ifaceMac,
>                        unsigned long long *new_rate)
>  {
> @@ -4723,6 +4733,8 @@ networkCheckBandwidth(virNetworkObjPtr net,
>      }
>  
>      tmp_new_rate = netBand->in->average;
> +    if (oldBandwidth && oldBandwidth->in)
> +        tmp_floor_sum -= oldBandwidth->in->floor;
>      tmp_floor_sum += ifaceBand->in->floor;
>  
>      /* check against peak */
> @@ -4749,7 +4761,8 @@ networkCheckBandwidth(virNetworkObjPtr net,
>          goto cleanup;
>      }
>  
> -    *new_rate = tmp_new_rate;
> +    if (new_rate)
> +        *new_rate = tmp_new_rate;
>      ret = 0;
>  
>   cleanup:
> @@ -4791,7 +4804,7 @@ networkPlugBandwidth(virNetworkObjPtr net,
>      char ifmac[VIR_MAC_STRING_BUFLEN];
>      virNetDevBandwidthPtr ifaceBand = virDomainNetGetActualBandwidth(iface);
>  
> -    if ((plug_ret = networkCheckBandwidth(net, ifaceBand,
> +    if ((plug_ret = networkCheckBandwidth(net, ifaceBand, NULL,
>                                            iface->mac, &new_rate)) < 0) {
>          /* helper reported error */
>          goto cleanup;
> @@ -4917,3 +4930,58 @@ networkNetworkObjTaint(virNetworkObjPtr net,
>                   virNetworkTaintTypeToString(taint));
>      }
>  }
> +
> +
> +static bool
> +networkBandwidthGenericChecks(virDomainNetDefPtr iface,
> +                              virNetDevBandwidthPtr newBandwidth)
> +{
> +    virNetDevBandwidthPtr ifaceBand = virDomainNetGetActualBandwidth(iface);
> +    unsigned long long old_floor, new_floor;
> +
> +    if (virDomainNetGetActualType(iface) != VIR_DOMAIN_NET_TYPE_NETWORK) {
> +        /* This is not an interface that's plugged into a network.
> +         * We don't care. Thus from our POV bandwidth change is allowed. */
> +        return false;
> +    }
> +
> +    old_floor = new_floor = 0;
> +
> +    if (ifaceBand && ifaceBand->in)
> +        old_floor = ifaceBand->in->floor;
> +    if (newBandwidth && newBandwidth->in)
> +        new_floor = newBandwidth->in->floor;
> +
> +    return new_floor != old_floor;
> +}
> +
> +
> +bool
> +networkBandwidthChangeAllowed(virDomainNetDefPtr iface,
> +                              virNetDevBandwidthPtr newBandwidth)
> +{
> +    virNetworkDriverStatePtr driver = networkGetDriver();
> +    virNetworkObjPtr network = NULL;
> +    virNetDevBandwidthPtr ifaceBand = virDomainNetGetActualBandwidth(iface);
> +    bool ret = false;
> +
> +    if (!networkBandwidthGenericChecks(iface, newBandwidth))
> +        return true;
> +
> +    network = virNetworkObjFindByName(driver->networks, iface->data.network.name);
> +    if (!network) {
> +        virReportError(VIR_ERR_NO_NETWORK,
> +                       _("no network with matching name '%s'"),
> +                       iface->data.network.name);
> +        return false;
> +    }
> +
> +    if (networkCheckBandwidth(network, newBandwidth, ifaceBand, iface->mac, NULL) < 0)
> +        goto cleanup;
> +
> +    ret = true;
> +
> + cleanup:
> +    virNetworkObjEndAPI(&network);
> +    return ret;
> +}
> diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h
> index 513ccf7..cce9237 100644
> --- a/src/network/bridge_driver.h
> +++ b/src/network/bridge_driver.h
> @@ -52,6 +52,11 @@ int networkDnsmasqConfContents(virNetworkObjPtr network,
>                          char **configstr,
>                          dnsmasqContext *dctx,
>                          dnsmasqCapsPtr caps);
> +
> +bool networkBandwidthChangeAllowed(virDomainNetDefPtr iface,
> +                                   virNetDevBandwidthPtr newBandwidth)
> +    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
> +
>  # else
>  /* Define no-op replacements that don't drag in any link dependencies.  */
>  #  define networkAllocateActualDevice(dom, iface) 0
> @@ -73,6 +78,13 @@ networkReleaseActualDevice(virDomainDefPtr dom ATTRIBUTE_UNUSED,
>      return 0;
>  }
>  
> +static inline bool
> +networkBandwidthChangeAllowed(virDomainNetDefPtr iface ATTRIBUTE_UNUSED,
> +                              virNetDevBandwidthPtr newBandwidth ATTRIBUTE_UNUSED)
> +{
> +    return true;
> +}
> +
>  # endif
>  
>  typedef char *(*networkDnsmasqLeaseFileNameFunc)(const char *netname);
> 




More information about the libvir-list mailing list