LCOV - code coverage report
Current view: top level - lib/sock - sock.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 347 492 70.5 %
Date: 2024-07-15 17:15:42 Functions: 43 54 79.6 %

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

Generated by: LCOV version 1.15