1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. All rights reserved. 5 * Copyright (c) 2020 Mellanox Technologies LTD. All rights reserved. 6 * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * * Neither the name of Intel Corporation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include "spdk/stdinc.h" 36 37 #include "spdk/sock.h" 38 #include "spdk_internal/sock.h" 39 #include "spdk/log.h" 40 #include "spdk/env.h" 41 #include "spdk/util.h" 42 43 #define SPDK_SOCK_DEFAULT_PRIORITY 0 44 #define SPDK_SOCK_DEFAULT_ZCOPY true 45 #define SPDK_SOCK_DEFAULT_ACK_TIMEOUT 0 46 47 #define SPDK_SOCK_OPTS_FIELD_OK(opts, field) (offsetof(struct spdk_sock_opts, field) + sizeof(opts->field) <= (opts->opts_size)) 48 49 static STAILQ_HEAD(, spdk_net_impl) g_net_impls = STAILQ_HEAD_INITIALIZER(g_net_impls); 50 static struct spdk_net_impl *g_default_impl; 51 52 struct spdk_sock_placement_id_entry { 53 int placement_id; 54 uint32_t ref; 55 struct spdk_sock_group_impl *group; 56 STAILQ_ENTRY(spdk_sock_placement_id_entry) link; 57 }; 58 59 static inline struct spdk_sock_group_impl * 60 sock_get_group_impl_from_group(struct spdk_sock *sock, struct spdk_sock_group *group) 61 { 62 struct spdk_sock_group_impl *group_impl = NULL; 63 64 STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) { 65 if (sock->net_impl == group_impl->net_impl) { 66 return group_impl; 67 } 68 } 69 return NULL; 70 } 71 72 /* Called under map->mtx lock */ 73 static struct spdk_sock_placement_id_entry * 74 _sock_map_entry_alloc(struct spdk_sock_map *map, int placement_id) 75 { 76 struct spdk_sock_placement_id_entry *entry; 77 78 entry = calloc(1, sizeof(*entry)); 79 if (!entry) { 80 SPDK_ERRLOG("Cannot allocate an entry for placement_id=%u\n", placement_id); 81 return NULL; 82 } 83 84 entry->placement_id = placement_id; 85 86 STAILQ_INSERT_TAIL(&map->entries, entry, link); 87 88 return entry; 89 } 90 91 int 92 spdk_sock_map_insert(struct spdk_sock_map *map, int placement_id, 93 struct spdk_sock_group_impl *group) 94 { 95 struct spdk_sock_placement_id_entry *entry; 96 int rc = 0; 97 98 pthread_mutex_lock(&map->mtx); 99 STAILQ_FOREACH(entry, &map->entries, link) { 100 if (placement_id == entry->placement_id) { 101 /* Can't set group to NULL if it is already not-NULL */ 102 if (group == NULL) { 103 rc = (entry->group == NULL) ? 0 : -EINVAL; 104 goto end; 105 } 106 107 if (entry->group == NULL) { 108 entry->group = group; 109 } else if (entry->group != group) { 110 rc = -EINVAL; 111 goto end; 112 } 113 114 entry->ref++; 115 goto end; 116 } 117 } 118 119 entry = _sock_map_entry_alloc(map, placement_id); 120 if (entry == NULL) { 121 rc = -ENOMEM; 122 goto end; 123 } 124 if (group) { 125 entry->group = group; 126 entry->ref++; 127 } 128 end: 129 pthread_mutex_unlock(&map->mtx); 130 131 return rc; 132 } 133 134 void 135 spdk_sock_map_release(struct spdk_sock_map *map, int placement_id) 136 { 137 struct spdk_sock_placement_id_entry *entry; 138 139 pthread_mutex_lock(&map->mtx); 140 STAILQ_FOREACH(entry, &map->entries, link) { 141 if (placement_id == entry->placement_id) { 142 assert(entry->ref > 0); 143 entry->ref--; 144 145 if (entry->ref == 0) { 146 entry->group = NULL; 147 } 148 break; 149 } 150 } 151 152 pthread_mutex_unlock(&map->mtx); 153 } 154 155 int 156 spdk_sock_map_lookup(struct spdk_sock_map *map, int placement_id, 157 struct spdk_sock_group_impl **group, struct spdk_sock_group_impl *hint) 158 { 159 struct spdk_sock_placement_id_entry *entry; 160 161 *group = NULL; 162 pthread_mutex_lock(&map->mtx); 163 STAILQ_FOREACH(entry, &map->entries, link) { 164 if (placement_id == entry->placement_id) { 165 *group = entry->group; 166 if (*group != NULL) { 167 /* Return previously assigned sock_group */ 168 pthread_mutex_unlock(&map->mtx); 169 return 0; 170 } 171 break; 172 } 173 } 174 175 /* No entry with assigned sock_group, nor hint to use */ 176 if (hint == NULL) { 177 pthread_mutex_unlock(&map->mtx); 178 return -EINVAL; 179 } 180 181 /* Create new entry if there is none with matching placement_id */ 182 if (entry == NULL) { 183 entry = _sock_map_entry_alloc(map, placement_id); 184 if (entry == NULL) { 185 pthread_mutex_unlock(&map->mtx); 186 return -ENOMEM; 187 } 188 } 189 190 entry->group = hint; 191 pthread_mutex_unlock(&map->mtx); 192 193 return 0; 194 } 195 196 void 197 spdk_sock_map_cleanup(struct spdk_sock_map *map) 198 { 199 struct spdk_sock_placement_id_entry *entry, *tmp; 200 201 pthread_mutex_lock(&map->mtx); 202 STAILQ_FOREACH_SAFE(entry, &map->entries, link, tmp) { 203 STAILQ_REMOVE(&map->entries, entry, spdk_sock_placement_id_entry, link); 204 free(entry); 205 } 206 pthread_mutex_unlock(&map->mtx); 207 } 208 209 int 210 spdk_sock_map_find_free(struct spdk_sock_map *map) 211 { 212 struct spdk_sock_placement_id_entry *entry; 213 int placement_id = -1; 214 215 pthread_mutex_lock(&map->mtx); 216 STAILQ_FOREACH(entry, &map->entries, link) { 217 if (entry->group == NULL) { 218 placement_id = entry->placement_id; 219 break; 220 } 221 } 222 223 pthread_mutex_unlock(&map->mtx); 224 225 return placement_id; 226 } 227 228 int 229 spdk_sock_get_optimal_sock_group(struct spdk_sock *sock, struct spdk_sock_group **group, 230 struct spdk_sock_group *hint) 231 { 232 struct spdk_sock_group_impl *group_impl; 233 struct spdk_sock_group_impl *hint_group_impl = NULL; 234 235 assert(group != NULL); 236 237 if (hint != NULL) { 238 hint_group_impl = sock_get_group_impl_from_group(sock, hint); 239 if (hint_group_impl == NULL) { 240 return -EINVAL; 241 } 242 } 243 244 group_impl = sock->net_impl->group_impl_get_optimal(sock, hint_group_impl); 245 246 if (group_impl) { 247 *group = group_impl->group; 248 } 249 250 return 0; 251 } 252 253 int 254 spdk_sock_getaddr(struct spdk_sock *sock, char *saddr, int slen, uint16_t *sport, 255 char *caddr, int clen, uint16_t *cport) 256 { 257 return sock->net_impl->getaddr(sock, saddr, slen, sport, caddr, clen, cport); 258 } 259 260 void 261 spdk_sock_get_default_opts(struct spdk_sock_opts *opts) 262 { 263 assert(opts); 264 265 if (SPDK_SOCK_OPTS_FIELD_OK(opts, priority)) { 266 opts->priority = SPDK_SOCK_DEFAULT_PRIORITY; 267 } 268 269 if (SPDK_SOCK_OPTS_FIELD_OK(opts, zcopy)) { 270 opts->zcopy = SPDK_SOCK_DEFAULT_ZCOPY; 271 } 272 273 if (SPDK_SOCK_OPTS_FIELD_OK(opts, ack_timeout)) { 274 opts->ack_timeout = SPDK_SOCK_DEFAULT_ACK_TIMEOUT; 275 } 276 } 277 278 /* 279 * opts The opts allocated in the current library. 280 * opts_user The opts passed by the caller. 281 * */ 282 static void 283 sock_init_opts(struct spdk_sock_opts *opts, struct spdk_sock_opts *opts_user) 284 { 285 assert(opts); 286 assert(opts_user); 287 288 opts->opts_size = sizeof(*opts); 289 spdk_sock_get_default_opts(opts); 290 291 /* reset the size according to the user */ 292 opts->opts_size = opts_user->opts_size; 293 if (SPDK_SOCK_OPTS_FIELD_OK(opts, priority)) { 294 opts->priority = opts_user->priority; 295 } 296 297 if (SPDK_SOCK_OPTS_FIELD_OK(opts, zcopy)) { 298 opts->zcopy = opts_user->zcopy; 299 } 300 301 if (SPDK_SOCK_OPTS_FIELD_OK(opts, ack_timeout)) { 302 opts->ack_timeout = opts_user->ack_timeout; 303 } 304 } 305 306 struct spdk_sock * 307 spdk_sock_connect(const char *ip, int port, char *impl_name) 308 { 309 struct spdk_sock_opts opts; 310 311 opts.opts_size = sizeof(opts); 312 spdk_sock_get_default_opts(&opts); 313 return spdk_sock_connect_ext(ip, port, impl_name, &opts); 314 } 315 316 struct spdk_sock * 317 spdk_sock_connect_ext(const char *ip, int port, char *_impl_name, struct spdk_sock_opts *opts) 318 { 319 struct spdk_net_impl *impl = NULL; 320 struct spdk_sock *sock; 321 struct spdk_sock_opts opts_local; 322 const char *impl_name = NULL; 323 struct spdk_sock_impl_opts impl_opts = {}; 324 size_t len; 325 326 if (opts == NULL) { 327 SPDK_ERRLOG("the opts should not be NULL pointer\n"); 328 return NULL; 329 } 330 331 if (_impl_name) { 332 impl_name = _impl_name; 333 } else if (g_default_impl) { 334 impl_name = g_default_impl->name; 335 } 336 337 STAILQ_FOREACH_FROM(impl, &g_net_impls, link) { 338 if (impl_name && strncmp(impl_name, impl->name, strlen(impl->name) + 1)) { 339 continue; 340 } 341 342 SPDK_DEBUGLOG(sock, "Creating a client socket using impl %s\n", impl->name); 343 sock_init_opts(&opts_local, opts); 344 sock = impl->connect(ip, port, &opts_local); 345 if (sock != NULL) { 346 /* Copy the contents, both the two structures are the same ABI version */ 347 memcpy(&sock->opts, &opts_local, sizeof(sock->opts)); 348 sock->net_impl = impl; 349 TAILQ_INIT(&sock->queued_reqs); 350 TAILQ_INIT(&sock->pending_reqs); 351 352 len = sizeof(struct spdk_sock_impl_opts); 353 spdk_sock_impl_get_opts(impl->name, &impl_opts, &len); 354 sock->zerocopy_threshold = impl_opts.zerocopy_threshold; 355 return sock; 356 } 357 } 358 359 return NULL; 360 } 361 362 struct spdk_sock * 363 spdk_sock_listen(const char *ip, int port, char *impl_name) 364 { 365 struct spdk_sock_opts opts; 366 367 opts.opts_size = sizeof(opts); 368 spdk_sock_get_default_opts(&opts); 369 return spdk_sock_listen_ext(ip, port, impl_name, &opts); 370 } 371 372 struct spdk_sock * 373 spdk_sock_listen_ext(const char *ip, int port, char *_impl_name, struct spdk_sock_opts *opts) 374 { 375 struct spdk_net_impl *impl = NULL; 376 struct spdk_sock *sock; 377 struct spdk_sock_opts opts_local; 378 const char *impl_name = NULL; 379 380 if (opts == NULL) { 381 SPDK_ERRLOG("the opts should not be NULL pointer\n"); 382 return NULL; 383 } 384 385 if (_impl_name) { 386 impl_name = _impl_name; 387 } else if (g_default_impl) { 388 impl_name = g_default_impl->name; 389 } 390 391 STAILQ_FOREACH_FROM(impl, &g_net_impls, link) { 392 if (impl_name && strncmp(impl_name, impl->name, strlen(impl->name) + 1)) { 393 continue; 394 } 395 396 SPDK_DEBUGLOG(sock, "Creating a listening socket using impl %s\n", impl->name); 397 sock_init_opts(&opts_local, opts); 398 sock = impl->listen(ip, port, &opts_local); 399 if (sock != NULL) { 400 /* Copy the contents, both the two structures are the same ABI version */ 401 memcpy(&sock->opts, &opts_local, sizeof(sock->opts)); 402 sock->net_impl = impl; 403 /* Don't need to initialize the request queues for listen 404 * sockets. */ 405 return sock; 406 } 407 } 408 409 return NULL; 410 } 411 412 struct spdk_sock * 413 spdk_sock_accept(struct spdk_sock *sock) 414 { 415 struct spdk_sock *new_sock; 416 struct spdk_sock_impl_opts impl_opts = {}; 417 size_t len; 418 419 new_sock = sock->net_impl->accept(sock); 420 if (new_sock != NULL) { 421 /* Inherit the opts from the "accept sock" */ 422 new_sock->opts = sock->opts; 423 memcpy(&new_sock->opts, &sock->opts, sizeof(new_sock->opts)); 424 new_sock->net_impl = sock->net_impl; 425 TAILQ_INIT(&new_sock->queued_reqs); 426 TAILQ_INIT(&new_sock->pending_reqs); 427 428 len = sizeof(struct spdk_sock_impl_opts); 429 spdk_sock_impl_get_opts(sock->net_impl->name, &impl_opts, &len); 430 new_sock->zerocopy_threshold = impl_opts.zerocopy_threshold; 431 } 432 433 return new_sock; 434 } 435 436 int 437 spdk_sock_close(struct spdk_sock **_sock) 438 { 439 struct spdk_sock *sock = *_sock; 440 441 if (sock == NULL) { 442 errno = EBADF; 443 return -1; 444 } 445 446 if (sock->cb_fn != NULL) { 447 /* This sock is still part of a sock_group. */ 448 errno = EBUSY; 449 return -1; 450 } 451 452 /* Beyond this point the socket is considered closed. */ 453 *_sock = NULL; 454 455 sock->flags.closed = true; 456 457 if (sock->cb_cnt > 0) { 458 /* Let the callback unwind before destroying the socket */ 459 return 0; 460 } 461 462 spdk_sock_abort_requests(sock); 463 464 return sock->net_impl->close(sock); 465 } 466 467 ssize_t 468 spdk_sock_recv(struct spdk_sock *sock, void *buf, size_t len) 469 { 470 if (sock == NULL || sock->flags.closed) { 471 errno = EBADF; 472 return -1; 473 } 474 475 return sock->net_impl->recv(sock, buf, len); 476 } 477 478 ssize_t 479 spdk_sock_readv(struct spdk_sock *sock, struct iovec *iov, int iovcnt) 480 { 481 if (sock == NULL || sock->flags.closed) { 482 errno = EBADF; 483 return -1; 484 } 485 486 return sock->net_impl->readv(sock, iov, iovcnt); 487 } 488 489 ssize_t 490 spdk_sock_writev(struct spdk_sock *sock, struct iovec *iov, int iovcnt) 491 { 492 if (sock == NULL || sock->flags.closed) { 493 errno = EBADF; 494 return -1; 495 } 496 497 return sock->net_impl->writev(sock, iov, iovcnt); 498 } 499 500 void 501 spdk_sock_writev_async(struct spdk_sock *sock, struct spdk_sock_request *req) 502 { 503 assert(req->cb_fn != NULL); 504 505 if (sock == NULL || sock->flags.closed) { 506 req->cb_fn(req->cb_arg, -EBADF); 507 return; 508 } 509 510 sock->net_impl->writev_async(sock, req); 511 } 512 513 int 514 spdk_sock_flush(struct spdk_sock *sock) 515 { 516 if (sock == NULL || sock->flags.closed) { 517 return -EBADF; 518 } 519 520 /* Sock is in a polling group, so group polling mechanism will work */ 521 if (sock->group_impl != NULL) { 522 return 0; 523 } 524 525 return sock->net_impl->flush(sock); 526 } 527 528 int 529 spdk_sock_set_recvlowat(struct spdk_sock *sock, int nbytes) 530 { 531 return sock->net_impl->set_recvlowat(sock, nbytes); 532 } 533 534 int 535 spdk_sock_set_recvbuf(struct spdk_sock *sock, int sz) 536 { 537 return sock->net_impl->set_recvbuf(sock, sz); 538 } 539 540 int 541 spdk_sock_set_sendbuf(struct spdk_sock *sock, int sz) 542 { 543 return sock->net_impl->set_sendbuf(sock, sz); 544 } 545 546 bool 547 spdk_sock_is_ipv6(struct spdk_sock *sock) 548 { 549 return sock->net_impl->is_ipv6(sock); 550 } 551 552 bool 553 spdk_sock_is_ipv4(struct spdk_sock *sock) 554 { 555 return sock->net_impl->is_ipv4(sock); 556 } 557 558 bool 559 spdk_sock_is_connected(struct spdk_sock *sock) 560 { 561 return sock->net_impl->is_connected(sock); 562 } 563 564 struct spdk_sock_group * 565 spdk_sock_group_create(void *ctx) 566 { 567 struct spdk_net_impl *impl = NULL; 568 struct spdk_sock_group *group; 569 struct spdk_sock_group_impl *group_impl; 570 571 group = calloc(1, sizeof(*group)); 572 if (group == NULL) { 573 return NULL; 574 } 575 576 STAILQ_INIT(&group->group_impls); 577 578 STAILQ_FOREACH_FROM(impl, &g_net_impls, link) { 579 group_impl = impl->group_impl_create(); 580 if (group_impl != NULL) { 581 STAILQ_INSERT_TAIL(&group->group_impls, group_impl, link); 582 TAILQ_INIT(&group_impl->socks); 583 group_impl->net_impl = impl; 584 group_impl->group = group; 585 } 586 } 587 588 group->ctx = ctx; 589 590 return group; 591 } 592 593 void * 594 spdk_sock_group_get_ctx(struct spdk_sock_group *group) 595 { 596 if (group == NULL) { 597 return NULL; 598 } 599 600 return group->ctx; 601 } 602 603 int 604 spdk_sock_group_add_sock(struct spdk_sock_group *group, struct spdk_sock *sock, 605 spdk_sock_cb cb_fn, void *cb_arg) 606 { 607 struct spdk_sock_group_impl *group_impl = NULL; 608 int rc; 609 610 if (cb_fn == NULL) { 611 errno = EINVAL; 612 return -1; 613 } 614 615 if (sock->group_impl != NULL) { 616 /* 617 * This sock is already part of a sock_group. 618 */ 619 errno = EINVAL; 620 return -1; 621 } 622 623 group_impl = sock_get_group_impl_from_group(sock, group); 624 if (group_impl == NULL) { 625 errno = EINVAL; 626 return -1; 627 } 628 629 rc = group_impl->net_impl->group_impl_add_sock(group_impl, sock); 630 if (rc != 0) { 631 return rc; 632 } 633 634 TAILQ_INSERT_TAIL(&group_impl->socks, sock, link); 635 sock->group_impl = group_impl; 636 sock->cb_fn = cb_fn; 637 sock->cb_arg = cb_arg; 638 639 return 0; 640 } 641 642 int 643 spdk_sock_group_remove_sock(struct spdk_sock_group *group, struct spdk_sock *sock) 644 { 645 struct spdk_sock_group_impl *group_impl = NULL; 646 int rc; 647 648 group_impl = sock_get_group_impl_from_group(sock, group); 649 if (group_impl == NULL) { 650 errno = EINVAL; 651 return -1; 652 } 653 654 assert(group_impl == sock->group_impl); 655 656 rc = group_impl->net_impl->group_impl_remove_sock(group_impl, sock); 657 if (rc == 0) { 658 TAILQ_REMOVE(&group_impl->socks, sock, link); 659 sock->group_impl = NULL; 660 sock->cb_fn = NULL; 661 sock->cb_arg = NULL; 662 } 663 664 return rc; 665 } 666 667 int 668 spdk_sock_group_poll(struct spdk_sock_group *group) 669 { 670 return spdk_sock_group_poll_count(group, MAX_EVENTS_PER_POLL); 671 } 672 673 static int 674 sock_group_impl_poll_count(struct spdk_sock_group_impl *group_impl, 675 struct spdk_sock_group *group, 676 int max_events) 677 { 678 struct spdk_sock *socks[MAX_EVENTS_PER_POLL]; 679 int num_events, i; 680 681 if (TAILQ_EMPTY(&group_impl->socks)) { 682 return 0; 683 } 684 685 num_events = group_impl->net_impl->group_impl_poll(group_impl, max_events, socks); 686 if (num_events == -1) { 687 return -1; 688 } 689 690 for (i = 0; i < num_events; i++) { 691 struct spdk_sock *sock = socks[i]; 692 assert(sock->cb_fn != NULL); 693 sock->cb_fn(sock->cb_arg, group, sock); 694 } 695 696 return num_events; 697 } 698 699 int 700 spdk_sock_group_poll_count(struct spdk_sock_group *group, int max_events) 701 { 702 struct spdk_sock_group_impl *group_impl = NULL; 703 int rc, num_events = 0; 704 705 if (max_events < 1) { 706 errno = -EINVAL; 707 return -1; 708 } 709 710 /* 711 * Only poll for up to 32 events at a time - if more events are pending, 712 * the next call to this function will reap them. 713 */ 714 if (max_events > MAX_EVENTS_PER_POLL) { 715 max_events = MAX_EVENTS_PER_POLL; 716 } 717 718 STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) { 719 rc = sock_group_impl_poll_count(group_impl, group, max_events); 720 if (rc < 0) { 721 num_events = -1; 722 SPDK_ERRLOG("group_impl_poll_count for net(%s) failed\n", 723 group_impl->net_impl->name); 724 } else if (num_events >= 0) { 725 num_events += rc; 726 } 727 } 728 729 return num_events; 730 } 731 732 int 733 spdk_sock_group_close(struct spdk_sock_group **group) 734 { 735 struct spdk_sock_group_impl *group_impl = NULL, *tmp; 736 int rc; 737 738 if (*group == NULL) { 739 errno = EBADF; 740 return -1; 741 } 742 743 STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) { 744 if (!TAILQ_EMPTY(&group_impl->socks)) { 745 errno = EBUSY; 746 return -1; 747 } 748 } 749 750 STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) { 751 rc = group_impl->net_impl->group_impl_close(group_impl); 752 if (rc != 0) { 753 SPDK_ERRLOG("group_impl_close for net(%s) failed\n", 754 group_impl->net_impl->name); 755 } 756 } 757 758 free(*group); 759 *group = NULL; 760 761 return 0; 762 } 763 764 static inline struct spdk_net_impl * 765 sock_get_impl_by_name(const char *impl_name) 766 { 767 struct spdk_net_impl *impl; 768 769 assert(impl_name != NULL); 770 STAILQ_FOREACH(impl, &g_net_impls, link) { 771 if (0 == strcmp(impl_name, impl->name)) { 772 return impl; 773 } 774 } 775 776 return NULL; 777 } 778 779 int 780 spdk_sock_impl_get_opts(const char *impl_name, struct spdk_sock_impl_opts *opts, size_t *len) 781 { 782 struct spdk_net_impl *impl; 783 784 if (!impl_name || !opts || !len) { 785 errno = EINVAL; 786 return -1; 787 } 788 789 impl = sock_get_impl_by_name(impl_name); 790 if (!impl) { 791 errno = EINVAL; 792 return -1; 793 } 794 795 if (!impl->get_opts) { 796 errno = ENOTSUP; 797 return -1; 798 } 799 800 return impl->get_opts(opts, len); 801 } 802 803 int 804 spdk_sock_impl_set_opts(const char *impl_name, const struct spdk_sock_impl_opts *opts, size_t len) 805 { 806 struct spdk_net_impl *impl; 807 808 if (!impl_name || !opts) { 809 errno = EINVAL; 810 return -1; 811 } 812 813 impl = sock_get_impl_by_name(impl_name); 814 if (!impl) { 815 errno = EINVAL; 816 return -1; 817 } 818 819 if (!impl->set_opts) { 820 errno = ENOTSUP; 821 return -1; 822 } 823 824 return impl->set_opts(opts, len); 825 } 826 827 void 828 spdk_sock_write_config_json(struct spdk_json_write_ctx *w) 829 { 830 struct spdk_net_impl *impl; 831 struct spdk_sock_impl_opts opts; 832 size_t len; 833 834 assert(w != NULL); 835 836 spdk_json_write_array_begin(w); 837 838 if (g_default_impl) { 839 spdk_json_write_object_begin(w); 840 spdk_json_write_named_string(w, "method", "sock_set_default_impl"); 841 spdk_json_write_named_object_begin(w, "params"); 842 spdk_json_write_named_string(w, "impl_name", g_default_impl->name); 843 spdk_json_write_object_end(w); 844 spdk_json_write_object_end(w); 845 } 846 847 STAILQ_FOREACH(impl, &g_net_impls, link) { 848 if (!impl->get_opts) { 849 continue; 850 } 851 852 len = sizeof(opts); 853 if (impl->get_opts(&opts, &len) == 0) { 854 spdk_json_write_object_begin(w); 855 spdk_json_write_named_string(w, "method", "sock_impl_set_options"); 856 spdk_json_write_named_object_begin(w, "params"); 857 spdk_json_write_named_string(w, "impl_name", impl->name); 858 spdk_json_write_named_uint32(w, "recv_buf_size", opts.recv_buf_size); 859 spdk_json_write_named_uint32(w, "send_buf_size", opts.send_buf_size); 860 spdk_json_write_named_bool(w, "enable_recv_pipe", opts.enable_recv_pipe); 861 spdk_json_write_named_bool(w, "enable_quickack", opts.enable_quickack); 862 spdk_json_write_named_uint32(w, "enable_placement_id", opts.enable_placement_id); 863 spdk_json_write_named_bool(w, "enable_zerocopy_send_server", opts.enable_zerocopy_send_server); 864 spdk_json_write_named_bool(w, "enable_zerocopy_send_client", opts.enable_zerocopy_send_client); 865 spdk_json_write_named_uint32(w, "zerocopy_threshold", opts.zerocopy_threshold); 866 spdk_json_write_object_end(w); 867 spdk_json_write_object_end(w); 868 } else { 869 SPDK_ERRLOG("Failed to get socket options for socket implementation %s\n", impl->name); 870 } 871 } 872 873 spdk_json_write_array_end(w); 874 } 875 876 void 877 spdk_net_impl_register(struct spdk_net_impl *impl, int priority) 878 { 879 struct spdk_net_impl *cur, *prev; 880 881 impl->priority = priority; 882 prev = NULL; 883 STAILQ_FOREACH(cur, &g_net_impls, link) { 884 if (impl->priority > cur->priority) { 885 break; 886 } 887 prev = cur; 888 } 889 890 if (prev) { 891 STAILQ_INSERT_AFTER(&g_net_impls, prev, impl, link); 892 } else { 893 STAILQ_INSERT_HEAD(&g_net_impls, impl, link); 894 } 895 } 896 897 int spdk_sock_set_default_impl(const char *impl_name) 898 { 899 struct spdk_net_impl *impl; 900 901 if (!impl_name) { 902 errno = EINVAL; 903 return -1; 904 } 905 906 impl = sock_get_impl_by_name(impl_name); 907 if (!impl) { 908 errno = EINVAL; 909 return -1; 910 } 911 912 if (impl == g_default_impl) { 913 return 0; 914 } 915 916 if (g_default_impl) { 917 SPDK_DEBUGLOG(sock, "Change the default sock impl from %s to %s\n", g_default_impl->name, 918 impl->name); 919 } else { 920 SPDK_DEBUGLOG(sock, "Set default sock implementation to %s\n", impl_name); 921 } 922 923 g_default_impl = impl; 924 925 return 0; 926 } 927 928 SPDK_LOG_REGISTER_COMPONENT(sock) 929