Change the settings from qemuDomainUpdateDeviceLive() as otherwise the
call would succeed even though nothing has changed.
Resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=1460862
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
src/qemu/qemu_hotplug.c | 13 ++++++
src/util/virnetdev.c | 103 +++++++++++++++++++++++++++++++-----------------
src/util/virnetdev.h | 3 +-
src/util/virnetdevtap.c | 2 +-
4 files changed, 83 insertions(+), 38 deletions(-)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 0b8d3d80f173..244dd5e605e6 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -2986,6 +2986,7 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
bool needLinkStateChange = false;
bool needReplaceDevDef = false;
bool needBandwidthSet = false;
+ bool needCoalesceChange = false;
int ret = -1;
int changeidx = -1;
@@ -3280,6 +3281,12 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
virDomainNetGetActualBandwidth(newdev)))
needBandwidthSet = true;
+ if (!!olddev->coalesce != !!newdev->coalesce ||
+ (olddev->coalesce && newdev->coalesce &&
+ !memcmp(olddev->coalesce, newdev->coalesce,
+ sizeof(*olddev->coalesce))))
+ needCoalesceChange = true;
+
/* FINALLY - actually perform the required actions */
if (needReconnect) {
@@ -3315,6 +3322,12 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
needReplaceDevDef = true;
}
+ if (needCoalesceChange) {
+ if (virNetDevSetCoalesce(newdev->ifname, newdev->coalesce, true) < 0)
+ goto cleanup;
+ needReplaceDevDef = true;
+ }
+
if (needLinkStateChange &&
qemuDomainChangeNetLinkState(driver, vm, olddev, newdev->linkstate) < 0) {
goto cleanup;
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index e75a1c970505..90b7bee34ae7 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -3086,7 +3086,8 @@ virNetDevGetEthtoolGFeatures(virBitmapPtr bitmap ATTRIBUTE_UNUSED,
/**
* virNetDevSetCoalesce:
* @ifname: interface name to modify
- * @coalesce: Coalesce settings to set and update
+ * @coalesce: Coalesce settings to set or update
+ * @update: Whether this is an update for existing settings or not
*
* This function sets the various coalesce settings for a given interface
* @ifname and updates them back into @coalesce.
@@ -3094,40 +3095,44 @@ virNetDevGetEthtoolGFeatures(virBitmapPtr bitmap
ATTRIBUTE_UNUSED,
* Returns 0 in case of success or -1 on failure
*/
int virNetDevSetCoalesce(const char *ifname,
- virNetDevCoalescePtr coalesce)
+ virNetDevCoalescePtr coalesce,
+ bool update)
{
int fd = -1;
int ret = -1;
struct ifreq ifr;
struct ethtool_coalesce coal = {0};
- if (!coalesce)
+ if (!coalesce && !update)
return 0;
- coal = (struct ethtool_coalesce) {
- .cmd = ETHTOOL_SCOALESCE,
- .rx_max_coalesced_frames = coalesce->rx_max_coalesced_frames,
- .rx_coalesce_usecs_irq = coalesce->rx_coalesce_usecs_irq,
- .rx_max_coalesced_frames_irq = coalesce->rx_max_coalesced_frames_irq,
- .tx_coalesce_usecs = coalesce->tx_coalesce_usecs,
- .tx_max_coalesced_frames = coalesce->tx_max_coalesced_frames,
- .tx_coalesce_usecs_irq = coalesce->tx_coalesce_usecs_irq,
- .tx_max_coalesced_frames_irq = coalesce->tx_max_coalesced_frames_irq,
- .stats_block_coalesce_usecs = coalesce->stats_block_coalesce_usecs,
- .use_adaptive_rx_coalesce = coalesce->use_adaptive_rx_coalesce,
- .use_adaptive_tx_coalesce = coalesce->use_adaptive_tx_coalesce,
- .pkt_rate_low = coalesce->pkt_rate_low,
- .rx_coalesce_usecs_low = coalesce->rx_coalesce_usecs_low,
- .rx_max_coalesced_frames_low = coalesce->rx_max_coalesced_frames_low,
- .tx_coalesce_usecs_low = coalesce->tx_coalesce_usecs_low,
- .tx_max_coalesced_frames_low = coalesce->tx_max_coalesced_frames_low,
- .pkt_rate_high = coalesce->pkt_rate_high,
- .rx_coalesce_usecs_high = coalesce->rx_coalesce_usecs_high,
- .rx_max_coalesced_frames_high = coalesce->rx_max_coalesced_frames_high,
- .tx_coalesce_usecs_high = coalesce->tx_coalesce_usecs_high,
- .tx_max_coalesced_frames_high = coalesce->tx_max_coalesced_frames_high,
- .rate_sample_interval = coalesce->rate_sample_interval,
- };
+ if (coalesce) {
+ coal = (struct ethtool_coalesce) {
+ .rx_max_coalesced_frames = coalesce->rx_max_coalesced_frames,
+ .rx_coalesce_usecs_irq = coalesce->rx_coalesce_usecs_irq,
+ .rx_max_coalesced_frames_irq = coalesce->rx_max_coalesced_frames_irq,
+ .tx_coalesce_usecs = coalesce->tx_coalesce_usecs,
+ .tx_max_coalesced_frames = coalesce->tx_max_coalesced_frames,
+ .tx_coalesce_usecs_irq = coalesce->tx_coalesce_usecs_irq,
+ .tx_max_coalesced_frames_irq = coalesce->tx_max_coalesced_frames_irq,
+ .stats_block_coalesce_usecs = coalesce->stats_block_coalesce_usecs,
+ .use_adaptive_rx_coalesce = coalesce->use_adaptive_rx_coalesce,
+ .use_adaptive_tx_coalesce = coalesce->use_adaptive_tx_coalesce,
+ .pkt_rate_low = coalesce->pkt_rate_low,
+ .rx_coalesce_usecs_low = coalesce->rx_coalesce_usecs_low,
+ .rx_max_coalesced_frames_low = coalesce->rx_max_coalesced_frames_low,
+ .tx_coalesce_usecs_low = coalesce->tx_coalesce_usecs_low,
+ .tx_max_coalesced_frames_low = coalesce->tx_max_coalesced_frames_low,
+ .pkt_rate_high = coalesce->pkt_rate_high,
+ .rx_coalesce_usecs_high = coalesce->rx_coalesce_usecs_high,
+ .rx_max_coalesced_frames_high = coalesce->rx_max_coalesced_frames_high,
+ .tx_coalesce_usecs_high = coalesce->tx_coalesce_usecs_high,
+ .tx_max_coalesced_frames_high = coalesce->tx_max_coalesced_frames_high,
+ .rate_sample_interval = coalesce->rate_sample_interval,
+ };
+ }
+
+ coal.cmd = ETHTOOL_SCOALESCE;
if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
return -1;
@@ -3141,12 +3146,36 @@ int virNetDevSetCoalesce(const char *ifname,
goto cleanup;
}
- coal = (struct ethtool_coalesce) {
- .cmd = ETHTOOL_GCOALESCE,
- };
+ if (coalesce) {
+ coal = (struct ethtool_coalesce) {
+ .cmd = ETHTOOL_GCOALESCE,
+ };
- /* Don't fail if the update itself fails */
- virNetDevSendEthtoolIoctl(fd, &ifr);
+ /* Don't fail if the update itself fails */
+ if (virNetDevSendEthtoolIoctl(fd, &ifr) == 0) {
+ coalesce->rx_max_coalesced_frames = coal.rx_max_coalesced_frames;
+ coalesce->rx_coalesce_usecs_irq = coal.rx_coalesce_usecs_irq;
+ coalesce->rx_max_coalesced_frames_irq = coal.rx_max_coalesced_frames_irq;
+ coalesce->tx_coalesce_usecs = coal.tx_coalesce_usecs;
+ coalesce->tx_max_coalesced_frames = coal.tx_max_coalesced_frames;
+ coalesce->tx_coalesce_usecs_irq = coal.tx_coalesce_usecs_irq;
+ coalesce->tx_max_coalesced_frames_irq = coal.tx_max_coalesced_frames_irq;
+ coalesce->stats_block_coalesce_usecs = coal.stats_block_coalesce_usecs;
+ coalesce->use_adaptive_rx_coalesce = coal.use_adaptive_rx_coalesce;
+ coalesce->use_adaptive_tx_coalesce = coal.use_adaptive_tx_coalesce;
+ coalesce->pkt_rate_low = coal.pkt_rate_low;
+ coalesce->rx_coalesce_usecs_low = coal.rx_coalesce_usecs_low;
+ coalesce->rx_max_coalesced_frames_low = coal.rx_max_coalesced_frames_low;
+ coalesce->tx_coalesce_usecs_low = coal.tx_coalesce_usecs_low;
+ coalesce->tx_max_coalesced_frames_low = coal.tx_max_coalesced_frames_low;
+ coalesce->pkt_rate_high = coal.pkt_rate_high;
+ coalesce->rx_coalesce_usecs_high = coal.rx_coalesce_usecs_high;
+ coalesce->rx_max_coalesced_frames_high =
coal.rx_max_coalesced_frames_high;
+ coalesce->tx_coalesce_usecs_high = coal.tx_coalesce_usecs_high;
+ coalesce->tx_max_coalesced_frames_high =
coal.tx_max_coalesced_frames_high;
+ coalesce->rate_sample_interval = coal.rate_sample_interval;
+ }
+ }
ret = 0;
cleanup:
@@ -3155,9 +3184,10 @@ int virNetDevSetCoalesce(const char *ifname,
}
# else
int virNetDevSetCoalesce(const char *ifname,
- virNetDevCoalescePtr coalesce)
+ virNetDevCoalescePtr coalesce,
+ bool update)
{
- if (!coalesce)
+ if (!coalesce && !update)
return 0;
virReportSystemError(ENOSYS,
@@ -3216,9 +3246,10 @@ virNetDevGetFeatures(const char *ifname ATTRIBUTE_UNUSED,
}
int virNetDevSetCoalesce(const char *ifname,
- virNetDevCoalescePtr coalesce)
+ virNetDevCoalescePtr coalesce,
+ bool update)
{
- if (!coalesce)
+ if (!coalesce && !update)
return 0;
virReportSystemError(ENOSYS,
diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h
index c7494cd608f3..51fcae544e89 100644
--- a/src/util/virnetdev.h
+++ b/src/util/virnetdev.h
@@ -180,7 +180,8 @@ int virNetDevRestoreMacAddress(const char *linkdev,
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
int virNetDevSetCoalesce(const char *ifname,
- virNetDevCoalescePtr coalesce)
+ virNetDevCoalescePtr coalesce,
+ bool update)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
int virNetDevSetMTU(const char *ifname,
diff --git a/src/util/virnetdevtap.c b/src/util/virnetdevtap.c
index c8dacfe27b94..175dc2bfaae3 100644
--- a/src/util/virnetdevtap.c
+++ b/src/util/virnetdevtap.c
@@ -663,7 +663,7 @@ int virNetDevTapCreateInBridgePort(const char *brname,
if (virNetDevSetOnline(*ifname, !!(flags & VIR_NETDEV_TAP_CREATE_IFUP)) < 0)
goto error;
- if (virNetDevSetCoalesce(*ifname, coalesce) < 0)
+ if (virNetDevSetCoalesce(*ifname, coalesce, false) < 0)
goto error;
return 0;
--
2.13.1