xref: /freebsd/lib/libnvmf/nvmf_transport.c (revision 2da066ef)
1*2da066efSJohn Baldwin /*-
2*2da066efSJohn Baldwin  * SPDX-License-Identifier: BSD-2-Clause
3*2da066efSJohn Baldwin  *
4*2da066efSJohn Baldwin  * Copyright (c) 2022-2024 Chelsio Communications, Inc.
5*2da066efSJohn Baldwin  * Written by: John Baldwin <jhb@FreeBSD.org>
6*2da066efSJohn Baldwin  */
7*2da066efSJohn Baldwin 
8*2da066efSJohn Baldwin #include <sys/refcount.h>
9*2da066efSJohn Baldwin #include <assert.h>
10*2da066efSJohn Baldwin #include <errno.h>
11*2da066efSJohn Baldwin #include <stdarg.h>
12*2da066efSJohn Baldwin #include <stdio.h>
13*2da066efSJohn Baldwin #include <stdlib.h>
14*2da066efSJohn Baldwin #include <string.h>
15*2da066efSJohn Baldwin 
16*2da066efSJohn Baldwin #include "libnvmf.h"
17*2da066efSJohn Baldwin #include "internal.h"
18*2da066efSJohn Baldwin 
19*2da066efSJohn Baldwin struct nvmf_association *
nvmf_allocate_association(enum nvmf_trtype trtype,bool controller,const struct nvmf_association_params * params)20*2da066efSJohn Baldwin nvmf_allocate_association(enum nvmf_trtype trtype, bool controller,
21*2da066efSJohn Baldwin     const struct nvmf_association_params *params)
22*2da066efSJohn Baldwin {
23*2da066efSJohn Baldwin 	struct nvmf_transport_ops *ops;
24*2da066efSJohn Baldwin 	struct nvmf_association *na;
25*2da066efSJohn Baldwin 
26*2da066efSJohn Baldwin 	switch (trtype) {
27*2da066efSJohn Baldwin 	case NVMF_TRTYPE_TCP:
28*2da066efSJohn Baldwin 		ops = &tcp_ops;
29*2da066efSJohn Baldwin 		break;
30*2da066efSJohn Baldwin 	default:
31*2da066efSJohn Baldwin 		errno = EINVAL;
32*2da066efSJohn Baldwin 		return (NULL);
33*2da066efSJohn Baldwin 	}
34*2da066efSJohn Baldwin 
35*2da066efSJohn Baldwin 	na = ops->allocate_association(controller, params);
36*2da066efSJohn Baldwin 	if (na == NULL)
37*2da066efSJohn Baldwin 		return (NULL);
38*2da066efSJohn Baldwin 
39*2da066efSJohn Baldwin 	na->na_ops = ops;
40*2da066efSJohn Baldwin 	na->na_trtype = trtype;
41*2da066efSJohn Baldwin 	na->na_controller = controller;
42*2da066efSJohn Baldwin 	na->na_params = *params;
43*2da066efSJohn Baldwin 	na->na_last_error = NULL;
44*2da066efSJohn Baldwin 	refcount_init(&na->na_refs, 1);
45*2da066efSJohn Baldwin 	return (na);
46*2da066efSJohn Baldwin }
47*2da066efSJohn Baldwin 
48*2da066efSJohn Baldwin void
nvmf_update_assocation(struct nvmf_association * na,const struct nvme_controller_data * cdata)49*2da066efSJohn Baldwin nvmf_update_assocation(struct nvmf_association *na,
50*2da066efSJohn Baldwin     const struct nvme_controller_data *cdata)
51*2da066efSJohn Baldwin {
52*2da066efSJohn Baldwin 	na->na_ops->update_association(na, cdata);
53*2da066efSJohn Baldwin }
54*2da066efSJohn Baldwin 
55*2da066efSJohn Baldwin void
nvmf_free_association(struct nvmf_association * na)56*2da066efSJohn Baldwin nvmf_free_association(struct nvmf_association *na)
57*2da066efSJohn Baldwin {
58*2da066efSJohn Baldwin 	if (refcount_release(&na->na_refs)) {
59*2da066efSJohn Baldwin 		free(na->na_last_error);
60*2da066efSJohn Baldwin 		na->na_ops->free_association(na);
61*2da066efSJohn Baldwin 	}
62*2da066efSJohn Baldwin }
63*2da066efSJohn Baldwin 
64*2da066efSJohn Baldwin const char *
nvmf_association_error(const struct nvmf_association * na)65*2da066efSJohn Baldwin nvmf_association_error(const struct nvmf_association *na)
66*2da066efSJohn Baldwin {
67*2da066efSJohn Baldwin 	return (na->na_last_error);
68*2da066efSJohn Baldwin }
69*2da066efSJohn Baldwin 
70*2da066efSJohn Baldwin void
na_clear_error(struct nvmf_association * na)71*2da066efSJohn Baldwin na_clear_error(struct nvmf_association *na)
72*2da066efSJohn Baldwin {
73*2da066efSJohn Baldwin 	free(na->na_last_error);
74*2da066efSJohn Baldwin 	na->na_last_error = NULL;
75*2da066efSJohn Baldwin }
76*2da066efSJohn Baldwin 
77*2da066efSJohn Baldwin void
na_error(struct nvmf_association * na,const char * fmt,...)78*2da066efSJohn Baldwin na_error(struct nvmf_association *na, const char *fmt, ...)
79*2da066efSJohn Baldwin {
80*2da066efSJohn Baldwin 	va_list ap;
81*2da066efSJohn Baldwin 	char *str;
82*2da066efSJohn Baldwin 
83*2da066efSJohn Baldwin 	if (na->na_last_error != NULL)
84*2da066efSJohn Baldwin 		return;
85*2da066efSJohn Baldwin 	va_start(ap, fmt);
86*2da066efSJohn Baldwin 	vasprintf(&str, fmt, ap);
87*2da066efSJohn Baldwin 	va_end(ap);
88*2da066efSJohn Baldwin 	na->na_last_error = str;
89*2da066efSJohn Baldwin }
90*2da066efSJohn Baldwin 
91*2da066efSJohn Baldwin struct nvmf_qpair *
nvmf_allocate_qpair(struct nvmf_association * na,const struct nvmf_qpair_params * params)92*2da066efSJohn Baldwin nvmf_allocate_qpair(struct nvmf_association *na,
93*2da066efSJohn Baldwin     const struct nvmf_qpair_params *params)
94*2da066efSJohn Baldwin {
95*2da066efSJohn Baldwin 	struct nvmf_qpair *qp;
96*2da066efSJohn Baldwin 
97*2da066efSJohn Baldwin 	na_clear_error(na);
98*2da066efSJohn Baldwin 	qp = na->na_ops->allocate_qpair(na, params);
99*2da066efSJohn Baldwin 	if (qp == NULL)
100*2da066efSJohn Baldwin 		return (NULL);
101*2da066efSJohn Baldwin 
102*2da066efSJohn Baldwin 	refcount_acquire(&na->na_refs);
103*2da066efSJohn Baldwin 	qp->nq_association = na;
104*2da066efSJohn Baldwin 	qp->nq_admin = params->admin;
105*2da066efSJohn Baldwin 	TAILQ_INIT(&qp->nq_rx_capsules);
106*2da066efSJohn Baldwin 	return (qp);
107*2da066efSJohn Baldwin }
108*2da066efSJohn Baldwin 
109*2da066efSJohn Baldwin void
nvmf_free_qpair(struct nvmf_qpair * qp)110*2da066efSJohn Baldwin nvmf_free_qpair(struct nvmf_qpair *qp)
111*2da066efSJohn Baldwin {
112*2da066efSJohn Baldwin 	struct nvmf_association *na;
113*2da066efSJohn Baldwin 	struct nvmf_capsule *nc, *tc;
114*2da066efSJohn Baldwin 
115*2da066efSJohn Baldwin 	TAILQ_FOREACH_SAFE(nc, &qp->nq_rx_capsules, nc_link, tc) {
116*2da066efSJohn Baldwin 		TAILQ_REMOVE(&qp->nq_rx_capsules, nc, nc_link);
117*2da066efSJohn Baldwin 		nvmf_free_capsule(nc);
118*2da066efSJohn Baldwin 	}
119*2da066efSJohn Baldwin 	na = qp->nq_association;
120*2da066efSJohn Baldwin 	na->na_ops->free_qpair(qp);
121*2da066efSJohn Baldwin 	nvmf_free_association(na);
122*2da066efSJohn Baldwin }
123*2da066efSJohn Baldwin 
124*2da066efSJohn Baldwin struct nvmf_capsule *
nvmf_allocate_command(struct nvmf_qpair * qp,const void * sqe)125*2da066efSJohn Baldwin nvmf_allocate_command(struct nvmf_qpair *qp, const void *sqe)
126*2da066efSJohn Baldwin {
127*2da066efSJohn Baldwin 	struct nvmf_capsule *nc;
128*2da066efSJohn Baldwin 
129*2da066efSJohn Baldwin 	nc = qp->nq_association->na_ops->allocate_capsule(qp);
130*2da066efSJohn Baldwin 	if (nc == NULL)
131*2da066efSJohn Baldwin 		return (NULL);
132*2da066efSJohn Baldwin 
133*2da066efSJohn Baldwin 	nc->nc_qpair = qp;
134*2da066efSJohn Baldwin 	nc->nc_qe_len = sizeof(struct nvme_command);
135*2da066efSJohn Baldwin 	memcpy(&nc->nc_sqe, sqe, nc->nc_qe_len);
136*2da066efSJohn Baldwin 
137*2da066efSJohn Baldwin 	/* 4.2 of NVMe base spec: Fabrics always uses SGL. */
138*2da066efSJohn Baldwin 	nc->nc_sqe.fuse &= ~NVMEM(NVME_CMD_PSDT);
139*2da066efSJohn Baldwin 	nc->nc_sqe.fuse |= NVMEF(NVME_CMD_PSDT, NVME_PSDT_SGL);
140*2da066efSJohn Baldwin 	return (nc);
141*2da066efSJohn Baldwin }
142*2da066efSJohn Baldwin 
143*2da066efSJohn Baldwin struct nvmf_capsule *
nvmf_allocate_response(struct nvmf_qpair * qp,const void * cqe)144*2da066efSJohn Baldwin nvmf_allocate_response(struct nvmf_qpair *qp, const void *cqe)
145*2da066efSJohn Baldwin {
146*2da066efSJohn Baldwin 	struct nvmf_capsule *nc;
147*2da066efSJohn Baldwin 
148*2da066efSJohn Baldwin 	nc = qp->nq_association->na_ops->allocate_capsule(qp);
149*2da066efSJohn Baldwin 	if (nc == NULL)
150*2da066efSJohn Baldwin 		return (NULL);
151*2da066efSJohn Baldwin 
152*2da066efSJohn Baldwin 	nc->nc_qpair = qp;
153*2da066efSJohn Baldwin 	nc->nc_qe_len = sizeof(struct nvme_completion);
154*2da066efSJohn Baldwin 	memcpy(&nc->nc_cqe, cqe, nc->nc_qe_len);
155*2da066efSJohn Baldwin 	return (nc);
156*2da066efSJohn Baldwin }
157*2da066efSJohn Baldwin 
158*2da066efSJohn Baldwin int
nvmf_capsule_append_data(struct nvmf_capsule * nc,void * buf,size_t len,bool send)159*2da066efSJohn Baldwin nvmf_capsule_append_data(struct nvmf_capsule *nc, void *buf, size_t len,
160*2da066efSJohn Baldwin     bool send)
161*2da066efSJohn Baldwin {
162*2da066efSJohn Baldwin 	if (nc->nc_qe_len == sizeof(struct nvme_completion))
163*2da066efSJohn Baldwin 		return (EINVAL);
164*2da066efSJohn Baldwin 	if (nc->nc_data_len != 0)
165*2da066efSJohn Baldwin 		return (EBUSY);
166*2da066efSJohn Baldwin 
167*2da066efSJohn Baldwin 	nc->nc_data = buf;
168*2da066efSJohn Baldwin 	nc->nc_data_len = len;
169*2da066efSJohn Baldwin 	nc->nc_send_data = send;
170*2da066efSJohn Baldwin 	return (0);
171*2da066efSJohn Baldwin }
172*2da066efSJohn Baldwin 
173*2da066efSJohn Baldwin void
nvmf_free_capsule(struct nvmf_capsule * nc)174*2da066efSJohn Baldwin nvmf_free_capsule(struct nvmf_capsule *nc)
175*2da066efSJohn Baldwin {
176*2da066efSJohn Baldwin 	nc->nc_qpair->nq_association->na_ops->free_capsule(nc);
177*2da066efSJohn Baldwin }
178*2da066efSJohn Baldwin 
179*2da066efSJohn Baldwin int
nvmf_transmit_capsule(struct nvmf_capsule * nc)180*2da066efSJohn Baldwin nvmf_transmit_capsule(struct nvmf_capsule *nc)
181*2da066efSJohn Baldwin {
182*2da066efSJohn Baldwin 	return (nc->nc_qpair->nq_association->na_ops->transmit_capsule(nc));
183*2da066efSJohn Baldwin }
184*2da066efSJohn Baldwin 
185*2da066efSJohn Baldwin int
nvmf_receive_capsule(struct nvmf_qpair * qp,struct nvmf_capsule ** ncp)186*2da066efSJohn Baldwin nvmf_receive_capsule(struct nvmf_qpair *qp, struct nvmf_capsule **ncp)
187*2da066efSJohn Baldwin {
188*2da066efSJohn Baldwin 	return (qp->nq_association->na_ops->receive_capsule(qp, ncp));
189*2da066efSJohn Baldwin }
190*2da066efSJohn Baldwin 
191*2da066efSJohn Baldwin const void *
nvmf_capsule_sqe(const struct nvmf_capsule * nc)192*2da066efSJohn Baldwin nvmf_capsule_sqe(const struct nvmf_capsule *nc)
193*2da066efSJohn Baldwin {
194*2da066efSJohn Baldwin 	assert(nc->nc_qe_len == sizeof(struct nvme_command));
195*2da066efSJohn Baldwin 	return (&nc->nc_sqe);
196*2da066efSJohn Baldwin }
197*2da066efSJohn Baldwin 
198*2da066efSJohn Baldwin const void *
nvmf_capsule_cqe(const struct nvmf_capsule * nc)199*2da066efSJohn Baldwin nvmf_capsule_cqe(const struct nvmf_capsule *nc)
200*2da066efSJohn Baldwin {
201*2da066efSJohn Baldwin 	assert(nc->nc_qe_len == sizeof(struct nvme_completion));
202*2da066efSJohn Baldwin 	return (&nc->nc_cqe);
203*2da066efSJohn Baldwin }
204*2da066efSJohn Baldwin 
205*2da066efSJohn Baldwin uint8_t
nvmf_validate_command_capsule(const struct nvmf_capsule * nc)206*2da066efSJohn Baldwin nvmf_validate_command_capsule(const struct nvmf_capsule *nc)
207*2da066efSJohn Baldwin {
208*2da066efSJohn Baldwin 	assert(nc->nc_qe_len == sizeof(struct nvme_command));
209*2da066efSJohn Baldwin 
210*2da066efSJohn Baldwin 	if (NVMEV(NVME_CMD_PSDT, nc->nc_sqe.fuse) != NVME_PSDT_SGL)
211*2da066efSJohn Baldwin 		return (NVME_SC_INVALID_FIELD);
212*2da066efSJohn Baldwin 
213*2da066efSJohn Baldwin 	return (nc->nc_qpair->nq_association->na_ops->validate_command_capsule(nc));
214*2da066efSJohn Baldwin }
215*2da066efSJohn Baldwin 
216*2da066efSJohn Baldwin size_t
nvmf_capsule_data_len(const struct nvmf_capsule * nc)217*2da066efSJohn Baldwin nvmf_capsule_data_len(const struct nvmf_capsule *nc)
218*2da066efSJohn Baldwin {
219*2da066efSJohn Baldwin 	return (nc->nc_qpair->nq_association->na_ops->capsule_data_len(nc));
220*2da066efSJohn Baldwin }
221*2da066efSJohn Baldwin 
222*2da066efSJohn Baldwin int
nvmf_receive_controller_data(const struct nvmf_capsule * nc,uint32_t data_offset,void * buf,size_t len)223*2da066efSJohn Baldwin nvmf_receive_controller_data(const struct nvmf_capsule *nc,
224*2da066efSJohn Baldwin     uint32_t data_offset, void *buf, size_t len)
225*2da066efSJohn Baldwin {
226*2da066efSJohn Baldwin 	return (nc->nc_qpair->nq_association->na_ops->receive_controller_data(nc,
227*2da066efSJohn Baldwin 	    data_offset, buf, len));
228*2da066efSJohn Baldwin }
229*2da066efSJohn Baldwin 
230*2da066efSJohn Baldwin int
nvmf_send_controller_data(const struct nvmf_capsule * nc,const void * buf,size_t len)231*2da066efSJohn Baldwin nvmf_send_controller_data(const struct nvmf_capsule *nc, const void *buf,
232*2da066efSJohn Baldwin     size_t len)
233*2da066efSJohn Baldwin {
234*2da066efSJohn Baldwin 	return (nc->nc_qpair->nq_association->na_ops->send_controller_data(nc,
235*2da066efSJohn Baldwin 	    buf, len));
236*2da066efSJohn Baldwin }
237*2da066efSJohn Baldwin 
238*2da066efSJohn Baldwin int
nvmf_kernel_handoff_params(struct nvmf_qpair * qp,struct nvmf_handoff_qpair_params * qparams)239*2da066efSJohn Baldwin nvmf_kernel_handoff_params(struct nvmf_qpair *qp,
240*2da066efSJohn Baldwin     struct nvmf_handoff_qpair_params *qparams)
241*2da066efSJohn Baldwin {
242*2da066efSJohn Baldwin 	memset(qparams, 0, sizeof(*qparams));
243*2da066efSJohn Baldwin 	qparams->admin = qp->nq_admin;
244*2da066efSJohn Baldwin 	qparams->sq_flow_control = qp->nq_flow_control;
245*2da066efSJohn Baldwin 	qparams->qsize = qp->nq_qsize;
246*2da066efSJohn Baldwin 	qparams->sqhd = qp->nq_sqhd;
247*2da066efSJohn Baldwin 	qparams->sqtail = qp->nq_sqtail;
248*2da066efSJohn Baldwin 	return (qp->nq_association->na_ops->kernel_handoff_params(qp, qparams));
249*2da066efSJohn Baldwin }
250*2da066efSJohn Baldwin 
251*2da066efSJohn Baldwin const char *
nvmf_transport_type(uint8_t trtype)252*2da066efSJohn Baldwin nvmf_transport_type(uint8_t trtype)
253*2da066efSJohn Baldwin {
254*2da066efSJohn Baldwin 	static _Thread_local char buf[8];
255*2da066efSJohn Baldwin 
256*2da066efSJohn Baldwin 	switch (trtype) {
257*2da066efSJohn Baldwin 	case NVMF_TRTYPE_RDMA:
258*2da066efSJohn Baldwin 		return ("RDMA");
259*2da066efSJohn Baldwin 	case NVMF_TRTYPE_FC:
260*2da066efSJohn Baldwin 		return ("Fibre Channel");
261*2da066efSJohn Baldwin 	case NVMF_TRTYPE_TCP:
262*2da066efSJohn Baldwin 		return ("TCP");
263*2da066efSJohn Baldwin 	case NVMF_TRTYPE_INTRA_HOST:
264*2da066efSJohn Baldwin 		return ("Intra-host");
265*2da066efSJohn Baldwin 	default:
266*2da066efSJohn Baldwin 		snprintf(buf, sizeof(buf), "0x%02x\n", trtype);
267*2da066efSJohn Baldwin 		return (buf);
268*2da066efSJohn Baldwin 	}
269*2da066efSJohn Baldwin }
270