[libvirt] [PATCH 2/3] conf, docs: Add support for coalesce setting(s)

Martin Kletzander mkletzan at redhat.com
Fri Apr 7 16:04:54 UTC 2017


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 at 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




More information about the libvir-list mailing list