mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 04:25:18 +00:00
Add XML config switch to enable/disable vhost-net support
This patch is in response to https://bugzilla.redhat.com/show_bug.cgi?id=643050 The existing libvirt support for the vhost-net backend to the virtio network driver happens automatically - if the vhost-net device is available, it is always enabled, otherwise the standard userland virtio backend is used. This patch makes it possible to force whether or not vhost-net is used with a bit of XML. Adding a <driver> element to the interface XML, eg: <interface type="network"> <model type="virtio"/> <driver name="vhost"/> will force use of vhost-net (if it's not available, the domain will fail to start). if driver name="qemu", vhost-net will not be used even if it is available. If there is no <driver name='xxx'/> in the config, libvirt will revert to the pre-existing automatic behavior - use vhost-net if it's available, and userland backend if vhost-net isn't available.
This commit is contained in:
parent
9d73efdbe3
commit
175077fd70
@ -1004,6 +1004,19 @@
|
||||
<empty/>
|
||||
</element>
|
||||
</optional>
|
||||
<optional>
|
||||
<element name="driver">
|
||||
<optional>
|
||||
<attribute name="name">
|
||||
<choice>
|
||||
<value>qemu</value>
|
||||
<value>vhost</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
</optional>
|
||||
<empty/>
|
||||
</element>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="address"/>
|
||||
</optional>
|
||||
|
@ -185,6 +185,11 @@ VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST,
|
||||
"internal",
|
||||
"direct")
|
||||
|
||||
VIR_ENUM_IMPL(virDomainNetBackend, VIR_DOMAIN_NET_BACKEND_TYPE_LAST,
|
||||
"default",
|
||||
"qemu",
|
||||
"vhost")
|
||||
|
||||
VIR_ENUM_IMPL(virDomainChrChannelTarget,
|
||||
VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST,
|
||||
"guestfwd",
|
||||
@ -2304,6 +2309,7 @@ virDomainNetDefParseXML(virCapsPtr caps,
|
||||
char *address = NULL;
|
||||
char *port = NULL;
|
||||
char *model = NULL;
|
||||
char *backend = NULL;
|
||||
char *filter = NULL;
|
||||
char *internal = NULL;
|
||||
char *devaddr = NULL;
|
||||
@ -2386,6 +2392,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
|
||||
script = virXMLPropString(cur, "path");
|
||||
} else if (xmlStrEqual (cur->name, BAD_CAST "model")) {
|
||||
model = virXMLPropString(cur, "type");
|
||||
} else if (xmlStrEqual (cur->name, BAD_CAST "driver")) {
|
||||
backend = virXMLPropString(cur, "name");
|
||||
} else if (xmlStrEqual (cur->name, BAD_CAST "filterref")) {
|
||||
filter = virXMLPropString(cur, "filter");
|
||||
VIR_FREE(filterparams);
|
||||
@ -2573,6 +2581,19 @@ virDomainNetDefParseXML(virCapsPtr caps,
|
||||
model = NULL;
|
||||
}
|
||||
|
||||
if ((backend != NULL) &&
|
||||
(def->model && STREQ(def->model, "virtio"))) {
|
||||
int b;
|
||||
if (((b = virDomainNetBackendTypeFromString(backend)) < 0) ||
|
||||
(b == VIR_DOMAIN_NET_BACKEND_TYPE_DEFAULT)) {
|
||||
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Unknown interface <driver name='%s'> "
|
||||
"has been specified"),
|
||||
backend);
|
||||
goto error;
|
||||
}
|
||||
def->backend = b;
|
||||
}
|
||||
if (filter != NULL) {
|
||||
switch (def->type) {
|
||||
case VIR_DOMAIN_NET_TYPE_ETHERNET:
|
||||
@ -2599,6 +2620,7 @@ cleanup:
|
||||
VIR_FREE(script);
|
||||
VIR_FREE(bridge);
|
||||
VIR_FREE(model);
|
||||
VIR_FREE(backend);
|
||||
VIR_FREE(filter);
|
||||
VIR_FREE(type);
|
||||
VIR_FREE(internal);
|
||||
@ -6318,9 +6340,14 @@ virDomainNetDefFormat(virBufferPtr buf,
|
||||
if (def->ifname)
|
||||
virBufferEscapeString(buf, " <target dev='%s'/>\n",
|
||||
def->ifname);
|
||||
if (def->model)
|
||||
if (def->model) {
|
||||
virBufferEscapeString(buf, " <model type='%s'/>\n",
|
||||
def->model);
|
||||
if (STREQ(def->model, "virtio") && def->backend) {
|
||||
virBufferVSprintf(buf, " <driver name='%s'/>\n",
|
||||
virDomainNetBackendTypeToString(def->backend));
|
||||
}
|
||||
}
|
||||
if (def->filter) {
|
||||
virBufferEscapeString(buf, " <filterref filter='%s'",
|
||||
def->filter);
|
||||
|
@ -292,6 +292,14 @@ enum virDomainNetType {
|
||||
VIR_DOMAIN_NET_TYPE_LAST,
|
||||
};
|
||||
|
||||
/* the backend driver used for virtio interfaces */
|
||||
enum virDomainNetBackendType {
|
||||
VIR_DOMAIN_NET_BACKEND_TYPE_DEFAULT, /* prefer kernel, fall back to user */
|
||||
VIR_DOMAIN_NET_BACKEND_TYPE_QEMU, /* userland */
|
||||
VIR_DOMAIN_NET_BACKEND_TYPE_VHOST, /* kernel */
|
||||
|
||||
VIR_DOMAIN_NET_BACKEND_TYPE_LAST,
|
||||
};
|
||||
|
||||
/* the mode type for macvtap devices */
|
||||
enum virDomainNetdevMacvtapType {
|
||||
@ -310,6 +318,7 @@ struct _virDomainNetDef {
|
||||
enum virDomainNetType type;
|
||||
unsigned char mac[VIR_MAC_BUFLEN];
|
||||
char *model;
|
||||
enum virDomainNetBackendType backend;
|
||||
union {
|
||||
struct {
|
||||
char *dev;
|
||||
@ -1273,6 +1282,7 @@ VIR_ENUM_DECL(virDomainControllerModel)
|
||||
VIR_ENUM_DECL(virDomainFS)
|
||||
VIR_ENUM_DECL(virDomainFSAccessMode)
|
||||
VIR_ENUM_DECL(virDomainNet)
|
||||
VIR_ENUM_DECL(virDomainNetBackend)
|
||||
VIR_ENUM_DECL(virDomainChrDevice)
|
||||
VIR_ENUM_DECL(virDomainChrChannelTarget)
|
||||
VIR_ENUM_DECL(virDomainChrConsoleTarget)
|
||||
|
@ -302,24 +302,58 @@ cleanup:
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
static int
|
||||
qemuOpenVhostNet(virDomainNetDefPtr net,
|
||||
unsigned long long qemuCmdFlags)
|
||||
unsigned long long qemuCmdFlags,
|
||||
int *vhostfd)
|
||||
{
|
||||
|
||||
/* If qemu supports vhost-net mode (including the -netdev command
|
||||
* option), the nic model is virtio, and we can open
|
||||
* /dev/vhost_net, assume that vhost-net mode is available and
|
||||
* return the fd to /dev/vhost_net. Otherwise, return -1.
|
||||
*/
|
||||
*vhostfd = -1; /* assume we won't use vhost */
|
||||
|
||||
/* If the config says explicitly to not use vhost, return now */
|
||||
if (net->backend == VIR_DOMAIN_NET_BACKEND_TYPE_QEMU) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If qemu doesn't support vhost-net mode (including the -netdev command
|
||||
* option), don't try to open the device.
|
||||
*/
|
||||
if (!(qemuCmdFlags & QEMUD_CMD_FLAG_VNET_HOST &&
|
||||
qemuCmdFlags & QEMUD_CMD_FLAG_NETDEV &&
|
||||
qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE &&
|
||||
net->model && STREQ(net->model, "virtio")))
|
||||
return -1;
|
||||
qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
|
||||
if (net->backend == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) {
|
||||
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
"%s", _("vhost-net is not supported with "
|
||||
"this QEMU binary"));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return open("/dev/vhost-net", O_RDWR, 0);
|
||||
/* If the nic model isn't virtio, don't try to open. */
|
||||
if (!(net->model && STREQ(net->model, "virtio"))) {
|
||||
if (net->backend == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST) {
|
||||
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
"%s", _("vhost-net is only supported for "
|
||||
"virtio network interfaces"));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
*vhostfd = open("/dev/vhost-net", O_RDWR);
|
||||
|
||||
/* If the config says explicitly to use vhost and we couldn't open it,
|
||||
* report an error.
|
||||
*/
|
||||
if ((*vhostfd < 0) &&
|
||||
(net->backend == VIR_DOMAIN_NET_BACKEND_TYPE_VHOST)) {
|
||||
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||
"%s", _("vhost-net was requested for an interface, "
|
||||
"but is unavailable"));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -3281,7 +3315,10 @@ qemuBuildCommandLine(virConnectPtr conn,
|
||||
net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
|
||||
/* Attempt to use vhost-net mode for these types of
|
||||
network device */
|
||||
int vhostfd = qemuOpenVhostNet(net, qemuCmdFlags);
|
||||
int vhostfd;
|
||||
|
||||
if (qemuOpenVhostNet(net, qemuCmdFlags, &vhostfd) < 0)
|
||||
goto error;
|
||||
if (vhostfd >= 0) {
|
||||
virCommandTransferFD(cmd, vhostfd);
|
||||
|
||||
@ -4626,6 +4663,12 @@ qemuParseCommandLineNet(virCapsPtr caps,
|
||||
} else if (STREQ(keywords[i], "model")) {
|
||||
def->model = values[i];
|
||||
values[i] = NULL;
|
||||
} else if (STREQ(keywords[i], "vhost")) {
|
||||
if ((values[i] == NULL) || STREQ(values[i], "on")) {
|
||||
def->backend = VIR_DOMAIN_NET_BACKEND_TYPE_VHOST;
|
||||
} else if (STREQ(keywords[i], "off")) {
|
||||
def->backend = VIR_DOMAIN_NET_BACKEND_TYPE_QEMU;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,9 +111,6 @@ int qemuNetworkIfaceConnect(virConnectPtr conn,
|
||||
unsigned long long qemCmdFlags)
|
||||
ATTRIBUTE_NONNULL(1);
|
||||
|
||||
int qemuOpenVhostNet(virDomainNetDefPtr net,
|
||||
unsigned long long qemuCmdFlags);
|
||||
|
||||
int qemuPhysIfaceConnect(virConnectPtr conn,
|
||||
struct qemud_driver *driver,
|
||||
virDomainNetDefPtr net,
|
||||
|
Loading…
x
Reference in New Issue
Block a user