xref: /freebsd/lib/libnvmf/libnvmf.h (revision b985c9ca)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2022-2024 Chelsio Communications, Inc.
5  * Written by: John Baldwin <jhb@FreeBSD.org>
6  */
7 
8 #ifndef __LIBNVMF_H__
9 #define	__LIBNVMF_H__
10 
11 #include <sys/uio.h>
12 #include <stdbool.h>
13 #include <stddef.h>
14 #include <dev/nvme/nvme.h>
15 #include <dev/nvmf/nvmf.h>
16 #include <dev/nvmf/nvmf_proto.h>
17 
18 struct nvmf_capsule;
19 struct nvmf_association;
20 struct nvmf_qpair;
21 
22 /*
23  * Parameters shared by all queue-pairs of an association.  Note that
24  * this contains the requested values used to initiate transport
25  * negotiation.
26  */
27 struct nvmf_association_params {
28 	bool sq_flow_control;		/* SQ flow control required. */
29 	bool dynamic_controller_model;	/* Controller only */
30 	uint16_t max_admin_qsize;	/* Controller only */
31 	uint32_t max_io_qsize;		/* Controller only, 0 for discovery */
32 	union {
33 		struct {
34 			uint8_t pda;	/* Tx-side PDA. */
35 			bool header_digests;
36 			bool data_digests;
37 			uint32_t maxr2t;	/* Host only */
38 			uint32_t maxh2cdata;	/* Controller only */
39 		} tcp;
40 	};
41 };
42 
43 /* Parameters specific to a single queue pair of an association. */
44 struct nvmf_qpair_params {
45 	bool admin;			/* Host only */
46 	union {
47 		struct {
48 			int fd;
49 		} tcp;
50 	};
51 };
52 
53 /* Transport-independent APIs. */
54 
55 /*
56  * A host should allocate a new association for each association with
57  * a controller.  After the admin queue has been allocated and the
58  * controller's data has been fetched, it should be passed to
59  * nvmf_update_association to update internal transport-specific
60  * parameters before allocating I/O queues.
61  *
62  * A controller uses a single association to manage all incoming
63  * queues since it is not known until after parsing the CONNECT
64  * command which transport queues are admin vs I/O and which
65  * controller they are created against.
66  */
67 struct nvmf_association *nvmf_allocate_association(enum nvmf_trtype trtype,
68     bool controller, const struct nvmf_association_params *params);
69 void	nvmf_update_assocation(struct nvmf_association *na,
70     const struct nvme_controller_data *cdata);
71 void	nvmf_free_association(struct nvmf_association *na);
72 
73 /* The most recent association-wide error message. */
74 const char *nvmf_association_error(const struct nvmf_association *na);
75 
76 /*
77  * A queue pair represents either an Admin or I/O
78  * submission/completion queue pair.
79  *
80  * Each open qpair holds a reference on its association.  Once queue
81  * pairs are allocated, callers can safely free the association to
82  * ease bookkeeping.
83  *
84  * If nvmf_allocate_qpair fails, a detailed error message can be obtained
85  * from nvmf_association_error.
86  */
87 struct nvmf_qpair *nvmf_allocate_qpair(struct nvmf_association *na,
88     const struct nvmf_qpair_params *params);
89 void	nvmf_free_qpair(struct nvmf_qpair *qp);
90 
91 /*
92  * Capsules are either commands (host -> controller) or responses
93  * (controller -> host).  A single data buffer segment may be
94  * associated with a command capsule.  Transmitted data is not copied
95  * by this API but instead must be preserved until the capsule is
96  * transmitted and freed.
97  */
98 struct nvmf_capsule *nvmf_allocate_command(struct nvmf_qpair *qp,
99     const void *sqe);
100 struct nvmf_capsule *nvmf_allocate_response(struct nvmf_qpair *qp,
101     const void *cqe);
102 void	nvmf_free_capsule(struct nvmf_capsule *nc);
103 int	nvmf_capsule_append_data(struct nvmf_capsule *nc,
104     void *buf, size_t len, bool send);
105 int	nvmf_transmit_capsule(struct nvmf_capsule *nc);
106 int	nvmf_receive_capsule(struct nvmf_qpair *qp, struct nvmf_capsule **ncp);
107 const void *nvmf_capsule_sqe(const struct nvmf_capsule *nc);
108 const void *nvmf_capsule_cqe(const struct nvmf_capsule *nc);
109 
110 /* Return a string name for a transport type. */
111 const char *nvmf_transport_type(uint8_t trtype);
112 
113 /* Validate a NVMe Qualified Name. */
114 bool	nvmf_nqn_valid(const char *nqn);
115 
116 /* Controller-specific APIs. */
117 
118 /*
119  * A controller calls this function to check for any
120  * transport-specific errors (invalid fields) in a received command
121  * capsule.  The callback returns a generic command status value:
122  * NVME_SC_SUCCESS if no error is found.
123  */
124 uint8_t	nvmf_validate_command_capsule(const struct nvmf_capsule *nc);
125 
126 /*
127  * A controller calls this function to query the amount of data
128  * associated with a command capsule.
129  */
130 size_t	nvmf_capsule_data_len(const struct nvmf_capsule *cc);
131 
132 /*
133  * A controller calls this function to receive data associated with a
134  * command capsule (e.g. the data for a WRITE command).  This can
135  * either return in-capsule data or fetch data from the host
136  * (e.g. using a R2T PDU over TCP).  The received command capsule
137  * should be passed in 'nc'.  The received data is stored in '*buf'.
138  */
139 int	nvmf_receive_controller_data(const struct nvmf_capsule *nc,
140     uint32_t data_offset, void *buf, size_t len);
141 
142 /*
143  * A controller calls this function to send data in response to a
144  * command along with a response capsule.  If the data transfer
145  * succeeds, a success response is sent.  If the data transfer fails,
146  * an appropriate error status capsule is sent.  Regardless, a
147  * response capsule is always sent.
148  */
149 int	nvmf_send_controller_data(const struct nvmf_capsule *nc,
150     const void *buf, size_t len);
151 
152 /*
153  * Construct a CQE for a reply to a command capsule in 'nc' with the
154  * completion status 'status'.  This is useful when additional CQE
155  * info is required beyond the completion status.
156  */
157 void	nvmf_init_cqe(void *cqe, const struct nvmf_capsule *nc,
158     uint16_t status);
159 
160 /*
161  * Construct and send a response capsule to a command capsule with
162  * the supplied CQE.
163  */
164 int	nvmf_send_response(const struct nvmf_capsule *nc, const void *cqe);
165 
166 /*
167  * Wait for a single command capsule and return it in *ncp.  This can
168  * fail if an invalid capsule is received or an I/O error occurs.
169  */
170 int	nvmf_controller_receive_capsule(struct nvmf_qpair *qp,
171     struct nvmf_capsule **ncp);
172 
173 /* Send a response capsule from a controller. */
174 int	nvmf_controller_transmit_response(struct nvmf_capsule *nc);
175 
176 /* Construct and send an error response capsule. */
177 int	nvmf_send_error(const struct nvmf_capsule *cc, uint8_t sc_type,
178     uint8_t sc_status);
179 
180 /*
181  * Construct and send an error response capsule using a generic status
182  * code.
183  */
184 int	nvmf_send_generic_error(const struct nvmf_capsule *nc,
185     uint8_t sc_status);
186 
187 /* Construct and send a simple success response capsule. */
188 int	nvmf_send_success(const struct nvmf_capsule *nc);
189 
190 /*
191  * Allocate a new queue pair and wait for the CONNECT command capsule.
192  * If this fails, a detailed error message can be obtained from
193  * nvmf_association_error.  On success, the command capsule is saved
194  * in '*ccp' and the connect data is saved in 'data'.  The caller
195  * must send an explicit response and free the the command capsule.
196  */
197 struct nvmf_qpair *nvmf_accept(struct nvmf_association *na,
198     const struct nvmf_qpair_params *params, struct nvmf_capsule **ccp,
199     struct nvmf_fabric_connect_data *data);
200 
201 /*
202  * Construct and send a response capsule with the Fabrics CONNECT
203  * invalid parameters error status.  If data is true the offset is
204  * relative to the CONNECT data structure, otherwise the offset is
205  * relative to the SQE.
206  */
207 void	nvmf_connect_invalid_parameters(const struct nvmf_capsule *cc,
208     bool data, uint16_t offset);
209 
210 /* Construct and send a response capsule for a successful CONNECT. */
211 int	nvmf_finish_accept(const struct nvmf_capsule *cc, uint16_t cntlid);
212 
213 /* Compute the initial state of CAP for a controller. */
214 uint64_t nvmf_controller_cap(struct nvmf_qpair *qp);
215 
216 /* Generate a serial number string from a host ID. */
217 void	nvmf_controller_serial(char *buf, size_t len, u_long hostid);
218 
219 /*
220  * Populate an Identify Controller data structure for a Discovery
221  * controller.
222  */
223 void	nvmf_init_discovery_controller_data(struct nvmf_qpair *qp,
224     struct nvme_controller_data *cdata);
225 
226 /*
227  * Populate an Identify Controller data structure for an I/O
228  * controller.
229  */
230 void	nvmf_init_io_controller_data(struct nvmf_qpair *qp, const char *serial,
231     const char *subnqn, int nn, uint32_t ioccsz,
232     struct nvme_controller_data *cdata);
233 
234 /*
235  * Validate if a new value for CC is legal given the existing values of
236  * CAP and CC.
237  */
238 bool	nvmf_validate_cc(struct nvmf_qpair *qp, uint64_t cap, uint32_t old_cc,
239     uint32_t new_cc);
240 
241 /* Return the log page id (LID) of a GET_LOG_PAGE command. */
242 uint8_t	nvmf_get_log_page_id(const struct nvme_command *cmd);
243 
244 /* Return the requested data length of a GET_LOG_PAGE command. */
245 uint64_t nvmf_get_log_page_length(const struct nvme_command *cmd);
246 
247 /* Return the requested data offset of a GET_LOG_PAGE command. */
248 uint64_t nvmf_get_log_page_offset(const struct nvme_command *cmd);
249 
250 /* Prepare to handoff a controller qpair. */
251 int	nvmf_handoff_controller_qpair(struct nvmf_qpair *qp,
252     struct nvmf_handoff_controller_qpair *h);
253 
254 /* Host-specific APIs. */
255 
256 /*
257  * Connect to an admin or I/O queue.  If this fails, a detailed error
258  * message can be obtained from nvmf_association_error.
259  */
260 struct nvmf_qpair *nvmf_connect(struct nvmf_association *na,
261     const struct nvmf_qpair_params *params, uint16_t qid, u_int queue_size,
262     const uint8_t hostid[16], uint16_t cntlid, const char *subnqn,
263     const char *hostnqn, uint32_t kato);
264 
265 /* Return the CNTLID for a queue returned from CONNECT. */
266 uint16_t nvmf_cntlid(struct nvmf_qpair *qp);
267 
268 /*
269  * Send a command to the controller.  This can fail with EBUSY if the
270  * submission queue is full.
271  */
272 int	nvmf_host_transmit_command(struct nvmf_capsule *nc);
273 
274 /*
275  * Wait for a response to a command.  If there are no outstanding
276  * commands in the SQ, fails with EWOULDBLOCK.
277  */
278 int	nvmf_host_receive_response(struct nvmf_qpair *qp,
279     struct nvmf_capsule **rcp);
280 
281 /*
282  * Wait for a response to a specific command.  The command must have been
283  * succesfully sent previously.
284  */
285 int	nvmf_host_wait_for_response(struct nvmf_capsule *cc,
286     struct nvmf_capsule **rcp);
287 
288 /* Build a KeepAlive command. */
289 struct nvmf_capsule *nvmf_keepalive(struct nvmf_qpair *qp);
290 
291 /* Read a controller property. */
292 int	nvmf_read_property(struct nvmf_qpair *qp, uint32_t offset, uint8_t size,
293     uint64_t *value);
294 
295 /* Write a controller property. */
296 int	nvmf_write_property(struct nvmf_qpair *qp, uint32_t offset,
297     uint8_t size, uint64_t value);
298 
299 /* Construct a 16-byte HostId from kern.hostuuid. */
300 int	nvmf_hostid_from_hostuuid(uint8_t hostid[16]);
301 
302 /* Construct a NQN from kern.hostuuid. */
303 int	nvmf_nqn_from_hostuuid(char nqn[NVMF_NQN_MAX_LEN]);
304 
305 /* Fetch controller data via IDENTIFY. */
306 int	nvmf_host_identify_controller(struct nvmf_qpair *qp,
307     struct nvme_controller_data *data);
308 
309 /* Fetch namespace data via IDENTIFY. */
310 int	nvmf_host_identify_namespace(struct nvmf_qpair *qp, uint32_t nsid,
311     struct nvme_namespace_data *nsdata);
312 
313 /*
314  * Fetch discovery log page.  The memory for the log page is allocated
315  * by malloc() and returned in *logp.  The caller must free the
316  * memory.
317  */
318 int	nvmf_host_fetch_discovery_log_page(struct nvmf_qpair *qp,
319     struct nvme_discovery_log **logp);
320 
321 /*
322  * Request a desired number of I/O queues via SET_FEATURES.  The
323  * number of actual I/O queues available is returned in *actual on
324  * success.
325  */
326 int	nvmf_host_request_queues(struct nvmf_qpair *qp, u_int requested,
327     u_int *actual);
328 
329 /*
330  * Handoff active host association to the kernel.  This frees the
331  * qpairs (even on error).
332  */
333 int	nvmf_handoff_host(struct nvmf_qpair *admin_qp, u_int num_queues,
334     struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata);
335 
336 /*
337  * Disconnect an active host association previously handed off to the
338  * kernel.  *name is either the name of the device (nvmeX) for this
339  * association or the remote subsystem NQN.
340  */
341 int	nvmf_disconnect_host(const char *host);
342 
343 /*
344  * Disconnect all active host associations previously handed off to
345  * the kernel.
346  */
347 int	nvmf_disconnect_all(void);
348 
349 /*
350  * Fetch reconnect parameters from an existing kernel host to use for
351  * establishing a new association.
352  */
353 int	nvmf_reconnect_params(int fd, struct nvmf_reconnect_params *rparams);
354 
355 /*
356  * Handoff active host association to an existing host in the kernel.
357  * This frees the qpairs (even on error).
358  */
359 int	nvmf_reconnect_host(int fd, struct nvmf_qpair *admin_qp,
360     u_int num_queues, struct nvmf_qpair **io_queues,
361     const struct nvme_controller_data *cdata);
362 
363 #endif /* !__LIBNVMF_H__ */
364