The current udev node device driver ignores all events related to vdpa
devices. Since libvirt now supports vDPA network devices, include these
devices in the device list.
Example output:
virsh # nodedev-list
[...ommitted long list of nodedevs...]
vdpa_vdpa0
virsh # nodedev-dumpxml vdpa_vdpa0
<device>
<name>vdpa_vdpa0</name>
<path>/sys/devices/vdpa0</path>
<parent>computer</parent>
<driver>
<name>vhost_vdpa</name>
</driver>
<capability type='vdpa'>
<chardev>/dev/vhost-vdpa-0</chardev>
</capability>
</device>
NOTE: normally the 'parent' would be a PCI device instead of 'computer',
but this example output is from the vdpa_sim kernel module, so it
doesn't have a normal parent device.
Signed-off-by: Jonathon Jongsma <jjongsma(a)redhat.com>
---
docs/formatnode.html.in | 9 +++++
docs/schemas/nodedev.rng | 10 ++++++
include/libvirt/libvirt-nodedev.h | 1 +
src/conf/node_device_conf.c | 14 ++++++++
src/conf/node_device_conf.h | 11 ++++++-
src/conf/virnodedeviceobj.c | 4 ++-
src/node_device/node_device_udev.c | 53 ++++++++++++++++++++++++++++++
tools/virsh-nodedev.c | 3 ++
8 files changed, 103 insertions(+), 2 deletions(-)
diff --git a/docs/formatnode.html.in b/docs/formatnode.html.in
index 594427468b..6928bdd69c 100644
--- a/docs/formatnode.html.in
+++ b/docs/formatnode.html.in
@@ -432,6 +432,15 @@
<dd>The device number.</dd>
</dl>
</dd>
+ <dt><code>vdpa</code></dt>
+ <dd>Describes a virtual datapath acceleration (vDPA) network device.
+ <span class="since">Since 6.9.0</span>. Sub-elements
include:
+ <dl>
+ <dt><code>chardev</code></dt>
+ <dd>The path to the character device that is used to access the
+ device.</dd>
+ </dl>
+ </dd>
</dl>
</dd>
</dl>
diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng
index 166e278cf8..0456ddbe93 100644
--- a/docs/schemas/nodedev.rng
+++ b/docs/schemas/nodedev.rng
@@ -86,6 +86,7 @@
<ref name="capmdev"/>
<ref name="capccwdev"/>
<ref name="capcssdev"/>
+ <ref name="capvdpa"/>
</choice>
</element>
</define>
@@ -675,6 +676,15 @@
</element>
</define>
+ <define name="capvdpa">
+ <attribute name="type">
+ <value>vdpa</value>
+ </attribute>
+ <element name="chardev">
+ <ref name="path"/>
+ </element>
+ </define>
+
<define name="address">
<element name="address">
<attribute name="domain"><ref
name="hexuint"/></attribute>
diff --git a/include/libvirt/libvirt-nodedev.h b/include/libvirt/libvirt-nodedev.h
index dd2ffd5782..b73b076f14 100644
--- a/include/libvirt/libvirt-nodedev.h
+++ b/include/libvirt/libvirt-nodedev.h
@@ -82,6 +82,7 @@ typedef enum {
VIR_CONNECT_LIST_NODE_DEVICES_CAP_MDEV = 1 << 14, /* Mediated device
*/
VIR_CONNECT_LIST_NODE_DEVICES_CAP_CCW_DEV = 1 << 15, /* CCW device */
VIR_CONNECT_LIST_NODE_DEVICES_CAP_CSS_DEV = 1 << 16, /* CSS device */
+ VIR_CONNECT_LIST_NODE_DEVICES_CAP_VDPA = 1 << 17, /* vDPA device */
} virConnectListAllNodeDeviceFlags;
int virConnectListAllNodeDevices (virConnectPtr conn,
diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
index 4adfdef572..9e75f6f3a2 100644
--- a/src/conf/node_device_conf.c
+++ b/src/conf/node_device_conf.c
@@ -66,6 +66,7 @@ VIR_ENUM_IMPL(virNodeDevCap,
"mdev",
"ccw",
"css",
+ "vdpa",
);
VIR_ENUM_IMPL(virNodeDevNetCap,
@@ -518,6 +519,13 @@ virNodeDeviceCapMdevDefFormat(virBufferPtr buf,
}
}
+static void
+virNodeDeviceCapVDPADefFormat(virBufferPtr buf,
+ const virNodeDevCapData *data)
+{
+ virBufferEscapeString(buf, "<chardev>%s</chardev>\n",
data->vdpa.chardev);
+}
+
char *
virNodeDeviceDefFormat(const virNodeDeviceDef *def)
{
@@ -611,6 +619,9 @@ virNodeDeviceDefFormat(const virNodeDeviceDef *def)
virBufferAsprintf(&buf, "<devno>0x%04x</devno>\n",
data->ccw_dev.devno);
break;
+ case VIR_NODE_DEV_CAP_VDPA:
+ virNodeDeviceCapVDPADefFormat(&buf, data);
+ break;
case VIR_NODE_DEV_CAP_MDEV_TYPES:
case VIR_NODE_DEV_CAP_FC_HOST:
case VIR_NODE_DEV_CAP_VPORTS:
@@ -1902,6 +1913,7 @@ virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt,
case VIR_NODE_DEV_CAP_FC_HOST:
case VIR_NODE_DEV_CAP_VPORTS:
case VIR_NODE_DEV_CAP_SCSI_GENERIC:
+ case VIR_NODE_DEV_CAP_VDPA:
case VIR_NODE_DEV_CAP_LAST:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("unknown capability type '%d' for
'%s'"),
@@ -2219,6 +2231,7 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
case VIR_NODE_DEV_CAP_VPORTS:
case VIR_NODE_DEV_CAP_CCW_DEV:
case VIR_NODE_DEV_CAP_CSS_DEV:
+ case VIR_NODE_DEV_CAP_VDPA:
case VIR_NODE_DEV_CAP_LAST:
/* This case is here to shutup the compiler */
break;
@@ -2273,6 +2286,7 @@ virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def)
case VIR_NODE_DEV_CAP_MDEV:
case VIR_NODE_DEV_CAP_CCW_DEV:
case VIR_NODE_DEV_CAP_CSS_DEV:
+ case VIR_NODE_DEV_CAP_VDPA:
case VIR_NODE_DEV_CAP_LAST:
break;
}
diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h
index 5484bc340f..3057c728a0 100644
--- a/src/conf/node_device_conf.h
+++ b/src/conf/node_device_conf.h
@@ -65,6 +65,7 @@ typedef enum {
VIR_NODE_DEV_CAP_MDEV, /* Mediated device */
VIR_NODE_DEV_CAP_CCW_DEV, /* s390 CCW device */
VIR_NODE_DEV_CAP_CSS_DEV, /* s390 channel subsystem device */
+ VIR_NODE_DEV_CAP_VDPA, /* vDPA device */
VIR_NODE_DEV_CAP_LAST
} virNodeDevCapType;
@@ -275,6 +276,12 @@ struct _virNodeDevCapCCW {
unsigned int devno;
};
+typedef struct _virNodeDevCapVDPA virNodeDevCapVDPA;
+typedef virNodeDevCapVDPA *virNodeDevCapVDPAPtr;
+struct _virNodeDevCapVDPA {
+ char *chardev;
+};
+
typedef struct _virNodeDevCapData virNodeDevCapData;
typedef virNodeDevCapData *virNodeDevCapDataPtr;
struct _virNodeDevCapData {
@@ -293,6 +300,7 @@ struct _virNodeDevCapData {
virNodeDevCapDRM drm;
virNodeDevCapMdev mdev;
virNodeDevCapCCW ccw_dev;
+ virNodeDevCapVDPA vdpa;
};
};
@@ -369,7 +377,8 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps);
VIR_CONNECT_LIST_NODE_DEVICES_CAP_MDEV_TYPES | \
VIR_CONNECT_LIST_NODE_DEVICES_CAP_MDEV | \
VIR_CONNECT_LIST_NODE_DEVICES_CAP_CCW_DEV | \
- VIR_CONNECT_LIST_NODE_DEVICES_CAP_CSS_DEV)
+ VIR_CONNECT_LIST_NODE_DEVICES_CAP_CSS_DEV | \
+ VIR_CONNECT_LIST_NODE_DEVICES_CAP_VDPA)
int
virNodeDeviceGetSCSIHostCaps(virNodeDevCapSCSIHostPtr scsi_host);
diff --git a/src/conf/virnodedeviceobj.c b/src/conf/virnodedeviceobj.c
index 9af80b8036..6331d1a981 100644
--- a/src/conf/virnodedeviceobj.c
+++ b/src/conf/virnodedeviceobj.c
@@ -711,6 +711,7 @@ virNodeDeviceObjHasCap(const virNodeDeviceObj *obj,
case VIR_NODE_DEV_CAP_MDEV:
case VIR_NODE_DEV_CAP_CCW_DEV:
case VIR_NODE_DEV_CAP_CSS_DEV:
+ case VIR_NODE_DEV_CAP_VDPA:
case VIR_NODE_DEV_CAP_LAST:
break;
}
@@ -862,7 +863,8 @@ virNodeDeviceObjMatch(virNodeDeviceObjPtr obj,
MATCH(MDEV_TYPES) ||
MATCH(MDEV) ||
MATCH(CCW_DEV) ||
- MATCH(CSS_DEV)))
+ MATCH(CSS_DEV) ||
+ MATCH(VDPA)))
return false;
}
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index 29a7eaa07c..b1b8427c05 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -1142,6 +1142,55 @@ udevProcessCSS(struct udev_device *device,
return 0;
}
+
+static int
+udevGetVDPACharDev(const char *sysfs_path,
+ virNodeDevCapDataPtr data)
+{
+ struct dirent *entry;
+ DIR *dir = NULL;
+ int direrr;
+
+ if (virDirOpenIfExists(&dir, sysfs_path) <= 0)
+ return -1;
+
+ while ((direrr = virDirRead(dir, &entry, NULL)) > 0) {
+ if (g_str_has_prefix(entry->d_name, "vhost-vdpa")) {
+ g_autofree char *chardev = g_strdup_printf("/dev/%s",
entry->d_name);
+
+ if (!virFileExists(chardev)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("vDPA chardev path '%s' does not
exist"),
+ chardev);
+ return -1;
+ }
+ VIR_DEBUG("vDPA chardev is at '%s'", chardev);
+
+ data->vdpa.chardev = g_steal_pointer(&chardev);
+ break;
+ }
+ }
+
+ if (direrr < 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+udevProcessVDPA(struct udev_device *device,
+ virNodeDeviceDefPtr def)
+{
+ if (udevGenerateDeviceName(device, def, NULL) != 0)
+ return -1;
+
+ if (udevGetVDPACharDev(def->sysfs_path, &def->caps->data) < 0)
+ return -1;
+
+ return 0;
+}
+
+
static int
udevGetDeviceNodes(struct udev_device *device,
virNodeDeviceDefPtr def)
@@ -1221,6 +1270,8 @@ udevGetDeviceType(struct udev_device *device,
*type = VIR_NODE_DEV_CAP_CCW_DEV;
else if (STREQ_NULLABLE(subsystem, "css"))
*type = VIR_NODE_DEV_CAP_CSS_DEV;
+ else if (STREQ_NULLABLE(subsystem, "vdpa"))
+ *type = VIR_NODE_DEV_CAP_VDPA;
VIR_FREE(subsystem);
}
@@ -1267,6 +1318,8 @@ udevGetDeviceDetails(struct udev_device *device,
return udevProcessCCW(device, def);
case VIR_NODE_DEV_CAP_CSS_DEV:
return udevProcessCSS(device, def);
+ case VIR_NODE_DEV_CAP_VDPA:
+ return udevProcessVDPA(device, def);
case VIR_NODE_DEV_CAP_MDEV_TYPES:
case VIR_NODE_DEV_CAP_SYSTEM:
case VIR_NODE_DEV_CAP_FC_HOST:
diff --git a/tools/virsh-nodedev.c b/tools/virsh-nodedev.c
index 483e36bd53..527bf49fc3 100644
--- a/tools/virsh-nodedev.c
+++ b/tools/virsh-nodedev.c
@@ -464,6 +464,9 @@ cmdNodeListDevices(vshControl *ctl, const vshCmd *cmd G_GNUC_UNUSED)
case VIR_NODE_DEV_CAP_CSS_DEV:
flags |= VIR_CONNECT_LIST_NODE_DEVICES_CAP_CSS_DEV;
break;
+ case VIR_NODE_DEV_CAP_VDPA:
+ flags |= VIR_CONNECT_LIST_NODE_DEVICES_CAP_VDPA;
+ break;
case VIR_NODE_DEV_CAP_LAST:
break;
}
--
2.26.2