Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause
2 : * Copyright (C) 2020 Intel Corporation. All rights reserved.
3 : * Copyright (c) 2019, 2021 Mellanox Technologies LTD. All rights reserved.
4 : */
5 :
6 : /** \file
7 : * NVMe-oF Target transport plugin API
8 : */
9 :
10 : #ifndef SPDK_NVMF_TRANSPORT_H_
11 : #define SPDK_NVMF_TRANSPORT_H_
12 :
13 : #include "spdk/bdev.h"
14 : #include "spdk/thread.h"
15 : #include "spdk/nvme_spec.h"
16 : #include "spdk/nvmf.h"
17 : #include "spdk/nvmf_cmd.h"
18 : #include "spdk/nvmf_spec.h"
19 : #include "spdk/memory.h"
20 : #include "spdk/trace.h"
21 :
22 : #ifdef __cplusplus
23 : extern "C" {
24 : #endif
25 :
26 : #define SPDK_NVMF_MAX_SGL_ENTRIES 16
27 :
28 : /* The maximum number of buffers per request */
29 : #define NVMF_REQ_MAX_BUFFERS (SPDK_NVMF_MAX_SGL_ENTRIES * 2 + 1)
30 :
31 : /* Maximum pending AERs that can be migrated */
32 : #define SPDK_NVMF_MIGR_MAX_PENDING_AERS 256
33 :
34 : #define SPDK_NVMF_MAX_ASYNC_EVENTS 4
35 :
36 : /* Some backends require 4K aligned buffers. The iobuf library gives us that
37 : * naturally, but there are buffers allocated other ways that need to use this.
38 : */
39 : #define NVMF_DATA_BUFFER_ALIGNMENT VALUE_4KB
40 : #define NVMF_DATA_BUFFER_MASK (NVMF_DATA_BUFFER_ALIGNMENT - 1LL)
41 :
42 : #define SPDK_NVMF_DEFAULT_ACCEPT_POLL_RATE_US 10000
43 :
44 : union nvmf_h2c_msg {
45 : struct spdk_nvmf_capsule_cmd nvmf_cmd;
46 : struct spdk_nvme_cmd nvme_cmd;
47 : struct spdk_nvmf_fabric_prop_set_cmd prop_set_cmd;
48 : struct spdk_nvmf_fabric_prop_get_cmd prop_get_cmd;
49 : struct spdk_nvmf_fabric_connect_cmd connect_cmd;
50 : struct spdk_nvmf_fabric_auth_send_cmd auth_send_cmd;
51 : struct spdk_nvmf_fabric_auth_recv_cmd auth_recv_cmd;
52 : };
53 : SPDK_STATIC_ASSERT(sizeof(union nvmf_h2c_msg) == 64, "Incorrect size");
54 :
55 : union nvmf_c2h_msg {
56 : struct spdk_nvme_cpl nvme_cpl;
57 : struct spdk_nvmf_fabric_prop_get_rsp prop_get_rsp;
58 : struct spdk_nvmf_fabric_connect_rsp connect_rsp;
59 : };
60 : SPDK_STATIC_ASSERT(sizeof(union nvmf_c2h_msg) == 16, "Incorrect size");
61 :
62 : struct spdk_nvmf_dif_info {
63 : struct spdk_dif_ctx dif_ctx;
64 : uint32_t elba_length;
65 : uint32_t orig_length;
66 : };
67 :
68 : struct spdk_nvmf_stripped_data {
69 : uint32_t iovcnt;
70 : struct iovec iov[NVMF_REQ_MAX_BUFFERS];
71 : };
72 :
73 : enum spdk_nvmf_zcopy_phase {
74 : NVMF_ZCOPY_PHASE_NONE, /* Request is not using ZCOPY */
75 : NVMF_ZCOPY_PHASE_INIT, /* Requesting Buffers */
76 : NVMF_ZCOPY_PHASE_EXECUTE, /* Got buffers processing commands */
77 : NVMF_ZCOPY_PHASE_END_PENDING, /* Releasing buffers */
78 : NVMF_ZCOPY_PHASE_COMPLETE, /* Buffers Released */
79 : NVMF_ZCOPY_PHASE_INIT_FAILED /* Failed to get the buffers */
80 : };
81 :
82 : struct spdk_nvmf_request {
83 : struct spdk_nvmf_qpair *qpair;
84 : uint32_t length;
85 : uint8_t xfer; /* type enum spdk_nvme_data_transfer */
86 : union {
87 : uint8_t raw;
88 : struct {
89 : uint8_t data_from_pool : 1;
90 : uint8_t dif_enabled : 1;
91 : uint8_t first_fused : 1;
92 : uint8_t rsvd : 5;
93 : };
94 : };
95 : uint8_t zcopy_phase; /* type enum spdk_nvmf_zcopy_phase */
96 : uint8_t iovcnt;
97 : union nvmf_h2c_msg *cmd;
98 : union nvmf_c2h_msg *rsp;
99 : STAILQ_ENTRY(spdk_nvmf_request) buf_link;
100 : TAILQ_ENTRY(spdk_nvmf_request) link;
101 :
102 : /* Memory domain which describes payload in this request. If the bdev doesn't support memory
103 : * domains, bdev layer will do the necessary push or pull operation. */
104 : struct spdk_memory_domain *memory_domain;
105 : /* Context to be passed to memory domain operations. */
106 : void *memory_domain_ctx;
107 : struct spdk_accel_sequence *accel_sequence;
108 :
109 : struct iovec iov[NVMF_REQ_MAX_BUFFERS];
110 :
111 : struct spdk_nvmf_stripped_data *stripped_data;
112 :
113 : struct spdk_nvmf_dif_info dif;
114 :
115 : struct spdk_bdev_io_wait_entry bdev_io_wait;
116 : spdk_nvmf_nvme_passthru_cmd_cb cmd_cb_fn;
117 : struct spdk_nvmf_request *first_fused_req;
118 : struct spdk_nvmf_request *req_to_abort;
119 : struct spdk_poller *poller;
120 : struct spdk_bdev_io *zcopy_bdev_io; /* Contains the bdev_io when using ZCOPY */
121 :
122 : /* Internal state that keeps track of the iobuf allocation progress */
123 : struct {
124 : struct spdk_iobuf_entry entry;
125 : uint32_t remaining_length;
126 : } iobuf;
127 :
128 : /* Timeout tracked for connect and abort flows. */
129 : uint64_t timeout_tsc;
130 : };
131 : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_request) == 808, "Incorrect size");
132 :
133 : enum spdk_nvmf_qpair_state {
134 : SPDK_NVMF_QPAIR_UNINITIALIZED = 0,
135 : SPDK_NVMF_QPAIR_CONNECTING,
136 : SPDK_NVMF_QPAIR_AUTHENTICATING,
137 : SPDK_NVMF_QPAIR_ENABLED,
138 : SPDK_NVMF_QPAIR_DEACTIVATING,
139 : SPDK_NVMF_QPAIR_ERROR,
140 : };
141 :
142 : typedef void (*spdk_nvmf_state_change_done)(void *cb_arg, int status);
143 :
144 : struct spdk_nvmf_qpair_auth;
145 :
146 : struct spdk_nvmf_qpair {
147 : uint8_t state; /* ref spdk_nvmf_qpair_state */
148 : uint8_t rsvd;
149 : uint16_t qid;
150 : uint16_t sq_head;
151 : uint16_t sq_head_max;
152 :
153 : struct spdk_nvmf_transport *transport;
154 : struct spdk_nvmf_ctrlr *ctrlr;
155 : struct spdk_nvmf_poll_group *group;
156 :
157 : union {
158 : struct spdk_nvmf_request *first_fused_req;
159 : struct spdk_nvmf_request *connect_req;
160 : };
161 :
162 : TAILQ_HEAD(, spdk_nvmf_request) outstanding;
163 : TAILQ_ENTRY(spdk_nvmf_qpair) link;
164 :
165 : spdk_nvmf_state_change_done state_cb;
166 : void *state_cb_arg;
167 :
168 : bool connect_received;
169 : bool disconnect_started;
170 :
171 : uint16_t trace_id;
172 :
173 : /* Number of IO outstanding at transport level */
174 : uint16_t queue_depth;
175 :
176 : struct spdk_nvmf_qpair_auth *auth;
177 :
178 : struct {
179 : /* Indicates whether numa.id is valid, needed for numa.id == 0 case */
180 : uint32_t id_valid : 1;
181 : int32_t id : 31;
182 : } numa;
183 : };
184 :
185 : static inline int32_t
186 : spdk_nvmf_qpair_get_numa_id(struct spdk_nvmf_qpair *qpair)
187 : {
188 : return qpair->numa.id_valid ? qpair->numa.id : SPDK_ENV_NUMA_ID_ANY;
189 : }
190 :
191 : struct spdk_nvmf_transport_poll_group {
192 : struct spdk_nvmf_transport *transport;
193 : /* Requests that are waiting to obtain a data buffer */
194 : STAILQ_HEAD(, spdk_nvmf_request) pending_buf_queue;
195 : struct spdk_iobuf_channel *buf_cache;
196 : struct spdk_nvmf_poll_group *group;
197 : TAILQ_ENTRY(spdk_nvmf_transport_poll_group) link;
198 : };
199 :
200 : struct spdk_nvmf_poll_group {
201 : struct spdk_thread *thread;
202 : struct spdk_poller *poller;
203 :
204 : TAILQ_HEAD(, spdk_nvmf_transport_poll_group) tgroups;
205 :
206 : /* Array of poll groups indexed by subsystem id (sid) */
207 : struct spdk_nvmf_subsystem_poll_group *sgroups;
208 : uint32_t num_sgroups;
209 :
210 : /* Protected by mutex. Counts qpairs that have connected at a
211 : * transport level, but are not associated with a subsystem
212 : * or controller yet (because the CONNECT capsule hasn't
213 : * been received). */
214 : uint32_t current_unassociated_qpairs;
215 :
216 : /* All of the queue pairs that belong to this poll group */
217 : TAILQ_HEAD(, spdk_nvmf_qpair) qpairs;
218 :
219 : /* Statistics */
220 : struct spdk_nvmf_poll_group_stat stat;
221 :
222 : spdk_nvmf_poll_group_destroy_done_fn destroy_cb_fn;
223 : void *destroy_cb_arg;
224 :
225 : struct spdk_nvmf_tgt *tgt;
226 :
227 : TAILQ_ENTRY(spdk_nvmf_poll_group) link;
228 :
229 : pthread_mutex_t mutex;
230 : };
231 :
232 : struct spdk_nvmf_listener {
233 : struct spdk_nvme_transport_id trid;
234 : uint32_t ref;
235 : char *sock_impl;
236 : TAILQ_ENTRY(spdk_nvmf_listener) link;
237 : };
238 :
239 : /**
240 : * A subset of struct spdk_nvme_ctrlr_data that are emulated by a fabrics device.
241 : */
242 : struct spdk_nvmf_ctrlr_data {
243 : uint8_t aerl;
244 : uint16_t kas;
245 : /** pci vendor id */
246 : uint16_t vid;
247 : /** pci subsystem vendor id */
248 : uint16_t ssvid;
249 : /** ieee oui identifier */
250 : uint8_t ieee[3];
251 : struct spdk_nvme_cdata_oacs oacs;
252 : struct spdk_nvme_cdata_oncs oncs;
253 : struct spdk_nvme_cdata_fuses fuses;
254 : struct spdk_nvme_cdata_sgls sgls;
255 : struct spdk_nvme_cdata_nvmf_specific nvmf_specific;
256 : };
257 :
258 : #define MAX_MEMPOOL_NAME_LENGTH 40
259 :
260 : /* abidiff has a problem with changes in spdk_nvmf_transport_opts, so spdk_nvmf_transport had to be
261 : * added to the suppression list, so if spdk_nvmf_transport is changed, we need to remove the
262 : * suppression and bump up the major version.
263 : */
264 : struct spdk_nvmf_transport {
265 : struct spdk_nvmf_tgt *tgt;
266 : const struct spdk_nvmf_transport_ops *ops;
267 : struct spdk_nvmf_transport_opts opts;
268 :
269 : char iobuf_name[MAX_MEMPOOL_NAME_LENGTH];
270 :
271 : TAILQ_HEAD(, spdk_nvmf_listener) listeners;
272 : TAILQ_ENTRY(spdk_nvmf_transport) link;
273 :
274 : pthread_mutex_t mutex;
275 : };
276 :
277 : typedef void (*spdk_nvmf_transport_qpair_fini_cb)(void *cb_arg);
278 :
279 : struct spdk_nvmf_transport_ops {
280 : /**
281 : * Transport name
282 : */
283 : char name[SPDK_NVMF_TRSTRING_MAX_LEN];
284 :
285 : /**
286 : * Transport type
287 : */
288 : enum spdk_nvme_transport_type type;
289 :
290 : /**
291 : * Initialize transport options to default value
292 : */
293 : void (*opts_init)(struct spdk_nvmf_transport_opts *opts);
294 :
295 : /**
296 : * Create a transport for the given transport opts. Either synchronous
297 : * or asynchronous version shall be implemented.
298 : */
299 : struct spdk_nvmf_transport *(*create)(struct spdk_nvmf_transport_opts *opts);
300 : int (*create_async)(struct spdk_nvmf_transport_opts *opts, spdk_nvmf_transport_create_done_cb cb_fn,
301 : void *cb_arg);
302 :
303 : /**
304 : * Dump transport-specific opts into JSON
305 : */
306 : void (*dump_opts)(struct spdk_nvmf_transport *transport,
307 : struct spdk_json_write_ctx *w);
308 :
309 : /**
310 : * Destroy the transport
311 : */
312 : int (*destroy)(struct spdk_nvmf_transport *transport,
313 : spdk_nvmf_transport_destroy_done_cb cb_fn, void *cb_arg);
314 :
315 : /**
316 : * Instruct the transport to accept new connections at the address
317 : * provided. This may be called multiple times.
318 : */
319 : int (*listen)(struct spdk_nvmf_transport *transport, const struct spdk_nvme_transport_id *trid,
320 : struct spdk_nvmf_listen_opts *opts);
321 :
322 : /**
323 : * Dump transport-specific listen opts into JSON
324 : */
325 : void (*listen_dump_opts)(struct spdk_nvmf_transport *transport,
326 : const struct spdk_nvme_transport_id *trid, struct spdk_json_write_ctx *w);
327 :
328 : /**
329 : * Stop accepting new connections at the given address.
330 : */
331 : void (*stop_listen)(struct spdk_nvmf_transport *transport,
332 : const struct spdk_nvme_transport_id *trid);
333 :
334 : /**
335 : * It is a notification that a listener is being associated with the subsystem.
336 : * Most transports will not need to take any action here, as the enforcement
337 : * of the association is done in the generic code.
338 : *
339 : * Returns a negated errno code to block the association. 0 to allow.
340 : */
341 : int (*listen_associate)(struct spdk_nvmf_transport *transport,
342 : const struct spdk_nvmf_subsystem *subsystem,
343 : const struct spdk_nvme_transport_id *trid);
344 :
345 : /**
346 : * It is a notification that a namespace is being added to the subsystem.
347 : * Most transports will not need to take any action here.
348 : *
349 : * Returns a negated errno code to block the attachment. 0 to allow.
350 : */
351 : int (*subsystem_add_ns)(struct spdk_nvmf_transport *transport,
352 : const struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ns *ns);
353 :
354 : /**
355 : * It is a notification that a namespace has been removed from the subsystem.
356 : * Most transports will not need to take any action here.
357 : */
358 : void (*subsystem_remove_ns)(struct spdk_nvmf_transport *transport,
359 : const struct spdk_nvmf_subsystem *subsystem, uint32_t nsid);
360 :
361 : /**
362 : * Initialize subset of identify controller data.
363 : */
364 : void (*cdata_init)(struct spdk_nvmf_transport *transport, struct spdk_nvmf_subsystem *subsystem,
365 : struct spdk_nvmf_ctrlr_data *cdata);
366 :
367 : /**
368 : * Fill out a discovery log entry for a specific listen address.
369 : */
370 : void (*listener_discover)(struct spdk_nvmf_transport *transport,
371 : struct spdk_nvme_transport_id *trid,
372 : struct spdk_nvmf_discovery_log_page_entry *entry);
373 :
374 : /**
375 : * Create a new poll group
376 : */
377 : struct spdk_nvmf_transport_poll_group *(*poll_group_create)(struct spdk_nvmf_transport *transport,
378 : struct spdk_nvmf_poll_group *group);
379 :
380 : /**
381 : * Get the polling group of the queue pair optimal for the specific transport
382 : */
383 : struct spdk_nvmf_transport_poll_group *(*get_optimal_poll_group)(struct spdk_nvmf_qpair *qpair);
384 :
385 : /**
386 : * Destroy a poll group
387 : */
388 : void (*poll_group_destroy)(struct spdk_nvmf_transport_poll_group *group);
389 :
390 : /**
391 : * Add a qpair to a poll group
392 : */
393 : int (*poll_group_add)(struct spdk_nvmf_transport_poll_group *group,
394 : struct spdk_nvmf_qpair *qpair);
395 :
396 : /**
397 : * Remove a qpair from a poll group
398 : */
399 : int (*poll_group_remove)(struct spdk_nvmf_transport_poll_group *group,
400 : struct spdk_nvmf_qpair *qpair);
401 :
402 : /**
403 : * Poll the group to process I/O
404 : */
405 : int (*poll_group_poll)(struct spdk_nvmf_transport_poll_group *group);
406 :
407 : /*
408 : * Free the request without sending a response
409 : * to the originator. Release memory tied to this request.
410 : */
411 : int (*req_free)(struct spdk_nvmf_request *req);
412 :
413 : /*
414 : * Signal request completion, which sends a response
415 : * to the originator.
416 : */
417 : int (*req_complete)(struct spdk_nvmf_request *req);
418 :
419 : /**
420 : * Callback for the iobuf based queuing of requests awaiting free buffers.
421 : * Called when all requested buffers are allocated for the given request.
422 : * Used only if initial spdk_iobuf_get() call didn't allocate all buffers at once
423 : * and request was queued internally in the iobuf until free buffers become available.
424 : * This callback is optional and not all transports need to implement it.
425 : * If not set then transport implementation must queue such requests internally.
426 : */
427 : void (*req_get_buffers_done)(struct spdk_nvmf_request *req);
428 :
429 : /*
430 : * Deinitialize a connection.
431 : */
432 : void (*qpair_fini)(struct spdk_nvmf_qpair *qpair,
433 : spdk_nvmf_transport_qpair_fini_cb cb_fn,
434 : void *cb_args);
435 :
436 : /*
437 : * Get the peer transport ID for the queue pair.
438 : */
439 : int (*qpair_get_peer_trid)(struct spdk_nvmf_qpair *qpair,
440 : struct spdk_nvme_transport_id *trid);
441 :
442 : /*
443 : * Get the local transport ID for the queue pair.
444 : */
445 : int (*qpair_get_local_trid)(struct spdk_nvmf_qpair *qpair,
446 : struct spdk_nvme_transport_id *trid);
447 :
448 : /*
449 : * Get the listener transport ID that accepted this qpair originally.
450 : */
451 : int (*qpair_get_listen_trid)(struct spdk_nvmf_qpair *qpair,
452 : struct spdk_nvme_transport_id *trid);
453 :
454 : /*
455 : * Abort the request which the abort request specifies.
456 : * This function can complete synchronously or asynchronously, but
457 : * is expected to call spdk_nvmf_request_complete() in the end
458 : * for both cases.
459 : */
460 : void (*qpair_abort_request)(struct spdk_nvmf_qpair *qpair,
461 : struct spdk_nvmf_request *req);
462 :
463 : /*
464 : * Dump transport poll group statistics into JSON.
465 : */
466 : void (*poll_group_dump_stat)(struct spdk_nvmf_transport_poll_group *group,
467 : struct spdk_json_write_ctx *w);
468 :
469 : /*
470 : * A notification that a subsystem has been configured to allow access
471 : * from the given host.
472 : * This callback is optional and not all transports need to implement it.
473 : */
474 : int (*subsystem_add_host)(struct spdk_nvmf_transport *transport,
475 : const struct spdk_nvmf_subsystem *subsystem,
476 : const char *hostnqn,
477 : const struct spdk_json_val *transport_specific);
478 :
479 : /*
480 : * A notification that a subsystem is no longer configured to allow access
481 : * from the given host.
482 : * This callback is optional and not all transports need to implement it.
483 : */
484 : void (*subsystem_remove_host)(struct spdk_nvmf_transport *transport,
485 : const struct spdk_nvmf_subsystem *subsystem,
486 : const char *hostnqn);
487 :
488 : /*
489 : * A callback used to dump subsystem's host data for a specific transport.
490 : * This callback is optional and not all transports need to implement it.
491 : */
492 : void (*subsystem_dump_host)(struct spdk_nvmf_transport *transport,
493 : const struct spdk_nvmf_subsystem *subsystem,
494 : const char *hostnqn, struct spdk_json_write_ctx *w);
495 : };
496 :
497 : /**
498 : * Register the operations for a given transport type.
499 : *
500 : * This function should be invoked by referencing the macro
501 : * SPDK_NVMF_TRANSPORT_REGISTER macro in the transport's .c file.
502 : *
503 : * \param ops The operations associated with an NVMe-oF transport.
504 : */
505 : void spdk_nvmf_transport_register(const struct spdk_nvmf_transport_ops *ops);
506 :
507 : int spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req);
508 :
509 : /**
510 : * Function to be called for each newly discovered qpair.
511 : *
512 : * \param tgt The nvmf target
513 : * \param qpair The newly discovered qpair.
514 : */
515 : void spdk_nvmf_tgt_new_qpair(struct spdk_nvmf_tgt *tgt, struct spdk_nvmf_qpair *qpair);
516 :
517 : static inline bool
518 54 : spdk_nvmf_qpair_is_active(struct spdk_nvmf_qpair *qpair)
519 : {
520 96 : return qpair->state == SPDK_NVMF_QPAIR_CONNECTING ||
521 96 : qpair->state == SPDK_NVMF_QPAIR_AUTHENTICATING ||
522 42 : qpair->state == SPDK_NVMF_QPAIR_ENABLED;
523 : }
524 :
525 : /**
526 : * A subset of struct spdk_nvme_registers that are emulated by a fabrics device.
527 : */
528 : struct spdk_nvmf_registers {
529 : union spdk_nvme_cap_register cap;
530 : union spdk_nvme_vs_register vs;
531 : union spdk_nvme_cc_register cc;
532 : union spdk_nvme_csts_register csts;
533 : union spdk_nvme_aqa_register aqa;
534 : uint64_t asq;
535 : uint64_t acq;
536 : };
537 : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_registers) == 40, "Incorrect size");
538 :
539 : const struct spdk_nvmf_registers *spdk_nvmf_ctrlr_get_regs(struct spdk_nvmf_ctrlr *ctrlr);
540 :
541 : void spdk_nvmf_request_free_buffers(struct spdk_nvmf_request *req,
542 : struct spdk_nvmf_transport_poll_group *group,
543 : struct spdk_nvmf_transport *transport);
544 : int spdk_nvmf_request_get_buffers(struct spdk_nvmf_request *req,
545 : struct spdk_nvmf_transport_poll_group *group,
546 : struct spdk_nvmf_transport *transport,
547 : uint32_t length);
548 :
549 : bool spdk_nvmf_request_get_dif_ctx(struct spdk_nvmf_request *req, struct spdk_dif_ctx *dif_ctx);
550 :
551 : void spdk_nvmf_request_exec(struct spdk_nvmf_request *req);
552 : int spdk_nvmf_request_free(struct spdk_nvmf_request *req);
553 : int spdk_nvmf_request_complete(struct spdk_nvmf_request *req);
554 : void spdk_nvmf_request_zcopy_start(struct spdk_nvmf_request *req);
555 : void spdk_nvmf_request_zcopy_end(struct spdk_nvmf_request *req, bool commit);
556 :
557 : static inline bool
558 8 : spdk_nvmf_request_using_zcopy(const struct spdk_nvmf_request *req)
559 : {
560 8 : return req->zcopy_phase != NVMF_ZCOPY_PHASE_NONE;
561 : }
562 :
563 : /**
564 : * Remove the given qpair from the poll group.
565 : *
566 : * \param qpair The qpair to remove.
567 : */
568 : void spdk_nvmf_poll_group_remove(struct spdk_nvmf_qpair *qpair);
569 :
570 : /**
571 : * Get the NVMe-oF subsystem associated with this controller.
572 : *
573 : * \param ctrlr The NVMe-oF controller
574 : *
575 : * \return The NVMe-oF subsystem
576 : */
577 : struct spdk_nvmf_subsystem *
578 : spdk_nvmf_ctrlr_get_subsystem(struct spdk_nvmf_ctrlr *ctrlr);
579 :
580 : /**
581 : * Get the NVMe-oF controller ID.
582 : *
583 : * \param ctrlr The NVMe-oF controller
584 : *
585 : * \return The NVMe-oF controller ID
586 : */
587 : uint16_t spdk_nvmf_ctrlr_get_id(struct spdk_nvmf_ctrlr *ctrlr);
588 :
589 : struct spdk_nvmf_ctrlr_feat {
590 : union spdk_nvme_feat_arbitration arbitration;
591 : union spdk_nvme_feat_power_management power_management;
592 : union spdk_nvme_feat_error_recovery error_recovery;
593 : union spdk_nvme_feat_volatile_write_cache volatile_write_cache;
594 : union spdk_nvme_feat_number_of_queues number_of_queues;
595 : union spdk_nvme_feat_interrupt_coalescing interrupt_coalescing;
596 : union spdk_nvme_feat_interrupt_vector_configuration interrupt_vector_configuration;
597 : union spdk_nvme_feat_write_atomicity write_atomicity;
598 : union spdk_nvme_feat_async_event_configuration async_event_configuration;
599 : union spdk_nvme_feat_keep_alive_timer keep_alive_timer;
600 : };
601 : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_ctrlr_feat) == 40, "Incorrect size");
602 :
603 : /*
604 : * Migration data structure used to save & restore a NVMe-oF controller.
605 : *
606 : * The data structure is experimental.
607 : *
608 : */
609 : struct spdk_nvmf_ctrlr_migr_data {
610 : /* `data_size` is valid size of `spdk_nvmf_ctrlr_migr_data` without counting `unused`.
611 : * We use this field to migrate `spdk_nvmf_ctrlr_migr_data` from source VM and restore
612 : * it in destination VM.
613 : */
614 : uint32_t data_size;
615 : /* `regs_size` is valid size of `spdk_nvmf_registers`. */
616 : uint32_t regs_size;
617 : /* `feat_size` is valid size of `spdk_nvmf_ctrlr_feat`. */
618 : uint32_t feat_size;
619 : uint32_t reserved;
620 :
621 : struct spdk_nvmf_registers regs;
622 : uint8_t regs_reserved[216];
623 :
624 : struct spdk_nvmf_ctrlr_feat feat;
625 : uint8_t feat_reserved[216];
626 :
627 : uint16_t cntlid;
628 : uint8_t acre;
629 : uint8_t num_aer_cids;
630 : uint32_t num_async_events;
631 :
632 : union spdk_nvme_async_event_completion async_events[SPDK_NVMF_MIGR_MAX_PENDING_AERS];
633 : uint16_t aer_cids[SPDK_NVMF_MAX_ASYNC_EVENTS];
634 : uint64_t notice_aen_mask;
635 :
636 : uint8_t unused[2516];
637 : };
638 : SPDK_STATIC_ASSERT(offsetof(struct spdk_nvmf_ctrlr_migr_data,
639 : regs) - offsetof(struct spdk_nvmf_ctrlr_migr_data, data_size) == 16, "Incorrect header size");
640 : SPDK_STATIC_ASSERT(offsetof(struct spdk_nvmf_ctrlr_migr_data,
641 : feat) - offsetof(struct spdk_nvmf_ctrlr_migr_data, regs) == 256, "Incorrect regs size");
642 : SPDK_STATIC_ASSERT(offsetof(struct spdk_nvmf_ctrlr_migr_data,
643 : cntlid) - offsetof(struct spdk_nvmf_ctrlr_migr_data, feat) == 256, "Incorrect feat size");
644 : SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_ctrlr_migr_data) == 4096, "Incorrect size");
645 :
646 : /**
647 : * Save the NVMe-oF controller state and configuration.
648 : *
649 : * The API is experimental.
650 : *
651 : * It is allowed to save the data only when the nvmf subsystem is in paused
652 : * state i.e. there are no outstanding cmds in nvmf layer (other than aer),
653 : * pending async event completions are getting blocked.
654 : *
655 : * To preserve thread safety this function must be executed on the same thread
656 : * the NVMe-OF controller was created.
657 : *
658 : * \param ctrlr The NVMe-oF controller
659 : * \param data The NVMe-oF controller state and configuration to be saved
660 : *
661 : * \return 0 on success or a negated errno on failure.
662 : */
663 : int spdk_nvmf_ctrlr_save_migr_data(struct spdk_nvmf_ctrlr *ctrlr,
664 : struct spdk_nvmf_ctrlr_migr_data *data);
665 :
666 : /**
667 : * Restore the NVMe-oF controller state and configuration.
668 : *
669 : * The API is experimental.
670 : *
671 : * It is allowed to restore the data only when the nvmf subsystem is in paused
672 : * state.
673 : *
674 : * To preserve thread safety this function must be executed on the same thread
675 : * the NVMe-OF controller was created.
676 : *
677 : * AERs shall be restored using spdk_nvmf_request_exec after this function is executed.
678 : *
679 : * \param ctrlr The NVMe-oF controller
680 : * \param data The NVMe-oF controller state and configuration to be restored
681 : *
682 : * \return 0 on success or a negated errno on failure.
683 : */
684 : int spdk_nvmf_ctrlr_restore_migr_data(struct spdk_nvmf_ctrlr *ctrlr,
685 : const struct spdk_nvmf_ctrlr_migr_data *data);
686 :
687 : static inline enum spdk_nvme_data_transfer
688 10 : spdk_nvmf_req_get_xfer(struct spdk_nvmf_request *req) {
689 : enum spdk_nvme_data_transfer xfer;
690 10 : struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
691 10 : struct spdk_nvme_sgl_descriptor *sgl = &cmd->dptr.sgl1;
692 :
693 : /* Figure out data transfer direction */
694 10 : if (cmd->opc == SPDK_NVME_OPC_FABRIC)
695 : {
696 2 : xfer = spdk_nvme_opc_get_data_transfer(req->cmd->nvmf_cmd.fctype);
697 : } else
698 : {
699 8 : xfer = spdk_nvme_opc_get_data_transfer(cmd->opc);
700 : }
701 :
702 10 : if (xfer == SPDK_NVME_DATA_NONE)
703 : {
704 0 : return xfer;
705 : }
706 :
707 : /* Even for commands that may transfer data, they could have specified 0 length.
708 : * We want those to show up with xfer SPDK_NVME_DATA_NONE.
709 : */
710 10 : switch (sgl->generic.type)
711 : {
712 4 : case SPDK_NVME_SGL_TYPE_DATA_BLOCK:
713 : case SPDK_NVME_SGL_TYPE_BIT_BUCKET:
714 : case SPDK_NVME_SGL_TYPE_SEGMENT:
715 : case SPDK_NVME_SGL_TYPE_LAST_SEGMENT:
716 : case SPDK_NVME_SGL_TYPE_TRANSPORT_DATA_BLOCK:
717 4 : if (sgl->unkeyed.length == 0) {
718 0 : xfer = SPDK_NVME_DATA_NONE;
719 : }
720 4 : break;
721 6 : case SPDK_NVME_SGL_TYPE_KEYED_DATA_BLOCK:
722 6 : if (sgl->keyed.length == 0) {
723 0 : xfer = SPDK_NVME_DATA_NONE;
724 : }
725 6 : break;
726 : }
727 :
728 10 : return xfer;
729 : }
730 :
731 : /**
732 : * Complete Asynchronous Event as Error.
733 : *
734 : * \param ctrlr Controller whose AER is going to be completed.
735 : * \param info Asynchronous Event Error Information to be reported.
736 : *
737 : * \return int. 0 if it completed successfully, or negative errno if it failed.
738 : */
739 : int spdk_nvmf_ctrlr_async_event_error_event(struct spdk_nvmf_ctrlr *ctrlr,
740 : enum spdk_nvme_async_event_info_error info);
741 :
742 : /**
743 : * Abort outstanding Asynchronous Event Requests (AERs).
744 : *
745 : * Completes AERs with ABORTED_BY_REQUEST status code.
746 : *
747 : * \param ctrlr Controller whose AERs are going to be aborted.
748 : */
749 : void spdk_nvmf_ctrlr_abort_aer(struct spdk_nvmf_ctrlr *ctrlr);
750 :
751 : /*
752 : * Macro used to register new transports.
753 : */
754 : #define SPDK_NVMF_TRANSPORT_REGISTER(name, transport_ops) \
755 : static void __attribute__((constructor)) _spdk_nvmf_transport_register_##name(void) \
756 : { \
757 : spdk_nvmf_transport_register(transport_ops); \
758 : }
759 :
760 : #ifdef __cplusplus
761 : }
762 : #endif
763 :
764 : #endif
|