[libvirt] [PATCHv4 RESEND] vhost-user: add support reconnect for vhost-user ports
Michal Privoznik
mprivozn at redhat.com
Fri Jan 26 13:06:46 UTC 2018
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 at zte.com.cn>
> Signed-off-by: Michal Privoznik <mprivozn at 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
More information about the libvir-list
mailing list