These functions take on input decimal numbers optionally followed
by unit. Units are exactly the same as 'tc' accepts.
---
src/conf/domain_conf.c | 3 +
src/conf/domain_conf.h | 1 +
src/conf/network_conf.c | 5 +
src/conf/network_conf.h | 1 +
src/libvirt_private.syms | 1 +
src/util/network.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++
src/util/network.h | 2 +
7 files changed, 216 insertions(+), 0 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3d290fb..b7c88c8 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2838,6 +2838,9 @@ virDomainNetDefParseXML(virCapsPtr caps,
if (virDomainDeviceBootParseXML(cur, &def->bootIndex,
bootMap))
goto error;
+ } else if (xmlStrEqual(cur->name, BAD_CAST "bandwidth")) {
+ if (virBandwidthDefParseNode(cur, &def->bandwidth) < 0)
+ goto error;
}
}
cur = cur->next;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index aa25e36..25fafee 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -398,6 +398,7 @@ struct _virDomainNetDef {
virDomainDeviceInfo info;
char *filter;
virNWFilterHashTablePtr filterparams;
+ virBandwidth bandwidth;
};
enum virDomainChrDeviceType {
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index e4765ea..ef5d31e 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -584,6 +584,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
virNetworkDefPtr def;
char *tmp;
xmlNodePtr *ipNodes = NULL;
+ xmlNodePtr bandwidthNode = NULL;
int nIps;
if (VIR_ALLOC(def) < 0) {
@@ -619,6 +620,10 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
/* Parse network domain information */
def->domain = virXPathString("string(./domain[1]/@name)", ctxt);
+ if ((bandwidthNode = virXPathNode("./bandwidth", ctxt)) != NULL &&
+ virBandwidthDefParseNode(bandwidthNode, &def->bandwidth) < 0)
+ goto error;
+
/* Parse bridge information */
def->bridge = virXPathString("string(./bridge[1]/@name)", ctxt);
tmp = virXPathString("string(./bridge[1]/@stp)", ctxt);
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 281124b..65fbedd 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -101,6 +101,7 @@ struct _virNetworkDef {
size_t nips;
virNetworkIpDefPtr ips; /* ptr to array of IP addresses on this network */
+ virBandwidth bandwidth;
};
typedef struct _virNetworkObj virNetworkObj;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d9d3913..a2c8470 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -681,6 +681,7 @@ nlComm;
# network.h
+virBandwidthDefParseNode;
virSocketAddrBroadcast;
virSocketAddrBroadcastByPrefix;
virSocketAddrIsNetmask;
diff --git a/src/util/network.c b/src/util/network.c
index eb16e0c..476ecde 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -10,6 +10,7 @@
#include <config.h>
#include <arpa/inet.h>
+#include <math.h>
#include "memory.h"
#include "network.h"
@@ -21,6 +22,9 @@
virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \
__FUNCTION__, __LINE__, __VA_ARGS__)
+#define virBandwidthError(code, ...) \
+ virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \
+ __FUNCTION__, __LINE__, __VA_ARGS__)
/*
* Helpers to extract the IP arrays from the virSocketAddrPtr
* That part is the less portable of the module
@@ -674,3 +678,202 @@ virSocketAddrPrefixToNetmask(unsigned int prefix,
error:
return result;
}
+
+static const struct rate_suffix {
+ const char *name;
+ double scale;
+} suffixes[] = {
+ { "bit", 1. },
+ { "Kibit", 1024. },
+ { "kbit", 1000. },
+ { "mibit", 1024.*1024. },
+ { "mbit", 1000.*1000. },
+ { "gibit", 1024.*1024.*1024. },
+ { "gbit", 1000.*1000.*1000. },
+ { "tibit", 1024.*1024.*1024.*1024. },
+ { "tbit", 1000.*1000.*1000.*1000. },
+ { "Bps", 8. },
+ { "KiBps", 8.*1024. },
+ { "KBps", 8.*1000. },
+ { "MiBps", 8.*1024.*1024. },
+ { "MBps", 8.*1000.*1000. },
+ { "GiBps", 8.*1024.*1024.*1024. },
+ { "GBps", 8.*1000.*1000.*1000. },
+ { "TiBps", 8.*1024.*1024.*1024.*1024. },
+ { "TBps", 8.*1000.*1000.*1000.*1000. },
+ { NULL, 0 }
+};
+
+static int
+virRateToBps(const char *str, unsigned long *rate)
+{
+ char *p;
+ double bps;
+ const struct rate_suffix *s;
+
+ if (virStrToDouble(str, &p, &bps) < 0)
+ return -1;
+
+ if (p == str)
+ return -1;
+
+ if (*p == '\0') {
+ *rate = bps / 8.; /* assume bytes/sec */
+ return 0;
+ }
+
+ for (s = suffixes; s->name; ++s) {
+ if (STRCASEEQ(s->name, p)) {
+ *rate = (bps * s->scale) / 8.;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static int
+virSizeToB(const char *str, unsigned long *size)
+{
+ double sz;
+ char *p;
+
+ if (virStrToDouble(str, &p, &sz) < 0)
+ return -1;
+
+ if (p == str)
+ return -1;
+
+ if (*p) {
+ if (STRCASEEQ(p, "kb") || STRCASEEQ(p, "k"))
+ sz *= 1024;
+ else if (STRCASEEQ(p, "gb") || STRCASEEQ(p, "g"))
+ sz *= 1024*1024*1024;
+ else if (STRCASEEQ(p, "gbit"))
+ sz *= 1024*1024*1024/8;
+ else if (STRCASEEQ(p, "mb") || STRCASEEQ(p, "m"))
+ sz *= 1024*1024;
+ else if (STRCASEEQ(p, "mbit"))
+ sz *= 1024*1024/8;
+ else if (STRCASEEQ(p, "kbit"))
+ sz *= 1024/8;
+ else if (STRCASENEQ(p, "b"))
+ return -1;
+ }
+
+ *size = sz;
+ return 0;
+}
+
+static int
+virBandwidthParseChildDefNode(xmlNodePtr node, virRatePtr rate)
+{
+ int ret = -1;
+ char *average = NULL;
+ char *peak = NULL;
+ char *burst = NULL;
+
+ if (!node || !rate)
+ return -1;
+
+ average = virXMLPropString(node, "average");
+ peak = virXMLPropString(node, "peak");
+ burst = virXMLPropString(node, "burst");
+
+ if (average) {
+ if (virRateToBps(average, &rate->average) < 0) {
+ virBandwidthError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("could not convert %s"),
+ average);
+ goto cleanup;
+ }
+ } else {
+ virBandwidthError(VIR_ERR_XML_DETAIL, "%s",
+ _("Missing mandatory average attribute"));
+ goto cleanup;
+ }
+
+ if (peak && virRateToBps(peak, &rate->peak) < 0) {
+ virBandwidthError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("could not convert %s"),
+ peak);
+ goto cleanup;
+ }
+
+ if (burst && virSizeToB(burst, &rate->burst) < 0) {
+ virBandwidthError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("could not convert %s"),
+ burst);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(average);
+ VIR_FREE(peak);
+ VIR_FREE(burst);
+
+ return ret;
+}
+
+/**
+ * virBandwidthParseXML:
+ * @node: XML node
+ * @def: where to store the parsed result
+ *
+ * Parse bandwidth XML and store into given pointer
+ *
+ * Returns 0 on success, -1 on error.
+ */
+int
+virBandwidthDefParseNode(xmlNodePtr node, virBandwidthPtr def)
+{
+ int ret = -1;
+ xmlNodePtr cur = node->children;
+ xmlNodePtr in = NULL, out = NULL;
+
+ if (!node || !def ||
+ !xmlStrEqual(node->name, BAD_CAST "bandwidth"))
+ return -1;
+
+ memset(def, 0, sizeof(virBandwidth));
+ while (cur) {
+ if (cur->type == XML_ELEMENT_NODE) {
+ if (xmlStrEqual(cur->name, BAD_CAST "inbound")) {
+ if (in) {
+ virBandwidthError(VIR_ERR_XML_DETAIL, "%s",
+ _("Only one child <inbound> "
+ "element allowed"));
+ goto cleanup;
+ }
+ in = cur;
+ } else if (xmlStrEqual(cur->name, BAD_CAST "outbound")) {
+ if (out) {
+ virBandwidthError(VIR_ERR_XML_DETAIL, "%s",
+ _("Only one child <outbound> "
+ "element allowed"));
+ goto cleanup;
+ }
+ out = cur;
+ } else {
+ virBandwidthError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Unknown element %s"),
+ cur->name);
+ goto cleanup;
+ }
+ }
+ cur = cur->next;
+ }
+
+ if (in && virBandwidthParseChildDefNode(in, &def->in) < 0)
+ goto cleanup;
+
+ if (out && virBandwidthParseChildDefNode(out, &def->out) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+cleanup:
+ return ret;
+}
diff --git a/src/util/network.h b/src/util/network.h
index 568bca1..28a6402 100644
--- a/src/util/network.h
+++ b/src/util/network.h
@@ -20,6 +20,7 @@
# endif
# include <netdb.h>
# include <netinet/in.h>
+# include "xml.h"
typedef struct {
union {
@@ -106,4 +107,5 @@ int virSocketAddrPrefixToNetmask(unsigned int prefix,
virSocketAddrPtr netmask,
int family);
+int virBandwidthDefParseNode(xmlNodePtr node, virBandwidthPtr def);
#endif /* __VIR_NETWORK_H__ */
--
1.7.5.rc3