138514Sdfr/*- 259603Sdfr * SPDX-License-Identifier: BSD-2-Clause 338514Sdfr * 438514Sdfr * Copyright (c) 2022-2024 Chelsio Communications, Inc. 538514Sdfr * Written by: John Baldwin <jhb@FreeBSD.org> 638514Sdfr */ 738514Sdfr 838514Sdfr#ifndef __LIBNVMF_H__ 938514Sdfr#define __LIBNVMF_H__ 1038514Sdfr 1138514Sdfr#include <sys/uio.h> 1238514Sdfr#include <stdbool.h> 1338514Sdfr#include <stddef.h> 1438514Sdfr#include <dev/nvme/nvme.h> 1538514Sdfr#include <dev/nvmf/nvmf.h> 1638514Sdfr#include <dev/nvmf/nvmf_proto.h> 1738514Sdfr 1838514Sdfrstruct nvmf_capsule; 1938514Sdfrstruct nvmf_association; 2038514Sdfrstruct nvmf_qpair; 2138514Sdfr 2238514Sdfr/* 2338514Sdfr * Parameters shared by all queue-pairs of an association. Note that 2438514Sdfr * this contains the requested values used to initiate transport 2538514Sdfr * negotiation. 2650477Speter */ 2738514Sdfrstruct nvmf_association_params { 2838514Sdfr bool sq_flow_control; /* SQ flow control required. */ 2959603Sdfr bool dynamic_controller_model; /* Controller only */ 3059603Sdfr uint16_t max_admin_qsize; /* Controller only */ 3138514Sdfr uint32_t max_io_qsize; /* Controller only, 0 for discovery */ 3276166Smarkm union { 3338514Sdfr struct { 3476166Smarkm uint8_t pda; /* Tx-side PDA. */ 3538514Sdfr bool header_digests; 3677642Sdd bool data_digests; 3738514Sdfr uint32_t maxr2t; /* Host only */ 3838514Sdfr uint32_t maxh2cdata; /* Controller only */ 3938514Sdfr } tcp; 4038514Sdfr }; 4138514Sdfr}; 4276166Smarkm 4338514Sdfr/* Parameters specific to a single queue pair of an association. */ 4485735Sgreenstruct nvmf_qpair_params { 4585735Sgreen bool admin; /* Host only */ 4685735Sgreen union { 4738514Sdfr struct { 4839071Sdfr int fd; 4939071Sdfr } tcp; 5052128Speter }; 5139071Sdfr}; 5239071Sdfr 5339071Sdfr/* Transport-independent APIs. */ 5452128Speter 5539071Sdfr/* 5639071Sdfr * A host should allocate a new association for each association with 5776166Smarkm * a controller. After the admin queue has been allocated and the 58102288Speter * controller's data has been fetched, it should be passed to 5939071Sdfr * nvmf_update_association to update internal transport-specific 6059603Sdfr * parameters before allocating I/O queues. 6138514Sdfr * 6238514Sdfr * A controller uses a single association to manage all incoming 6359603Sdfr * queues since it is not known until after parsing the CONNECT 6459603Sdfr * command which transport queues are admin vs I/O and which 6539071Sdfr * controller they are created against. 6639071Sdfr */ 6739071Sdfrstruct nvmf_association *nvmf_allocate_association(enum nvmf_trtype trtype, 6839071Sdfr bool controller, const struct nvmf_association_params *params); 6959603Sdfrvoid nvmf_update_assocation(struct nvmf_association *na, 7080700Sjake const struct nvme_controller_data *cdata); 7180700Sjakevoid nvmf_free_association(struct nvmf_association *na); 7280700Sjake 7380700Sjake/* The most recent association-wide error message. */ 7438514Sdfrconst char *nvmf_association_error(const struct nvmf_association *na); 7538514Sdfr 7640254Speter/* 7739071Sdfr * A queue pair represents either an Admin or I/O 7839071Sdfr * submission/completion queue pair. 7939071Sdfr * 8039071Sdfr * Each open qpair holds a reference on its association. Once queue 8139071Sdfr * pairs are allocated, callers can safely free the association to 8239071Sdfr * ease bookkeeping. 8339071Sdfr * 8439071Sdfr * If nvmf_allocate_qpair fails, a detailed error message can be obtained 8539071Sdfr * from nvmf_association_error. 8639071Sdfr */ 8740254Speterstruct nvmf_qpair *nvmf_allocate_qpair(struct nvmf_association *na, 8840254Speter const struct nvmf_qpair_params *params); 8940254Spetervoid nvmf_free_qpair(struct nvmf_qpair *qp); 9040254Speter 9140254Speter/* 9240292Speter * Capsules are either commands (host -> controller) or responses 9340292Speter * (controller -> host). A single data buffer segment may be 9459603Sdfr * associated with a command capsule. Transmitted data is not copied 9559603Sdfr * by this API but instead must be preserved until the capsule is 9659603Sdfr * transmitted and freed. 9738514Sdfr */ 9838514Sdfrstruct nvmf_capsule *nvmf_allocate_command(struct nvmf_qpair *qp, 9959751Speter const void *sqe); 10059751Speterstruct nvmf_capsule *nvmf_allocate_response(struct nvmf_qpair *qp, 10159751Speter const void *cqe); 10259751Spetervoid nvmf_free_capsule(struct nvmf_capsule *nc); 10359603Sdfrint nvmf_capsule_append_data(struct nvmf_capsule *nc, 10459603Sdfr void *buf, size_t len, bool send); 10559603Sdfrint nvmf_transmit_capsule(struct nvmf_capsule *nc); 10659603Sdfrint nvmf_receive_capsule(struct nvmf_qpair *qp, struct nvmf_capsule **ncp); 10759603Sdfrconst void *nvmf_capsule_sqe(const struct nvmf_capsule *nc); 10838514Sdfrconst void *nvmf_capsule_cqe(const struct nvmf_capsule *nc); 10959603Sdfr 11059751Speter/* Return a string name for a transport type. */ 11178161Speterconst char *nvmf_transport_type(uint8_t trtype); 11278161Speter 11385736Sgreen/* Validate a NVMe Qualified Name. */ 11485736Sgreenbool nvmf_nqn_valid(const char *nqn); 11585736Sgreen 11659603Sdfr/* Controller-specific APIs. */ 11759603Sdfr 11859603Sdfr/* 11959603Sdfr * A controller calls this function to check for any 12059603Sdfr * transport-specific errors (invalid fields) in a received command 12159603Sdfr * capsule. The callback returns a generic command status value: 12259751Speter * NVME_SC_SUCCESS if no error is found. 12359751Speter */ 12459751Speteruint8_t nvmf_validate_command_capsule(const struct nvmf_capsule *nc); 12578161Speter 12685736Sgreen/* 12759603Sdfr * A controller calls this function to query the amount of data 12859603Sdfr * associated with a command capsule. 12959603Sdfr */ 13059603Sdfrsize_t nvmf_capsule_data_len(const struct nvmf_capsule *cc); 13159603Sdfr 13259603Sdfr/* 13359603Sdfr * A controller calls this function to receive data associated with a 13459603Sdfr * command capsule (e.g. the data for a WRITE command). This can 13559603Sdfr * either return in-capsule data or fetch data from the host 13659603Sdfr * (e.g. using a R2T PDU over TCP). The received command capsule 13759603Sdfr * should be passed in 'nc'. The received data is stored in '*buf'. 13859603Sdfr */ 13959603Sdfrint nvmf_receive_controller_data(const struct nvmf_capsule *nc, 14059603Sdfr uint32_t data_offset, void *buf, size_t len); 14159751Speter 14259603Sdfr/* 14359603Sdfr * A controller calls this function to send data in response to a 14466719Sjhb * command along with a response capsule. If the data transfer 14566719Sjhb * succeeds, a success response is sent. If the data transfer fails, 14659603Sdfr * an appropriate error status capsule is sent. Regardless, a 14738514Sdfr * response capsule is always sent. 14859603Sdfr */ 14959603Sdfrint nvmf_send_controller_data(const struct nvmf_capsule *nc, 15059603Sdfr const void *buf, size_t len); 15159603Sdfr 15266719Sjhb/* 15359603Sdfr * Construct a CQE for a reply to a command capsule in 'nc' with the 15459603Sdfr * completion status 'status'. This is useful when additional CQE 15559603Sdfr * info is required beyond the completion status. 15659603Sdfr */ 157104094Sphkvoid nvmf_init_cqe(void *cqe, const struct nvmf_capsule *nc, 15866719Sjhb uint16_t status); 15966719Sjhb 16059603Sdfr/* 16159603Sdfr * Construct and send a response capsule to a command capsule with 16259603Sdfr * the supplied CQE. 16359603Sdfr */ 16459603Sdfrint nvmf_send_response(const struct nvmf_capsule *nc, const void *cqe); 16595228Smarcel 16695228Smarcel/* 16795228Smarcel * Wait for a single command capsule and return it in *ncp. This can 16895228Smarcel * fail if an invalid capsule is received or an I/O error occurs. 16959603Sdfr */ 17038514Sdfrint nvmf_controller_receive_capsule(struct nvmf_qpair *qp, 17138514Sdfr struct nvmf_capsule **ncp); 17238514Sdfr 17338514Sdfr/* Send a response capsule from a controller. */ 17438514Sdfrint nvmf_controller_transmit_response(struct nvmf_capsule *nc); 17538514Sdfr 17638514Sdfr/* Construct and send an error response capsule. */ 17740156Speterint nvmf_send_error(const struct nvmf_capsule *cc, uint8_t sc_type, 17840156Speter uint8_t sc_status); 17940156Speter 18040156Speter/* 18181500Swpaul * Construct and send an error response capsule using a generic status 18281500Swpaul * code. 18340156Speter */ 18438514Sdfrint nvmf_send_generic_error(const struct nvmf_capsule *nc, 18559603Sdfr uint8_t sc_status); 18638514Sdfr 18740156Speter/* Construct and send a simple success response capsule. */ 18882848Speterint nvmf_send_success(const struct nvmf_capsule *nc); 18982848Speter 19082848Speter/* 19182848Speter * Allocate a new queue pair and wait for the CONNECT command capsule. 19282848Speter * If this fails, a detailed error message can be obtained from 19382848Speter * nvmf_association_error. On success, the command capsule is saved 19482848Speter * in '*ccp' and the connect data is saved in 'data'. The caller 19582848Speter * must send an explicit response and free the the command capsule. 19682848Speter */ 19782848Speterstruct nvmf_qpair *nvmf_accept(struct nvmf_association *na, 19882848Speter const struct nvmf_qpair_params *params, struct nvmf_capsule **ccp, 19982848Speter struct nvmf_fabric_connect_data *data); 20082848Speter 20159603Sdfr/* 20282848Speter * Construct and send a response capsule with the Fabrics CONNECT 20359603Sdfr * invalid parameters error status. If data is true the offset is 20482848Speter * relative to the CONNECT data structure, otherwise the offset is 20559603Sdfr * relative to the SQE. 20682848Speter */ 20782848Spetervoid nvmf_connect_invalid_parameters(const struct nvmf_capsule *cc, 20882848Speter bool data, uint16_t offset); 20982848Speter 21040156Speter/* Construct and send a response capsule for a successful CONNECT. */ 21182848Speterint nvmf_finish_accept(const struct nvmf_capsule *cc, uint16_t cntlid); 21282848Speter 21382848Speter/* Compute the initial state of CAP for a controller. */ 21482848Speteruint64_t nvmf_controller_cap(struct nvmf_qpair *qp); 21582848Speter 21682848Speter/* Generate a serial number string from a host ID. */ 21782848Spetervoid nvmf_controller_serial(char *buf, size_t len, u_long hostid); 21882848Speter 21982848Speter/* 22082848Speter * Populate an Identify Controller data structure for a Discovery 22159603Sdfr * controller. 22259603Sdfr */ 22382848Spetervoid nvmf_init_discovery_controller_data(struct nvmf_qpair *qp, 22482848Speter struct nvme_controller_data *cdata); 22582848Speter 22682848Speter/* 22782848Speter * Populate an Identify Controller data structure for an I/O 22882848Speter * controller. 22982848Speter */ 23059603Sdfrvoid nvmf_init_io_controller_data(struct nvmf_qpair *qp, const char *serial, 23182848Speter const char *subnqn, int nn, uint32_t ioccsz, 23282848Speter struct nvme_controller_data *cdata); 23382848Speter 23459603Sdfr/* 23582848Speter * Validate if a new value for CC is legal given the existing values of 23659603Sdfr * CAP and CC. 23738514Sdfr */ 23838514Sdfrbool nvmf_validate_cc(struct nvmf_qpair *qp, uint64_t cap, uint32_t old_cc, 23940156Speter uint32_t new_cc); 24038514Sdfr 24138514Sdfr/* Return the log page id (LID) of a GET_LOG_PAGE command. */ 24259751Speteruint8_t nvmf_get_log_page_id(const struct nvme_command *cmd); 24340254Speter 24440254Speter/* Return the requested data length of a GET_LOG_PAGE command. */ 24540254Speteruint64_t nvmf_get_log_page_length(const struct nvme_command *cmd); 24640254Speter 24740254Speter/* Return the requested data offset of a GET_LOG_PAGE command. */ 24840254Speteruint64_t nvmf_get_log_page_offset(const struct nvme_command *cmd); 24940254Speter 25040254Speter/* Prepare to handoff a controller qpair. */ 25140292Speterint nvmf_handoff_controller_qpair(struct nvmf_qpair *qp, 25240292Speter struct nvmf_handoff_controller_qpair *h); 25340254Speter 25440254Speter/* Host-specific APIs. */ 25540254Speter 25640254Speter/* 25740254Speter * Connect to an admin or I/O queue. If this fails, a detailed error 25840254Speter * message can be obtained from nvmf_association_error. 25940254Speter */ 26040254Speterstruct nvmf_qpair *nvmf_connect(struct nvmf_association *na, 26140254Speter const struct nvmf_qpair_params *params, uint16_t qid, u_int queue_size, 26240254Speter const uint8_t hostid[16], uint16_t cntlid, const char *subnqn, 26340254Speter const char *hostnqn, uint32_t kato); 26440254Speter 26540254Speter/* Return the CNTLID for a queue returned from CONNECT. */ 26640254Speteruint16_t nvmf_cntlid(struct nvmf_qpair *qp); 26740254Speter 26840254Speter/* 26940254Speter * Send a command to the controller. This can fail with EBUSY if the 27040254Speter * submission queue is full. 27140254Speter */ 27240254Speterint nvmf_host_transmit_command(struct nvmf_capsule *nc); 27340254Speter 27440254Speter/* 27540254Speter * Wait for a response to a command. If there are no outstanding 27640254Speter * commands in the SQ, fails with EWOULDBLOCK. 27740254Speter */ 27840254Speterint nvmf_host_receive_response(struct nvmf_qpair *qp, 27940254Speter struct nvmf_capsule **rcp); 28040254Speter 28140254Speter/* 28240254Speter * Wait for a response to a specific command. The command must have been 28340254Speter * succesfully sent previously. 28440254Speter */ 28540254Speterint nvmf_host_wait_for_response(struct nvmf_capsule *cc, 28640254Speter struct nvmf_capsule **rcp); 28740254Speter 28840254Speter/* Build a KeepAlive command. */ 28940254Speterstruct nvmf_capsule *nvmf_keepalive(struct nvmf_qpair *qp); 29040254Speter 29140254Speter/* Read a controller property. */ 29240254Speterint nvmf_read_property(struct nvmf_qpair *qp, uint32_t offset, uint8_t size, 29359603Sdfr uint64_t *value); 29438514Sdfr 29559603Sdfr/* Write a controller property. */ 29639071Sdfrint nvmf_write_property(struct nvmf_qpair *qp, uint32_t offset, 29738514Sdfr uint8_t size, uint64_t value); 29838514Sdfr 29938514Sdfr/* Construct a 16-byte HostId from kern.hostuuid. */ 30038514Sdfrint nvmf_hostid_from_hostuuid(uint8_t hostid[16]); 30138514Sdfr 30238514Sdfr/* Construct a NQN from kern.hostuuid. */ 30380700Sjakeint nvmf_nqn_from_hostuuid(char nqn[NVMF_NQN_MAX_LEN]); 30438514Sdfr 30538514Sdfr/* Fetch controller data via IDENTIFY. */ 30638514Sdfrint nvmf_host_identify_controller(struct nvmf_qpair *qp, 30738514Sdfr struct nvme_controller_data *data); 30838514Sdfr 30938514Sdfr/* Fetch namespace data via IDENTIFY. */ 31038514Sdfrint nvmf_host_identify_namespace(struct nvmf_qpair *qp, uint32_t nsid, 31138514Sdfr struct nvme_namespace_data *nsdata); 31239071Sdfr 31338514Sdfr/* 31440254Speter * Fetch discovery log page. The memory for the log page is allocated 31540254Speter * by malloc() and returned in *logp. The caller must free the 31640254Speter * memory. 31738514Sdfr */ 31839071Sdfrint nvmf_host_fetch_discovery_log_page(struct nvmf_qpair *qp, 31938514Sdfr struct nvme_discovery_log **logp); 32038514Sdfr 32138514Sdfr/* 32238514Sdfr * Request a desired number of I/O queues via SET_FEATURES. The 32339071Sdfr * number of actual I/O queues available is returned in *actual on 32439071Sdfr * success. 32539071Sdfr */ 32639071Sdfrint nvmf_host_request_queues(struct nvmf_qpair *qp, u_int requested, 32739071Sdfr u_int *actual); 32839071Sdfr 32939071Sdfr/* 33039071Sdfr * Handoff active host association to the kernel. This frees the 33139071Sdfr * qpairs (even on error). 33239071Sdfr */ 33339071Sdfrint nvmf_handoff_host(struct nvmf_qpair *admin_qp, u_int num_queues, 33439071Sdfr struct nvmf_qpair **io_queues, const struct nvme_controller_data *cdata); 33539071Sdfr 33639071Sdfr/* 33739071Sdfr * Disconnect an active host association previously handed off to the 33839071Sdfr * kernel. *name is either the name of the device (nvmeX) for this 33939071Sdfr * association or the remote subsystem NQN. 34039071Sdfr */ 34139071Sdfrint nvmf_disconnect_host(const char *host); 34239071Sdfr 34339071Sdfr/* 34439071Sdfr * Disconnect all active host associations previously handed off to 34539071Sdfr * the kernel. 34639071Sdfr */ 34739071Sdfrint nvmf_disconnect_all(void); 34839071Sdfr 34939071Sdfr/* 35039071Sdfr * Fetch reconnect parameters from an existing kernel host to use for 35139071Sdfr * establishing a new association. 35239071Sdfr */ 35339071Sdfrint nvmf_reconnect_params(int fd, struct nvmf_reconnect_params *rparams); 35439071Sdfr 35539071Sdfr/* 35639071Sdfr * Handoff active host association to an existing host in the kernel. 35739071Sdfr * This frees the qpairs (even on error). 35859603Sdfr */ 35959603Sdfrint nvmf_reconnect_host(int fd, struct nvmf_qpair *admin_qp, 36059603Sdfr u_int num_queues, struct nvmf_qpair **io_queues, 36159603Sdfr const struct nvme_controller_data *cdata); 36259603Sdfr 36338514Sdfr#endif /* !__LIBNVMF_H__ */ 36438514Sdfr