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
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 = {
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}')
except Exception as e:
sys.exit(f'Failed to disconnect: {e}')
+ctrl = None
+host = None
+root = None
```
%{
#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;
}
%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),
// 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