This patch adds new schema and adds support for parsing and formatting
domain configurations that include vdpa devices.
vDPA network devices allow high-performance networking in a virtual
machine by providing a wire-speed data path. These devices require a
vendor-specific host driver but the data path follows the virtio
specification.
When a device on the host is bound to an appropriate vendor-specific
driver, it will create a chardev on the host at e.g. /dev/vhost-vdpa-0.
That chardev path can then be used to define a new interface with
type='vdpa'.
Signed-off-by: Jonathon Jongsma <jjongsma(a)redhat.com>
---
docs/formatdomain.rst | 24 ++++++++++++++++++++++++
docs/schemas/domaincommon.rng | 15 +++++++++++++++
src/conf/domain_conf.c | 31 +++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 4 ++++
src/conf/netdev_bandwidth_conf.c | 1 +
src/libxl/libxl_conf.c | 1 +
src/libxl/xen_common.c | 1 +
src/lxc/lxc_controller.c | 1 +
src/lxc/lxc_driver.c | 3 +++
src/lxc/lxc_process.c | 1 +
src/qemu/qemu_command.c | 3 +++
src/qemu/qemu_domain.c | 4 +++-
src/qemu/qemu_hotplug.c | 3 +++
src/qemu/qemu_interface.c | 2 ++
src/qemu/qemu_process.c | 2 ++
src/qemu/qemu_validate.c | 1 +
src/vmx/vmx.c | 1 +
tools/virsh-domain.c | 1 +
18 files changed, 98 insertions(+), 1 deletion(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 83dec62f30..f4e4bf7fe7 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -4644,6 +4644,30 @@ or stopping the guest.
</devices>
...
+:anchor:`<a id="elementsNICSVDPA"/>`
+
+vDPA devices
+^^^^^^^^^^^^
+
+A vDPA network device can be used to provide wire speed network performance
+within a domain. A vDPA device is a specialized type of network device that
+uses a datapath that complies with the virtio specification but has a
+vendor-specific control path. To use such a device with libvirt, the host
+device must already be bound to the appropriate device-specific vDPA driver.
+This creates a vDPA char device (e.g. /dev/vhost-vdpa-0) that can be used to
+assign the device to a libvirt domain. :since:`Since 6.9.0 (QEMU only,
+requires QEMU 5.1.0 or newer)`
+
+::
+
+ ...
+ <devices>
+ <interface type='vdpa'>
+ <source dev='/dev/vhost-vdpa-0'/>
+ </interface>
+ </devices>
+ ...
+
:anchor:`<a id="elementsTeaming"/>`
Teaming a virtio/hostdev NIC pair
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 0a0f0ed8a8..45193feb68 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3117,6 +3117,21 @@
<ref name="interface-options"/>
</interleave>
</group>
+
+ <group>
+ <attribute name="type">
+ <value>vdpa</value>
+ </attribute>
+ <interleave>
+ <element name="source">
+ <attribute name="dev">
+ <ref name="deviceName"/>
+ </attribute>
+ </element>
+ <ref name="interface-options"/>
+ </interleave>
+ </group>
+
</choice>
<optional>
<attribute name="trustGuestRxFilters">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 1d3661c21f..518c9ca1c2 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -554,6 +554,7 @@ VIR_ENUM_IMPL(virDomainNet,
"direct",
"hostdev",
"udp",
+ "vdpa",
);
VIR_ENUM_IMPL(virDomainNetModel,
@@ -2495,6 +2496,10 @@ virDomainNetDefFree(virDomainNetDefPtr def)
def->data.vhostuser = NULL;
break;
+ case VIR_DOMAIN_NET_TYPE_VDPA:
+ VIR_FREE(def->data.vdpa.devicepath);
+ break;
+
case VIR_DOMAIN_NET_TYPE_SERVER:
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_MCAST:
@@ -12095,6 +12100,10 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
if (virDomainChrSourceReconnectDefParseXML(&reconnect, cur, ctxt)
< 0)
goto error;
+ } else if (!dev
+ && def->type == VIR_DOMAIN_NET_TYPE_VDPA
+ && virXMLNodeNameEqual(cur, "source")) {
+ dev = virXMLPropString(cur, "dev");
} else if (!def->virtPortProfile
&& virXMLNodeNameEqual(cur, "virtualport")) {
if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
@@ -12352,6 +12361,16 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
}
break;
+ case VIR_DOMAIN_NET_TYPE_VDPA:
+ if (dev == NULL) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("No <source> 'dev' attribute "
+ "specified with <interface
type='vdpa'/>"));
+ goto error;
+ }
+ def->data.vdpa.devicepath = g_steal_pointer(&dev);
+ break;
+
case VIR_DOMAIN_NET_TYPE_BRIDGE:
if (bridge == NULL) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -12741,6 +12760,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
case VIR_DOMAIN_NET_TYPE_DIRECT:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
break;
case VIR_DOMAIN_NET_TYPE_LAST:
default:
@@ -26974,6 +26994,14 @@ virDomainNetDefFormat(virBufferPtr buf,
}
break;
+ case VIR_DOMAIN_NET_TYPE_VDPA:
+ if (def->data.vdpa.devicepath) {
+ virBufferEscapeString(buf, "<source dev='%s'",
+ def->data.vdpa.devicepath);
+ sourceLines++;
+ }
+ break;
+
case VIR_DOMAIN_NET_TYPE_USER:
case VIR_DOMAIN_NET_TYPE_LAST:
break;
@@ -31191,6 +31219,7 @@ virDomainNetGetActualVirtPortProfile(const virDomainNetDef
*iface)
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
case VIR_DOMAIN_NET_TYPE_LAST:
default:
return NULL;
@@ -32022,6 +32051,7 @@ virDomainNetTypeSharesHostView(const virDomainNetDef *net)
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
case VIR_DOMAIN_NET_TYPE_LAST:
break;
}
@@ -32283,6 +32313,7 @@ virDomainNetDefActualToNetworkPort(virDomainDefPtr dom,
case VIR_DOMAIN_NET_TYPE_UDP:
case VIR_DOMAIN_NET_TYPE_USER:
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unexpected network port type %s"),
virDomainNetTypeToString(virDomainNetGetActualType(iface)));
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 902dd58112..8b663d7623 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -883,6 +883,7 @@ typedef enum {
VIR_DOMAIN_NET_TYPE_DIRECT,
VIR_DOMAIN_NET_TYPE_HOSTDEV,
VIR_DOMAIN_NET_TYPE_UDP,
+ VIR_DOMAIN_NET_TYPE_VDPA,
VIR_DOMAIN_NET_TYPE_LAST
} virDomainNetType;
@@ -1056,6 +1057,9 @@ struct _virDomainNetDef {
*/
virDomainActualNetDefPtr actual;
} network;
+ struct {
+ char *devicepath;
+ } vdpa;
struct {
char *brname;
} bridge;
diff --git a/src/conf/netdev_bandwidth_conf.c b/src/conf/netdev_bandwidth_conf.c
index 831ee036ac..4fb7aa4e3d 100644
--- a/src/conf/netdev_bandwidth_conf.c
+++ b/src/conf/netdev_bandwidth_conf.c
@@ -312,6 +312,7 @@ bool virNetDevSupportsBandwidth(virDomainNetType type)
case VIR_DOMAIN_NET_TYPE_UDP:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
case VIR_DOMAIN_NET_TYPE_LAST:
break;
}
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index 03ec37d6c5..43d23565f1 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -1386,6 +1386,7 @@ libxlMakeNic(virDomainDefPtr def,
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_DIRECT:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
case VIR_DOMAIN_NET_TYPE_LAST:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("unsupported interface type %s"),
diff --git a/src/libxl/xen_common.c b/src/libxl/xen_common.c
index 7b6a7b6e9f..c82e487d80 100644
--- a/src/libxl/xen_common.c
+++ b/src/libxl/xen_common.c
@@ -1759,6 +1759,7 @@ xenFormatNet(virConnectPtr conn,
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
case VIR_DOMAIN_NET_TYPE_UDP:
case VIR_DOMAIN_NET_TYPE_USER:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported net type
'%s'"),
virDomainNetTypeToString(net->type));
return -1;
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index e6dee85ec7..4f77a6ace8 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -422,6 +422,7 @@ static int virLXCControllerGetNICIndexes(virLXCControllerPtr ctrl)
case VIR_DOMAIN_NET_TYPE_UDP:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unsupported net type %s"),
virDomainNetTypeToString(actualType));
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index ec3cb60a78..a6905b5a54 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -3504,6 +3504,7 @@ lxcDomainAttachDeviceNetLive(virLXCDriverPtr driver,
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Network device type is not supported"));
goto cleanup;
@@ -3558,6 +3559,7 @@ lxcDomainAttachDeviceNetLive(virLXCDriverPtr driver,
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
case VIR_DOMAIN_NET_TYPE_LAST:
default:
/* no-op */
@@ -3999,6 +4001,7 @@ lxcDomainDetachDeviceNetLive(virDomainObjPtr vm,
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Only bridged veth devices can be detached"));
goto cleanup;
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index e392d98f5d..c5a710fc3f 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -607,6 +607,7 @@ virLXCProcessSetupInterfaces(virLXCDriverPtr driver,
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_LAST:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unsupported network type %s"),
virDomainNetTypeToString(type));
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 697a2db62b..91fff432a1 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3699,6 +3699,7 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
return NULL;
break;
+ case VIR_DOMAIN_NET_TYPE_VDPA:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
/* Should have been handled earlier via PCI/USB hotplug code. */
case VIR_DOMAIN_NET_TYPE_LAST:
@@ -8208,6 +8209,7 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver,
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
case VIR_DOMAIN_NET_TYPE_LAST:
/* nada */
break;
@@ -8244,6 +8246,7 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver,
case VIR_DOMAIN_NET_TYPE_UDP:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
case VIR_DOMAIN_NET_TYPE_LAST:
/* These types don't use a network device on the host, but
* instead use some other type of connection to the emulated
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 5e603284be..0ad8007962 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -5120,7 +5120,8 @@ qemuDomainDeviceNetDefPostParse(virDomainNetDefPtr net,
const virDomainDef *def,
virQEMUCapsPtr qemuCaps)
{
- if (net->type != VIR_DOMAIN_NET_TYPE_HOSTDEV &&
+ if (net->type != VIR_DOMAIN_NET_TYPE_VDPA &&
+ net->type != VIR_DOMAIN_NET_TYPE_HOSTDEV &&
!virDomainNetGetModelString(net) &&
virDomainNetResolveActualType(net) != VIR_DOMAIN_NET_TYPE_HOSTDEV)
net->model = qemuDomainDefaultNetModel(def, qemuCaps);
@@ -9313,6 +9314,7 @@ qemuDomainNetSupportsMTU(virDomainNetType type)
case VIR_DOMAIN_NET_TYPE_DIRECT:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
case VIR_DOMAIN_NET_TYPE_LAST:
break;
}
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 2c184b9ba0..7bbf28ea6a 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1339,6 +1339,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
case VIR_DOMAIN_NET_TYPE_LAST:
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("hotplug of interface type of %s is not implemented
yet"),
@@ -3390,6 +3391,7 @@ qemuDomainChangeNetFilter(virDomainObjPtr vm,
case VIR_DOMAIN_NET_TYPE_DIRECT:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("filters not supported on interfaces of type %s"),
virDomainNetTypeToString(virDomainNetGetActualType(newdev)));
@@ -3727,6 +3729,7 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
_("unable to change config on '%s' network
type"),
virDomainNetTypeToString(newdev->type));
diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c
index cbf3d99981..b24f9060a9 100644
--- a/src/qemu/qemu_interface.c
+++ b/src/qemu/qemu_interface.c
@@ -118,6 +118,7 @@ qemuInterfaceStartDevice(virDomainNetDefPtr net)
case VIR_DOMAIN_NET_TYPE_UDP:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
case VIR_DOMAIN_NET_TYPE_LAST:
/* these types all require no action */
break;
@@ -203,6 +204,7 @@ qemuInterfaceStopDevice(virDomainNetDefPtr net)
case VIR_DOMAIN_NET_TYPE_UDP:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
case VIR_DOMAIN_NET_TYPE_LAST:
/* these types all require no action */
break;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 5bc76a75e3..423e1ffa60 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3347,6 +3347,7 @@ qemuProcessNotifyNets(virDomainDefPtr def)
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
case VIR_DOMAIN_NET_TYPE_LAST:
break;
}
@@ -7578,6 +7579,7 @@ void qemuProcessStop(virQEMUDriverPtr driver,
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
case VIR_DOMAIN_NET_TYPE_LAST:
/* No special cleanup procedure for these types. */
break;
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index bc3043bb3f..f5c07f1521 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -1145,6 +1145,7 @@ qemuValidateNetSupportsCoalesce(virDomainNetType type)
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
case VIR_DOMAIN_NET_TYPE_LAST:
break;
}
diff --git a/src/vmx/vmx.c b/src/vmx/vmx.c
index e0777a9ddd..b7794540fe 100644
--- a/src/vmx/vmx.c
+++ b/src/vmx/vmx.c
@@ -3810,6 +3810,7 @@ virVMXFormatEthernet(virDomainNetDefPtr def, int controller,
case VIR_DOMAIN_NET_TYPE_DIRECT:
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported net type
'%s'"),
virDomainNetTypeToString(def->type));
return -1;
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 8f11393197..01b4cfda4e 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -1007,6 +1007,7 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_MCAST:
case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
case VIR_DOMAIN_NET_TYPE_INTERNAL:
case VIR_DOMAIN_NET_TYPE_LAST:
vshError(ctl, _("No support for %s in command
'attach-interface'"),
--
2.26.2