LCOV - code coverage report
Current view: top level - lib/sock - sock.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 350 475 73.7 %
Date: 2024-07-14 17:38:19 Functions: 41 48 85.4 %

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

Generated by: LCOV version 1.15