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