LCOV - code coverage report
Current view: top level - lib/sock - sock.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 344 484 71.1 %
Date: 2024-07-15 18:43:01 Functions: 42 52 80.8 %

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

Generated by: LCOV version 1.15