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 ssize_t 480 spdk_sock_writev(struct spdk_sock *sock, struct iovec *iov, int iovcnt) 481 { 482 if (sock == NULL || sock->flags.closed) { 483 errno = EBADF; 484 return -1; 485 } 486 487 return sock->net_impl->writev(sock, iov, iovcnt); 488 } 489 490 void 491 spdk_sock_writev_async(struct spdk_sock *sock, struct spdk_sock_request *req) 492 { 493 assert(req->cb_fn != NULL); 494 495 if (sock == NULL || sock->flags.closed) { 496 req->cb_fn(req->cb_arg, -EBADF); 497 return; 498 } 499 500 sock->net_impl->writev_async(sock, req); 501 } 502 503 int 504 spdk_sock_flush(struct spdk_sock *sock) 505 { 506 if (sock == NULL || sock->flags.closed) { 507 return -EBADF; 508 } 509 510 /* Sock is in a polling group, so group polling mechanism will work */ 511 if (sock->group_impl != NULL) { 512 return 0; 513 } 514 515 return sock->net_impl->flush(sock); 516 } 517 518 int 519 spdk_sock_set_recvlowat(struct spdk_sock *sock, int nbytes) 520 { 521 return sock->net_impl->set_recvlowat(sock, nbytes); 522 } 523 524 int 525 spdk_sock_set_recvbuf(struct spdk_sock *sock, int sz) 526 { 527 return sock->net_impl->set_recvbuf(sock, sz); 528 } 529 530 int 531 spdk_sock_set_sendbuf(struct spdk_sock *sock, int sz) 532 { 533 return sock->net_impl->set_sendbuf(sock, sz); 534 } 535 536 bool 537 spdk_sock_is_ipv6(struct spdk_sock *sock) 538 { 539 return sock->net_impl->is_ipv6(sock); 540 } 541 542 bool 543 spdk_sock_is_ipv4(struct spdk_sock *sock) 544 { 545 return sock->net_impl->is_ipv4(sock); 546 } 547 548 bool 549 spdk_sock_is_connected(struct spdk_sock *sock) 550 { 551 return sock->net_impl->is_connected(sock); 552 } 553 554 struct spdk_sock_group * 555 spdk_sock_group_create(void *ctx) 556 { 557 struct spdk_net_impl *impl = NULL; 558 struct spdk_sock_group *group; 559 struct spdk_sock_group_impl *group_impl; 560 561 group = calloc(1, sizeof(*group)); 562 if (group == NULL) { 563 return NULL; 564 } 565 566 STAILQ_INIT(&group->group_impls); 567 568 STAILQ_FOREACH_FROM(impl, &g_net_impls, link) { 569 group_impl = impl->group_impl_create(); 570 if (group_impl != NULL) { 571 STAILQ_INSERT_TAIL(&group->group_impls, group_impl, link); 572 TAILQ_INIT(&group_impl->socks); 573 group_impl->net_impl = impl; 574 group_impl->group = group; 575 } 576 } 577 578 group->ctx = ctx; 579 580 return group; 581 } 582 583 void * 584 spdk_sock_group_get_ctx(struct spdk_sock_group *group) 585 { 586 if (group == NULL) { 587 return NULL; 588 } 589 590 return group->ctx; 591 } 592 593 int 594 spdk_sock_group_add_sock(struct spdk_sock_group *group, struct spdk_sock *sock, 595 spdk_sock_cb cb_fn, void *cb_arg) 596 { 597 struct spdk_sock_group_impl *group_impl = NULL; 598 int rc; 599 600 if (cb_fn == NULL) { 601 errno = EINVAL; 602 return -1; 603 } 604 605 if (sock->group_impl != NULL) { 606 /* 607 * This sock is already part of a sock_group. 608 */ 609 errno = EINVAL; 610 return -1; 611 } 612 613 group_impl = sock_get_group_impl_from_group(sock, group); 614 if (group_impl == NULL) { 615 errno = EINVAL; 616 return -1; 617 } 618 619 rc = group_impl->net_impl->group_impl_add_sock(group_impl, sock); 620 if (rc != 0) { 621 return rc; 622 } 623 624 TAILQ_INSERT_TAIL(&group_impl->socks, sock, link); 625 sock->group_impl = group_impl; 626 sock->cb_fn = cb_fn; 627 sock->cb_arg = cb_arg; 628 629 return 0; 630 } 631 632 int 633 spdk_sock_group_remove_sock(struct spdk_sock_group *group, struct spdk_sock *sock) 634 { 635 struct spdk_sock_group_impl *group_impl = NULL; 636 int rc; 637 638 group_impl = sock_get_group_impl_from_group(sock, group); 639 if (group_impl == NULL) { 640 errno = EINVAL; 641 return -1; 642 } 643 644 assert(group_impl == sock->group_impl); 645 646 rc = group_impl->net_impl->group_impl_remove_sock(group_impl, sock); 647 if (rc == 0) { 648 TAILQ_REMOVE(&group_impl->socks, sock, link); 649 sock->group_impl = NULL; 650 sock->cb_fn = NULL; 651 sock->cb_arg = NULL; 652 } 653 654 return rc; 655 } 656 657 int 658 spdk_sock_group_poll(struct spdk_sock_group *group) 659 { 660 return spdk_sock_group_poll_count(group, MAX_EVENTS_PER_POLL); 661 } 662 663 static int 664 sock_group_impl_poll_count(struct spdk_sock_group_impl *group_impl, 665 struct spdk_sock_group *group, 666 int max_events) 667 { 668 struct spdk_sock *socks[MAX_EVENTS_PER_POLL]; 669 int num_events, i; 670 671 if (TAILQ_EMPTY(&group_impl->socks)) { 672 return 0; 673 } 674 675 num_events = group_impl->net_impl->group_impl_poll(group_impl, max_events, socks); 676 if (num_events == -1) { 677 return -1; 678 } 679 680 for (i = 0; i < num_events; i++) { 681 struct spdk_sock *sock = socks[i]; 682 assert(sock->cb_fn != NULL); 683 sock->cb_fn(sock->cb_arg, group, sock); 684 } 685 686 return num_events; 687 } 688 689 int 690 spdk_sock_group_poll_count(struct spdk_sock_group *group, int max_events) 691 { 692 struct spdk_sock_group_impl *group_impl = NULL; 693 int rc, num_events = 0; 694 695 if (max_events < 1) { 696 errno = -EINVAL; 697 return -1; 698 } 699 700 /* 701 * Only poll for up to 32 events at a time - if more events are pending, 702 * the next call to this function will reap them. 703 */ 704 if (max_events > MAX_EVENTS_PER_POLL) { 705 max_events = MAX_EVENTS_PER_POLL; 706 } 707 708 STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) { 709 rc = sock_group_impl_poll_count(group_impl, group, max_events); 710 if (rc < 0) { 711 num_events = -1; 712 SPDK_ERRLOG("group_impl_poll_count for net(%s) failed\n", 713 group_impl->net_impl->name); 714 } else if (num_events >= 0) { 715 num_events += rc; 716 } 717 } 718 719 return num_events; 720 } 721 722 int 723 spdk_sock_group_close(struct spdk_sock_group **group) 724 { 725 struct spdk_sock_group_impl *group_impl = NULL, *tmp; 726 int rc; 727 728 if (*group == NULL) { 729 errno = EBADF; 730 return -1; 731 } 732 733 STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) { 734 if (!TAILQ_EMPTY(&group_impl->socks)) { 735 errno = EBUSY; 736 return -1; 737 } 738 } 739 740 STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) { 741 rc = group_impl->net_impl->group_impl_close(group_impl); 742 if (rc != 0) { 743 SPDK_ERRLOG("group_impl_close for net(%s) failed\n", 744 group_impl->net_impl->name); 745 } 746 } 747 748 free(*group); 749 *group = NULL; 750 751 return 0; 752 } 753 754 static inline struct spdk_net_impl * 755 sock_get_impl_by_name(const char *impl_name) 756 { 757 struct spdk_net_impl *impl; 758 759 assert(impl_name != NULL); 760 STAILQ_FOREACH(impl, &g_net_impls, link) { 761 if (0 == strcmp(impl_name, impl->name)) { 762 return impl; 763 } 764 } 765 766 return NULL; 767 } 768 769 int 770 spdk_sock_impl_get_opts(const char *impl_name, struct spdk_sock_impl_opts *opts, size_t *len) 771 { 772 struct spdk_net_impl *impl; 773 774 if (!impl_name || !opts || !len) { 775 errno = EINVAL; 776 return -1; 777 } 778 779 impl = sock_get_impl_by_name(impl_name); 780 if (!impl) { 781 errno = EINVAL; 782 return -1; 783 } 784 785 if (!impl->get_opts) { 786 errno = ENOTSUP; 787 return -1; 788 } 789 790 return impl->get_opts(opts, len); 791 } 792 793 int 794 spdk_sock_impl_set_opts(const char *impl_name, const struct spdk_sock_impl_opts *opts, size_t len) 795 { 796 struct spdk_net_impl *impl; 797 798 if (!impl_name || !opts) { 799 errno = EINVAL; 800 return -1; 801 } 802 803 impl = sock_get_impl_by_name(impl_name); 804 if (!impl) { 805 errno = EINVAL; 806 return -1; 807 } 808 809 if (!impl->set_opts) { 810 errno = ENOTSUP; 811 return -1; 812 } 813 814 return impl->set_opts(opts, len); 815 } 816 817 void 818 spdk_sock_write_config_json(struct spdk_json_write_ctx *w) 819 { 820 struct spdk_net_impl *impl; 821 struct spdk_sock_impl_opts opts; 822 size_t len; 823 824 assert(w != NULL); 825 826 spdk_json_write_array_begin(w); 827 828 if (g_default_impl) { 829 spdk_json_write_object_begin(w); 830 spdk_json_write_named_string(w, "method", "sock_set_default_impl"); 831 spdk_json_write_named_object_begin(w, "params"); 832 spdk_json_write_named_string(w, "impl_name", g_default_impl->name); 833 spdk_json_write_object_end(w); 834 spdk_json_write_object_end(w); 835 } 836 837 STAILQ_FOREACH(impl, &g_net_impls, link) { 838 if (!impl->get_opts) { 839 continue; 840 } 841 842 len = sizeof(opts); 843 if (impl->get_opts(&opts, &len) == 0) { 844 spdk_json_write_object_begin(w); 845 spdk_json_write_named_string(w, "method", "sock_impl_set_options"); 846 spdk_json_write_named_object_begin(w, "params"); 847 spdk_json_write_named_string(w, "impl_name", impl->name); 848 spdk_json_write_named_uint32(w, "recv_buf_size", opts.recv_buf_size); 849 spdk_json_write_named_uint32(w, "send_buf_size", opts.send_buf_size); 850 spdk_json_write_named_bool(w, "enable_recv_pipe", opts.enable_recv_pipe); 851 spdk_json_write_named_bool(w, "enable_quickack", opts.enable_quickack); 852 spdk_json_write_named_uint32(w, "enable_placement_id", opts.enable_placement_id); 853 spdk_json_write_named_bool(w, "enable_zerocopy_send_server", opts.enable_zerocopy_send_server); 854 spdk_json_write_named_bool(w, "enable_zerocopy_send_client", opts.enable_zerocopy_send_client); 855 spdk_json_write_named_uint32(w, "zerocopy_threshold", opts.zerocopy_threshold); 856 spdk_json_write_object_end(w); 857 spdk_json_write_object_end(w); 858 } else { 859 SPDK_ERRLOG("Failed to get socket options for socket implementation %s\n", impl->name); 860 } 861 } 862 863 spdk_json_write_array_end(w); 864 } 865 866 void 867 spdk_net_impl_register(struct spdk_net_impl *impl, int priority) 868 { 869 struct spdk_net_impl *cur, *prev; 870 871 impl->priority = priority; 872 prev = NULL; 873 STAILQ_FOREACH(cur, &g_net_impls, link) { 874 if (impl->priority > cur->priority) { 875 break; 876 } 877 prev = cur; 878 } 879 880 if (prev) { 881 STAILQ_INSERT_AFTER(&g_net_impls, prev, impl, link); 882 } else { 883 STAILQ_INSERT_HEAD(&g_net_impls, impl, link); 884 } 885 } 886 887 int 888 spdk_sock_set_default_impl(const char *impl_name) 889 { 890 struct spdk_net_impl *impl; 891 892 if (!impl_name) { 893 errno = EINVAL; 894 return -1; 895 } 896 897 impl = sock_get_impl_by_name(impl_name); 898 if (!impl) { 899 errno = EINVAL; 900 return -1; 901 } 902 903 if (impl == g_default_impl) { 904 return 0; 905 } 906 907 if (g_default_impl) { 908 SPDK_DEBUGLOG(sock, "Change the default sock impl from %s to %s\n", g_default_impl->name, 909 impl->name); 910 } else { 911 SPDK_DEBUGLOG(sock, "Set default sock implementation to %s\n", impl_name); 912 } 913 914 g_default_impl = impl; 915 916 return 0; 917 } 918 919 SPDK_LOG_REGISTER_COMPONENT(sock) 920