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