LCOV - code coverage report
Current view: top level - lib/sock - sock.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 344 469 73.3 %
Date: 2024-07-11 23:29:16 Functions: 42 50 84.0 %

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

Generated by: LCOV version 1.15