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