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 #include "spdk/trace.h" 15 #include "spdk_internal/trace_defs.h" 16 17 #define SPDK_SOCK_DEFAULT_PRIORITY 0 18 #define SPDK_SOCK_DEFAULT_ZCOPY true 19 #define SPDK_SOCK_DEFAULT_ACK_TIMEOUT 0 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 const char * 235 spdk_sock_get_impl_name(struct spdk_sock *sock) 236 { 237 return sock->net_impl->name; 238 } 239 240 void 241 spdk_sock_get_default_opts(struct spdk_sock_opts *opts) 242 { 243 assert(opts); 244 245 if (SPDK_SOCK_OPTS_FIELD_OK(opts, priority)) { 246 opts->priority = SPDK_SOCK_DEFAULT_PRIORITY; 247 } 248 249 if (SPDK_SOCK_OPTS_FIELD_OK(opts, zcopy)) { 250 opts->zcopy = SPDK_SOCK_DEFAULT_ZCOPY; 251 } 252 253 if (SPDK_SOCK_OPTS_FIELD_OK(opts, ack_timeout)) { 254 opts->ack_timeout = SPDK_SOCK_DEFAULT_ACK_TIMEOUT; 255 } 256 257 if (SPDK_SOCK_OPTS_FIELD_OK(opts, impl_opts)) { 258 opts->impl_opts = NULL; 259 } 260 261 if (SPDK_SOCK_OPTS_FIELD_OK(opts, impl_opts_size)) { 262 opts->impl_opts_size = 0; 263 } 264 } 265 266 /* 267 * opts The opts allocated in the current library. 268 * opts_user The opts passed by the caller. 269 * */ 270 static void 271 sock_init_opts(struct spdk_sock_opts *opts, struct spdk_sock_opts *opts_user) 272 { 273 assert(opts); 274 assert(opts_user); 275 276 opts->opts_size = sizeof(*opts); 277 spdk_sock_get_default_opts(opts); 278 279 /* reset the size according to the user */ 280 opts->opts_size = opts_user->opts_size; 281 if (SPDK_SOCK_OPTS_FIELD_OK(opts, priority)) { 282 opts->priority = opts_user->priority; 283 } 284 285 if (SPDK_SOCK_OPTS_FIELD_OK(opts, zcopy)) { 286 opts->zcopy = opts_user->zcopy; 287 } 288 289 if (SPDK_SOCK_OPTS_FIELD_OK(opts, ack_timeout)) { 290 opts->ack_timeout = opts_user->ack_timeout; 291 } 292 293 if (SPDK_SOCK_OPTS_FIELD_OK(opts, impl_opts)) { 294 opts->impl_opts = opts_user->impl_opts; 295 } 296 297 if (SPDK_SOCK_OPTS_FIELD_OK(opts, impl_opts)) { 298 opts->impl_opts_size = opts_user->impl_opts_size; 299 } 300 } 301 302 struct spdk_sock * 303 spdk_sock_connect(const char *ip, int port, const char *impl_name) 304 { 305 struct spdk_sock_opts opts; 306 307 opts.opts_size = sizeof(opts); 308 spdk_sock_get_default_opts(&opts); 309 return spdk_sock_connect_ext(ip, port, impl_name, &opts); 310 } 311 312 struct spdk_sock * 313 spdk_sock_connect_ext(const char *ip, int port, const char *_impl_name, struct spdk_sock_opts *opts) 314 { 315 struct spdk_net_impl *impl = NULL; 316 struct spdk_sock *sock; 317 struct spdk_sock_opts opts_local; 318 const char *impl_name = NULL; 319 320 if (opts == NULL) { 321 SPDK_ERRLOG("the opts should not be NULL pointer\n"); 322 return NULL; 323 } 324 325 if (_impl_name) { 326 impl_name = _impl_name; 327 } else if (g_default_impl) { 328 impl_name = g_default_impl->name; 329 } 330 331 STAILQ_FOREACH_FROM(impl, &g_net_impls, link) { 332 if (impl_name && strncmp(impl_name, impl->name, strlen(impl->name) + 1)) { 333 continue; 334 } 335 336 SPDK_DEBUGLOG(sock, "Creating a client socket using impl %s\n", impl->name); 337 sock_init_opts(&opts_local, opts); 338 sock = impl->connect(ip, port, &opts_local); 339 if (sock != NULL) { 340 /* Copy the contents, both the two structures are the same ABI version */ 341 memcpy(&sock->opts, &opts_local, sizeof(sock->opts)); 342 /* Clear out impl_opts to make sure we don't keep reference to a dangling 343 * pointer */ 344 sock->opts.impl_opts = NULL; 345 sock->net_impl = impl; 346 TAILQ_INIT(&sock->queued_reqs); 347 TAILQ_INIT(&sock->pending_reqs); 348 349 return sock; 350 } 351 } 352 353 return NULL; 354 } 355 356 struct spdk_sock * 357 spdk_sock_listen(const char *ip, int port, const char *impl_name) 358 { 359 struct spdk_sock_opts opts; 360 361 opts.opts_size = sizeof(opts); 362 spdk_sock_get_default_opts(&opts); 363 return spdk_sock_listen_ext(ip, port, impl_name, &opts); 364 } 365 366 struct spdk_sock * 367 spdk_sock_listen_ext(const char *ip, int port, const char *_impl_name, struct spdk_sock_opts *opts) 368 { 369 struct spdk_net_impl *impl = NULL; 370 struct spdk_sock *sock; 371 struct spdk_sock_opts opts_local; 372 const char *impl_name = NULL; 373 374 if (opts == NULL) { 375 SPDK_ERRLOG("the opts should not be NULL pointer\n"); 376 return NULL; 377 } 378 379 if (_impl_name) { 380 impl_name = _impl_name; 381 } else if (g_default_impl) { 382 impl_name = g_default_impl->name; 383 } 384 385 STAILQ_FOREACH_FROM(impl, &g_net_impls, link) { 386 if (impl_name && strncmp(impl_name, impl->name, strlen(impl->name) + 1)) { 387 continue; 388 } 389 390 SPDK_DEBUGLOG(sock, "Creating a listening socket using impl %s\n", impl->name); 391 sock_init_opts(&opts_local, opts); 392 sock = impl->listen(ip, port, &opts_local); 393 if (sock != NULL) { 394 /* Copy the contents, both the two structures are the same ABI version */ 395 memcpy(&sock->opts, &opts_local, sizeof(sock->opts)); 396 /* Clear out impl_opts to make sure we don't keep reference to a dangling 397 * pointer */ 398 sock->opts.impl_opts = NULL; 399 sock->net_impl = impl; 400 /* Don't need to initialize the request queues for listen 401 * sockets. */ 402 return sock; 403 } 404 } 405 406 return NULL; 407 } 408 409 struct spdk_sock * 410 spdk_sock_accept(struct spdk_sock *sock) 411 { 412 struct spdk_sock *new_sock; 413 414 new_sock = sock->net_impl->accept(sock); 415 if (new_sock != NULL) { 416 /* Inherit the opts from the "accept sock" */ 417 new_sock->opts = sock->opts; 418 memcpy(&new_sock->opts, &sock->opts, sizeof(new_sock->opts)); 419 new_sock->net_impl = sock->net_impl; 420 TAILQ_INIT(&new_sock->queued_reqs); 421 TAILQ_INIT(&new_sock->pending_reqs); 422 } 423 424 return new_sock; 425 } 426 427 int 428 spdk_sock_close(struct spdk_sock **_sock) 429 { 430 struct spdk_sock *sock = *_sock; 431 432 if (sock == NULL) { 433 errno = EBADF; 434 return -1; 435 } 436 437 if (sock->cb_fn != NULL) { 438 /* This sock is still part of a sock_group. */ 439 errno = EBUSY; 440 return -1; 441 } 442 443 /* Beyond this point the socket is considered closed. */ 444 *_sock = NULL; 445 446 sock->flags.closed = true; 447 448 if (sock->cb_cnt > 0) { 449 /* Let the callback unwind before destroying the socket */ 450 return 0; 451 } 452 453 spdk_sock_abort_requests(sock); 454 455 return sock->net_impl->close(sock); 456 } 457 458 ssize_t 459 spdk_sock_recv(struct spdk_sock *sock, void *buf, size_t len) 460 { 461 if (sock == NULL || sock->flags.closed) { 462 errno = EBADF; 463 return -1; 464 } 465 466 return sock->net_impl->recv(sock, buf, len); 467 } 468 469 ssize_t 470 spdk_sock_readv(struct spdk_sock *sock, struct iovec *iov, int iovcnt) 471 { 472 if (sock == NULL || sock->flags.closed) { 473 errno = EBADF; 474 return -1; 475 } 476 477 return sock->net_impl->readv(sock, iov, iovcnt); 478 } 479 480 ssize_t 481 spdk_sock_writev(struct spdk_sock *sock, struct iovec *iov, int iovcnt) 482 { 483 if (sock == NULL || sock->flags.closed) { 484 errno = EBADF; 485 return -1; 486 } 487 488 return sock->net_impl->writev(sock, iov, iovcnt); 489 } 490 491 void 492 spdk_sock_writev_async(struct spdk_sock *sock, struct spdk_sock_request *req) 493 { 494 assert(req->cb_fn != NULL); 495 496 if (sock == NULL || sock->flags.closed) { 497 req->cb_fn(req->cb_arg, -EBADF); 498 return; 499 } 500 501 sock->net_impl->writev_async(sock, req); 502 } 503 504 int 505 spdk_sock_recv_next(struct spdk_sock *sock, void **buf, void **ctx) 506 { 507 if (sock == NULL || sock->flags.closed) { 508 errno = EBADF; 509 return -1; 510 } 511 512 if (sock->group_impl == NULL) { 513 errno = ENOTSUP; 514 return -1; 515 } 516 517 return sock->net_impl->recv_next(sock, buf, ctx); 518 } 519 520 int 521 spdk_sock_flush(struct spdk_sock *sock) 522 { 523 if (sock == NULL || sock->flags.closed) { 524 errno = EBADF; 525 return -1; 526 } 527 528 return sock->net_impl->flush(sock); 529 } 530 531 int 532 spdk_sock_set_recvlowat(struct spdk_sock *sock, int nbytes) 533 { 534 return sock->net_impl->set_recvlowat(sock, nbytes); 535 } 536 537 int 538 spdk_sock_set_recvbuf(struct spdk_sock *sock, int sz) 539 { 540 return sock->net_impl->set_recvbuf(sock, sz); 541 } 542 543 int 544 spdk_sock_set_sendbuf(struct spdk_sock *sock, int sz) 545 { 546 return sock->net_impl->set_sendbuf(sock, sz); 547 } 548 549 bool 550 spdk_sock_is_ipv6(struct spdk_sock *sock) 551 { 552 return sock->net_impl->is_ipv6(sock); 553 } 554 555 bool 556 spdk_sock_is_ipv4(struct spdk_sock *sock) 557 { 558 return sock->net_impl->is_ipv4(sock); 559 } 560 561 bool 562 spdk_sock_is_connected(struct spdk_sock *sock) 563 { 564 return sock->net_impl->is_connected(sock); 565 } 566 567 struct spdk_sock_group * 568 spdk_sock_group_create(void *ctx) 569 { 570 struct spdk_net_impl *impl = NULL; 571 struct spdk_sock_group *group; 572 struct spdk_sock_group_impl *group_impl; 573 574 group = calloc(1, sizeof(*group)); 575 if (group == NULL) { 576 return NULL; 577 } 578 579 STAILQ_INIT(&group->group_impls); 580 STAILQ_INIT(&group->pool); 581 582 STAILQ_FOREACH_FROM(impl, &g_net_impls, link) { 583 group_impl = impl->group_impl_create(); 584 if (group_impl != NULL) { 585 STAILQ_INSERT_TAIL(&group->group_impls, group_impl, link); 586 TAILQ_INIT(&group_impl->socks); 587 group_impl->net_impl = impl; 588 group_impl->group = group; 589 } 590 } 591 592 group->ctx = ctx; 593 594 return group; 595 } 596 597 void * 598 spdk_sock_group_get_ctx(struct spdk_sock_group *group) 599 { 600 if (group == NULL) { 601 return NULL; 602 } 603 604 return group->ctx; 605 } 606 607 int 608 spdk_sock_group_add_sock(struct spdk_sock_group *group, struct spdk_sock *sock, 609 spdk_sock_cb cb_fn, void *cb_arg) 610 { 611 struct spdk_sock_group_impl *group_impl = NULL; 612 int rc; 613 614 if (cb_fn == NULL) { 615 errno = EINVAL; 616 return -1; 617 } 618 619 if (sock->group_impl != NULL) { 620 /* 621 * This sock is already part of a sock_group. 622 */ 623 errno = EINVAL; 624 return -1; 625 } 626 627 group_impl = sock_get_group_impl_from_group(sock, group); 628 if (group_impl == NULL) { 629 errno = EINVAL; 630 return -1; 631 } 632 633 rc = group_impl->net_impl->group_impl_add_sock(group_impl, sock); 634 if (rc != 0) { 635 return rc; 636 } 637 638 TAILQ_INSERT_TAIL(&group_impl->socks, sock, link); 639 sock->group_impl = group_impl; 640 sock->cb_fn = cb_fn; 641 sock->cb_arg = cb_arg; 642 643 return 0; 644 } 645 646 int 647 spdk_sock_group_remove_sock(struct spdk_sock_group *group, struct spdk_sock *sock) 648 { 649 struct spdk_sock_group_impl *group_impl = NULL; 650 int rc; 651 652 group_impl = sock_get_group_impl_from_group(sock, group); 653 if (group_impl == NULL) { 654 errno = EINVAL; 655 return -1; 656 } 657 658 assert(group_impl == sock->group_impl); 659 660 rc = group_impl->net_impl->group_impl_remove_sock(group_impl, sock); 661 if (rc == 0) { 662 TAILQ_REMOVE(&group_impl->socks, sock, link); 663 sock->group_impl = NULL; 664 sock->cb_fn = NULL; 665 sock->cb_arg = NULL; 666 } 667 668 return rc; 669 } 670 671 int 672 spdk_sock_group_provide_buf(struct spdk_sock_group *group, void *buf, size_t len, void *ctx) 673 { 674 struct spdk_sock_group_provided_buf *provided; 675 676 provided = (struct spdk_sock_group_provided_buf *)buf; 677 678 provided->len = len; 679 provided->ctx = ctx; 680 STAILQ_INSERT_HEAD(&group->pool, provided, link); 681 682 return 0; 683 } 684 685 size_t 686 spdk_sock_group_get_buf(struct spdk_sock_group *group, void **buf, void **ctx) 687 { 688 struct spdk_sock_group_provided_buf *provided; 689 690 provided = STAILQ_FIRST(&group->pool); 691 if (provided == NULL) { 692 *buf = NULL; 693 return 0; 694 } 695 STAILQ_REMOVE_HEAD(&group->pool, link); 696 697 *buf = provided; 698 *ctx = provided->ctx; 699 return provided->len; 700 } 701 702 int 703 spdk_sock_group_poll(struct spdk_sock_group *group) 704 { 705 return spdk_sock_group_poll_count(group, MAX_EVENTS_PER_POLL); 706 } 707 708 static int 709 sock_group_impl_poll_count(struct spdk_sock_group_impl *group_impl, 710 struct spdk_sock_group *group, 711 int max_events) 712 { 713 struct spdk_sock *socks[MAX_EVENTS_PER_POLL]; 714 int num_events, i; 715 716 if (TAILQ_EMPTY(&group_impl->socks)) { 717 return 0; 718 } 719 720 num_events = group_impl->net_impl->group_impl_poll(group_impl, max_events, socks); 721 if (num_events == -1) { 722 return -1; 723 } 724 725 for (i = 0; i < num_events; i++) { 726 struct spdk_sock *sock = socks[i]; 727 assert(sock->cb_fn != NULL); 728 sock->cb_fn(sock->cb_arg, group, sock); 729 } 730 731 return num_events; 732 } 733 734 int 735 spdk_sock_group_poll_count(struct spdk_sock_group *group, int max_events) 736 { 737 struct spdk_sock_group_impl *group_impl = NULL; 738 int rc, num_events = 0; 739 740 if (max_events < 1) { 741 errno = -EINVAL; 742 return -1; 743 } 744 745 /* 746 * Only poll for up to 32 events at a time - if more events are pending, 747 * the next call to this function will reap them. 748 */ 749 if (max_events > MAX_EVENTS_PER_POLL) { 750 max_events = MAX_EVENTS_PER_POLL; 751 } 752 753 STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) { 754 rc = sock_group_impl_poll_count(group_impl, group, max_events); 755 if (rc < 0) { 756 num_events = -1; 757 SPDK_ERRLOG("group_impl_poll_count for net(%s) failed\n", 758 group_impl->net_impl->name); 759 } else if (num_events >= 0) { 760 num_events += rc; 761 } 762 } 763 764 return num_events; 765 } 766 767 int 768 spdk_sock_group_close(struct spdk_sock_group **group) 769 { 770 struct spdk_sock_group_impl *group_impl = NULL, *tmp; 771 int rc; 772 773 if (*group == NULL) { 774 errno = EBADF; 775 return -1; 776 } 777 778 STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) { 779 if (!TAILQ_EMPTY(&group_impl->socks)) { 780 errno = EBUSY; 781 return -1; 782 } 783 } 784 785 STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) { 786 rc = group_impl->net_impl->group_impl_close(group_impl); 787 if (rc != 0) { 788 SPDK_ERRLOG("group_impl_close for net failed\n"); 789 } 790 } 791 792 free(*group); 793 *group = NULL; 794 795 return 0; 796 } 797 798 static inline struct spdk_net_impl * 799 sock_get_impl_by_name(const char *impl_name) 800 { 801 struct spdk_net_impl *impl; 802 803 assert(impl_name != NULL); 804 STAILQ_FOREACH(impl, &g_net_impls, link) { 805 if (0 == strcmp(impl_name, impl->name)) { 806 return impl; 807 } 808 } 809 810 return NULL; 811 } 812 813 int 814 spdk_sock_impl_get_opts(const char *impl_name, struct spdk_sock_impl_opts *opts, size_t *len) 815 { 816 struct spdk_net_impl *impl; 817 818 if (!impl_name || !opts || !len) { 819 errno = EINVAL; 820 return -1; 821 } 822 823 impl = sock_get_impl_by_name(impl_name); 824 if (!impl) { 825 errno = EINVAL; 826 return -1; 827 } 828 829 if (!impl->get_opts) { 830 errno = ENOTSUP; 831 return -1; 832 } 833 834 return impl->get_opts(opts, len); 835 } 836 837 int 838 spdk_sock_impl_set_opts(const char *impl_name, const struct spdk_sock_impl_opts *opts, size_t len) 839 { 840 struct spdk_net_impl *impl; 841 842 if (!impl_name || !opts) { 843 errno = EINVAL; 844 return -1; 845 } 846 847 impl = sock_get_impl_by_name(impl_name); 848 if (!impl) { 849 errno = EINVAL; 850 return -1; 851 } 852 853 if (!impl->set_opts) { 854 errno = ENOTSUP; 855 return -1; 856 } 857 858 return impl->set_opts(opts, len); 859 } 860 861 void 862 spdk_sock_write_config_json(struct spdk_json_write_ctx *w) 863 { 864 struct spdk_net_impl *impl; 865 struct spdk_sock_impl_opts opts; 866 size_t len; 867 868 assert(w != NULL); 869 870 spdk_json_write_array_begin(w); 871 872 if (g_default_impl) { 873 spdk_json_write_object_begin(w); 874 spdk_json_write_named_string(w, "method", "sock_set_default_impl"); 875 spdk_json_write_named_object_begin(w, "params"); 876 spdk_json_write_named_string(w, "impl_name", g_default_impl->name); 877 spdk_json_write_object_end(w); 878 spdk_json_write_object_end(w); 879 } 880 881 STAILQ_FOREACH(impl, &g_net_impls, link) { 882 if (!impl->get_opts) { 883 continue; 884 } 885 886 len = sizeof(opts); 887 if (impl->get_opts(&opts, &len) == 0) { 888 spdk_json_write_object_begin(w); 889 spdk_json_write_named_string(w, "method", "sock_impl_set_options"); 890 spdk_json_write_named_object_begin(w, "params"); 891 spdk_json_write_named_string(w, "impl_name", impl->name); 892 spdk_json_write_named_uint32(w, "recv_buf_size", opts.recv_buf_size); 893 spdk_json_write_named_uint32(w, "send_buf_size", opts.send_buf_size); 894 spdk_json_write_named_bool(w, "enable_recv_pipe", opts.enable_recv_pipe); 895 spdk_json_write_named_bool(w, "enable_quickack", opts.enable_quickack); 896 spdk_json_write_named_uint32(w, "enable_placement_id", opts.enable_placement_id); 897 spdk_json_write_named_bool(w, "enable_zerocopy_send_server", opts.enable_zerocopy_send_server); 898 spdk_json_write_named_bool(w, "enable_zerocopy_send_client", opts.enable_zerocopy_send_client); 899 spdk_json_write_named_uint32(w, "zerocopy_threshold", opts.zerocopy_threshold); 900 spdk_json_write_named_uint32(w, "tls_version", opts.tls_version); 901 spdk_json_write_named_bool(w, "enable_ktls", opts.enable_ktls); 902 spdk_json_write_object_end(w); 903 spdk_json_write_object_end(w); 904 } else { 905 SPDK_ERRLOG("Failed to get socket options for socket implementation %s\n", impl->name); 906 } 907 } 908 909 spdk_json_write_array_end(w); 910 } 911 912 void 913 spdk_net_impl_register(struct spdk_net_impl *impl, int priority) 914 { 915 struct spdk_net_impl *cur, *prev; 916 917 impl->priority = priority; 918 prev = NULL; 919 STAILQ_FOREACH(cur, &g_net_impls, link) { 920 if (impl->priority > cur->priority) { 921 break; 922 } 923 prev = cur; 924 } 925 926 if (prev) { 927 STAILQ_INSERT_AFTER(&g_net_impls, prev, impl, link); 928 } else { 929 STAILQ_INSERT_HEAD(&g_net_impls, impl, link); 930 } 931 } 932 933 int 934 spdk_sock_set_default_impl(const char *impl_name) 935 { 936 struct spdk_net_impl *impl; 937 938 if (!impl_name) { 939 errno = EINVAL; 940 return -1; 941 } 942 943 impl = sock_get_impl_by_name(impl_name); 944 if (!impl) { 945 errno = EINVAL; 946 return -1; 947 } 948 949 if (impl == g_default_impl) { 950 return 0; 951 } 952 953 if (g_default_impl) { 954 SPDK_DEBUGLOG(sock, "Change the default sock impl from %s to %s\n", g_default_impl->name, 955 impl->name); 956 } else { 957 SPDK_DEBUGLOG(sock, "Set default sock implementation to %s\n", impl_name); 958 } 959 960 g_default_impl = impl; 961 962 return 0; 963 } 964 965 const char * 966 spdk_sock_get_default_impl(void) 967 { 968 struct spdk_net_impl *impl = NULL; 969 970 if (g_default_impl) { 971 return g_default_impl->name; 972 } 973 974 impl = STAILQ_FIRST(&g_net_impls); 975 if (impl) { 976 return impl->name; 977 } 978 979 return NULL; 980 } 981 982 SPDK_LOG_REGISTER_COMPONENT(sock) 983 984 SPDK_TRACE_REGISTER_FN(sock_trace, "sock", TRACE_GROUP_SOCK) 985 { 986 struct spdk_trace_tpoint_opts opts[] = { 987 { 988 "SOCK_REQ_QUEUE", TRACE_SOCK_REQ_QUEUE, 989 OWNER_TYPE_SOCK, OBJECT_SOCK_REQ, 1, 990 { 991 { "ctx", SPDK_TRACE_ARG_TYPE_PTR, 8 }, 992 } 993 }, 994 { 995 "SOCK_REQ_PEND", TRACE_SOCK_REQ_PEND, 996 OWNER_TYPE_SOCK, OBJECT_SOCK_REQ, 0, 997 { 998 { "ctx", SPDK_TRACE_ARG_TYPE_PTR, 8 }, 999 } 1000 }, 1001 { 1002 "SOCK_REQ_COMPLETE", TRACE_SOCK_REQ_COMPLETE, 1003 OWNER_TYPE_SOCK, OBJECT_SOCK_REQ, 0, 1004 { 1005 { "ctx", SPDK_TRACE_ARG_TYPE_PTR, 8 }, 1006 } 1007 }, 1008 }; 1009 1010 spdk_trace_register_owner_type(OWNER_TYPE_SOCK, 's'); 1011 spdk_trace_register_object(OBJECT_SOCK_REQ, 's'); 1012 spdk_trace_register_description_ext(opts, SPDK_COUNTOF(opts)); 1013 } 1014