[libvirt] [PATCH v4] vhost-user: add support reconnect for vhost-user ports

ZhiPeng Lu posted 1 patch 6 years, 4 months ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/libvirt tags/patchew/1510536888-13104-1-git-send-email-lu.zhipeng@zte.com.cn
docs/formatdomain.html.in                          |   7 +-
docs/schemas/domaincommon.rng                      |  26 ++--
src/conf/domain_conf.c                             | 158 ++++++++++++---------
.../qemuxml2argv-net-vhostuser-multiq.args         |  12 +-
.../qemuxml2argv-net-vhostuser-multiq.xml          |  11 +-
5 files changed, 127 insertions(+), 87 deletions(-)
[libvirt] [PATCH v4] vhost-user: add support reconnect for vhost-user ports
Posted by ZhiPeng Lu 6 years, 4 months ago
For vhost-user ports, Open vSwitch acts as the server and QEMU the client.
When OVS crashes or restarts, the QEMU process should be reconnected to
OVS.

Signed-off-by: ZhiPeng Lu <lu.zhipeng@zte.com.cn>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
v1->v2:
 - modify xml format 
v2->v3:
 - fix commit message syntax
 - reimplemente functions and the struct about reconnect
v3->v4:
 - revert reimplemente functions and the struct about reconnect

 docs/formatdomain.html.in                          |   7 +-
 docs/schemas/domaincommon.rng                      |  26 ++--
 src/conf/domain_conf.c                             | 158 ++++++++++++---------
 .../qemuxml2argv-net-vhostuser-multiq.args         |  12 +-
 .../qemuxml2argv-net-vhostuser-multiq.xml          |  11 +-
 5 files changed, 127 insertions(+), 87 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 92e14a9..7ea72ed 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -5756,7 +5756,9 @@ qemu-kvm -net nic,model=? /dev/null
   &lt;/interface&gt;
   &lt;interface type='vhostuser'&gt;
     &lt;mac address='52:54:00:3b:83:1b'/&gt;
-    &lt;source type='unix' path='/tmp/vhost2.sock' mode='client'/&gt;
+    &lt;source type='unix' path='/tmp/vhost2.sock' mode='client'&gt;
+      &lt;reconnect enabled='yes' timeout='10'/&gt;
+    &lt;/source&gt; 
     &lt;model type='virtio'/&gt;
     &lt;driver queues='5'/&gt;
   &lt;/interface&gt;
@@ -5772,6 +5774,9 @@ qemu-kvm -net nic,model=? /dev/null
       are supported.
       vhost-user requires the virtio model type, thus the
       <code>&lt;model&gt;</code> element is mandatory.
+      <span class="since">Since 3.10.0</span> the element has an optional
+      attribute <code>reconnect</code> which configures reconnect timeout
+      (in seconds) if the connection is lost.
     </p>
 
     <h5><a id="elementNwfilter">Traffic filtering with NWFilter</a></h5>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 9cec1a0..66b9758 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2399,6 +2399,18 @@
       </attribute>
     </optional>
   </define>
+  <define name="reconnect">
+    <element name="reconnect">
+      <attribute name="enabled">
+        <ref name="virYesNo"/>
+      </attribute>
+      <optional>
+        <attribute name="timeout">
+          <ref name="unsignedInt"/>
+        </attribute>
+      </optional>
+    </element>
+  </define>
 
   <!--
       An interface description can either be of type bridge in which case
@@ -2460,6 +2472,9 @@
                   <value>client</value>
                 </choice>
               </attribute>
+              <optional>
+                 <ref name="reconnect"/>
+              </optional>
               <empty/>
             </element>
             <ref name="interface-options"/>
@@ -3708,16 +3723,7 @@
           </attribute>
         </optional>
         <optional>
-          <element name="reconnect">
-            <attribute name="enabled">
-              <ref name="virYesNo"/>
-            </attribute>
-            <optional>
-              <attribute name="timeout">
-                <ref name="unsignedInt"/>
-              </attribute>
-            </optional>
-          </element>
+          <ref name="reconnect"/>
         </optional>
         <zeroOrMore>
           <ref name='devSeclabel'/>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f9ae057..be3374d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -10584,6 +10584,56 @@ virDomainNetAppendIPAddress(virDomainNetDefPtr def,
     return -1;
 }
 
