]> www.infradead.org Git - users/sagi/libnvme.git/commitdiff
python: Use nvmf_get_discovery_wargs()
authorMartin Belanger <martin.belanger@dell.com>
Mon, 26 Sep 2022 12:30:39 +0000 (08:30 -0400)
committerMartin Belanger <martin.belanger@dell.com>
Mon, 26 Sep 2022 12:30:39 +0000 (08:30 -0400)
Refactor code to use nvmf_get_discovery_wargs() which allows setting
the LSP field. Needed for TP8010 support (i.e. setting PLEO bit).

Also, added supported_log_pages() which is used to determine
whether the PLEO bit is supported (PLOES).

Signed-off-by: Martin Belanger <martin.belanger@dell.com>
examples/discover-loop.py
libnvme/README.md
libnvme/nvme.i

index 22c51e64b3bfdd4de3e34ad83dcb85694134f959..9b007c922a37eaac4ac8b5820277867a0576ab6a 100644 (file)
@@ -17,20 +17,44 @@ License for the specific language governing permissions and limitations
 under the License.
 '''
 
+import sys
+import pprint
 from libnvme import nvme
+
+def disc_supp_str(disc_log_page_support):
+    d = {
+        nvme.NVMF_LOG_DISC_LID_EXTDLPES: "Extended Discovery Log Page Entry Supported (EXTDLPES)",
+        nvme.NVMF_LOG_DISC_LID_PLEOS:    "Port Local Entries Only Supported (PLEOS)",
+        nvme.NVMF_LOG_DISC_LID_ALLSUBES: "All NVM Subsystem Entries Supported (ALLSUBES)",
+    }
+    return [txt for msk, txt in d.items() if disc_log_page_support & msk]
+
 r = nvme.root()
 h = nvme.host(r)
-c = nvme.ctrl(nvme.NVME_DISC_SUBSYS_NAME, 'loop')
+c = nvme.ctrl(r, nvme.NVME_DISC_SUBSYS_NAME, 'loop')
 try:
     c.connect(h)
-except:
-    sys.exit("Failed to connect!")
+except Exception as e:
+    sys.exit(f'Failed to connect: {e}')
 
 print("connected to %s subsys %s" % (c.name, c.subsystem.name))
+
+slp = c.supported_log_pages()
+disc_log_page_support = slp[nvme.NVME_LOG_LID_DISCOVER] if slp is not None else 0
+print(f"LID {nvme.NVME_LOG_LID_DISCOVER}h (Discovery), supports: {disc_supp_str(disc_log_page_support)}")
+
+try:
+    lsp = nvme.NVMF_LOG_DISC_LSP_PLEO if disc_log_page_support & nvme.NVMF_LOG_DISC_LID_PLEOS else 0
+    d = c.discover(lsp=lsp)
+    print(pprint.pformat(d))
+except Exception as e:
+    sys.exit(f'Failed to discover: {e}')
+
 try:
-    d = c.discover()
-    print (d)
-except:
-    print("Failed to discover!")
-    pass
 c.disconnect()
+except Exception as e:
+    sys.exit(f'Failed to disconnect: {e}')
+
+c = None
+h = None
+r = None
index f61e5cc8cb0ab21808f2ef55e4503197b0961e30..9071c36291a0403a9545087cdf5318a5c9ae1d9e 100644 (file)
@@ -10,16 +10,24 @@ import sys
 import pprint
 from libnvme import nvme
 
+def disc_supp_str(disc_log_page_support):
+    d = {
+        nvme.NVMF_LOG_DISC_LID_EXTDLPES: "Extended Discovery Log Page Entry Supported (EXTDLPES)",
+        nvme.NVMF_LOG_DISC_LID_PLEOS:    "Port Local Entries Only Supported (PLEOS)",
+        nvme.NVMF_LOG_DISC_LID_ALLSUBES: "All NVM Subsystem Entries Supported (ALLSUBES)",
+    }
+    return [txt for msk, txt in d.items() if disc_log_page_support & msk]
+
 root = nvme.root()      # This is a singleton
 root.log_level('debug') # Optional: extra debug info
 
 host = nvme.host(root)      # This "may be" a singleton. 
-sybsysnqn  = [string]       # e.g. 'nqn.2014-08.org.nvmexpress.discovery', nvme.NVME_DISC_SUBSYS_NAME, ...
-transport  = [string]       # One of: 'tcp, 'rdma', 'fc', 'loop'.
+subsysnqn  = [string]       # e.g. nvme.NVME_DISC_SUBSYS_NAME, ...
+transport  = [string]       # One of: 'tcp', 'rdma', 'fc', 'loop'.
 traddr     = [IPv4 or IPv6] # e.g. '192.168.10.10', 'fd2e:853b:3cad:e135:506a:65ee:29f2:1b18', ...
 trsvcid    = [string]          # e.g. '8009', '4420', ...
 host_iface = [interface]    # e.g. 'eth1', ens256', ...
-ctrl = nvme.ctrl(subsysnqn=subsysnqn, transport=transport, traddr=traddr, trsvcid=trsvcid, host_iface=host_iface)
+ctrl = nvme.ctrl(root, subsysnqn=subsysnqn, transport=transport, traddr=traddr, trsvcid=trsvcid, host_iface=host_iface)
 
 try:
     cfg = {
@@ -31,8 +39,17 @@ try:
 except Exception as e:
     sys.exit(f'Failed to connect: {e}')
 
+supported_log_pages = ctrl.supported_log_pages()
+if supported_log_pages is not None:
+    disc_log_page_support = supported_log_pages[nvme.NVME_LOG_LID_DISCOVER]
+    print(f"LID {nvme.NVME_LOG_LID_DISCOVER:02x}h (Discovery), supports: {disc_supp_str(disc_log_page_support)}")
+
 try:
-    log_pages = ctrl.discover()
+    if disc_log_page_support and (disc_log_page_support & nvme.NVMF_LOG_DISC_LID_PLEOS):
+        lsp = nvme.NVMF_LOG_DISC_LSP_PLEO
+    else:
+        lsp = 0
+    log_pages = ctrl.discover(lsp=lsp)
     print(pprint.pformat(log_pages))
 except Exception as e:
     sys.exit(f'Failed to retrieve log pages: {e}')
@@ -42,5 +59,8 @@ try:
 except Exception as e:
     sys.exit(f'Failed to disconnect: {e}')
 
+ctrl = None
+host = None
+root = None
 ```
 
index c74a7e80f0d56b902262fa9a34ec9cab95182433..6f20e2cccf8912404d19f213c76cdbadbc8b8c8b 100644 (file)
 
 %{
 #include <ccan/list/list.h>
+#include <ccan/endian/endian.h>
 #include "nvme/tree.h"
 #include "nvme/fabrics.h"
 #include "nvme/private.h"
 #include "nvme/log.h"
+#include "nvme/ioctl.h"
+#include "nvme/types.h"
 
 static int host_iter_err = 0;
 static int subsys_iter_err = 0;
@@ -625,25 +628,46 @@ struct nvme_ns {
   }
 
   %newobject discover;
-  struct nvmf_discovery_log *discover(int max_retries = 6) {
-    struct nvmf_discovery_log *logp = NULL;
+  struct nvmf_discovery_log *discover(int lsp = 0, int max_retries = 6) {
+    struct nvme_get_discovery_args args = {
+      .c = $self,
+      .args_size = sizeof(args),
+      .max_retries = max_retries,
+      .result = NULL,
+      .timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
+      .lsp = lsp,
+    };
+    struct nvmf_discovery_log *logp = nvmf_get_discovery_wargs(&args);
+    if (logp == NULL)
+      discover_err = 1;
+    return logp;
+  }
+
+  %feature("autodoc", "@return: List of supported log pages") supported_log_pages;
+  PyObject * supported_log_pages(bool rae=true) {
+    struct nvme_supported_log_pages log;
+    PyObject *obj = NULL;
     int ret = 0;
-    ret = nvmf_get_discovery_log($self, &logp, max_retries);
+
+    ret = nvme_get_log_supported_log_pages(nvme_ctrl_get_fd($self), rae, &log);
     if (ret < 0) {
-      discover_err = 1;
-      return NULL;
+      Py_RETURN_NONE;
     }
-    return logp;
+
+    obj = PyList_New(NVME_LOG_SUPPORTED_LOG_PAGES_MAX);
+    if (!obj)
+      Py_RETURN_NONE;
+
+    for (int i = 0; i < NVME_LOG_SUPPORTED_LOG_PAGES_MAX; i++)
+      PyList_SetItem(obj, i, PyLong_FromLong(le32_to_cpu(log.lid_support[i]))); /* steals ref. */
+
+    return obj;
   }
-  char *__str__() {
-    static char tmp[1024];
 
-    if ($self->address)
-      sprintf(tmp, "nvme_ctrl(transport=%s,%s)", $self->transport,
-             $self->address);
-    else
-      sprintf(tmp, "nvme_ctrl(transport=%s)", $self->transport);
-    return tmp;
+  PyObject *__str__() {
+    return $self->address ?
+      PyUnicode_FromFormat("nvme_ctrl(transport=%s,%s)", $self->transport, $self->address) :
+      PyUnicode_FromFormat("nvme_ctrl(transport=%s)", $self->transport);
   }
   struct ctrl_iter __iter__() {
     struct ctrl_iter ret = { .subsystem = nvme_ctrl_get_subsystem($self),
@@ -710,9 +734,6 @@ struct nvme_ns {
 
 
 // We want to swig all the #define and enum from types.h, but none of the structs.
-%{
-#include "nvme/types.h"
-%}
 #define __attribute__(x)
 %rename($ignore, %$isclass) "";     // ignore all classes/structs
 %rename($ignore, %$isfunction) "";  // ignore all functions