[libvirt] [PATCH v3 2/8] bandwidth: add new 'floor' attribute

Laine Stump laine at laine.org
Tue Dec 11 16:28:45 UTC 2012


On 12/11/2012 11:09 AM, Michal Privoznik wrote:
> This is however supported only on domain interfaces with
> type='network'. Moreover, target network needs to have at least
> inbound QoS set. This is required by hierarchical traffic shaping.
>
> >From now on, the required attribute for <inbound/> is either 'average'
> (old) or 'floor' (new). This new attribute can be used just for
> interfaces type of network (<interface type='network'/>) currently.
> ---
>  docs/formatdomain.html.in        |   23 +++++++++++--
>  docs/schemas/networkcommon.rng   |    5 +++
>  src/conf/domain_conf.c           |    6 ++-
>  src/conf/netdev_bandwidth_conf.c |   67 ++++++++++++++++++++++++++++++++------
>  src/conf/netdev_bandwidth_conf.h |    3 +-
>  src/conf/network_conf.c          |    4 +-
>  src/util/virnetdevbandwidth.h    |    1 +
>  7 files changed, 90 insertions(+), 19 deletions(-)
>
> diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
> index c81af8a..8e234fd 100644
> --- a/docs/formatdomain.html.in
> +++ b/docs/formatdomain.html.in
> @@ -3080,7 +3080,7 @@ qemu-kvm -net nic,model=? /dev/null
>        <source network='default'/>
>        <target dev='vnet0'/>
>        <b><bandwidth>
> -        <inbound average='1000' peak='5000' burst='1024'/>
> +        <inbound average='1000' peak='5000' floor='200' burst='1024'/>
>          <outbound average='128' peak='256' burst='256'/>
>        </bandwidth></b>
>      </interface>
> @@ -3095,14 +3095,29 @@ qemu-kvm -net nic,model=? /dev/null
>        children element out result in no QoS applied on that traffic direction.
>        So, when you want to shape only domain's incoming traffic, use
>        <code>inbound</code> only, and vice versa. Each of these elements have one
> -      mandatory attribute <code>average</code>. It specifies average bit rate on
> -      interface being shaped. Then there are two optional attributes:
> +      mandatory attribute <code>average</code> (or <code>floor</code> as
> +      described below). <code>average</code> specifies average bit rate on
> +      the interface being shaped. Then there are two optional attributes:
>        <code>peak</code>, which specifies maximum rate at which interface can send
>        data, and <code>burst</code>, amount of bytes that can be burst at
>        <code>peak</code> speed. Accepted values for attributes are integer
>        numbers. The units for <code>average</code> and <code>peak</code> attributes
>        are kilobytes per second, and for the <code>burst</code> just kilobytes.
> -      <span class="since">Since 0.9.4</span>
> +      <span class="since">Since 0.9.4</span> The <code>inbound</code> can
> +      optionally have <code>floor</code> attribute. This is there for
> +      guaranteeing minimal throughput for shaped interfaces. This, however,
> +      requires that all traffic goes through one point where QoS decisions can
> +      take place. That's why this attribute works only for virtual networks for
> +      now (that is <code><interface type='network'/></code> with a
> +      forward type of route, nat, or no forward at all). Moreover, the
> +      virtual network the interface is connected to is required to have at least
> +      inbound QoS set (<code>average</code> at least). Moreover, with
> +      <code>floor<code> attribute users don't need to specify
> +      <code>average</code>. However, <code>peak</code> and <code>burst</code>
> +      attributes still require <code>average</code>. Currently, linux kernel
> +      doesn't allow ingress qdiscs to have any classes therefore
> +      <code>floor</code> can be applied only on <code>inbound</code> and not
> +      </code>outbound</code>. <span class="since">Since 1.0.1</span>
>      </p>
>  
>      <h5><a name="elementVlanTag">Setting VLAN tag (on supported network types only)</a></h5>
> diff --git a/docs/schemas/networkcommon.rng b/docs/schemas/networkcommon.rng
> index c7749e7..51ff759 100644
> --- a/docs/schemas/networkcommon.rng
> +++ b/docs/schemas/networkcommon.rng
> @@ -149,6 +149,11 @@
>        </attribute>
>      </optional>
>      <optional>
> +      <attribute name="floor">
> +        <ref name="speed"/>
> +      </attribute>
> +    </optional>
> +    <optional>
>        <attribute name='burst'>
>          <ref name="BurstSize"/>
>        </attribute>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 6aa5f79..18e65ca 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -4823,7 +4823,8 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
>  
>      bandwidth_node = virXPathNode("./bandwidth", ctxt);
>      if (bandwidth_node &&
> -        !(actual->bandwidth = virNetDevBandwidthParse(bandwidth_node)))
> +        !(actual->bandwidth = virNetDevBandwidthParse(bandwidth_node,
> +                                                      actual->type)))
>          goto error;
>  
>      vlanNode = virXPathNode("./vlan", ctxt);
> @@ -5011,7 +5012,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
>                      goto error;
>                  }
>              } else if (xmlStrEqual(cur->name, BAD_CAST "bandwidth")) {
> -                if (!(def->bandwidth = virNetDevBandwidthParse(cur)))
> +                if (!(def->bandwidth = virNetDevBandwidthParse(cur,
> +                                                               def->type)))
>                      goto error;
>              } else if (xmlStrEqual(cur->name, BAD_CAST "vlan")) {
>                  if (virNetDevVlanParse(cur, ctxt, &def->vlan) < 0)
> diff --git a/src/conf/netdev_bandwidth_conf.c b/src/conf/netdev_bandwidth_conf.c
> index 5802eba..15840b9 100644
> --- a/src/conf/netdev_bandwidth_conf.c
> +++ b/src/conf/netdev_bandwidth_conf.c
> @@ -26,6 +26,7 @@
>  #include "virterror_internal.h"
>  #include "util.h"
>  #include "memory.h"
> +#include "domain_conf.h"
>  
>  #define VIR_FROM_THIS VIR_FROM_NONE
>  
> @@ -36,6 +37,7 @@ virNetDevBandwidthParseRate(xmlNodePtr node, virNetDevBandwidthRatePtr rate)
>      char *average = NULL;
>      char *peak = NULL;
>      char *burst = NULL;
> +    char *floor = NULL;
>  
>      if (!node || !rate) {
>          virReportError(VIR_ERR_INVALID_ARG, "%s",
> @@ -46,40 +48,55 @@ virNetDevBandwidthParseRate(xmlNodePtr node, virNetDevBandwidthRatePtr rate)
>      average = virXMLPropString(node, "average");
>      peak = virXMLPropString(node, "peak");
>      burst = virXMLPropString(node, "burst");
> +    floor = virXMLPropString(node, "floor");
>  
>      if (average) {
>          if (virStrToLong_ull(average, NULL, 10, &rate->average) < 0) {
>              virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> -                           _("could not convert %s"),
> +                           _("could not convert bandwidth average value '%s'"),
>                             average);
>              goto cleanup;
>          }
> -    } else {
> +    } else if (!floor) {
>          virReportError(VIR_ERR_XML_DETAIL, "%s",
> -                       _("Missing mandatory average attribute"));
> +                       _("Missing mandatory average or floor attributes"));
> +        goto cleanup;
> +    }
> +
> +    if ((peak || burst) && !average) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                       _("'peak' and 'burst' require 'average' attribute"));
>          goto cleanup;
>      }
>  
>      if (peak && virStrToLong_ull(peak, NULL, 10, &rate->peak) < 0) {
>          virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> -                       _("could not convert %s"),
> +                       _("could not convert bandwidth peak value '%s'"),
>                         peak);
>          goto cleanup;
>      }
>  
>      if (burst && virStrToLong_ull(burst, NULL, 10, &rate->burst) < 0) {
>          virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> -                       _("could not convert %s"),
> +                       _("could not convert bandwidth burst value '%s'"),
>                         burst);
>          goto cleanup;
>      }
>  
> +    if (floor && virStrToLong_ull(floor, NULL, 10, &rate->floor) < 0) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                       _("could not convert bandwidth floor value '%s'"),
> +                       floor);
> +        goto cleanup;
> +    }
> +
>      ret = 0;
>  
>  cleanup:
>      VIR_FREE(average);
>      VIR_FREE(peak);
>      VIR_FREE(burst);
> +    VIR_FREE(floor);
>  
>      return ret;
>  }
> @@ -87,13 +104,17 @@ cleanup:
>  /**
>   * virNetDevBandwidthParse:
>   * @node: XML node
> + * @net_type: one of virDomainNetType
>   *
> - * Parse bandwidth XML and return pointer to structure
> + * Parse bandwidth XML and return pointer to structure.
> + * @net_type tell to which type will/is interface connected to.
> + * Pass -1 if this is not called on interface.
>   *
>   * Returns !NULL on success, NULL on error.
>   */
>  virNetDevBandwidthPtr
> -virNetDevBandwidthParse(xmlNodePtr node)
> +virNetDevBandwidthParse(xmlNodePtr node,
> +                        int net_type)
>  {
>      virNetDevBandwidthPtr def = NULL;
>      xmlNodePtr cur;
> @@ -146,6 +167,20 @@ virNetDevBandwidthParse(xmlNodePtr node)
>              /* helper reported error for us */
>              goto error;
>          }
> +
> +        if (def->in->floor && net_type != VIR_DOMAIN_NET_TYPE_NETWORK) {
> +            if (net_type == -1) {
> +                /* 'floor' on network isn't supported */
> +                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                               _("floor attribute isn't supported for "
> +                                 "network's bandwidth yet"));
> +            } else {
> +                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                               _("floor attribute is supported only for "
> +                                 "interfaces of type network"));
> +            }
> +            goto error;
> +        }
>      }
>  
>      if (out) {
> @@ -158,6 +193,13 @@ virNetDevBandwidthParse(xmlNodePtr node)
>              /* helper reported error for us */
>              goto error;
>          }
> +
> +        if (def->out->floor) {
> +            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                           _("'floor' attribute allowed "
> +                             "only in <inbound> element"));
> +            goto error;
> +        }
>      }
>  
>      return def;
> @@ -177,13 +219,18 @@ virNetDevBandwidthRateFormat(virNetDevBandwidthRatePtr def,
>      if (!def)
>          return 0;
>  
> -    if (def->average) {
> -        virBufferAsprintf(buf, "  <%s average='%llu'", elem_name,
> -                          def->average);
> +    if (def->average || def->floor) {
> +        virBufferAsprintf(buf, "  <%s", elem_name);
> +
> +        if (def->average)
> +            virBufferAsprintf(buf, " average='%llu'", def->average);
>  
>          if (def->peak)
>              virBufferAsprintf(buf, " peak='%llu'", def->peak);
>  
> +        if (def->floor)
> +            virBufferAsprintf(buf, " floor='%llu'", def->floor);
> +
>          if (def->burst)
>              virBufferAsprintf(buf, " burst='%llu'", def->burst);
>          virBufferAddLit(buf, "/>\n");
> diff --git a/src/conf/netdev_bandwidth_conf.h b/src/conf/netdev_bandwidth_conf.h
> index bca5c50..0080165 100644
> --- a/src/conf/netdev_bandwidth_conf.h
> +++ b/src/conf/netdev_bandwidth_conf.h
> @@ -28,7 +28,8 @@
>  # include "buf.h"
>  # include "xml.h"
>  
> -virNetDevBandwidthPtr virNetDevBandwidthParse(xmlNodePtr node)
> +virNetDevBandwidthPtr virNetDevBandwidthParse(xmlNodePtr node,
> +                                              int net_type)
>      ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
>  int virNetDevBandwidthFormat(virNetDevBandwidthPtr def,
>                               virBufferPtr buf)
> diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
> index 7220659..3093418 100644
> --- a/src/conf/network_conf.c
> +++ b/src/conf/network_conf.c
> @@ -1192,7 +1192,7 @@ virNetworkPortGroupParseXML(virPortGroupDefPtr def,
>  
>      bandwidth_node = virXPathNode("./bandwidth", ctxt);
>      if (bandwidth_node &&
> -        !(def->bandwidth = virNetDevBandwidthParse(bandwidth_node))) {
> +        !(def->bandwidth = virNetDevBandwidthParse(bandwidth_node, -1))) {
>          goto error;
>      }
>  
> @@ -1285,7 +1285,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
>      def->domain = virXPathString("string(./domain[1]/@name)", ctxt);
>  
>      if ((bandwidthNode = virXPathNode("./bandwidth", ctxt)) != NULL &&
> -        (def->bandwidth = virNetDevBandwidthParse(bandwidthNode)) == NULL)
> +        (def->bandwidth = virNetDevBandwidthParse(bandwidthNode, -1)) == NULL)
>          goto error;
>  
>      vlanNode = virXPathNode("./vlan", ctxt);
> diff --git a/src/util/virnetdevbandwidth.h b/src/util/virnetdevbandwidth.h
> index e046230..35f8b89 100644
> --- a/src/util/virnetdevbandwidth.h
> +++ b/src/util/virnetdevbandwidth.h
> @@ -30,6 +30,7 @@ typedef virNetDevBandwidthRate *virNetDevBandwidthRatePtr;
>  struct _virNetDevBandwidthRate {
>      unsigned long long average;  /* kbytes/s */
>      unsigned long long peak;     /* kbytes/s */
> +    unsigned long long floor;    /* kbytes/s */
>      unsigned long long burst;    /* kbytes */
>  };
>  

ACK.




More information about the libvir-list mailing list