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