Skip to content

Commit 56e2daf

Browse files
committed
mi: make management interface support optional
The MI code depends on Linux-specific interfaces (networking), which makes porting to other platforms more difficult. Make it optional. This also helps reduce the footprint for minimal setups. Signed-off-by: Daniel Wagner <[email protected]>
1 parent 2a88e6f commit 56e2daf

13 files changed

Lines changed: 237 additions & 152 deletions

File tree

libnvme/examples/meson.build

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -47,46 +47,48 @@ if want_fabrics
4747
)
4848
endif
4949

50-
executable(
51-
'mi-mctp',
52-
['mi-mctp.c'],
53-
dependencies: [
54-
config_dep,
55-
ccan_dep,
56-
libnvme_dep,
57-
],
58-
)
59-
60-
executable(
61-
'mi-mctp-csi-test',
62-
['mi-mctp-csi-test.c'],
63-
dependencies: [
64-
config_dep,
65-
ccan_dep,
66-
libnvme_dep,
67-
threads_dep,
68-
],
69-
)
50+
if want_mi
51+
executable(
52+
'mi-mctp',
53+
['mi-mctp.c'],
54+
dependencies: [
55+
config_dep,
56+
ccan_dep,
57+
libnvme_dep,
58+
],
59+
)
7060

71-
executable(
72-
'mi-mctp-ae',
73-
['mi-mctp-ae.c'],
74-
dependencies: [
75-
config_dep,
76-
ccan_dep,
77-
libnvme_dep,
78-
],
79-
)
61+
executable(
62+
'mi-mctp-csi-test',
63+
['mi-mctp-csi-test.c'],
64+
dependencies: [
65+
config_dep,
66+
ccan_dep,
67+
libnvme_dep,
68+
threads_dep,
69+
],
70+
)
8071

81-
if libdbus_dep.found()
8272
executable(
83-
'mi-conf',
84-
['mi-conf.c'],
73+
'mi-mctp-ae',
74+
['mi-mctp-ae.c'],
8575
dependencies: [
8676
config_dep,
8777
ccan_dep,
8878
libnvme_dep,
89-
libdbus_dep,
9079
],
9180
)
81+
82+
if libdbus_dep.found()
83+
executable(
84+
'mi-conf',
85+
['mi-conf.c'],
86+
dependencies: [
87+
config_dep,
88+
ccan_dep,
89+
libnvme_dep,
90+
libdbus_dep,
91+
],
92+
)
93+
endif
9294
endif

libnvme/src/meson.build

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ else
1919
'nvme/lib.c',
2020
'nvme/linux.c',
2121
'nvme/log.c',
22-
'nvme/mi-mctp.c',
23-
'nvme/mi.c',
2422
'nvme/sysfs.c',
2523
'nvme/tree.c',
2624
'nvme/util.c',
@@ -34,8 +32,6 @@ headers = [
3432
'nvme/lib-types.h',
3533
'nvme/lib.h',
3634
'nvme/linux.h',
37-
'nvme/mi-types.h',
38-
'nvme/mi.h',
3935
'nvme/tree.h',
4036
'nvme/types.h',
4137
'nvme/util.h',
@@ -54,6 +50,21 @@ if want_fabrics
5450
]
5551
endif
5652

53+
if want_mi
54+
sources += [
55+
'nvme/mi-mctp.c',
56+
'nvme/mi.c',
57+
]
58+
headers += [
59+
'nvme/mi-types.h',
60+
'nvme/mi.h',
61+
]
62+
else
63+
sources += [
64+
'nvme/no-mi.c'
65+
]
66+
endif
67+
5768
if liburing_dep.found()
5869
sources += 'nvme/uring.c'
5970
else
@@ -158,14 +169,17 @@ libnvme_test_dep = declare_dependency(
158169
)
159170

160171
mode = 'rw-r--r--'
161-
install_headers(
162-
[
163-
'libnvme-mi.h',
164-
],
165-
install_mode: mode,
166-
)
167172
install_headers(
168173
headers,
169174
subdir: 'nvme',
170175
install_mode: mode,
171176
)
177+
if want_mi
178+
install_headers(
179+
[
180+
'libnvme-mi.h',
181+
],
182+
install_mode: mode,
183+
)
184+
endif
185+

