I remembered to document this bit, but somehow forgot to implement it.
This adds <driver name='kvm|vfio'/> as a subelement to the <forward>
element of a network (this puts it parallel to the match between
mode='hostdev' attribute in a network and type='hostdev' in an
<interface>).
Since it's already documented, only the parser, formatter, backend
driver recognition (it just translates/moves the flag into the
<interface> at the appropriate time), and a test case were needed.
(I used a separate enum for the values both because the original is
defined in domain_conf.h, which is unavailable from network_conf.h,
and because in the future it's possible that we may want to support
other non-hostdev oriented driver names in the network parser; this
makes sure that one can be expanded without the other).
---
src/conf/network_conf.c | 39 +++++++++++++++++++++++++++++++++-
src/conf/network_conf.h | 17 ++++++++++++++-
src/network/bridge_driver.c | 23 ++++++++++++++++++++
tests/networkxml2xmlin/hostdev-pf.xml | 1 +
tests/networkxml2xmlout/hostdev-pf.xml | 1 +
5 files changed, 79 insertions(+), 2 deletions(-)
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 1c88547..d910a27 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -60,6 +60,12 @@ VIR_ENUM_IMPL(virNetworkForwardHostdevDevice,
VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_LAST,
"none", "pci", "netdev")
+VIR_ENUM_IMPL(virNetworkForwardDriverName,
+ VIR_NETWORK_FORWARD_DRIVER_NAME_LAST,
+ "default",
+ "kvm",
+ "vfio")
+
virNetworkObjPtr virNetworkFindByUUID(const virNetworkObjListPtr nets,
const unsigned char *uuid)
{
@@ -1443,6 +1449,7 @@ virNetworkForwardDefParseXML(const char *networkName,
int nForwardIfs, nForwardAddrs, nForwardPfs, nForwardNats;
char *forwardDev = NULL;
char *forwardManaged = NULL;
+ char *forwardDriverName = NULL;
char *type = NULL;
xmlNodePtr save = ctxt->node;
@@ -1465,6 +1472,21 @@ virNetworkForwardDefParseXML(const char *networkName,
def->managed = true;
}
+ forwardDriverName = virXPathString("string(./driver/@name)", ctxt);
+ if (forwardDriverName) {
+ int driverName
+ = virNetworkForwardDriverNameTypeFromString(forwardDriverName);
+
+ if (driverName <= 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unknown forward <driver name='%s'/>
"
+ "in network %s"),
+ forwardDriverName, networkName);
+ goto cleanup;
+ }
+ def->driverName = driverName;
+ }
+
/* bridge and hostdev modes can use a pool of physical interfaces */
nForwardIfs = virXPathNodeSet("./interface", ctxt, &forwardIfNodes);
if (nForwardIfs < 0) {
@@ -1646,6 +1668,7 @@ cleanup:
VIR_FREE(type);
VIR_FREE(forwardDev);
VIR_FREE(forwardManaged);
+ VIR_FREE(forwardDriverName);
VIR_FREE(forwardPfNodes);
VIR_FREE(forwardIfNodes);
VIR_FREE(forwardAddrNodes);
@@ -2230,10 +2253,24 @@ virNetworkDefFormatInternal(virBufferPtr buf,
|| VIR_SOCKET_ADDR_VALID(&def->forward.addr.start)
|| VIR_SOCKET_ADDR_VALID(&def->forward.addr.end)
|| def->forward.port.start
- || def->forward.port.end);
+ || def->forward.port.end
+ || (def->forward.driverName
+ != VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT));
virBufferAsprintf(buf, "%s>\n", shortforward ? "/" :
"");
virBufferAdjustIndent(buf, 2);
+ if (def->forward.driverName
+ != VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT) {
+ const char *driverName
+ = virNetworkForwardDriverNameTypeToString(def->forward.driverName);
+ if (!driverName) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected hostdev driver name type %d "),
+ def->forward.driverName);
+ goto error;
+ }
+ virBufferAsprintf(buf, "<driver name='%s'/>\n",
driverName);
+ }
if (def->forward.type == VIR_NETWORK_FORWARD_NAT) {
if (virNetworkForwardNatDefFormat(buf, &def->forward) < 0)
goto error;
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 163478c..e187f05 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -1,7 +1,7 @@
/*
* network_conf.h: network XML handling
*
- * Copyright (C) 2006-2008, 2012 Red Hat, Inc.
+ * Copyright (C) 2006-2013 Red Hat, Inc.
* Copyright (C) 2006-2008 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -62,6 +62,20 @@ enum virNetworkForwardHostdevDeviceType {
VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_LAST,
};
+/* The backend driver used for devices from the pool. Currently used
+ * only for PCI devices (vfio vs. kvm), but could be used for other
+ * device types in the future.
+ */
+typedef enum {
+ VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT, /* kvm now, could change */
+ VIR_NETWORK_FORWARD_DRIVER_NAME_KVM, /* force legacy kvm style */
+ VIR_NETWORK_FORWARD_DRIVER_NAME_VFIO, /* force vfio */
+
+ VIR_NETWORK_FORWARD_DRIVER_NAME_LAST
+} virNetworkForwardDriverNameType;
+
+VIR_ENUM_DECL(virNetworkForwardDriverName)
+
typedef struct _virNetworkDHCPHostDef virNetworkDHCPHostDef;
typedef virNetworkDHCPHostDef *virNetworkDHCPHostDefPtr;
struct _virNetworkDHCPHostDef {
@@ -159,6 +173,7 @@ typedef virNetworkForwardDef *virNetworkForwardDefPtr;
struct _virNetworkForwardDef {
int type; /* One of virNetworkForwardType constants */
bool managed; /* managed attribute for hostdev mode */
+ int driverName; /* enum virNetworkForwardDriverNameType */
/* If there are multiple forward devices (i.e. a pool of
* interfaces), they will be listed here.
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 20d1cb0..0c0b356 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -3859,6 +3859,8 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
} else if (netdef->forward.type == VIR_NETWORK_FORWARD_HOSTDEV) {
+ virDomainHostdevSubsysPciBackendType backend;
+
if (!iface->data.network.actual
&& (VIR_ALLOC(iface->data.network.actual) < 0)) {
virReportOOMError();
@@ -3893,6 +3895,27 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
iface->data.network.actual->data.hostdev.def.source.subsys.type =
dev->type;
iface->data.network.actual->data.hostdev.def.source.subsys.u.pci.addr =
dev->device.pci;
+ switch (netdef->forward.driverName)
+ {
+ case VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT:
+ backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_DEFAULT;
+ break;
+ case VIR_NETWORK_FORWARD_DRIVER_NAME_KVM:
+ backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_KVM;
+ break;
+ case VIR_NETWORK_FORWARD_DRIVER_NAME_VFIO:
+ backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_VFIO;
+ break;
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unrecognized driver name value %d "
+ " in network '%s'"),
+ netdef->forward.driverName, netdef->name);
+ goto error;
+ }
+ iface->data.network.actual->data.hostdev.def.source.subsys.u.pci.backend
+ = backend;
+
/* merge virtualports from interface, network, and portgroup to
* arrive at actual virtualport to use
*/
diff --git a/tests/networkxml2xmlin/hostdev-pf.xml
b/tests/networkxml2xmlin/hostdev-pf.xml
index 7bf857d..5b8f598 100644
--- a/tests/networkxml2xmlin/hostdev-pf.xml
+++ b/tests/networkxml2xmlin/hostdev-pf.xml
@@ -2,6 +2,7 @@
<name>hostdev</name>
<uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
<forward mode='hostdev' managed='yes'>
+ <driver name='vfio'/>
<pf dev='eth2'/>
</forward>
</network>
diff --git a/tests/networkxml2xmlout/hostdev-pf.xml
b/tests/networkxml2xmlout/hostdev-pf.xml
index 7bf857d..5b8f598 100644
--- a/tests/networkxml2xmlout/hostdev-pf.xml
+++ b/tests/networkxml2xmlout/hostdev-pf.xml
@@ -2,6 +2,7 @@
<name>hostdev</name>
<uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
<forward mode='hostdev' managed='yes'>
+ <driver name='vfio'/>
<pf dev='eth2'/>
</forward>
</network>
--
1.7.11.7