1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. All rights reserved. 5 * Copyright (c) 2018-2019 Mellanox Technologies LTD. All rights reserved. 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 34 #include "spdk/stdinc.h" 35 36 #include "nvmf_internal.h" 37 #include "transport.h" 38 39 #include "spdk/config.h" 40 #include "spdk/log.h" 41 #include "spdk/nvmf.h" 42 #include "spdk/queue.h" 43 #include "spdk/util.h" 44 45 static const struct spdk_nvmf_transport_ops *const g_transport_ops[] = { 46 #ifdef SPDK_CONFIG_RDMA 47 &spdk_nvmf_transport_rdma, 48 #endif 49 &spdk_nvmf_transport_tcp, 50 #ifdef SPDK_CONFIG_FC 51 &spdk_nvmf_transport_fc, 52 #endif 53 }; 54 55 #define NUM_TRANSPORTS (SPDK_COUNTOF(g_transport_ops)) 56 #define MAX_MEMPOOL_NAME_LENGTH 40 57 58 static inline const struct spdk_nvmf_transport_ops * 59 spdk_nvmf_get_transport_ops(enum spdk_nvme_transport_type type) 60 { 61 size_t i; 62 for (i = 0; i != NUM_TRANSPORTS; i++) { 63 if (g_transport_ops[i]->type == type) { 64 return g_transport_ops[i]; 65 } 66 } 67 return NULL; 68 } 69 70 const struct spdk_nvmf_transport_opts * 71 spdk_nvmf_get_transport_opts(struct spdk_nvmf_transport *transport) 72 { 73 return &transport->opts; 74 } 75 76 spdk_nvme_transport_type_t 77 spdk_nvmf_get_transport_type(struct spdk_nvmf_transport *transport) 78 { 79 return transport->ops->type; 80 } 81 82 struct spdk_nvmf_transport * 83 spdk_nvmf_transport_create(enum spdk_nvme_transport_type type, 84 struct spdk_nvmf_transport_opts *opts) 85 { 86 const struct spdk_nvmf_transport_ops *ops = NULL; 87 struct spdk_nvmf_transport *transport; 88 char spdk_mempool_name[MAX_MEMPOOL_NAME_LENGTH]; 89 int chars_written; 90 91 ops = spdk_nvmf_get_transport_ops(type); 92 if (!ops) { 93 SPDK_ERRLOG("Transport type '%s' unavailable.\n", 94 spdk_nvme_transport_id_trtype_str(type)); 95 return NULL; 96 } 97 98 transport = ops->create(opts); 99 if (!transport) { 100 SPDK_ERRLOG("Unable to create new transport of type %s\n", 101 spdk_nvme_transport_id_trtype_str(type)); 102 return NULL; 103 } 104 105 transport->ops = ops; 106 transport->opts = *opts; 107 chars_written = snprintf(spdk_mempool_name, MAX_MEMPOOL_NAME_LENGTH, "%s_%s_%s", "spdk_nvmf", 108 spdk_nvme_transport_id_trtype_str(type), "data"); 109 if (chars_written < 0) { 110 SPDK_ERRLOG("Unable to generate transport data buffer pool name.\n"); 111 ops->destroy(transport); 112 return NULL; 113 } 114 115 transport->data_buf_pool = spdk_mempool_create(spdk_mempool_name, 116 opts->num_shared_buffers, 117 opts->io_unit_size + NVMF_DATA_BUFFER_ALIGNMENT, 118 SPDK_MEMPOOL_DEFAULT_CACHE_SIZE, 119 SPDK_ENV_SOCKET_ID_ANY); 120 121 if (!transport->data_buf_pool) { 122 SPDK_ERRLOG("Unable to allocate buffer pool for poll group\n"); 123 ops->destroy(transport); 124 return NULL; 125 } 126 127 return transport; 128 } 129 130 struct spdk_nvmf_transport * 131 spdk_nvmf_transport_get_first(struct spdk_nvmf_tgt *tgt) 132 { 133 return TAILQ_FIRST(&tgt->transports); 134 } 135 136 struct spdk_nvmf_transport * 137 spdk_nvmf_transport_get_next(struct spdk_nvmf_transport *transport) 138 { 139 return TAILQ_NEXT(transport, link); 140 } 141 142 int 143 spdk_nvmf_transport_destroy(struct spdk_nvmf_transport *transport) 144 { 145 if (transport->data_buf_pool != NULL) { 146 if (spdk_mempool_count(transport->data_buf_pool) != 147 transport->opts.num_shared_buffers) { 148 SPDK_ERRLOG("transport buffer pool count is %zu but should be %u\n", 149 spdk_mempool_count(transport->data_buf_pool), 150 transport->opts.num_shared_buffers); 151 } 152 } 153 154 spdk_mempool_free(transport->data_buf_pool); 155 156 return transport->ops->destroy(transport); 157 } 158 159 int 160 spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport, 161 const struct spdk_nvme_transport_id *trid) 162 { 163 return transport->ops->listen(transport, trid); 164 } 165 166 int 167 spdk_nvmf_transport_stop_listen(struct spdk_nvmf_transport *transport, 168 const struct spdk_nvme_transport_id *trid) 169 { 170 return transport->ops->stop_listen(transport, trid); 171 } 172 173 void 174 spdk_nvmf_transport_accept(struct spdk_nvmf_transport *transport, new_qpair_fn cb_fn) 175 { 176 transport->ops->accept(transport, cb_fn); 177 } 178 179 void 180 spdk_nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport, 181 struct spdk_nvme_transport_id *trid, 182 struct spdk_nvmf_discovery_log_page_entry *entry) 183 { 184 transport->ops->listener_discover(transport, trid, entry); 185 } 186 187 struct spdk_nvmf_transport_poll_group * 188 spdk_nvmf_transport_poll_group_create(struct spdk_nvmf_transport *transport) 189 { 190 struct spdk_nvmf_transport_poll_group *group; 191 struct spdk_nvmf_transport_pg_cache_buf *buf; 192 193 group = transport->ops->poll_group_create(transport); 194 if (!group) { 195 return NULL; 196 } 197 group->transport = transport; 198 199 STAILQ_INIT(&group->buf_cache); 200 201 if (transport->opts.buf_cache_size) { 202 group->buf_cache_count = 0; 203 group->buf_cache_size = transport->opts.buf_cache_size; 204 while (group->buf_cache_count < group->buf_cache_size) { 205 buf = (struct spdk_nvmf_transport_pg_cache_buf *)spdk_mempool_get(transport->data_buf_pool); 206 if (!buf) { 207 SPDK_NOTICELOG("Unable to reserve the full number of buffers for the pg buffer cache.\n"); 208 break; 209 } 210 STAILQ_INSERT_HEAD(&group->buf_cache, buf, link); 211 group->buf_cache_count++; 212 } 213 } 214 return group; 215 } 216 217 struct spdk_nvmf_transport_poll_group * 218 spdk_nvmf_transport_get_optimal_poll_group(struct spdk_nvmf_transport *transport, 219 struct spdk_nvmf_qpair *qpair) 220 { 221 if (transport->ops->get_optimal_poll_group) { 222 return transport->ops->get_optimal_poll_group(qpair); 223 } else { 224 return NULL; 225 } 226 } 227 228 void 229 spdk_nvmf_transport_poll_group_destroy(struct spdk_nvmf_transport_poll_group *group) 230 { 231 struct spdk_nvmf_transport_pg_cache_buf *buf, *tmp; 232 233 STAILQ_FOREACH_SAFE(buf, &group->buf_cache, link, tmp) { 234 STAILQ_REMOVE(&group->buf_cache, buf, spdk_nvmf_transport_pg_cache_buf, link); 235 spdk_mempool_put(group->transport->data_buf_pool, buf); 236 } 237 group->transport->ops->poll_group_destroy(group); 238 } 239 240 int 241 spdk_nvmf_transport_poll_group_add(struct spdk_nvmf_transport_poll_group *group, 242 struct spdk_nvmf_qpair *qpair) 243 { 244 if (qpair->transport) { 245 assert(qpair->transport == group->transport); 246 if (qpair->transport != group->transport) { 247 return -1; 248 } 249 } else { 250 qpair->transport = group->transport; 251 } 252 253 return group->transport->ops->poll_group_add(group, qpair); 254 } 255 256 int 257 spdk_nvmf_transport_poll_group_remove(struct spdk_nvmf_transport_poll_group *group, 258 struct spdk_nvmf_qpair *qpair) 259 { 260 int rc = ENOTSUP; 261 262 assert(qpair->transport == group->transport); 263 if (group->transport->ops->poll_group_remove) { 264 rc = group->transport->ops->poll_group_remove(group, qpair); 265 } 266 267 return rc; 268 } 269 270 int 271 spdk_nvmf_transport_poll_group_poll(struct spdk_nvmf_transport_poll_group *group) 272 { 273 return group->transport->ops->poll_group_poll(group); 274 } 275 276 int 277 spdk_nvmf_transport_req_free(struct spdk_nvmf_request *req) 278 { 279 return req->qpair->transport->ops->req_free(req); 280 } 281 282 int 283 spdk_nvmf_transport_req_complete(struct spdk_nvmf_request *req) 284 { 285 return req->qpair->transport->ops->req_complete(req); 286 } 287 288 void 289 spdk_nvmf_transport_qpair_fini(struct spdk_nvmf_qpair *qpair) 290 { 291 qpair->transport->ops->qpair_fini(qpair); 292 } 293 294 int 295 spdk_nvmf_transport_qpair_get_peer_trid(struct spdk_nvmf_qpair *qpair, 296 struct spdk_nvme_transport_id *trid) 297 { 298 return qpair->transport->ops->qpair_get_peer_trid(qpair, trid); 299 } 300 301 int 302 spdk_nvmf_transport_qpair_get_local_trid(struct spdk_nvmf_qpair *qpair, 303 struct spdk_nvme_transport_id *trid) 304 { 305 return qpair->transport->ops->qpair_get_local_trid(qpair, trid); 306 } 307 308 int 309 spdk_nvmf_transport_qpair_get_listen_trid(struct spdk_nvmf_qpair *qpair, 310 struct spdk_nvme_transport_id *trid) 311 { 312 return qpair->transport->ops->qpair_get_listen_trid(qpair, trid); 313 } 314 315 bool 316 spdk_nvmf_transport_opts_init(enum spdk_nvme_transport_type type, 317 struct spdk_nvmf_transport_opts *opts) 318 { 319 const struct spdk_nvmf_transport_ops *ops; 320 321 ops = spdk_nvmf_get_transport_ops(type); 322 if (!ops) { 323 SPDK_ERRLOG("Transport type %s unavailable.\n", 324 spdk_nvme_transport_id_trtype_str(type)); 325 return false; 326 } 327 328 ops->opts_init(opts); 329 return true; 330 } 331 332 int 333 spdk_nvmf_transport_qpair_set_sqsize(struct spdk_nvmf_qpair *qpair) 334 { 335 if (qpair->transport->ops->qpair_set_sqsize) { 336 return qpair->transport->ops->qpair_set_sqsize(qpair); 337 } 338 339 return 0; 340 } 341 342 int 343 spdk_nvmf_transport_poll_group_get_stat(struct spdk_nvmf_tgt *tgt, 344 struct spdk_nvmf_transport *transport, 345 struct spdk_nvmf_transport_poll_group_stat **stat) 346 { 347 if (transport->ops->poll_group_get_stat) { 348 return transport->ops->poll_group_get_stat(tgt, stat); 349 } else { 350 return -ENOTSUP; 351 } 352 } 353 354 void 355 spdk_nvmf_transport_poll_group_free_stat(struct spdk_nvmf_transport *transport, 356 struct spdk_nvmf_transport_poll_group_stat *stat) 357 { 358 if (transport->ops->poll_group_free_stat) { 359 transport->ops->poll_group_free_stat(stat); 360 } 361 } 362