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