+static int
+virDomainChrSourceReconnectDefParseXML(virDomainChrSourceReconnectDefPtr def,
+                                       xmlNodePtr node,
+                                       xmlXPathContextPtr ctxt)
+{
+    int ret = -1;
+    int tmpVal;
+    char *tmp = NULL;
+    xmlNodePtr saveNode = ctxt->node;
+    xmlNodePtr cur;
+
+    ctxt->node = node;
+
+    if ((cur = virXPathNode("./reconnect", ctxt))) {
+        if ((tmp = virXMLPropString(cur, "enabled"))) {
+            if ((tmpVal = virTristateBoolTypeFromString(tmp)) < 0) {
+                virReportError(VIR_ERR_XML_ERROR,
+                               _("invalid reconnect enabled value: '%s'"),
+                               tmp);
+                goto cleanup;
+            }
+            def->enabled = tmpVal;
+            VIR_FREE(tmp);
+        }
+
+        if (def->enabled == VIR_TRISTATE_BOOL_YES) {
+            if ((tmp = virXMLPropString(cur, "timeout"))) {
+                if (virStrToLong_ui(tmp, NULL, 10, &def->timeout) < 0) {
+                    virReportError(VIR_ERR_XML_ERROR,
+                                   _("invalid reconnect timeout value: '%s'"),
+                                   tmp);
+                    goto cleanup;
+                }
+                VIR_FREE(tmp);
+            } else {
+                virReportError(VIR_ERR_XML_ERROR, "%s",
+                               _("missing timeout for chardev with "
+                                 "reconnect enabled"));
+                goto cleanup;
+            }
+        }
+    }
+
+    ret = 0;
+ cleanup:
+    ctxt->node = saveNode;
+    VIR_FREE(tmp);
+    return ret;
+}
+
 /* Parse the XML definition for a network interface
  * @param node XML nodeset to parse for net definition
  * @return 0 on success, -1 on failure
@@ -10638,6 +10688,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
     virNWFilterHashTablePtr filterparams = NULL;
     virDomainActualNetDefPtr actual = NULL;
     xmlNodePtr oldnode = ctxt->node;
+    virDomainChrSourceReconnectDef reconnect = {0};
     int rv, val;
 
     if (VIR_ALLOC(def) < 0)
@@ -10719,11 +10770,14 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
                     goto error;
                 }
             } else if (!vhostuser_path && !vhostuser_mode && !vhostuser_type
-                       && def->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER &&
-                       virXMLNodeNameEqual(cur, "source")) {
+                       && def->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER
+                       && virXMLNodeNameEqual(cur, "source")) {
                 vhostuser_type = virXMLPropString(cur, "type");
                 vhostuser_path = virXMLPropString(cur, "path");
                 vhostuser_mode = virXMLPropString(cur, "mode");
+                if (virDomainChrSourceReconnectDefParseXML(&reconnect, cur, ctxt) < 0)
+                    goto error;
+
             } else if (!def->virtPortProfile
                        && virXMLNodeNameEqual(cur, "virtualport")) {
                 if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
@@ -10945,8 +10999,16 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
 
         if (STREQ(vhostuser_mode, "server")) {
             def->data.vhostuser->data.nix.listen = true;
+            if (reconnect.enabled != VIR_TRISTATE_BOOL_ABSENT) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("'reconnect' attribute  unsupported "
+                                 "'server' mode for <interface type='vhostuser'>"));
+                goto error;
+           }
         } else if (STREQ(vhostuser_mode, "client")) {
             def->data.vhostuser->data.nix.listen = false;
+            def->data.vhostuser->data.nix.reconnect.enabled = reconnect.enabled;
+            def->data.vhostuser->data.nix.reconnect.timeout = reconnect.timeout;
         } else {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                            _("Wrong <source> 'mode' attribute "
@@ -11608,57 +11670,6 @@ virDomainChrDefParseTargetXML(virDomainChrDefPtr def,
     return ret;
 }
 
-static int
-virDomainChrSourceReconnectDefParseXML(virDomainChrSourceReconnectDefPtr def,
-                                       xmlNodePtr node,
-                                       xmlXPathContextPtr ctxt)
-{
-    int ret = -1;
-    int tmpVal;
-    char *tmp = NULL;
-    xmlNodePtr saveNode = ctxt->node;
-    xmlNodePtr cur;
-
-    ctxt->node = node;
-
-    if ((cur = virXPathNode("./reconnect", ctxt))) {
-        if ((tmp = virXMLPropString(cur, "enabled"))) {
-            if ((tmpVal = virTristateBoolTypeFromString(tmp)) < 0) {
-                virReportError(VIR_ERR_XML_ERROR,
-                               _("invalid reconnect enabled value: '%s'"),
-                               tmp);
-                goto cleanup;
-            }
-            def->enabled = tmpVal;
-            VIR_FREE(tmp);
-        }
-
-        if (def->enabled == VIR_TRISTATE_BOOL_YES) {
-            if ((tmp = virXMLPropString(cur, "timeout"))) {
-                if (virStrToLong_ui(tmp, NULL, 10, &def->timeout) < 0) {
-                    virReportError(VIR_ERR_XML_ERROR,
-                                   _("invalid reconnect timeout value: '%s'"),
-                                   tmp);
-                    goto cleanup;
-                }
-                VIR_FREE(tmp);
-            } else {
-                virReportError(VIR_ERR_XML_ERROR, "%s",
-                               _("missing timeout for chardev with "
-                                 "reconnect enabled"));
-                goto cleanup;
-            }
-        }
-    }
-
-    ret = 0;
- cleanup:
-    ctxt->node = saveNode;
-    VIR_FREE(tmp);
-    return ret;
-}
-
-
 typedef enum {
     VIR_DOMAIN_CHR_SOURCE_MODE_CONNECT,
     VIR_DOMAIN_CHR_SOURCE_MODE_BIND,
@@ -23399,6 +23410,21 @@ virDomainVirtioNetDriverFormat(char **outstr,
     return 0;
 }
 
+static void
+virDomainChrSourceReconnectDefFormat(virBufferPtr buf,
+                                     virDomainChrSourceReconnectDefPtr def)
+{
+    if (def->enabled == VIR_TRISTATE_BOOL_ABSENT)
+        return;
+
+    virBufferAsprintf(buf, "<reconnect enabled='%s'",
+                      virTristateBoolTypeToString(def->enabled));
+
+    if (def->enabled == VIR_TRISTATE_BOOL_YES)
+        virBufferAsprintf(buf, " timeout='%u'", def->timeout);
+
+    virBufferAddLit(buf, "/>\n");
+}
 
 int
 virDomainNetDefFormat(virBufferPtr buf,
@@ -23493,6 +23519,14 @@ virDomainNetDefFormat(virBufferPtr buf,
                                   def->data.vhostuser->data.nix.listen ?
                                   "server"  : "client");
                 sourceLines++;
+                if (def->data.vhostuser->data.nix.reconnect.enabled != VIR_TRISTATE_BOOL_ABSENT) {
+                    virBufferAddLit(buf, ">\n");
+                    sourceLines++;
+                    virBufferAdjustIndent(buf, 2);
+                    virDomainChrSourceReconnectDefFormat(buf, &def->data.vhostuser->data.nix.reconnect);
+                    virBufferAdjustIndent(buf, -2);
+                }
+
             }
             break;
 
@@ -23725,24 +23759,6 @@ virDomainChrAttrsDefFormat(virBufferPtr buf,
     return 0;
 }
 
-
-static void
-virDomainChrSourceReconnectDefFormat(virBufferPtr buf,
-                                     virDomainChrSourceReconnectDefPtr def)
-{
-    if (def->enabled == VIR_TRISTATE_BOOL_ABSENT)
-        return;
-
-    virBufferAsprintf(buf, "<reconnect enabled='%s'",
-                      virTristateBoolTypeToString(def->enabled));
-
-    if (def->enabled == VIR_TRISTATE_BOOL_YES)
-        virBufferAsprintf(buf, " timeout='%u'", def->timeout);
-
-    virBufferAddLit(buf, "/>\n");
-}
-
-
 static int
 virDomainChrSourceDefFormat(virBufferPtr buf,
                             virDomainChrSourceDefPtr def,
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser-multiq.args b/tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser-multiq.args
index b69ebd8..f2aec7b 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser-multiq.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser-multiq.args
@@ -32,7 +32,11 @@ addr=0x4 \
 -netdev socket,listen=:2015,id=hostnet2 \
 -device rtl8139,netdev=hostnet2,id=net2,mac=52:54:00:95:db:c0,bus=pci.0,\
 addr=0x5 \
--chardev socket,id=charnet3,path=/tmp/vhost2.sock \
--netdev vhost-user,chardev=charnet3,queues=4,id=hostnet3 \
--device virtio-net-pci,mq=on,vectors=10,netdev=hostnet3,id=net3,\
-mac=52:54:00:ee:96:6d,bus=pci.0,addr=0x6
+-chardev socket,id=charnet3,path=/tmp/vhost2.sock,reconnect=10 \
+-netdev vhost-user,chardev=charnet3,id=hostnet3 \
+-device virtio-net-pci,netdev=hostnet3,id=net3,\
+mac=52:54:00:ee:96:6d,bus=pci.0,addr=0x6 \
+-chardev socket,id=charnet4,path=/tmp/vhost3.sock,reconnect=0 \
+-netdev vhost-user,chardev=charnet4,queues=4,id=hostnet4 \
+-device virtio-net-pci,mq=on,vectors=10,netdev=hostnet4,id=net4,\
+mac=52:54:00:ee:96:6e,bus=pci.0,addr=0x7
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser-multiq.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser-multiq.xml
index d5c42fe..a30cce6 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser-multiq.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-vhostuser-multiq.xml
@@ -40,7 +40,16 @@
     </interface>
     <interface type='vhostuser'>
       <mac address='52:54:00:ee:96:6d'/>
-      <source type='unix' path='/tmp/vhost2.sock' mode='client'/>
+      <source type='unix' path='/tmp/vhost2.sock' mode='client'>
+        <reconnect enabled='yes' timeout='10'/>
+      </source>
+      <model type='virtio'/>
+    </interface>
+    <interface type='vhostuser'>
+      <mac address='52:54:00:ee:96:6e'/>
+      <source type='unix' path='/tmp/vhost3.sock' mode='client'>
+        <reconnect enabled='no'/>
+      </source>
       <model type='virtio'/>
       <driver queues='4'/>
     </interface>
-- 
1.8.3.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list