xref: /freebsd/usr.sbin/nvmfd/discovery.c (revision a8089ea5aee578e08acab2438e82fc9a9ae50ed8)
1*a8089ea5SJohn Baldwin /*-
2*a8089ea5SJohn Baldwin  * SPDX-License-Identifier: BSD-2-Clause
3*a8089ea5SJohn Baldwin  *
4*a8089ea5SJohn Baldwin  * Copyright (c) 2023-2024 Chelsio Communications, Inc.
5*a8089ea5SJohn Baldwin  * Written by: John Baldwin <jhb@FreeBSD.org>
6*a8089ea5SJohn Baldwin  */
7*a8089ea5SJohn Baldwin 
8*a8089ea5SJohn Baldwin #include <sys/socket.h>
9*a8089ea5SJohn Baldwin #include <netinet/in.h>
10*a8089ea5SJohn Baldwin #include <arpa/inet.h>
11*a8089ea5SJohn Baldwin #include <assert.h>
12*a8089ea5SJohn Baldwin #include <err.h>
13*a8089ea5SJohn Baldwin #include <libnvmf.h>
14*a8089ea5SJohn Baldwin #include <pthread.h>
15*a8089ea5SJohn Baldwin #include <stdio.h>
16*a8089ea5SJohn Baldwin #include <stdlib.h>
17*a8089ea5SJohn Baldwin #include <string.h>
18*a8089ea5SJohn Baldwin #include <unistd.h>
19*a8089ea5SJohn Baldwin 
20*a8089ea5SJohn Baldwin #include "internal.h"
21*a8089ea5SJohn Baldwin 
22*a8089ea5SJohn Baldwin struct io_controller_data {
23*a8089ea5SJohn Baldwin 	struct nvme_discovery_log_entry entry;
24*a8089ea5SJohn Baldwin 	bool wildcard;
25*a8089ea5SJohn Baldwin };
26*a8089ea5SJohn Baldwin 
27*a8089ea5SJohn Baldwin struct discovery_controller {
28*a8089ea5SJohn Baldwin 	struct nvme_discovery_log *discovery_log;
29*a8089ea5SJohn Baldwin 	size_t discovery_log_len;
30*a8089ea5SJohn Baldwin 	int s;
31*a8089ea5SJohn Baldwin };
32*a8089ea5SJohn Baldwin 
33*a8089ea5SJohn Baldwin struct discovery_thread_arg {
34*a8089ea5SJohn Baldwin 	struct controller *c;
35*a8089ea5SJohn Baldwin 	struct nvmf_qpair *qp;
36*a8089ea5SJohn Baldwin 	int s;
37*a8089ea5SJohn Baldwin };
38*a8089ea5SJohn Baldwin 
39*a8089ea5SJohn Baldwin static struct io_controller_data *io_controllers;
40*a8089ea5SJohn Baldwin static struct nvmf_association *discovery_na;
41*a8089ea5SJohn Baldwin static u_int num_io_controllers;
42*a8089ea5SJohn Baldwin 
43*a8089ea5SJohn Baldwin static bool
44*a8089ea5SJohn Baldwin init_discovery_log_entry(struct nvme_discovery_log_entry *entry, int s,
45*a8089ea5SJohn Baldwin     const char *subnqn)
46*a8089ea5SJohn Baldwin {
47*a8089ea5SJohn Baldwin 	struct sockaddr_storage ss;
48*a8089ea5SJohn Baldwin 	socklen_t len;
49*a8089ea5SJohn Baldwin 	bool wildcard;
50*a8089ea5SJohn Baldwin 
51*a8089ea5SJohn Baldwin 	len = sizeof(ss);
52*a8089ea5SJohn Baldwin 	if (getsockname(s, (struct sockaddr *)&ss, &len) == -1)
53*a8089ea5SJohn Baldwin 		err(1, "getsockname");
54*a8089ea5SJohn Baldwin 
55*a8089ea5SJohn Baldwin 	memset(entry, 0, sizeof(*entry));
56*a8089ea5SJohn Baldwin 	entry->trtype = NVMF_TRTYPE_TCP;
57*a8089ea5SJohn Baldwin 	switch (ss.ss_family) {
58*a8089ea5SJohn Baldwin 	case AF_INET:
59*a8089ea5SJohn Baldwin 	{
60*a8089ea5SJohn Baldwin 		struct sockaddr_in *sin;
61*a8089ea5SJohn Baldwin 
62*a8089ea5SJohn Baldwin 		sin = (struct sockaddr_in *)&ss;
63*a8089ea5SJohn Baldwin 		entry->adrfam = NVMF_ADRFAM_IPV4;
64*a8089ea5SJohn Baldwin 		snprintf(entry->trsvcid, sizeof(entry->trsvcid), "%u",
65*a8089ea5SJohn Baldwin 		    htons(sin->sin_port));
66*a8089ea5SJohn Baldwin 		if (inet_ntop(AF_INET, &sin->sin_addr, entry->traddr,
67*a8089ea5SJohn Baldwin 		    sizeof(entry->traddr)) == NULL)
68*a8089ea5SJohn Baldwin 			err(1, "inet_ntop");
69*a8089ea5SJohn Baldwin 		wildcard = (sin->sin_addr.s_addr == htonl(INADDR_ANY));
70*a8089ea5SJohn Baldwin 		break;
71*a8089ea5SJohn Baldwin 	}
72*a8089ea5SJohn Baldwin 	case AF_INET6:
73*a8089ea5SJohn Baldwin 	{
74*a8089ea5SJohn Baldwin 		struct sockaddr_in6 *sin6;
75*a8089ea5SJohn Baldwin 
76*a8089ea5SJohn Baldwin 		sin6 = (struct sockaddr_in6 *)&ss;
77*a8089ea5SJohn Baldwin 		entry->adrfam = NVMF_ADRFAM_IPV6;
78*a8089ea5SJohn Baldwin 		snprintf(entry->trsvcid, sizeof(entry->trsvcid), "%u",
79*a8089ea5SJohn Baldwin 		    htons(sin6->sin6_port));
80*a8089ea5SJohn Baldwin 		if (inet_ntop(AF_INET6, &sin6->sin6_addr, entry->traddr,
81*a8089ea5SJohn Baldwin 		    sizeof(entry->traddr)) == NULL)
82*a8089ea5SJohn Baldwin 			err(1, "inet_ntop");
83*a8089ea5SJohn Baldwin 		wildcard = (memcmp(&sin6->sin6_addr, &in6addr_any,
84*a8089ea5SJohn Baldwin 		    sizeof(in6addr_any)) == 0);
85*a8089ea5SJohn Baldwin 		break;
86*a8089ea5SJohn Baldwin 	}
87*a8089ea5SJohn Baldwin 	default:
88*a8089ea5SJohn Baldwin 		errx(1, "Unsupported address family %u", ss.ss_family);
89*a8089ea5SJohn Baldwin 	}
90*a8089ea5SJohn Baldwin 	entry->subtype = NVMF_SUBTYPE_NVME;
91*a8089ea5SJohn Baldwin 	if (flow_control_disable)
92*a8089ea5SJohn Baldwin 		entry->treq |= (1 << 2);
93*a8089ea5SJohn Baldwin 	entry->portid = htole16(1);
94*a8089ea5SJohn Baldwin 	entry->cntlid = htole16(NVMF_CNTLID_DYNAMIC);
95*a8089ea5SJohn Baldwin 	entry->aqsz = NVME_MAX_ADMIN_ENTRIES;
96*a8089ea5SJohn Baldwin 	strlcpy(entry->subnqn, subnqn, sizeof(entry->subnqn));
97*a8089ea5SJohn Baldwin 	return (wildcard);
98*a8089ea5SJohn Baldwin }
99*a8089ea5SJohn Baldwin 
100*a8089ea5SJohn Baldwin void
101*a8089ea5SJohn Baldwin init_discovery(void)
102*a8089ea5SJohn Baldwin {
103*a8089ea5SJohn Baldwin 	struct nvmf_association_params aparams;
104*a8089ea5SJohn Baldwin 
105*a8089ea5SJohn Baldwin 	memset(&aparams, 0, sizeof(aparams));
106*a8089ea5SJohn Baldwin 	aparams.sq_flow_control = false;
107*a8089ea5SJohn Baldwin 	aparams.dynamic_controller_model = true;
108*a8089ea5SJohn Baldwin 	aparams.max_admin_qsize = NVME_MAX_ADMIN_ENTRIES;
109*a8089ea5SJohn Baldwin 	aparams.tcp.pda = 0;
110*a8089ea5SJohn Baldwin 	aparams.tcp.header_digests = header_digests;
111*a8089ea5SJohn Baldwin 	aparams.tcp.data_digests = data_digests;
112*a8089ea5SJohn Baldwin 	aparams.tcp.maxr2t = 1;
113*a8089ea5SJohn Baldwin 	aparams.tcp.maxh2cdata = 256 * 1024;
114*a8089ea5SJohn Baldwin 	discovery_na = nvmf_allocate_association(NVMF_TRTYPE_TCP, true,
115*a8089ea5SJohn Baldwin 	    &aparams);
116*a8089ea5SJohn Baldwin 	if (discovery_na == NULL)
117*a8089ea5SJohn Baldwin 		err(1, "Failed to create discovery association");
118*a8089ea5SJohn Baldwin }
119*a8089ea5SJohn Baldwin 
120*a8089ea5SJohn Baldwin void
121*a8089ea5SJohn Baldwin discovery_add_io_controller(int s, const char *subnqn)
122*a8089ea5SJohn Baldwin {
123*a8089ea5SJohn Baldwin 	struct io_controller_data *icd;
124*a8089ea5SJohn Baldwin 
125*a8089ea5SJohn Baldwin 	io_controllers = reallocf(io_controllers, (num_io_controllers + 1) *
126*a8089ea5SJohn Baldwin 	    sizeof(*io_controllers));
127*a8089ea5SJohn Baldwin 
128*a8089ea5SJohn Baldwin 	icd = &io_controllers[num_io_controllers];
129*a8089ea5SJohn Baldwin 	num_io_controllers++;
130*a8089ea5SJohn Baldwin 
131*a8089ea5SJohn Baldwin 	icd->wildcard = init_discovery_log_entry(&icd->entry, s, subnqn);
132*a8089ea5SJohn Baldwin }
133*a8089ea5SJohn Baldwin 
134*a8089ea5SJohn Baldwin static void
135*a8089ea5SJohn Baldwin build_discovery_log_page(struct discovery_controller *dc)
136*a8089ea5SJohn Baldwin {
137*a8089ea5SJohn Baldwin 	struct sockaddr_storage ss;
138*a8089ea5SJohn Baldwin 	socklen_t len;
139*a8089ea5SJohn Baldwin 	char traddr[256];
140*a8089ea5SJohn Baldwin 	u_int i, nentries;
141*a8089ea5SJohn Baldwin 	uint8_t adrfam;
142*a8089ea5SJohn Baldwin 
143*a8089ea5SJohn Baldwin 	if (dc->discovery_log != NULL)
144*a8089ea5SJohn Baldwin 		return;
145*a8089ea5SJohn Baldwin 
146*a8089ea5SJohn Baldwin 	len = sizeof(ss);
147*a8089ea5SJohn Baldwin 	if (getsockname(dc->s, (struct sockaddr *)&ss, &len) == -1) {
148*a8089ea5SJohn Baldwin 		warn("build_discovery_log_page: getsockname");
149*a8089ea5SJohn Baldwin 		return;
150*a8089ea5SJohn Baldwin 	}
151*a8089ea5SJohn Baldwin 
152*a8089ea5SJohn Baldwin 	memset(traddr, 0, sizeof(traddr));
153*a8089ea5SJohn Baldwin 	switch (ss.ss_family) {
154*a8089ea5SJohn Baldwin 	case AF_INET:
155*a8089ea5SJohn Baldwin 	{
156*a8089ea5SJohn Baldwin 		struct sockaddr_in *sin;
157*a8089ea5SJohn Baldwin 
158*a8089ea5SJohn Baldwin 		sin = (struct sockaddr_in *)&ss;
159*a8089ea5SJohn Baldwin 		adrfam = NVMF_ADRFAM_IPV4;
160*a8089ea5SJohn Baldwin 		if (inet_ntop(AF_INET, &sin->sin_addr, traddr,
161*a8089ea5SJohn Baldwin 		    sizeof(traddr)) == NULL) {
162*a8089ea5SJohn Baldwin 			warn("build_discovery_log_page: inet_ntop");
163*a8089ea5SJohn Baldwin 			return;
164*a8089ea5SJohn Baldwin 		}
165*a8089ea5SJohn Baldwin 		break;
166*a8089ea5SJohn Baldwin 	}
167*a8089ea5SJohn Baldwin 	case AF_INET6:
168*a8089ea5SJohn Baldwin 	{
169*a8089ea5SJohn Baldwin 		struct sockaddr_in6 *sin6;
170*a8089ea5SJohn Baldwin 
171*a8089ea5SJohn Baldwin 		sin6 = (struct sockaddr_in6 *)&ss;
172*a8089ea5SJohn Baldwin 		adrfam = NVMF_ADRFAM_IPV6;
173*a8089ea5SJohn Baldwin 		if (inet_ntop(AF_INET6, &sin6->sin6_addr, traddr,
174*a8089ea5SJohn Baldwin 		    sizeof(traddr)) == NULL) {
175*a8089ea5SJohn Baldwin 			warn("build_discovery_log_page: inet_ntop");
176*a8089ea5SJohn Baldwin 			return;
177*a8089ea5SJohn Baldwin 		}
178*a8089ea5SJohn Baldwin 		break;
179*a8089ea5SJohn Baldwin 	}
180*a8089ea5SJohn Baldwin 	default:
181*a8089ea5SJohn Baldwin 		assert(false);
182*a8089ea5SJohn Baldwin 	}
183*a8089ea5SJohn Baldwin 
184*a8089ea5SJohn Baldwin 	nentries = 0;
185*a8089ea5SJohn Baldwin 	for (i = 0; i < num_io_controllers; i++) {
186*a8089ea5SJohn Baldwin 		if (io_controllers[i].wildcard &&
187*a8089ea5SJohn Baldwin 		    io_controllers[i].entry.adrfam != adrfam)
188*a8089ea5SJohn Baldwin 			continue;
189*a8089ea5SJohn Baldwin 		nentries++;
190*a8089ea5SJohn Baldwin 	}
191*a8089ea5SJohn Baldwin 
192*a8089ea5SJohn Baldwin 	dc->discovery_log_len = sizeof(*dc->discovery_log) +
193*a8089ea5SJohn Baldwin 	    nentries * sizeof(struct nvme_discovery_log_entry);
194*a8089ea5SJohn Baldwin 	dc->discovery_log = calloc(dc->discovery_log_len, 1);
195*a8089ea5SJohn Baldwin 	dc->discovery_log->numrec = nentries;
196*a8089ea5SJohn Baldwin 	dc->discovery_log->recfmt = 0;
197*a8089ea5SJohn Baldwin 	nentries = 0;
198*a8089ea5SJohn Baldwin 	for (i = 0; i < num_io_controllers; i++) {
199*a8089ea5SJohn Baldwin 		if (io_controllers[i].wildcard &&
200*a8089ea5SJohn Baldwin 		    io_controllers[i].entry.adrfam != adrfam)
201*a8089ea5SJohn Baldwin 			continue;
202*a8089ea5SJohn Baldwin 
203*a8089ea5SJohn Baldwin 		dc->discovery_log->entries[nentries] = io_controllers[i].entry;
204*a8089ea5SJohn Baldwin 		if (io_controllers[i].wildcard)
205*a8089ea5SJohn Baldwin 			memcpy(dc->discovery_log->entries[nentries].traddr,
206*a8089ea5SJohn Baldwin 			    traddr, sizeof(traddr));
207*a8089ea5SJohn Baldwin 	}
208*a8089ea5SJohn Baldwin }
209*a8089ea5SJohn Baldwin 
210*a8089ea5SJohn Baldwin static void
211*a8089ea5SJohn Baldwin handle_get_log_page_command(const struct nvmf_capsule *nc,
212*a8089ea5SJohn Baldwin     const struct nvme_command *cmd, struct discovery_controller *dc)
213*a8089ea5SJohn Baldwin {
214*a8089ea5SJohn Baldwin 	uint64_t offset;
215*a8089ea5SJohn Baldwin 	uint32_t length;
216*a8089ea5SJohn Baldwin 
217*a8089ea5SJohn Baldwin 	switch (nvmf_get_log_page_id(cmd)) {
218*a8089ea5SJohn Baldwin 	case NVME_LOG_DISCOVERY:
219*a8089ea5SJohn Baldwin 		break;
220*a8089ea5SJohn Baldwin 	default:
221*a8089ea5SJohn Baldwin 		warnx("Unsupported log page %u for discovery controller",
222*a8089ea5SJohn Baldwin 		    nvmf_get_log_page_id(cmd));
223*a8089ea5SJohn Baldwin 		goto error;
224*a8089ea5SJohn Baldwin 	}
225*a8089ea5SJohn Baldwin 
226*a8089ea5SJohn Baldwin 	build_discovery_log_page(dc);
227*a8089ea5SJohn Baldwin 
228*a8089ea5SJohn Baldwin 	offset = nvmf_get_log_page_offset(cmd);
229*a8089ea5SJohn Baldwin 	if (offset >= dc->discovery_log_len)
230*a8089ea5SJohn Baldwin 		goto error;
231*a8089ea5SJohn Baldwin 
232*a8089ea5SJohn Baldwin 	length = nvmf_get_log_page_length(cmd);
233*a8089ea5SJohn Baldwin 	if (length > dc->discovery_log_len - offset)
234*a8089ea5SJohn Baldwin 		length = dc->discovery_log_len - offset;
235*a8089ea5SJohn Baldwin 
236*a8089ea5SJohn Baldwin 	nvmf_send_controller_data(nc, (char *)dc->discovery_log + offset,
237*a8089ea5SJohn Baldwin 	    length);
238*a8089ea5SJohn Baldwin 	return;
239*a8089ea5SJohn Baldwin error:
240*a8089ea5SJohn Baldwin 	nvmf_send_generic_error(nc, NVME_SC_INVALID_FIELD);
241*a8089ea5SJohn Baldwin }
242*a8089ea5SJohn Baldwin 
243*a8089ea5SJohn Baldwin static bool
244*a8089ea5SJohn Baldwin discovery_command(const struct nvmf_capsule *nc, const struct nvme_command *cmd,
245*a8089ea5SJohn Baldwin     void *arg)
246*a8089ea5SJohn Baldwin {
247*a8089ea5SJohn Baldwin 	struct discovery_controller *dc = arg;
248*a8089ea5SJohn Baldwin 
249*a8089ea5SJohn Baldwin 	switch (cmd->opc) {
250*a8089ea5SJohn Baldwin 	case NVME_OPC_GET_LOG_PAGE:
251*a8089ea5SJohn Baldwin 		handle_get_log_page_command(nc, cmd, dc);
252*a8089ea5SJohn Baldwin 		return (true);
253*a8089ea5SJohn Baldwin 	default:
254*a8089ea5SJohn Baldwin 		return (false);
255*a8089ea5SJohn Baldwin 	}
256*a8089ea5SJohn Baldwin }
257*a8089ea5SJohn Baldwin 
258*a8089ea5SJohn Baldwin static void *
259*a8089ea5SJohn Baldwin discovery_thread(void *arg)
260*a8089ea5SJohn Baldwin {
261*a8089ea5SJohn Baldwin 	struct discovery_thread_arg *dta = arg;
262*a8089ea5SJohn Baldwin 	struct discovery_controller dc;
263*a8089ea5SJohn Baldwin 
264*a8089ea5SJohn Baldwin 	pthread_detach(pthread_self());
265*a8089ea5SJohn Baldwin 
266*a8089ea5SJohn Baldwin 	memset(&dc, 0, sizeof(dc));
267*a8089ea5SJohn Baldwin 	dc.s = dta->s;
268*a8089ea5SJohn Baldwin 
269*a8089ea5SJohn Baldwin 	controller_handle_admin_commands(dta->c, discovery_command, &dc);
270*a8089ea5SJohn Baldwin 
271*a8089ea5SJohn Baldwin 	free(dc.discovery_log);
272*a8089ea5SJohn Baldwin 	free_controller(dta->c);
273*a8089ea5SJohn Baldwin 
274*a8089ea5SJohn Baldwin 	nvmf_free_qpair(dta->qp);
275*a8089ea5SJohn Baldwin 
276*a8089ea5SJohn Baldwin 	close(dta->s);
277*a8089ea5SJohn Baldwin 	free(dta);
278*a8089ea5SJohn Baldwin 	return (NULL);
279*a8089ea5SJohn Baldwin }
280*a8089ea5SJohn Baldwin 
281*a8089ea5SJohn Baldwin void
282*a8089ea5SJohn Baldwin handle_discovery_socket(int s)
283*a8089ea5SJohn Baldwin {
284*a8089ea5SJohn Baldwin 	struct nvmf_fabric_connect_data data;
285*a8089ea5SJohn Baldwin 	struct nvme_controller_data cdata;
286*a8089ea5SJohn Baldwin 	struct nvmf_qpair_params qparams;
287*a8089ea5SJohn Baldwin 	struct discovery_thread_arg *dta;
288*a8089ea5SJohn Baldwin 	struct nvmf_capsule *nc;
289*a8089ea5SJohn Baldwin 	struct nvmf_qpair *qp;
290*a8089ea5SJohn Baldwin 	pthread_t thr;
291*a8089ea5SJohn Baldwin 	int error;
292*a8089ea5SJohn Baldwin 
293*a8089ea5SJohn Baldwin 	memset(&qparams, 0, sizeof(qparams));
294*a8089ea5SJohn Baldwin 	qparams.tcp.fd = s;
295*a8089ea5SJohn Baldwin 
296*a8089ea5SJohn Baldwin 	nc = NULL;
297*a8089ea5SJohn Baldwin 	qp = nvmf_accept(discovery_na, &qparams, &nc, &data);
298*a8089ea5SJohn Baldwin 	if (qp == NULL) {
299*a8089ea5SJohn Baldwin 		warnx("Failed to create discovery qpair: %s",
300*a8089ea5SJohn Baldwin 		    nvmf_association_error(discovery_na));
301*a8089ea5SJohn Baldwin 		goto error;
302*a8089ea5SJohn Baldwin 	}
303*a8089ea5SJohn Baldwin 
304*a8089ea5SJohn Baldwin 	if (strcmp(data.subnqn, NVMF_DISCOVERY_NQN) != 0) {
305*a8089ea5SJohn Baldwin 		warn("Discovery qpair with invalid SubNQN: %.*s",
306*a8089ea5SJohn Baldwin 		    (int)sizeof(data.subnqn), data.subnqn);
307*a8089ea5SJohn Baldwin 		nvmf_connect_invalid_parameters(nc, true,
308*a8089ea5SJohn Baldwin 		    offsetof(struct nvmf_fabric_connect_data, subnqn));
309*a8089ea5SJohn Baldwin 		goto error;
310*a8089ea5SJohn Baldwin 	}
311*a8089ea5SJohn Baldwin 
312*a8089ea5SJohn Baldwin 	/* Just use a controller ID of 1 for all discovery controllers. */
313*a8089ea5SJohn Baldwin 	error = nvmf_finish_accept(nc, 1);
314*a8089ea5SJohn Baldwin 	if (error != 0) {
315*a8089ea5SJohn Baldwin 		warnc(error, "Failed to send CONNECT reponse");
316*a8089ea5SJohn Baldwin 		goto error;
317*a8089ea5SJohn Baldwin 	}
318*a8089ea5SJohn Baldwin 
319*a8089ea5SJohn Baldwin 	nvmf_init_discovery_controller_data(qp, &cdata);
320*a8089ea5SJohn Baldwin 
321*a8089ea5SJohn Baldwin 	dta = malloc(sizeof(*dta));
322*a8089ea5SJohn Baldwin 	dta->qp = qp;
323*a8089ea5SJohn Baldwin 	dta->s = s;
324*a8089ea5SJohn Baldwin 	dta->c = init_controller(qp, &cdata);
325*a8089ea5SJohn Baldwin 
326*a8089ea5SJohn Baldwin 	error = pthread_create(&thr, NULL, discovery_thread, dta);
327*a8089ea5SJohn Baldwin 	if (error != 0) {
328*a8089ea5SJohn Baldwin 		warnc(error, "Failed to create discovery thread");
329*a8089ea5SJohn Baldwin 		free_controller(dta->c);
330*a8089ea5SJohn Baldwin 		free(dta);
331*a8089ea5SJohn Baldwin 		goto error;
332*a8089ea5SJohn Baldwin 	}
333*a8089ea5SJohn Baldwin 
334*a8089ea5SJohn Baldwin 	nvmf_free_capsule(nc);
335*a8089ea5SJohn Baldwin 	return;
336*a8089ea5SJohn Baldwin 
337*a8089ea5SJohn Baldwin error:
338*a8089ea5SJohn Baldwin 	if (nc != NULL)
339*a8089ea5SJohn Baldwin 		nvmf_free_capsule(nc);
340*a8089ea5SJohn Baldwin 	if (qp != NULL)
341*a8089ea5SJohn Baldwin 		nvmf_free_qpair(qp);
342*a8089ea5SJohn Baldwin 	close(s);
343*a8089ea5SJohn Baldwin }
344