]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/lib/nvmf/transport.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / lib / nvmf / transport.c
CommitLineData
7c673cae
FG
1/*-
2 * BSD LICENSE
3 *
9f95a23c
TL
4 * Copyright (c) Intel Corporation. All rights reserved.
5 * Copyright (c) 2018 Mellanox Technologies LTD. All rights reserved.
7c673cae
FG
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
11fdf7f2 34#include "spdk/stdinc.h"
7c673cae 35
11fdf7f2
TL
36#include "nvmf_internal.h"
37#include "transport.h"
7c673cae 38
11fdf7f2 39#include "spdk/config.h"
7c673cae
FG
40#include "spdk/log.h"
41#include "spdk/nvmf.h"
42#include "spdk/queue.h"
43#include "spdk/util.h"
44
11fdf7f2 45static const struct spdk_nvmf_transport_ops *const g_transport_ops[] = {
7c673cae
FG
46#ifdef SPDK_CONFIG_RDMA
47 &spdk_nvmf_transport_rdma,
48#endif
9f95a23c 49 &spdk_nvmf_transport_tcp,
7c673cae
FG
50};
51
11fdf7f2 52#define NUM_TRANSPORTS (SPDK_COUNTOF(g_transport_ops))
9f95a23c 53#define MAX_MEMPOOL_NAME_LENGTH 40
7c673cae 54
11fdf7f2
TL
55static inline const struct spdk_nvmf_transport_ops *
56spdk_nvmf_get_transport_ops(enum spdk_nvme_transport_type type)
7c673cae
FG
57{
58 size_t i;
7c673cae 59 for (i = 0; i != NUM_TRANSPORTS; i++) {
11fdf7f2
TL
60 if (g_transport_ops[i]->type == type) {
61 return g_transport_ops[i];
7c673cae
FG
62 }
63 }
11fdf7f2
TL
64 return NULL;
65}
66
9f95a23c
TL
67const struct spdk_nvmf_transport_opts *
68spdk_nvmf_get_transport_opts(struct spdk_nvmf_transport *transport)
69{
70 return &transport->opts;
71}
72
73spdk_nvme_transport_type_t
74spdk_nvmf_get_transport_type(struct spdk_nvmf_transport *transport)
75{
76 return transport->ops->type;
77}
78
11fdf7f2
TL
79struct spdk_nvmf_transport *
80spdk_nvmf_transport_create(enum spdk_nvme_transport_type type,
81 struct spdk_nvmf_transport_opts *opts)
82{
83 const struct spdk_nvmf_transport_ops *ops = NULL;
84 struct spdk_nvmf_transport *transport;
9f95a23c
TL
85 char spdk_mempool_name[MAX_MEMPOOL_NAME_LENGTH];
86 int chars_written;
11fdf7f2
TL
87
88 ops = spdk_nvmf_get_transport_ops(type);
89 if (!ops) {
90 SPDK_ERRLOG("Transport type %s unavailable.\n",
91 spdk_nvme_transport_id_trtype_str(type));
92 return NULL;
93 }
94
95 transport = ops->create(opts);
96 if (!transport) {
97 SPDK_ERRLOG("Unable to create new transport of type %s\n",
98 spdk_nvme_transport_id_trtype_str(type));
99 return NULL;
100 }
101
102 transport->ops = ops;
103 transport->opts = *opts;
9f95a23c
TL
104 chars_written = snprintf(spdk_mempool_name, MAX_MEMPOOL_NAME_LENGTH, "%s_%s_%s", "spdk_nvmf",
105 spdk_nvme_transport_id_trtype_str(type), "data");
106 if (chars_written < 0) {
107 SPDK_ERRLOG("Unable to generate transport data buffer pool name.\n");
108 ops->destroy(transport);
109 return NULL;
110 }
111
112 transport->data_buf_pool = spdk_mempool_create(spdk_mempool_name,
113 opts->num_shared_buffers,
114 opts->io_unit_size + NVMF_DATA_BUFFER_ALIGNMENT,
115 SPDK_MEMPOOL_DEFAULT_CACHE_SIZE,
116 SPDK_ENV_SOCKET_ID_ANY);
117
118 if (!transport->data_buf_pool) {
119 SPDK_ERRLOG("Unable to allocate buffer pool for poll group\n");
120 ops->destroy(transport);
121 return NULL;
122 }
7c673cae 123
11fdf7f2 124 return transport;
7c673cae
FG
125}
126
9f95a23c
TL
127struct spdk_nvmf_transport *
128spdk_nvmf_transport_get_first(struct spdk_nvmf_tgt *tgt)
129{
130 return TAILQ_FIRST(&tgt->transports);
131}
132
133struct spdk_nvmf_transport *
134spdk_nvmf_transport_get_next(struct spdk_nvmf_transport *transport)
135{
136 return TAILQ_NEXT(transport, link);
137}
138
7c673cae 139int
11fdf7f2 140spdk_nvmf_transport_destroy(struct spdk_nvmf_transport *transport)
7c673cae 141{
9f95a23c
TL
142 if (transport->data_buf_pool != NULL) {
143 if (spdk_mempool_count(transport->data_buf_pool) !=
144 transport->opts.num_shared_buffers) {
145 SPDK_ERRLOG("transport buffer pool count is %zu but should be %u\n",
146 spdk_mempool_count(transport->data_buf_pool),
147 transport->opts.num_shared_buffers);
148 }
149 }
150
151 spdk_mempool_free(transport->data_buf_pool);
152
11fdf7f2
TL
153 return transport->ops->destroy(transport);
154}
7c673cae 155
11fdf7f2
TL
156int
157spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport,
158 const struct spdk_nvme_transport_id *trid)
159{
160 return transport->ops->listen(transport, trid);
161}
162
163int
164spdk_nvmf_transport_stop_listen(struct spdk_nvmf_transport *transport,
165 const struct spdk_nvme_transport_id *trid)
166{
167 return transport->ops->stop_listen(transport, trid);
168}
169
170void
171spdk_nvmf_transport_accept(struct spdk_nvmf_transport *transport, new_qpair_fn cb_fn)
172{
173 transport->ops->accept(transport, cb_fn);
174}
175
176void
177spdk_nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport,
178 struct spdk_nvme_transport_id *trid,
179 struct spdk_nvmf_discovery_log_page_entry *entry)
180{
181 transport->ops->listener_discover(transport, trid, entry);
182}
183
184struct spdk_nvmf_transport_poll_group *
185spdk_nvmf_transport_poll_group_create(struct spdk_nvmf_transport *transport)
186{
187 struct spdk_nvmf_transport_poll_group *group;
9f95a23c 188 struct spdk_nvmf_transport_pg_cache_buf *buf;
11fdf7f2
TL
189
190 group = transport->ops->poll_group_create(transport);
9f95a23c
TL
191 if (!group) {
192 return NULL;
193 }
11fdf7f2
TL
194 group->transport = transport;
195
9f95a23c
TL
196 STAILQ_INIT(&group->buf_cache);
197
198 if (transport->opts.buf_cache_size) {
199 group->buf_cache_count = 0;
200 group->buf_cache_size = transport->opts.buf_cache_size;
201 while (group->buf_cache_count < group->buf_cache_size) {
202 buf = (struct spdk_nvmf_transport_pg_cache_buf *)spdk_mempool_get(transport->data_buf_pool);
203 if (!buf) {
204 SPDK_NOTICELOG("Unable to reserve the full number of buffers for the pg buffer cache.\n");
205 break;
206 }
207 STAILQ_INSERT_HEAD(&group->buf_cache, buf, link);
208 group->buf_cache_count++;
209 }
210 }
11fdf7f2
TL
211 return group;
212}
213
214void
215spdk_nvmf_transport_poll_group_destroy(struct spdk_nvmf_transport_poll_group *group)
216{
9f95a23c
TL
217 struct spdk_nvmf_transport_pg_cache_buf *buf, *tmp;
218
219 STAILQ_FOREACH_SAFE(buf, &group->buf_cache, link, tmp) {
220 STAILQ_REMOVE(&group->buf_cache, buf, spdk_nvmf_transport_pg_cache_buf, link);
221 spdk_mempool_put(group->transport->data_buf_pool, buf);
222 }
11fdf7f2
TL
223 group->transport->ops->poll_group_destroy(group);
224}
225
226int
227spdk_nvmf_transport_poll_group_add(struct spdk_nvmf_transport_poll_group *group,
228 struct spdk_nvmf_qpair *qpair)
229{
230 if (qpair->transport) {
231 assert(qpair->transport == group->transport);
232 if (qpair->transport != group->transport) {
233 return -1;
7c673cae 234 }
11fdf7f2
TL
235 } else {
236 qpair->transport = group->transport;
7c673cae
FG
237 }
238
11fdf7f2
TL
239 return group->transport->ops->poll_group_add(group, qpair);
240}
241
9f95a23c
TL
242int
243spdk_nvmf_transport_poll_group_remove(struct spdk_nvmf_transport_poll_group *group,
244 struct spdk_nvmf_qpair *qpair)
245{
246 int rc = ENOTSUP;
247
248 assert(qpair->transport == group->transport);
249 if (group->transport->ops->poll_group_remove) {
250 rc = group->transport->ops->poll_group_remove(group, qpair);
251 }
252
253 return rc;
254}
255
11fdf7f2
TL
256int
257spdk_nvmf_transport_poll_group_poll(struct spdk_nvmf_transport_poll_group *group)
258{
259 return group->transport->ops->poll_group_poll(group);
260}
261
262int
263spdk_nvmf_transport_req_free(struct spdk_nvmf_request *req)
264{
265 return req->qpair->transport->ops->req_free(req);
266}
267
268int
269spdk_nvmf_transport_req_complete(struct spdk_nvmf_request *req)
270{
271 return req->qpair->transport->ops->req_complete(req);
7c673cae
FG
272}
273
274void
11fdf7f2 275spdk_nvmf_transport_qpair_fini(struct spdk_nvmf_qpair *qpair)
7c673cae 276{
11fdf7f2
TL
277 qpair->transport->ops->qpair_fini(qpair);
278}
7c673cae 279
11fdf7f2
TL
280int
281spdk_nvmf_transport_qpair_get_peer_trid(struct spdk_nvmf_qpair *qpair,
282 struct spdk_nvme_transport_id *trid)
7c673cae 283{
11fdf7f2
TL
284 return qpair->transport->ops->qpair_get_peer_trid(qpair, trid);
285}
7c673cae 286
11fdf7f2
TL
287int
288spdk_nvmf_transport_qpair_get_local_trid(struct spdk_nvmf_qpair *qpair,
289 struct spdk_nvme_transport_id *trid)
290{
291 return qpair->transport->ops->qpair_get_local_trid(qpair, trid);
292}
293
294int
295spdk_nvmf_transport_qpair_get_listen_trid(struct spdk_nvmf_qpair *qpair,
296 struct spdk_nvme_transport_id *trid)
297{
298 return qpair->transport->ops->qpair_get_listen_trid(qpair, trid);
299}
300
301bool
302spdk_nvmf_transport_opts_init(enum spdk_nvme_transport_type type,
303 struct spdk_nvmf_transport_opts *opts)
304{
305 const struct spdk_nvmf_transport_ops *ops;
306
307 ops = spdk_nvmf_get_transport_ops(type);
308 if (!ops) {
309 SPDK_ERRLOG("Transport type %s unavailable.\n",
310 spdk_nvme_transport_id_trtype_str(type));
311 return false;
7c673cae
FG
312 }
313
11fdf7f2
TL
314 ops->opts_init(opts);
315 return true;
7c673cae 316}
9f95a23c
TL
317
318int
319spdk_nvmf_transport_qpair_set_sqsize(struct spdk_nvmf_qpair *qpair)
320{
321 if (qpair->transport->ops->qpair_set_sqsize) {
322 return qpair->transport->ops->qpair_set_sqsize(qpair);
323 }
324
325 return 0;
326}