LCOV - code coverage report
Current view: top level - lib/sock - sock.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 569 0.0 %
Date: 2024-12-14 14:09:10 Functions: 0 54 0.0 %

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

Generated by: LCOV version 1.15