From 53aec799fa31711ffaeacc7ec17ec6d3c2e3cadf Mon Sep 17 00:00:00 2001 From: Jonathon Jongsma Date: Wed, 14 Oct 2020 12:08:30 -0500 Subject: [PATCH] Include vdpa devices in node device list 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 vdpa_vdpa0 /sys/devices/vdpa0 computer vhost_vdpa /dev/vhost-vdpa-0 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 --- 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 @@
The device number.
+
vdpa
+
Describes a virtual datapath acceleration (vDPA) network device. + Since 6.9.0. Sub-elements include: +
+
chardev
+
The path to the character device that is used to access the + device.
+
+
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 @@ + @@ -675,6 +676,15 @@ + + + vdpa + + + + + + 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, "%s\n", data->vdpa.chardev); +} + char * virNodeDeviceDefFormat(const virNodeDeviceDef *def) { @@ -611,6 +619,9 @@ virNodeDeviceDefFormat(const virNodeDeviceDef *def) virBufferAsprintf(&buf, "0x%04x\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 f240abf315..ad3726ba51 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; }