[PATCH v2 1/2] conf: Introduce virNetDevBandwidthValidate()

Michal Privoznik posted 2 patches 3 months, 1 week ago
[PATCH v2 1/2] conf: Introduce virNetDevBandwidthValidate()
Posted by Michal Privoznik 3 months, 1 week ago
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@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