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@xxxxxxxxxx> --- 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