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