libnvme/src/nvme/lib.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "cleanup.h"
2525
#include "cleanup-linux.h"
2626
#include "private.h"
27+
#include "private-mi.h"
2728
#include "compiler-attributes.h"
2829

2930
static bool libnvme_mi_probe_enabled_default(void)
@@ -73,7 +74,9 @@ __public struct libnvme_global_ctx *libnvme_create_global_ctx(FILE *fp, int log_
7374
__public void libnvme_free_global_ctx(struct libnvme_global_ctx *ctx)
7475
{
7576
struct libnvme_host *h, *_h;
77+
#ifdef CONFIG_MI
7678
libnvme_mi_ep_t ep, tmp;
79+
#endif
7780

7881
if (!ctx)
7982
return;
@@ -86,8 +89,10 @@ __public void libnvme_free_global_ctx(struct libnvme_global_ctx *ctx)
8689

8790
libnvme_for_each_host_safe(ctx, h, _h)
8891
__libnvme_free_host(h);
92+
#ifdef CONFIG_MI
8993
libnvme_mi_for_each_endpoint_safe(ctx, ep, tmp)
9094
libnvme_mi_close(ep);
95+
#endif
9196
free(ctx->config_file);
9297
free(ctx->application);
9398
libnvme_close_uring(ctx);

libnvme/src/nvme/mi-mctp.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828
#include <ccan/endian/endian.h>
2929

30+
#include "private-mi.h"
31+
3032
#ifdef CONFIG_DBUS
3133
#include <dbus/dbus.h>
3234

libnvme/src/nvme/mi.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <libnvme-mi.h>
2121

2222
#include "private.h"
23+
#include "private-mi.h"
2324
#include "compiler-attributes.h"
2425

2526
#define NUM_ENABLES (256u)

libnvme/src/nvme/no-mi.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// SPDX-License-Identifier: LGPL-2.1-or-later
2+
/*
3+
* This file is part of libnvme.
4+
* Copyright (c) 2026 SUSE Software Solutions
5+
*
6+
* Authors: Daniel Wagner <[email protected]>
7+
*/
8+
9+
#include <errno.h>
10+
11+
#include <libnvme.h>
12+
13+
const char *libnvme_mi_status_to_string(int status)
14+
{
15+
return "";
16+
}
17+
18+
int __libnvme_transport_handle_open_mi(struct libnvme_transport_handle *hdl,
19+
const char *devname)
20+
{
21+
return -ENOTSUP;
22+
}
23+
24+
int __libnvme_transport_handle_init_mi(struct libnvme_transport_handle *hdl)
25+
{
26+
return -ENOTSUP;
27+
}
28+
29+
void __libnvme_transport_handle_close_mi(struct libnvme_transport_handle *hdl)
30+
{
31+
}
32+
33+
int libnvme_mi_admin_admin_passthru(struct libnvme_transport_handle *hdl,
34+
struct libnvme_passthru_cmd *cmd)
35+
{
36+
return -ENOTSUP;
37+
}

libnvme/src/nvme/private-mi.h

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// SPDX-License-Identifier: LGPL-2.1-or-later
2+
/*
3+
* This file is part of libnvme.
4+
* Copyright (c) 2021 Code Construct Pty Ltd
5+
*
6+
* Authors: Jeremy Kerr <[email protected]>
7+
*/
8+
9+
#pragma once
10+
11+
#include <poll.h>
12+
13+
#include <sys/socket.h>
14+
15+
#include <ccan/list/list.h>
16+
17+
#include <nvme/mi.h>
18+
19+
/* internal transport API */
20+
struct libnvme_mi_req {
21+
struct nvme_mi_msg_hdr *hdr;
22+
size_t hdr_len;
23+
void *data;
24+
size_t data_len;
25+
__u32 mic;
26+
};
27+
28+
struct libnvme_mi_resp {
29+
struct nvme_mi_msg_hdr *hdr;
30+
size_t hdr_len;
31+
void *data;
32+
size_t data_len;
33+
__u32 mic;
34+
};
35+
36+
struct libnvme_mi_aem_ctx {
37+
struct nvme_mi_aem_occ_list_hdr *occ_header;
38+
struct nvme_mi_aem_occ_data *list_start;
39+
struct nvme_mi_aem_occ_data *list_current;
40+
int list_current_index;
41+
struct libnvme_mi_aem_config callbacks;
42+
int last_generation_num;
43+
struct libnvme_mi_event event;
44+
};
45+
46+
struct libnvme_mi_ep {
47+
struct libnvme_global_ctx *ctx;
48+
const struct libnvme_mi_transport *transport;
49+
void *transport_data;
50+
struct list_node root_entry;
51+
struct list_head controllers;
52+
bool quirks_probed;
53+
bool controllers_scanned;
54+
unsigned int timeout;
55+
unsigned int mprt_max;
56+
unsigned long quirks;
57+
58+
__u8 csi;
59+
60+
/* inter-command delay, for LIBNVME_QUIRK_MIN_INTER_COMMAND_TIME */
61+
unsigned int inter_command_us;
62+
struct timespec last_resp_time;
63+
bool last_resp_time_valid;
64+
65+
struct libnvme_mi_aem_ctx *aem_ctx;
66+
};
67+
68+
struct libnvme_mi_transport {
69+
const char *name;
70+
bool mic_enabled;
71+
int (*submit)(struct libnvme_mi_ep *ep,
72+
struct libnvme_mi_req *req,
73+
struct libnvme_mi_resp *resp);
74+
void (*close)(struct libnvme_mi_ep *ep);
75+
int (*desc_ep)(struct libnvme_mi_ep *ep, char *buf, size_t len);
76+
int (*check_timeout)(struct libnvme_mi_ep *ep, unsigned int timeout);
77+
int (*aem_fd)(struct libnvme_mi_ep *ep);
78+
int (*aem_read)(struct libnvme_mi_ep *ep,
79+
struct libnvme_mi_resp *resp);
80+
int (*aem_purge)(struct libnvme_mi_ep *ep);
81+
};
82+
83+
struct libnvme_mi_ep *libnvme_mi_init_ep(struct libnvme_global_ctx *ctx);
84+
void libnvme_mi_ep_probe(struct libnvme_mi_ep *ep);
85+
86+
/* for tests, we need to calculate the correct MICs */
87+
__u32 libnvme_mi_crc32_update(__u32 crc, void *data, size_t len);
88+
89+
/* we have a facility to mock MCTP socket operations in the mi-mctp transport,
90+
* using this ops type. This should only be used for test, and isn't exposed
91+
* in the shared lib */;
92+
struct mctp_ioc_tag_ctl;
93+
struct __mi_mctp_socket_ops {
94+
int (*msg_socket)(void);
95+
int (*aem_socket)(__u8 eid, unsigned int network);
96+
ssize_t (*sendmsg)(int, const struct msghdr *, int);
97+
ssize_t (*recvmsg)(int, struct msghdr *, int);
98+
int (*poll)(struct pollfd *, nfds_t, int);
99+
int (*ioctl_tag)(int, unsigned long, struct mctp_ioc_tag_ctl *);
100+
};
101+
void __libnvme_mi_mctp_set_ops(const struct __mi_mctp_socket_ops *newops);
102+
103+
/* quirks */
104+
105+
/* Set a minimum time between receiving a response from one command and
106+
* sending the next request. Some devices may ignore new commands sent too soon
107+
* after the previous request, so manually insert a delay
108+
*/
109+
#define LIBNVME_QUIRK_MIN_INTER_COMMAND_TIME (1 << 0)
110+
111+
/* Some devices may not support using CSI 1. Attempting to set an
112+
* endpoint to use this with these devices should return an error
113+
*/
114+
#define LIBNVME_QUIRK_CSI_1_NOT_SUPPORTED (1 << 1)
115+
116+
int __libnvme_transport_handle_open_mi(struct libnvme_transport_handle *hdl,
117+
const char *devname);
118+
int __libnvme_transport_handle_init_mi(struct libnvme_transport_handle *hdl);
119+
void __libnvme_transport_handle_close_mi(struct libnvme_transport_handle *hdl);

0 commit comments

Comments
 (0)