提交 614be3b8 编写于 作者: Z ZhiPeng Lu 提交者: Michal Privoznik

vhost-user: add support reconnect for vhost-user ports

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: NZhiPeng Lu <lu.zhipeng@zte.com.cn>
Signed-off-by: NMichal Privoznik <mprivozn@redhat.com>
上级 6aba0715
...@@ -5900,7 +5900,9 @@ qemu-kvm -net nic,model=? /dev/null ...@@ -5900,7 +5900,9 @@ qemu-kvm -net nic,model=? /dev/null
&lt;/interface&gt; &lt;/interface&gt;
&lt;interface type='vhostuser'&gt; &lt;interface type='vhostuser'&gt;
&lt;mac address='52:54:00:3b:83:1b'/&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;model type='virtio'/&gt;
&lt;driver queues='5'/&gt; &lt;driver queues='5'/&gt;
&lt;/interface&gt; &lt;/interface&gt;
...@@ -5916,6 +5918,13 @@ qemu-kvm -net nic,model=? /dev/null ...@@ -5916,6 +5918,13 @@ qemu-kvm -net nic,model=? /dev/null
are supported. are supported.
vhost-user requires the virtio model type, thus the vhost-user requires the virtio model type, thus the
<code>&lt;model&gt;</code> element is mandatory. <code>&lt;model&gt;</code> element is mandatory.
<span class="since">Since 4.1.0</span> the element has an
optional child element <code>reconnect</code> which
configures reconnect timeout if the connection is lost. It
has two attributes <code>enabled</code> (which accepts
<code>yes</code> and <code>no</code>) and
<code>timeout</code> which specifies the amount of seconds
after which hypervisor tries to reconnect.
</p> </p>
<h5><a id="elementNwfilter">Traffic filtering with NWFilter</a></h5> <h5><a id="elementNwfilter">Traffic filtering with NWFilter</a></h5>
......
...@@ -2431,6 +2431,18 @@ ...@@ -2431,6 +2431,18 @@
</attribute> </attribute>
</optional> </optional>
</define> </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 An interface description can either be of type bridge in which case
...@@ -2492,6 +2504,9 @@ ...@@ -2492,6 +2504,9 @@
<value>client</value> <value>client</value>
</choice> </choice>
</attribute> </attribute>
<optional>
<ref name="reconnect"/>
</optional>
<empty/> <empty/>
</element> </element>
<ref name="interface-options"/> <ref name="interface-options"/>
...@@ -3760,16 +3775,7 @@ ...@@ -3760,16 +3775,7 @@
</attribute> </attribute>
</optional> </optional>
<optional> <optional>
<element name="reconnect"> <ref name="reconnect"/>
<attribute name="enabled">
<ref name="virYesNo"/>
</attribute>
<optional>
<attribute name="timeout">
<ref name="unsignedInt"/>
</attribute>
</optional>
</element>
</optional> </optional>
<zeroOrMore> <zeroOrMore>
<ref name='devSeclabel'/> <ref name='devSeclabel'/>
......
...@@ -10712,6 +10712,58 @@ virDomainNetAppendIPAddress(virDomainNetDefPtr def, ...@@ -10712,6 +10712,58 @@ virDomainNetAppendIPAddress(virDomainNetDefPtr def,
return -1; 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 /* Parse the XML definition for a network interface
* @param node XML nodeset to parse for net definition * @param node XML nodeset to parse for net definition
* @return 0 on success, -1 on failure * @return 0 on success, -1 on failure
...@@ -10766,6 +10818,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, ...@@ -10766,6 +10818,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
virNWFilterHashTablePtr filterparams = NULL; virNWFilterHashTablePtr filterparams = NULL;
virDomainActualNetDefPtr actual = NULL; virDomainActualNetDefPtr actual = NULL;
xmlNodePtr oldnode = ctxt->node; xmlNodePtr oldnode = ctxt->node;
virDomainChrSourceReconnectDef reconnect = {0};
int rv, val; int rv, val;
if (VIR_ALLOC(def) < 0) if (VIR_ALLOC(def) < 0)
...@@ -10847,11 +10900,14 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, ...@@ -10847,11 +10900,14 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
goto error; goto error;
} }
} else if (!vhostuser_path && !vhostuser_mode && !vhostuser_type } else if (!vhostuser_path && !vhostuser_mode && !vhostuser_type
&& def->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER && && def->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER
virXMLNodeNameEqual(cur, "source")) { && virXMLNodeNameEqual(cur, "source")) {
vhostuser_type = virXMLPropString(cur, "type"); vhostuser_type = virXMLPropString(cur, "type");
vhostuser_path = virXMLPropString(cur, "path"); vhostuser_path = virXMLPropString(cur, "path");
vhostuser_mode = virXMLPropString(cur, "mode"); vhostuser_mode = virXMLPropString(cur, "mode");
if (virDomainChrSourceReconnectDefParseXML(&reconnect, cur, ctxt) < 0)
goto error;
} else if (!def->virtPortProfile } else if (!def->virtPortProfile
&& virXMLNodeNameEqual(cur, "virtualport")) { && virXMLNodeNameEqual(cur, "virtualport")) {
if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) { if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
...@@ -11073,8 +11129,15 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, ...@@ -11073,8 +11129,15 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
if (STREQ(vhostuser_mode, "server")) { if (STREQ(vhostuser_mode, "server")) {
def->data.vhostuser->data.nix.listen = true; def->data.vhostuser->data.nix.listen = true;
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")) { } else if (STREQ(vhostuser_mode, "client")) {
def->data.vhostuser->data.nix.listen = false; def->data.vhostuser->data.nix.listen = false;
def->data.vhostuser->data.nix.reconnect = reconnect;
} else { } else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Wrong <source> 'mode' attribute " _("Wrong <source> 'mode' attribute "
...@@ -11780,57 +11843,6 @@ virDomainChrDefParseTargetXML(virDomainChrDefPtr def, ...@@ -11780,57 +11843,6 @@ virDomainChrDefParseTargetXML(virDomainChrDefPtr def,
return ret; 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 { typedef enum {
VIR_DOMAIN_CHR_SOURCE_MODE_CONNECT, VIR_DOMAIN_CHR_SOURCE_MODE_CONNECT,
VIR_DOMAIN_CHR_SOURCE_MODE_BIND, VIR_DOMAIN_CHR_SOURCE_MODE_BIND,
...@@ -23899,6 +23911,23 @@ virDomainVirtioNetDriverFormat(char **outstr, ...@@ -23899,6 +23911,23 @@ virDomainVirtioNetDriverFormat(char **outstr,
} }
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 int
virDomainNetDefFormat(virBufferPtr buf, virDomainNetDefFormat(virBufferPtr buf,
virDomainNetDefPtr def, virDomainNetDefPtr def,
...@@ -23992,6 +24021,15 @@ virDomainNetDefFormat(virBufferPtr buf, ...@@ -23992,6 +24021,15 @@ virDomainNetDefFormat(virBufferPtr buf,
def->data.vhostuser->data.nix.listen ? def->data.vhostuser->data.nix.listen ?
"server" : "client"); "server" : "client");
sourceLines++; sourceLines++;
if (def->data.vhostuser->data.nix.reconnect.enabled) {
virBufferAddLit(buf, ">\n");
sourceLines++;
virBufferAdjustIndent(buf, 2);
virDomainChrSourceReconnectDefFormat(buf,
&def->data.vhostuser->data.nix.reconnect);
virBufferAdjustIndent(buf, -2);
}
} }
break; break;
...@@ -24224,24 +24262,6 @@ virDomainChrAttrsDefFormat(virBufferPtr buf, ...@@ -24224,24 +24262,6 @@ virDomainChrAttrsDefFormat(virBufferPtr buf,
return 0; 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 static int
virDomainChrSourceDefFormat(virBufferPtr buf, virDomainChrSourceDefFormat(virBufferPtr buf,
virDomainChrSourceDefPtr def, virDomainChrSourceDefPtr def,
......
...@@ -32,7 +32,11 @@ addr=0x4 \ ...@@ -32,7 +32,11 @@ addr=0x4 \
-netdev socket,listen=:2015,id=hostnet2 \ -netdev socket,listen=:2015,id=hostnet2 \
-device rtl8139,netdev=hostnet2,id=net2,mac=52:54:00:95:db:c0,bus=pci.0,\ -device rtl8139,netdev=hostnet2,id=net2,mac=52:54:00:95:db:c0,bus=pci.0,\
addr=0x5 \ addr=0x5 \
-chardev socket,id=charnet3,path=/tmp/vhost2.sock \ -chardev socket,id=charnet3,path=/tmp/vhost2.sock,reconnect=10 \
-netdev vhost-user,chardev=charnet3,queues=4,id=hostnet3 \ -netdev vhost-user,chardev=charnet3,id=hostnet3 \
-device virtio-net-pci,mq=on,vectors=10,netdev=hostnet3,id=net3,\ -device virtio-net-pci,netdev=hostnet3,id=net3,mac=52:54:00:ee:96:6d,bus=pci.0,\
mac=52:54:00:ee:96:6d,bus=pci.0,addr=0x6 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
...@@ -40,7 +40,16 @@ ...@@ -40,7 +40,16 @@
</interface> </interface>
<interface type='vhostuser'> <interface type='vhostuser'>
<mac address='52:54:00:ee:96:6d'/> <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'/> <model type='virtio'/>
<driver queues='4'/> <driver queues='4'/>
</interface> </interface>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册