[libvirt PATCH v5 6/6] Include vdpa devices in node device list

Jonathon Jongsma jjongsma at redhat.com
Wed Oct 14 17:08:30 UTC 2020


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




More information about the libvir-list mailing list