[libvirt] [PATCH 3/7] bandwidth: Add format parsing functions

Michal Privoznik mprivozn at redhat.com
Thu Jun 23 15:36:43 UTC 2011


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




More information about the libvir-list mailing list