This function validates whether parsed limits are within range as
defined by 'tc' sources (since we use tc to set QoS; or OVS which
then uses tc too). The 'tc' program stores speeds in 64bit
integers (unit is bytes per second) and sizes in uints (unit is
bytes). We use different units: kilobytes per second and
kibibytes and therefore we can parse values larger than 'tc' can
handle and thus need a function to check if values still fit.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/conf/netdev_bandwidth_conf.c | 42 ++++++++++++++++++++++++++++++++
src/conf/netdev_bandwidth_conf.h | 2 ++
src/libvirt_private.syms | 1 +
3 files changed, 45 insertions(+)
diff --git a/src/conf/netdev_bandwidth_conf.c b/src/conf/netdev_bandwidth_conf.c
index 9faa46a27f..43a2c62240 100644
--- a/src/conf/netdev_bandwidth_conf.c
+++ b/src/conf/netdev_bandwidth_conf.c
@@ -200,6 +200,48 @@ virNetDevBandwidthFormat(const virNetDevBandwidth *def,
}
+#define CHECK_LIMIT(val, limit, name) \
+ do { \
+ if ((val) > (limit)) { \
+ virReportError(VIR_ERR_OVERFLOW, \
+ _("value '%1$llu' is too big for '%2$s'
parameter, maximum is '%3$llu'"), \
+ val, name, (unsigned long long) limit); \
+ return false; \
+ } \
+ } while (0)
+
+static bool
+virNetDevBandwidthRateValidate(const virNetDevBandwidthRate *rate)
+{
+ const unsigned long long speedLimit = 1ULL << 54;
+ const unsigned int sizeLimit = UINT_MAX >> 10;
+
+ /* These limits are taken straight from 'tc' sources. */
+
+ if (!rate)
+ return true;
+
+ CHECK_LIMIT(rate->average, speedLimit, "average");
+ CHECK_LIMIT(rate->peak, speedLimit, "peak");
+ CHECK_LIMIT(rate->burst, sizeLimit, "burst");
+ CHECK_LIMIT(rate->floor, speedLimit, "floor");
+
+ return true;
+}
+
+#undef CHECK_LIMIT
+
+bool
+virNetDevBandwidthValidate(const virNetDevBandwidth *def)
+{
+ if (!def)
+ return true;
+
+ return virNetDevBandwidthRateValidate(def->in) &&
+ virNetDevBandwidthRateValidate(def->out);
+}
+
+
bool virNetDevSupportsBandwidth(virDomainNetType type)
{
switch ((virDomainNetType) type) {
diff --git a/src/conf/netdev_bandwidth_conf.h b/src/conf/netdev_bandwidth_conf.h
index b679b0f51f..6dbe0298f6 100644
--- a/src/conf/netdev_bandwidth_conf.h
+++ b/src/conf/netdev_bandwidth_conf.h
@@ -34,6 +34,8 @@ int virNetDevBandwidthFormat(const virNetDevBandwidth *def,
unsigned int class_id,
virBuffer *buf);
+bool virNetDevBandwidthValidate(const virNetDevBandwidth *def);
+
bool virNetDevSupportsBandwidth(virDomainNetType type);
bool virNetDevBandwidthHasFloor(const virNetDevBandwidth *b);
bool virNetDevBandwidthSupportsFloor(virNetworkForwardType type);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0accca442a..7a5df5a6a4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -825,6 +825,7 @@ virNetDevBandwidthFormat;
virNetDevBandwidthHasFloor;
virNetDevBandwidthParse;
virNetDevBandwidthSupportsFloor;
+virNetDevBandwidthValidate;
virNetDevSupportsBandwidth;
--
2.44.2