<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>
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>
#include "virterror_internal.h"
#include "util.h"
#include "memory.h"
+#include "domain_conf.h"
#define VIR_FROM_THIS VIR_FROM_NONE
char *average = NULL;
char *peak = NULL;
char *burst = NULL;
+ char *floor = NULL;
if (!node || !rate) {
virReportError(VIR_ERR_INVALID_ARG, "%s",
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;
}
/**
* 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;
/* 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) {
/* 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;
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");