[libvirt] [PATCH 0/3] Add support for coalesce settings on interfaces

In linux this is supported since 4.11-rc3, I tested it with 4.11.0-rc5-next-20170407. The particular patch can be found here: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git/commit/?i... Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1414627 Martin Kletzander (3): util: Add virNetDevSetCoalesce function conf, docs: Add support for coalesce setting(s) Set coalesce settings for domain interfaces configure.ac | 3 +- docs/formatdomain.html.in | 24 ++++++ docs/schemas/domaincommon.rng | 3 + docs/schemas/networkcommon.rng | 17 ++++ src/bhyve/bhyve_command.c | 2 +- src/conf/domain_conf.c | 9 +++ src/conf/domain_conf.h | 2 + src/conf/networkcommon_conf.c | 91 ++++++++++++++++++++++ src/conf/networkcommon_conf.h | 9 +++ src/libvirt_private.syms | 3 + src/network/bridge_driver.c | 2 +- src/qemu/qemu_domain.c | 31 ++++++++ src/qemu/qemu_interface.c | 2 +- src/uml/uml_conf.c | 2 +- src/util/virnetdev.c | 83 ++++++++++++++++++++ src/util/virnetdev.h | 34 ++++++++ src/util/virnetdevtap.c | 8 +- src/util/virnetdevtap.h | 2 + tests/bhyvexml2argvmock.c | 1 + .../qemuxml2argvdata/qemuxml2argv-net-coalesce.xml | 64 +++++++++++++++ .../qemuxml2xmlout-net-coalesce.xml | 69 ++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 22 files changed, 456 insertions(+), 6 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-coalesce.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-net-coalesce.xml -- 2.12.2

