]>
Commit | Line | Data |
---|---|---|
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 | 45 | static 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 |
55 | static inline const struct spdk_nvmf_transport_ops * |
56 | spdk_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 |
67 | const struct spdk_nvmf_transport_opts * |
68 | spdk_nvmf_get_transport_opts(struct spdk_nvmf_transport *transport) | |
69 | { | |
70 | return &transport->opts; | |
71 | } | |
72 | ||
73 | spdk_nvme_transport_type_t | |
74 | spdk_nvmf_get_transport_type(struct spdk_nvmf_transport *transport) | |
75 | { | |
76 | return transport->ops->type; | |
77 | } | |
78 | ||
11fdf7f2 TL |
79 | struct spdk_nvmf_transport * |
80 | spdk_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 |
127 | struct spdk_nvmf_transport * |
128 | spdk_nvmf_transport_get_first(struct spdk_nvmf_tgt *tgt) | |
129 | { | |
130 | return TAILQ_FIRST(&tgt->transports); | |
131 | } | |
132 | ||
133 | struct spdk_nvmf_transport * | |
134 | spdk_nvmf_transport_get_next(struct spdk_nvmf_transport *transport) | |
135 | { | |
136 | return TAILQ_NEXT(transport, link); | |
137 | } | |
138 | ||
7c673cae | 139 | int |
11fdf7f2 | 140 | spdk_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 |
156 | int |
157 | spdk_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 | ||
163 | int | |
164 | spdk_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 | ||
170 | void | |
171 | spdk_nvmf_transport_accept(struct spdk_nvmf_transport *transport, new_qpair_fn cb_fn) | |
172 | { | |
173 | transport->ops->accept(transport, cb_fn); | |
174 | } | |
175 | ||
176 | void | |
177 | spdk_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 | ||
184 | struct spdk_nvmf_transport_poll_group * | |
185 | spdk_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 | ||
214 | void | |
215 | spdk_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 | ||
226 | int | |
227 | spdk_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 |
242 | int |
243 | spdk_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 |
256 | int |
257 | spdk_nvmf_transport_poll_group_poll(struct spdk_nvmf_transport_poll_group *group) | |
258 | { | |
259 | return group->transport->ops->poll_group_poll(group); | |
260 | } | |
261 | ||
262 | int | |
263 | spdk_nvmf_transport_req_free(struct spdk_nvmf_request *req) | |
264 | { | |
265 | return req->qpair->transport->ops->req_free(req); | |
266 | } | |
267 | ||
268 | int | |
269 | spdk_nvmf_transport_req_complete(struct spdk_nvmf_request *req) | |
270 | { | |
271 | return req->qpair->transport->ops->req_complete(req); | |
7c673cae FG |
272 | } |
273 | ||
274 | void | |
11fdf7f2 | 275 | spdk_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 |
280 | int |
281 | spdk_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 |
287 | int |
288 | spdk_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 | ||
294 | int | |
295 | spdk_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 | ||
301 | bool | |
302 | spdk_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 | |
318 | int | |
319 | spdk_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 | } |