docs/formatdomain.html.in | 7 +- docs/schemas/domaincommon.rng | 26 ++-- src/conf/domain_conf.c | 158 +++++++++++++---------- tests/qemuxml2argvdata/net-vhostuser-multiq.args | 12 +- tests/qemuxml2argvdata/net-vhostuser-multiq.xml | 11 +- 5 files changed, 127 insertions(+), 87 deletions(-)
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 +++++++++++++----------
tests/qemuxml2argvdata/net-vhostuser-multiq.args | 12 +-
tests/qemuxml2argvdata/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 d272cc1..f0f9f4b 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -5832,7 +5832,9 @@ qemu-kvm -net nic,model=? /dev/null
</interface>
<interface type='vhostuser'>
<mac address='52:54:00:3b:83:1b'/>
- <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'/>
<driver queues='5'/>
</interface>
@@ -5848,6 +5850,9 @@ qemu-kvm -net nic,model=? /dev/null
are supported.
vhost-user requires the virtio model type, thus the
<code><model></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 f22c932..9258c7d 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"/>
@@ -3728,16 +3743,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 a1c2506..ccc8ff7 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -10695,6 +10695,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
@@ -10749,6 +10799,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)
@@ -10830,11 +10881,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) {
@@ -11056,8 +11110,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 "
@@ -11763,57 +11825,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,
@@ -23634,6 +23645,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,
@@ -23728,6 +23754,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;
@@ -23960,24 +23994,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/net-vhostuser-multiq.args b/tests/qemuxml2argvdata/net-vhostuser-multiq.args
index b69ebd8..f2aec7b 100644
--- a/tests/qemuxml2argvdata/net-vhostuser-multiq.args
+++ b/tests/qemuxml2argvdata/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/net-vhostuser-multiq.xml b/tests/qemuxml2argvdata/net-vhostuser-multiq.xml
index d5c42fe..a30cce6 100644
--- a/tests/qemuxml2argvdata/net-vhostuser-multiq.xml
+++ b/tests/qemuxml2argvdata/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
On 01/17/2018 05:14 PM, ZhiPeng Lu wrote: > 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 +++++++++++++---------- > tests/qemuxml2argvdata/net-vhostuser-multiq.args | 12 +- > tests/qemuxml2argvdata/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 d272cc1..f0f9f4b 100644 > --- a/docs/formatdomain.html.in > +++ b/docs/formatdomain.html.in > @@ -5832,7 +5832,9 @@ qemu-kvm -net nic,model=? /dev/null > </interface> > <interface type='vhostuser'> > <mac address='52:54:00:3b:83:1b'/> > - <source type='unix' path='/tmp/vhost2.sock' mode='client'/> > + <source type='unix' path='/tmp/vhost2.sock' mode='client'> > + <reconnect enabled='yes' timeout='10'/> > + </source> Extra space at EOL. > <model type='virtio'/> > <driver queues='5'/> > </interface> > @@ -5848,6 +5850,9 @@ qemu-kvm -net nic,model=? /dev/null > are supported. > vhost-user requires the virtio model type, thus the > <code><model></code> element is mandatory. > + <span class="since">Since 3.10.0</span> the element has an optional Since 4.1.0 > + attribute <code>reconnect</code> which configures reconnect timeout Not attribute. Child element. > + (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 f22c932..9258c7d 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"/> > @@ -3728,16 +3743,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 a1c2506..ccc8ff7 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -10695,6 +10695,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 > @@ -10749,6 +10799,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) > @@ -10830,11 +10881,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")) { In fact we like logical operands at the end of previous line. > 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) { > @@ -11056,8 +11110,16 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, > > if (STREQ(vhostuser_mode, "server")) { > def->data.vhostuser->data.nix.listen = true; > + if (reconnect.enabled != VIR_TRISTATE_BOOL_ABSENT) { We can accept BOOL_NO. Therefore the check needs to be: if (reconnect.enabled == VIR_TRISTATE_BOOL_YES) { ... } > + 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; Or just ->data.nix.reconnect = reconnect; > } else { > virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > _("Wrong <source> 'mode' attribute " > @@ -11763,57 +11825,6 @@ virDomainChrDefParseTargetXML(virDomainChrDefPtr def, > return ret; > } There are some other small nits. Anyway, I'm fixing all of the raised points, ACKing and pushing. Michal -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
© 2016 - 2025 Red Hat, Inc.