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