That function is able to configure coalesce settings for an interface, similarly to 'ethtool -C'. This function also updates back the structure so that it contains actual data on the device (if the device doesn't support some settings kernel might just return 0 and not set whatever is not supported), so this way we'll have up-to-date information in the live domain XML. Signed-off-by: Martin Kletzander <mkletzan@redhat.com> --- configure.ac | 3 +- src/libvirt_private.syms | 1 + src/util/virnetdev.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++ src/util/virnetdev.h | 34 ++++++++++++++++++++ 4 files changed, 120 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 383493836bff..5f7a07a2a67a 100644 --- a/configure.ac +++ b/configure.ac @@ -347,7 +347,8 @@ AC_CHECK_TYPE([struct sockpeercred], ]]) AC_CHECK_DECLS([ETH_FLAG_TXVLAN, ETH_FLAG_NTUPLE, ETH_FLAG_RXHASH, ETH_FLAG_LRO, - ETHTOOL_GGSO, ETHTOOL_GGRO, ETHTOOL_GFLAGS, ETHTOOL_GFEATURES], + ETHTOOL_GGSO, ETHTOOL_GGRO, ETHTOOL_GFLAGS, ETHTOOL_GFEATURES, + ETHTOOL_SCOALESCE, ETHTOOL_GCOALESCE], [], [], [[#include <linux/ethtool.h> ]]) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 49d49db81265..7ba9b7d98d86 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2062,6 +2062,7 @@ virNetDevRxFilterModeTypeFromString; virNetDevRxFilterModeTypeToString; virNetDevRxFilterNew; virNetDevSaveNetConfig; +virNetDevSetCoalesce; virNetDevSetMAC; virNetDevSetMTU; virNetDevSetMTUFromDevice; diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index 170e34827f12..6ff1b489857d 100644 --- a/src/util/virnetdev.c +++ b/src/util/virnetdev.c @@ -3078,6 +3078,89 @@ virNetDevGetEthtoolGFeatures(virBitmapPtr bitmap ATTRIBUTE_UNUSED, # endif +# if HAVE_DECL_ETHTOOL_SCOALESCE && HAVE_DECL_ETHTOOL_GCOALESCE +/** + * virNetDevSetCoalesce: + * @ifname: interface name to modify + * @coalesce: Coalesce settings to set and update + * + * This function sets the various coalesce settings for a given interface + * @ifname and updates them back into @coalesce. + * + * Returns 0 in case of success or -1 on failure + */ +int virNetDevSetCoalesce(const char *ifname, + virNetDevCoalescePtr coalesce) +{ + int fd = -1; + int ret = -1; + struct ifreq ifr; + struct ethtool_coalesce coal = {0}; + + if (!coalesce) + 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 ((fd = virNetDevSetupControl(ifname, &ifr)) < 0) + return -1; + + ifr.ifr_data = (void *) &coal; + + if (virNetDevSendEthtoolIoctl(fd, &ifr) < 0) { + virReportSystemError(errno, + _("Cannot set coalesce info on '%s'"), + ifname); + goto cleanup; + } + + coal = (struct ethtool_coalesce) { + .cmd = ETHTOOL_GCOALESCE, + }; + + /* Don't fail if the update itself fails */ + virNetDevSendEthtoolIoctl(fd, &ifr); + + ret = 0; + cleanup: + VIR_FORCE_CLOSE(fd); + return ret; +} +# else +int virNetDevSetCoalesce(const char *ifname, + virNetDevCoalescePtr coalesce ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, + _("Cannot set coalesce info on interface '%s'"), + ifname); + return -1; +} +# endif + + /** * virNetDevGetFeatures: * This function gets the nic offloads features available for ifname diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h index 437a776257b6..cff8cb51c2bb 100644 --- a/src/util/virnetdev.h +++ b/src/util/virnetdev.h @@ -112,6 +112,36 @@ typedef enum { VIR_ENUM_DECL(virNetDevFeature) +/* Modeled after struct ethtool_coalesce, see linux/ethtool.h for explanations + * of particular fields */ +typedef struct _virNetDevCoalesce virNetDevCoalesce; +typedef virNetDevCoalesce *virNetDevCoalescePtr; +struct _virNetDevCoalesce { + uint32_t rx_coalesce_usecs; + uint32_t rx_max_coalesced_frames; + uint32_t rx_coalesce_usecs_irq; + uint32_t rx_max_coalesced_frames_irq; + uint32_t tx_coalesce_usecs; + uint32_t tx_max_coalesced_frames; + uint32_t tx_coalesce_usecs_irq; + uint32_t tx_max_coalesced_frames_irq; + uint32_t stats_block_coalesce_usecs; + uint32_t use_adaptive_rx_coalesce; + uint32_t use_adaptive_tx_coalesce; + uint32_t pkt_rate_low; + uint32_t rx_coalesce_usecs_low; + uint32_t rx_max_coalesced_frames_low; + uint32_t tx_coalesce_usecs_low; + uint32_t tx_max_coalesced_frames_low; + uint32_t pkt_rate_high; + uint32_t rx_coalesce_usecs_high; + uint32_t rx_max_coalesced_frames_high; + uint32_t tx_coalesce_usecs_high; + uint32_t tx_max_coalesced_frames_high; + uint32_t rate_sample_interval; +}; + + int virNetDevSetupControl(const char *ifname, virIfreq *ifr) ATTRIBUTE_RETURN_CHECK; @@ -144,6 +174,10 @@ int virNetDevRestoreMacAddress(const char *linkdev, const char *stateDir) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; +int virNetDevSetCoalesce(const char *ifname, + virNetDevCoalescePtr coalesce) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; + int virNetDevSetMTU(const char *ifname, int mtu) ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; -- 2.12.2

We are currently parsing only rx_max_coalesced_frames because that's the only value that makes sense for us. The tun device just added support for this one and the others are only supported by hardware devices which we don't need to worry about as the only way we'd pass those to the domain is using <hostdev/> or <interface type='hostdev'/>. And in those cases the guest can modify the settings itself. Signed-off-by: Martin Kletzander <mkletzan@redhat.com> --- docs/formatdomain.html.in | 24 ++++++ docs/schemas/domaincommon.rng | 3 + docs/schemas/networkcommon.rng | 17 ++++ src/conf/domain_conf.c | 9 +++ src/conf/domain_conf.h | 2 + src/conf/networkcommon_conf.c | 91 ++++++++++++++++++++++ src/conf/networkcommon_conf.h | 9 +++ src/libvirt_private.syms | 2 + src/qemu/qemu_domain.c | 31 ++++++++ .../qemuxml2argvdata/qemuxml2argv-net-coalesce.xml | 64 +++++++++++++++ .../qemuxml2xmlout-net-coalesce.xml | 69 ++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 12 files changed, 322 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-coalesce.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-net-coalesce.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index b1e38f00e423..ea64b7fd1193 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -5405,6 +5405,30 @@ qemu-kvm -net nic,model=? /dev/null <span class="since">Since 3.1.0</span> </p> + <h5><a name="coalesce">Coalesce settings</a></h5> +<pre> +... +<devices> + <interface type='network'> + <source network='default'/> + <target dev='vnet0'/> + <b><coalesce> + <rx_max_coalesced_frames>5</rx_max_coalesced_frames> + </coalesce></b> + </interface> +</devices> +...</pre> + + <p> + This element provides means of setting coalesce settings for some + interface devices (currently only type <code>network</code> + and <code>bridge</code>. Currently there is just one sub-element + named <code>rx_max_coalesced_frames</code> which accepts a non-negative + integer that specifies the maximum number of packets that will be received + before an interrupt. + <span class="since">Since 3.3.0</span> + </p> + <h5><a name="ipconfig">IP configuration</a></h5> <pre> ... diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index edc225fe50c5..b703515fb897 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2509,6 +2509,9 @@ <ref name="mtu"/> </optional> <optional> + <ref name="coalesce"/> + </optional> + <optional> <element name="target"> <attribute name="dev"> <ref name="deviceName"/> diff --git a/docs/schemas/networkcommon.rng b/docs/schemas/networkcommon.rng index 26995556d48d..27e78d13e4a6 100644 --- a/docs/schemas/networkcommon.rng +++ b/docs/schemas/networkcommon.rng @@ -275,4 +275,21 @@ </attribute> </element> </define> + + <define name="coalesce"> + <element name="coalesce"> + <interleave> + <!-- + Other parameters can just be added here the same way the + following one is. + --> + <optional> + <element name="rx_max_coalesced_frames"> + <ref name="unsignedInt"/> + </element> + </optional> + </interleave> + </element> + </define> + </grammar> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 80baa090a7f8..3cc17b5fd228 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -10251,6 +10251,13 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, goto error; } + node = virXPathNode("./coalesce", ctxt); + if (node) { + def->coalesce = virNetDevCoalesceParseXML(node, ctxt); + if (!def->coalesce) + goto error; + } + cleanup: ctxt->node = oldnode; VIR_FREE(macaddr); @@ -22144,6 +22151,8 @@ virDomainNetDefFormat(virBufferPtr buf, if (def->mtu) virBufferAsprintf(buf, "<mtu size='%u'/>\n", def->mtu); + virNetDevCoalesceFormatXML(buf, def->coalesce); + if (virDomainDeviceInfoFormat(buf, &def->info, flags | VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT | VIR_DOMAIN_DEF_FORMAT_ALLOW_ROM) < 0) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 26c0e6b88759..6c3de9cc2cd4 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -41,6 +41,7 @@ # include "numa_conf.h" # include "virnetdevmacvlan.h" # include "virsysinfo.h" +# include "virnetdev.h" # include "virnetdevip.h" # include "virnetdevvportprofile.h" # include "virnetdevbandwidth.h" @@ -1036,6 +1037,7 @@ struct _virDomainNetDef { int trustGuestRxFilters; /* enum virTristateBool */ int linkstate; unsigned int mtu; + virNetDevCoalescePtr coalesce; }; /* Used for prefix of ifname of any network name generated dynamically diff --git a/src/conf/networkcommon_conf.c b/src/conf/networkcommon_conf.c index 29e978bbdfe5..e0756da6c9ec 100644 --- a/src/conf/networkcommon_conf.c +++ b/src/conf/networkcommon_conf.c @@ -328,3 +328,94 @@ virNetDevIPRouteFormat(virBufferPtr buf, cleanup: return result; } + +virNetDevCoalescePtr +virNetDevCoalesceParseXML(xmlNodePtr node, + xmlXPathContextPtr ctxt) +{ + virNetDevCoalescePtr ret = NULL; + xmlNodePtr save = NULL; + char *str = NULL; + unsigned long long tmp = 0; + + save = ctxt->node; + ctxt->node = node; + +#define GET_COALESCE_PARAM(name) \ + do { \ + str = virXPathString("string(./" #name ")", ctxt); \ + if (!str) \ + break; \ + \ + if (!ret && VIR_ALLOC(ret) < 0) \ + return NULL; \ + \ + if (virStrToLong_ullp(str, NULL, 10, &tmp) < 0) { \ + virReportError(VIR_ERR_XML_DETAIL, \ + _("cannot parse value '%s' for parameter '%s'"), \ + str, #name); \ + VIR_FREE(str); \ + goto error; \ + } \ + VIR_FREE(str); \ + \ + if (tmp > UINT32_MAX) { \ + virReportError(VIR_ERR_OVERFLOW, \ + _("value '%llu' is too big for " #name \ + ", maximum is '%lu'"), \ + tmp, (unsigned long) UINT32_MAX); \ + goto error; \ + } \ + \ + ret->name = tmp; \ + } while (0) + + /* Just add more parameters if needed */ + + GET_COALESCE_PARAM(rx_max_coalesced_frames); + +#undef GET_COALESCE_PARAM + + cleanup: + ctxt->node = save; + return ret; + + error: + VIR_FREE(ret); + goto cleanup; +} + +void +virNetDevCoalesceFormatXML(virBufferPtr buf, + virNetDevCoalescePtr coalesce) +{ + virBuffer childrenBuf = VIR_BUFFER_INITIALIZER; + int indent = virBufferGetIndent(buf, false); + + if (!coalesce) + return; + + virBufferAdjustIndent(&childrenBuf, indent + 2); + +#define SET_COALESCE_PARAM(name) \ + do { \ + if (coalesce->name) { \ + virBufferAsprintf(&childrenBuf, \ + /* TODO: turn %u into something 32-bit compatible */ \ + "<" #name ">%u</" #name ">\n", \ + coalesce->name); \ + } \ + } while (0) + + /* Just add more parameters if needed */ + + SET_COALESCE_PARAM(rx_max_coalesced_frames); + +#undef SET_COALESCE_PARAM + + if (virBufferUse(&childrenBuf)) { + virBufferAddLit(buf, "<coalesce>\n"); + virBufferAddBuffer(buf, &childrenBuf); + virBufferAddLit(buf, "</coalesce>\n"); + } +} diff --git a/src/conf/networkcommon_conf.h b/src/conf/networkcommon_conf.h index 70e46793f67b..a842e2075292 100644 --- a/src/conf/networkcommon_conf.h +++ b/src/conf/networkcommon_conf.h @@ -32,6 +32,7 @@ # include "virbuffer.h" # include "virsocketaddr.h" # include "virnetdevip.h" +# include "virnetdev.h" virNetDevIPRoutePtr virNetDevIPRouteCreate(const char *networkName, @@ -52,4 +53,12 @@ int virNetDevIPRouteFormat(virBufferPtr buf, const virNetDevIPRoute *def); +virNetDevCoalescePtr +virNetDevCoalesceParseXML(xmlNodePtr node, + xmlXPathContextPtr ctxt); + +void +virNetDevCoalesceFormatXML(virBufferPtr buf, + virNetDevCoalescePtr coalesce); + #endif /* __NETWORKCOMMON_CONF_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 7ba9b7d98d86..7712e3d0a7f2 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -685,6 +685,8 @@ virNetworkEventStateRegisterID; # conf/networkcommon_conf.h +virNetDevCoalesceFormatXML; +virNetDevCoalesceParseXML; virNetDevIPRouteCreate; virNetDevIPRouteFormat; virNetDevIPRouteParseXML; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index a3bb7dbc9a25..ac7193c9743f 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2953,6 +2953,30 @@ qemuDomainDefValidate(const virDomainDef *def, } +static bool +qemuDomainNetSupportsCoalesce(virDomainNetType type) +{ + switch (type) { + case VIR_DOMAIN_NET_TYPE_NETWORK: + case VIR_DOMAIN_NET_TYPE_BRIDGE: + return true; + case VIR_DOMAIN_NET_TYPE_VHOSTUSER: + case VIR_DOMAIN_NET_TYPE_ETHERNET: + case VIR_DOMAIN_NET_TYPE_DIRECT: + case VIR_DOMAIN_NET_TYPE_HOSTDEV: + case VIR_DOMAIN_NET_TYPE_USER: + case VIR_DOMAIN_NET_TYPE_SERVER: + case VIR_DOMAIN_NET_TYPE_CLIENT: + case VIR_DOMAIN_NET_TYPE_MCAST: + case VIR_DOMAIN_NET_TYPE_INTERNAL: + case VIR_DOMAIN_NET_TYPE_UDP: + case VIR_DOMAIN_NET_TYPE_LAST: + break; + } + return false; +} + + static int qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev, const virDomainDef *def ATTRIBUTE_UNUSED, @@ -2987,6 +3011,13 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev, virDomainNetTypeToString(net->type)); goto cleanup; } + + if (net->coalesce && !qemuDomainNetSupportsCoalesce(net->type)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("coalesce settings on interface type %s are not supported"), + virDomainNetTypeToString(net->type)); + goto cleanup; + } } ret = 0; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-coalesce.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-coalesce.xml new file mode 100644 index 000000000000..0c44cb1c8abc --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-coalesce.xml @@ -0,0 +1,64 @@ +<domain type='qemu'> + <name>test</name> + <uuid>15d091de-0181-456b-9554-e4382dc1f1ab</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-0.13'>hvm</type> + <boot dev='cdrom'/> + <boot dev='hd'/> + <bootmenu enable='yes'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2' event_idx='on'/> + <source file='/var/lib/libvirt/images/f14.img'/> + <target dev='vda' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/var/lib/libvirt/Fedora-14-x86_64-Live-KDE.iso'/> + <target dev='hdc' bus='ide'/> + <readonly/> + <address type='drive' controller='0' bus='1' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'/> + <controller type='virtio-serial' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </controller> + <controller type='ide' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <interface type='network'> + <source network='default'/> + <mac address='52:54:00:e5:48:58'/> + <model type='virtio'/> + <coalesce> + <rx_max_coalesced_frames>7</rx_max_coalesced_frames> + </coalesce> + </interface> + <interface type='network'> + <source network='default'/> + <mac address='52:54:00:e5:48:59'/> + <model type='virtio'/> + <coalesce> + <rx_max_coalesced_frames>0</rx_max_coalesced_frames> + </coalesce> + </interface> + <serial type='pty'> + <target port='0'/> + </serial> + <console type='pty'> + <target type='serial' port='0'/> + </console> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-coalesce.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-coalesce.xml new file mode 100644 index 000000000000..facf3212c79c --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-coalesce.xml @@ -0,0 +1,69 @@ +<domain type='qemu'> + <name>test</name> + <uuid>15d091de-0181-456b-9554-e4382dc1f1ab</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='x86_64' machine='pc-0.13'>hvm</type> + <boot dev='cdrom'/> + <boot dev='hd'/> + <bootmenu enable='yes'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2' event_idx='on'/> + <source file='/var/lib/libvirt/images/f14.img'/> + <target dev='vda' bus='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </disk> + <disk type='file' device='cdrom'> + <driver name='qemu' type='raw'/> + <source file='/var/lib/libvirt/Fedora-14-x86_64-Live-KDE.iso'/> + <target dev='hdc' bus='ide'/> + <readonly/> + <address type='drive' controller='0' bus='1' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='virtio-serial' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <interface type='network'> + <mac address='52:54:00:e5:48:58'/> + <source network='default'/> + <model type='virtio'/> + <coalesce> + <rx_max_coalesced_frames>7</rx_max_coalesced_frames> + </coalesce> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </interface> + <interface type='network'> + <mac address='52:54:00:e5:48:59'/> + <source network='default'/> + <model type='virtio'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </interface> + <serial type='pty'> + <target port='0'/> + </serial> + <console type='pty'> + <target type='serial' port='0'/> + </console> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='virtio'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/> + </memballoon> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 252f1ed5f2a8..692b63866e53 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -532,6 +532,7 @@ mymain(void) DO_TEST("net-bandwidth", NONE); DO_TEST("net-bandwidth2", NONE); DO_TEST("net-mtu", NONE); + DO_TEST("net-coalesce", NONE); DO_TEST("serial-vc", NONE); DO_TEST("serial-pty", NONE); -- 2.12.2

On 04/07/2017 06:04 PM, Martin Kletzander wrote:
We are currently parsing only rx_max_coalesced_frames because that's the only value that makes sense for us. The tun device just added support for this one and the others are only supported by hardware devices which we don't need to worry about as the only way we'd pass those to the domain is using <hostdev/> or <interface type='hostdev'/>. And in those cases the guest can modify the settings itself.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com> --- docs/formatdomain.html.in | 24 ++++++ docs/schemas/domaincommon.rng | 3 + docs/schemas/networkcommon.rng | 17 ++++ src/conf/domain_conf.c | 9 +++ src/conf/domain_conf.h | 2 + src/conf/networkcommon_conf.c | 91 ++++++++++++++++++++++ src/conf/networkcommon_conf.h | 9 +++ src/libvirt_private.syms | 2 + src/qemu/qemu_domain.c | 31 ++++++++ .../qemuxml2argvdata/qemuxml2argv-net-coalesce.xml | 64 +++++++++++++++ .../qemuxml2xmlout-net-coalesce.xml | 69 ++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 12 files changed, 322 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-coalesce.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-net-coalesce.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index b1e38f00e423..ea64b7fd1193 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -5405,6 +5405,30 @@ qemu-kvm -net nic,model=? /dev/null <span class="since">Since 3.1.0</span> </p>
+ <h5><a name="coalesce">Coalesce settings</a></h5> +<pre> +... +<devices> + <interface type='network'> + <source network='default'/> + <target dev='vnet0'/> + <b><coalesce> + <rx_max_coalesced_frames>5</rx_max_coalesced_frames> + </coalesce></b> + </interface> +</devices> +...</pre> + + <p> + This element provides means of setting coalesce settings for some + interface devices (currently only type <code>network</code> + and <code>bridge</code>. Currently there is just one sub-element + named <code>rx_max_coalesced_frames</code> which accepts a non-negative + integer that specifies the maximum number of packets that will be received + before an interrupt. + <span class="since">Since 3.3.0</span> + </p> + <h5><a name="ipconfig">IP configuration</a></h5> <pre> ... diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index edc225fe50c5..b703515fb897 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2509,6 +2509,9 @@ <ref name="mtu"/> </optional> <optional> + <ref name="coalesce"/> + </optional> + <optional> <element name="target"> <attribute name="dev"> <ref name="deviceName"/> diff --git a/docs/schemas/networkcommon.rng b/docs/schemas/networkcommon.rng index 26995556d48d..27e78d13e4a6 100644 --- a/docs/schemas/networkcommon.rng +++ b/docs/schemas/networkcommon.rng @@ -275,4 +275,21 @@ </attribute> </element> </define> + + <define name="coalesce"> + <element name="coalesce"> + <interleave> + <!-- + Other parameters can just be added here the same way the + following one is. + --> + <optional> + <element name="rx_max_coalesced_frames"> + <ref name="unsignedInt"/> + </element> + </optional> + </interleave> + </element> + </define> +
Not sure what's happening here (one has to love libxml2 error reporting), but when I try to add the following to my domain XML I get a schema error: <coalesce> <rx_max_coalesced_frames>7</rx_max_coalesced_frames> </coalesce> virsh # edit fedora error: XML document failed to validate against schema: Unable to validate doc against /home/zippy/work/libvirt/libvirt.git/docs/schemas/domain.rng Extra element devices in interleave Element domain failed to validate content BTW: is there a reason why this element is defined in networkcommon.rng? And a side note, frankly I'm not a big fan of <elements_with_underscore_in_their_name/> but I guess this is the best we can do - everybody touching this setting is already familiar with that from
</grammar> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 80baa090a7f8..3cc17b5fd228 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -10251,6 +10251,13 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, goto error; }
+ node = virXPathNode("./coalesce", ctxt); + if (node) { + def->coalesce = virNetDevCoalesceParseXML(node, ctxt); + if (!def->coalesce) + goto error; + } + cleanup: ctxt->node = oldnode; VIR_FREE(macaddr); @@ -22144,6 +22151,8 @@ virDomainNetDefFormat(virBufferPtr buf, if (def->mtu) virBufferAsprintf(buf, "<mtu size='%u'/>\n", def->mtu);
+ virNetDevCoalesceFormatXML(buf, def->coalesce); + if (virDomainDeviceInfoFormat(buf, &def->info, flags | VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT | VIR_DOMAIN_DEF_FORMAT_ALLOW_ROM) < 0) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 26c0e6b88759..6c3de9cc2cd4 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -41,6 +41,7 @@ # include "numa_conf.h" # include "virnetdevmacvlan.h" # include "virsysinfo.h" +# include "virnetdev.h" # include "virnetdevip.h" # include "virnetdevvportprofile.h" # include "virnetdevbandwidth.h" @@ -1036,6 +1037,7 @@ struct _virDomainNetDef { int trustGuestRxFilters; /* enum virTristateBool */ int linkstate; unsigned int mtu; + virNetDevCoalescePtr coalesce; };
/* Used for prefix of ifname of any network name generated dynamically diff --git a/src/conf/networkcommon_conf.c b/src/conf/networkcommon_conf.c index 29e978bbdfe5..e0756da6c9ec 100644 --- a/src/conf/networkcommon_conf.c +++ b/src/conf/networkcommon_conf.c @@ -328,3 +328,94 @@ virNetDevIPRouteFormat(virBufferPtr buf, cleanup: return result; } + +virNetDevCoalescePtr +virNetDevCoalesceParseXML(xmlNodePtr node, + xmlXPathContextPtr ctxt) +{ + virNetDevCoalescePtr ret = NULL; + xmlNodePtr save = NULL; + char *str = NULL; + unsigned long long tmp = 0; + + save = ctxt->node; + ctxt->node = node; + +#define GET_COALESCE_PARAM(name) \ + do { \ + str = virXPathString("string(./" #name ")", ctxt); \ + if (!str) \ + break; \ + \ + if (!ret && VIR_ALLOC(ret) < 0) \ + return NULL; \ + \ + if (virStrToLong_ullp(str, NULL, 10, &tmp) < 0) { \ + virReportError(VIR_ERR_XML_DETAIL, \ + _("cannot parse value '%s' for parameter '%s'"), \ + str, #name); \ + VIR_FREE(str); \ + goto error; \ + } \ + VIR_FREE(str); \ + \ + if (tmp > UINT32_MAX) { \ + virReportError(VIR_ERR_OVERFLOW, \ + _("value '%llu' is too big for " #name \ + ", maximum is '%lu'"), \ + tmp, (unsigned long) UINT32_MAX); \ + goto error; \ + } \ + \ + ret->name = tmp; \ + } while (0) + + /* Just add more parameters if needed */ + + GET_COALESCE_PARAM(rx_max_coalesced_frames); + +#undef GET_COALESCE_PARAM + + cleanup: + ctxt->node = save; + return ret; + + error: + VIR_FREE(ret); + goto cleanup; +} + +void +virNetDevCoalesceFormatXML(virBufferPtr buf, + virNetDevCoalescePtr coalesce) +{ + virBuffer childrenBuf = VIR_BUFFER_INITIALIZER; + int indent = virBufferGetIndent(buf, false); + + if (!coalesce) + return; + + virBufferAdjustIndent(&childrenBuf, indent + 2); + +#define SET_COALESCE_PARAM(name) \ + do { \ + if (coalesce->name) { \ + virBufferAsprintf(&childrenBuf, \ + /* TODO: turn %u into something 32-bit compatible */ \ + "<" #name ">%u</" #name ">\n", \ + coalesce->name); \ + } \ + } while (0) + + /* Just add more parameters if needed */ + + SET_COALESCE_PARAM(rx_max_coalesced_frames); + +#undef SET_COALESCE_PARAM + + if (virBufferUse(&childrenBuf)) { + virBufferAddLit(buf, "<coalesce>\n"); + virBufferAddBuffer(buf, &childrenBuf); + virBufferAddLit(buf, "</coalesce>\n"); + } +} diff --git a/src/conf/networkcommon_conf.h b/src/conf/networkcommon_conf.h index 70e46793f67b..a842e2075292 100644 --- a/src/conf/networkcommon_conf.h +++ b/src/conf/networkcommon_conf.h @@ -32,6 +32,7 @@ # include "virbuffer.h" # include "virsocketaddr.h" # include "virnetdevip.h" +# include "virnetdev.h"
virNetDevIPRoutePtr virNetDevIPRouteCreate(const char *networkName, @@ -52,4 +53,12 @@ int virNetDevIPRouteFormat(virBufferPtr buf, const virNetDevIPRoute *def);
+virNetDevCoalescePtr +virNetDevCoalesceParseXML(xmlNodePtr node, + xmlXPathContextPtr ctxt); + +void +virNetDevCoalesceFormatXML(virBufferPtr buf, + virNetDevCoalescePtr coalesce); + #endif /* __NETWORKCOMMON_CONF_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 7ba9b7d98d86..7712e3d0a7f2 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -685,6 +685,8 @@ virNetworkEventStateRegisterID;
# conf/networkcommon_conf.h +virNetDevCoalesceFormatXML; +virNetDevCoalesceParseXML; virNetDevIPRouteCreate; virNetDevIPRouteFormat; virNetDevIPRouteParseXML; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index a3bb7dbc9a25..ac7193c9743f 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2953,6 +2953,30 @@ qemuDomainDefValidate(const virDomainDef *def, }
+static bool +qemuDomainNetSupportsCoalesce(virDomainNetType type) +{ + switch (type) { + case VIR_DOMAIN_NET_TYPE_NETWORK: + case VIR_DOMAIN_NET_TYPE_BRIDGE: + return true;
Maybe I'm running old kernel, but I get ENOSUPP for type network.
+ case VIR_DOMAIN_NET_TYPE_VHOSTUSER: + case VIR_DOMAIN_NET_TYPE_ETHERNET: + case VIR_DOMAIN_NET_TYPE_DIRECT: + case VIR_DOMAIN_NET_TYPE_HOSTDEV: + case VIR_DOMAIN_NET_TYPE_USER: + case VIR_DOMAIN_NET_TYPE_SERVER: + case VIR_DOMAIN_NET_TYPE_CLIENT: + case VIR_DOMAIN_NET_TYPE_MCAST: + case VIR_DOMAIN_NET_TYPE_INTERNAL: + case VIR_DOMAIN_NET_TYPE_UDP: + case VIR_DOMAIN_NET_TYPE_LAST: + break; + } + return false; +} + +
Michal

On Mon, Apr 10, 2017 at 02:21:50PM +0200, Michal Privoznik wrote:
On 04/07/2017 06:04 PM, Martin Kletzander wrote:
We are currently parsing only rx_max_coalesced_frames because that's the only value that makes sense for us. The tun device just added support for this one and the others are only supported by hardware devices which we don't need to worry about as the only way we'd pass those to the domain is using <hostdev/> or <interface type='hostdev'/>. And in those cases the guest can modify the settings itself.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com> --- docs/formatdomain.html.in | 24 ++++++ docs/schemas/domaincommon.rng | 3 + docs/schemas/networkcommon.rng | 17 ++++ src/conf/domain_conf.c | 9 +++ src/conf/domain_conf.h | 2 + src/conf/networkcommon_conf.c | 91 ++++++++++++++++++++++ src/conf/networkcommon_conf.h | 9 +++ src/libvirt_private.syms | 2 + src/qemu/qemu_domain.c | 31 ++++++++ .../qemuxml2argvdata/qemuxml2argv-net-coalesce.xml | 64 +++++++++++++++ .../qemuxml2xmlout-net-coalesce.xml | 69 ++++++++++++++++ tests/qemuxml2xmltest.c | 1 + 12 files changed, 322 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-coalesce.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-net-coalesce.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index b1e38f00e423..ea64b7fd1193 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -5405,6 +5405,30 @@ qemu-kvm -net nic,model=? /dev/null <span class="since">Since 3.1.0</span> </p>
+ <h5><a name="coalesce">Coalesce settings</a></h5> +<pre> +... +<devices> + <interface type='network'> + <source network='default'/> + <target dev='vnet0'/> + <b><coalesce> + <rx_max_coalesced_frames>5</rx_max_coalesced_frames> + </coalesce></b> + </interface> +</devices> +...</pre> + + <p> + This element provides means of setting coalesce settings for some + interface devices (currently only type <code>network</code> + and <code>bridge</code>. Currently there is just one sub-element + named <code>rx_max_coalesced_frames</code> which accepts a non-negative + integer that specifies the maximum number of packets that will be received + before an interrupt. + <span class="since">Since 3.3.0</span> + </p> + <h5><a name="ipconfig">IP configuration</a></h5> <pre> ... diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index edc225fe50c5..b703515fb897 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2509,6 +2509,9 @@ <ref name="mtu"/> </optional> <optional> + <ref name="coalesce"/> + </optional> + <optional> <element name="target"> <attribute name="dev"> <ref name="deviceName"/> diff --git a/docs/schemas/networkcommon.rng b/docs/schemas/networkcommon.rng index 26995556d48d..27e78d13e4a6 100644 --- a/docs/schemas/networkcommon.rng +++ b/docs/schemas/networkcommon.rng @@ -275,4 +275,21 @@ </attribute> </element> </define> + + <define name="coalesce"> + <element name="coalesce"> + <interleave> + <!-- + Other parameters can just be added here the same way the + following one is. + --> + <optional> + <element name="rx_max_coalesced_frames"> + <ref name="unsignedInt"/> + </element> + </optional> + </interleave> + </element> + </define> +
Not sure what's happening here (one has to love libxml2 error reporting), but when I try to add the following to my domain XML I get a schema error:
I wonder why I didn't see the error when tests were running. Where did you add it?
<coalesce> <rx_max_coalesced_frames>7</rx_max_coalesced_frames> </coalesce>
virsh # edit fedora error: XML document failed to validate against schema: Unable to validate doc against /home/zippy/work/libvirt/libvirt.git/docs/schemas/domain.rng Extra element devices in interleave Element domain failed to validate content
BTW: is there a reason why this element is defined in networkcommon.rng?
There was. I first had it defined for both domains and networks, but then scratched the network option as that's not available now and it would be there for no reason. But I didn't move the definition. I'll put it in domaincommon.rng in v2.
And a side note, frankly I'm not a big fan of <elements_with_underscore_in_their_name/> but I guess this is the best we can do - everybody touching this setting is already familiar with that from
I first encountered this when adding dumpCore to <memory/>. I first proposed it as dump_core and that was rejected due to the fact that we're trying to use camelCase everywhere. OK, so I changed it. Now when adding this, I 1) forgot about it and 2) saw all the on_{reboot,poweroff,crash}, event_idx and during this I was working on another patch where I saw os_type, uri_transports, migration_features, you get the point. All cpuid features and other things that we're modelling after something else have the same (usually underscore-based) naming as the thing they are modelled after. I'm fine with changing it. Although the code won't be that extensible. Also, what I was thinking about wen writing it, we could somehow get prepared for the future by splitting it into categories, e.g.: <coalesce> <rx> <frames max='3' high='100' low='2'/> <usecs max='3' high='100' low='2'/> </rx> <tx> <frames irq='5'/> </tx> </coalesce> There would be no need for camelCasing, multiple prameters would be way nicer to read, the XML wouldn't be so huge, it would be extensible, and maybe something else as well. It's just that for now, someone might not like it: <coalesce> <rx> <frames max='3'/> </rx> </coalesce> But if it was my choice, I would go with this one ^^ and maybe even added all of the possible attributes that are there currently. A very simple and dumb test, just to show how consistent we are (the regexps are not fool-proof, just the quickest one that popped out of my head): Number of camelCase elements $ sed -n 's/.*element name=.*\(\b[a-z]\+[A-Z][a-zA-Z]*\b\).*/\1/p' $(g ls-files '*.rng') | sort -u | wc -l 10 Number of camelCase attributes $ sed -n 's/.*attribute name=.*\(\b[a-z]\+[A-Z][a-zA-Z]*\b\).*/\1/p' $(g ls-files '*.rng') | sort -u | wc -l 27 Number of under_score elements $ sed -n 's/.*element name=.*\(\b.*[a-z]_[a-z]*\b\).*/\1/p' $(g ls-files '*.rng') | sort -u | wc -l 82 Number of under_score attributes $ sed -n 's/.*attribute name=.*\(\b.*[a-z]_[a-z]*\b\).*/\1/p' $(g ls-files '*.rng') | sort -u | wc -l 20
+static bool +qemuDomainNetSupportsCoalesce(virDomainNetType type) +{ + switch (type) { + case VIR_DOMAIN_NET_TYPE_NETWORK: + case VIR_DOMAIN_NET_TYPE_BRIDGE: + return true;
Maybe I'm running old kernel, but I get ENOSUPP for type network.
Do you get it from libvirt or from the kernel? In upstream, it's in 4.11-rc3 onwards. I hpe I didn't forget to mention it in the commit message or cover letter.

This patch makes use of the virNetDevSetCoalesce() function to make appropriate settings effective for devices that support them. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1414627 Signed-off-by: Martin Kletzander <mkletzan@redhat.com> --- src/bhyve/bhyve_command.c | 2 +- src/network/bridge_driver.c | 2 +- src/qemu/qemu_interface.c | 2 +- src/uml/uml_conf.c | 2 +- src/util/virnetdevtap.c | 8 +++++++- src/util/virnetdevtap.h | 2 ++ tests/bhyvexml2argvmock.c | 1 + 7 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c index e0528ed77a2c..e9c072b9f578 100644 --- a/src/bhyve/bhyve_command.c +++ b/src/bhyve/bhyve_command.c @@ -100,7 +100,7 @@ bhyveBuildNetArgStr(virConnectPtr conn, def->uuid, NULL, NULL, 0, virDomainNetGetActualVirtPortProfile(net), virDomainNetGetActualVlan(net), - 0, NULL, + NULL, 0, NULL, VIR_NETDEV_TAP_CREATE_IFUP | VIR_NETDEV_TAP_CREATE_PERSIST) < 0) { goto cleanup; } diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 5ccd37a3213b..9517f97dfb40 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -2312,7 +2312,7 @@ networkStartNetworkVirtual(virNetworkDriverStatePtr driver, if (virNetDevTapCreateInBridgePort(network->def->bridge, &macTapIfName, &network->def->mac, NULL, NULL, &tapfd, 1, NULL, NULL, - network->def->mtu, NULL, + NULL, network->def->mtu, NULL, VIR_NETDEV_TAP_CREATE_USE_MAC_FOR_BRIDGE | VIR_NETDEV_TAP_CREATE_IFUP | VIR_NETDEV_TAP_CREATE_PERSIST) < 0) { diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c index c5dca60f1f65..2057ac9293f2 100644 --- a/src/qemu/qemu_interface.c +++ b/src/qemu/qemu_interface.c @@ -545,7 +545,7 @@ qemuInterfaceBridgeConnect(virDomainDefPtr def, def->uuid, tunpath, tapfd, *tapfdSize, virDomainNetGetActualVirtPortProfile(net), virDomainNetGetActualVlan(net), - net->mtu, mtu, + net->coalesce, net->mtu, mtu, tap_create_flags) < 0) { virDomainAuditNetDevice(def, net, tunpath, false); goto cleanup; diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c index 871653c5a64c..bdef78324385 100644 --- a/src/uml/uml_conf.c +++ b/src/uml/uml_conf.c @@ -125,7 +125,7 @@ umlConnectTapDevice(virDomainDefPtr vm, vm->uuid, net->backend.tap, &tapfd, 1, virDomainNetGetActualVirtPortProfile(net), virDomainNetGetActualVlan(net), - 0, NULL, + NULL, 0, NULL, VIR_NETDEV_TAP_CREATE_IFUP | VIR_NETDEV_TAP_CREATE_PERSIST) < 0) { if (template_ifname) diff --git a/src/util/virnetdevtap.c b/src/util/virnetdevtap.c index 02ef7fd24047..fe452943ab5e 100644 --- a/src/util/virnetdevtap.c +++ b/src/util/virnetdevtap.c @@ -584,6 +584,7 @@ virNetDevTapAttachBridge(const char *tapname, * @tapfd: array of file descriptor return value for the new tap device * @tapfdSize: number of file descriptors in @tapfd * @virtPortProfile: bridge/port specific configuration + * @coalesce: optional coalesce parameters * @mtu: requested MTU for port (or 0 for "default") * @actualMTU: MTU actually set for port (after accounting for bridge's MTU) * @flags: OR of virNetDevTapCreateFlags: @@ -616,6 +617,7 @@ int virNetDevTapCreateInBridgePort(const char *brname, size_t tapfdSize, virNetDevVPortProfilePtr virtPortProfile, virNetDevVlanPtr virtVlan, + virNetDevCoalescePtr coalesce, unsigned int mtu, unsigned int *actualMTU, unsigned int flags) @@ -654,13 +656,17 @@ int virNetDevTapCreateInBridgePort(const char *brname, goto error; if (virNetDevTapAttachBridge(*ifname, brname, macaddr, vmuuid, - virtPortProfile, virtVlan, mtu, actualMTU) < 0) { + virtPortProfile, virtVlan, + mtu, actualMTU) < 0) { goto error; } if (virNetDevSetOnline(*ifname, !!(flags & VIR_NETDEV_TAP_CREATE_IFUP)) < 0) goto error; + if (virNetDevSetCoalesce(*ifname, coalesce) < 0) + goto error; + return 0; error: diff --git a/src/util/virnetdevtap.h b/src/util/virnetdevtap.h index 6bb3b8891c21..bd5ec14d448f 100644 --- a/src/util/virnetdevtap.h +++ b/src/util/virnetdevtap.h @@ -24,6 +24,7 @@ # define __VIR_NETDEV_TAP_H__ # include "internal.h" +# include "virnetdev.h" # include "virnetdevvportprofile.h" # include "virnetdevvlan.h" @@ -83,6 +84,7 @@ int virNetDevTapCreateInBridgePort(const char *brname, size_t tapfdSize, virNetDevVPortProfilePtr virtPortProfile, virNetDevVlanPtr virtVlan, + virNetDevCoalescePtr coalesce, unsigned int mtu, unsigned int *actualMTU, unsigned int flags) diff --git a/tests/bhyvexml2argvmock.c b/tests/bhyvexml2argvmock.c index fd714694f0bd..7afa0e34c43c 100644 --- a/tests/bhyvexml2argvmock.c +++ b/tests/bhyvexml2argvmock.c @@ -28,6 +28,7 @@ int virNetDevTapCreateInBridgePort(const char *brname ATTRIBUTE_UNUSED, size_t tapfdSize ATTRIBUTE_UNUSED, virNetDevVPortProfilePtr virtPortProfile ATTRIBUTE_UNUSED, virNetDevVlanPtr virtVlan ATTRIBUTE_UNUSED, + virNetDevCoalescePtr coalesce ATTRIBUTE_UNUSED, unsigned int mtu ATTRIBUTE_UNUSED, unsigned int *actualMTU ATTRIBUTE_UNUSED, unsigned int fakeflags ATTRIBUTE_UNUSED) -- 2.12.2
participants (2)
-
Martin Kletzander
-
Michal Privoznik