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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list