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@xxxxxxxxxx> --- 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