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