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
<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@redhat.com>
This commit is contained in:
Jonathon Jongsma 2020-10-14 12:08:30 -05:00 committed by Laine Stump
parent 04b1c2d1e2
commit 53aec799fa
8 changed files with 103 additions and 2 deletions

View File

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

View File

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

View File

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

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

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

View File

@ -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;
}