LCOV - code coverage report
Current view: top level - lib/sock - sock.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 350 494 70.9 %
Date: 2024-12-15 03:51:54 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             : 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             : }
     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             : 
     286          44 :         if (SPDK_SOCK_OPTS_FIELD_OK(opts, src_addr)) {
     287          42 :                 opts->src_addr = NULL;
     288             :         }
     289             : 
     290          44 :         if (SPDK_SOCK_OPTS_FIELD_OK(opts, src_port)) {
     291          42 :                 opts->src_port = 0;
     292             :         }
     293          44 : }
     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          20 : sock_init_opts(struct spdk_sock_opts *opts, struct spdk_sock_opts *opts_user)
     301             : {
     302          20 :         assert(opts);
     303          20 :         assert(opts_user);
     304             : 
     305          20 :         opts->opts_size = sizeof(*opts);
     306          20 :         spdk_sock_get_default_opts(opts);
     307             : 
     308             :         /* reset the size according to the user */
     309          20 :         opts->opts_size = opts_user->opts_size;
     310          20 :         if (SPDK_SOCK_OPTS_FIELD_OK(opts, priority)) {
     311          20 :                 opts->priority = opts_user->priority;
     312             :         }
     313             : 
     314          20 :         if (SPDK_SOCK_OPTS_FIELD_OK(opts, zcopy)) {
     315          20 :                 opts->zcopy = opts_user->zcopy;
     316             :         }
     317             : 
     318          20 :         if (SPDK_SOCK_OPTS_FIELD_OK(opts, ack_timeout)) {
     319          20 :                 opts->ack_timeout = opts_user->ack_timeout;
     320             :         }
     321             : 
     322          20 :         if (SPDK_SOCK_OPTS_FIELD_OK(opts, impl_opts)) {
     323          20 :                 opts->impl_opts = opts_user->impl_opts;
     324             :         }
     325             : 
     326          20 :         if (SPDK_SOCK_OPTS_FIELD_OK(opts, impl_opts_size)) {
     327          20 :                 opts->impl_opts_size = opts_user->impl_opts_size;
     328             :         }
     329             : 
     330          20 :         if (SPDK_SOCK_OPTS_FIELD_OK(opts, src_addr)) {
     331          20 :                 opts->src_addr = opts_user->src_addr;
     332             :         }
     333             : 
     334          20 :         if (SPDK_SOCK_OPTS_FIELD_OK(opts, src_port)) {
     335          20 :                 opts->src_port = opts_user->src_port;
     336             :         }
     337          20 : }
     338             : 
     339             : struct spdk_sock *
     340           8 : spdk_sock_connect(const char *ip, int port, const char *impl_name)
     341             : {
     342             :         struct spdk_sock_opts opts;
     343             : 
     344           8 :         opts.opts_size = sizeof(opts);
     345           8 :         spdk_sock_get_default_opts(&opts);
     346           8 :         return spdk_sock_connect_ext(ip, port, impl_name, &opts);
     347             : }
     348             : 
     349             : struct spdk_sock *
     350          11 : spdk_sock_connect_ext(const char *ip, int port, const char *_impl_name, struct spdk_sock_opts *opts)
     351             : {
     352          11 :         struct spdk_net_impl *impl = NULL;
     353             :         struct spdk_sock *sock;
     354             :         struct spdk_sock_opts opts_local;
     355          11 :         const char *impl_name = NULL;
     356             : 
     357          11 :         if (opts == NULL) {
     358           0 :                 SPDK_ERRLOG("the opts should not be NULL pointer\n");
     359           0 :                 return NULL;
     360             :         }
     361             : 
     362          11 :         if (_impl_name) {
     363          11 :                 impl_name = _impl_name;
     364           0 :         } else if (g_default_impl) {
     365           0 :                 impl_name = g_default_impl->name;
     366             :         }
     367             : 
     368          29 :         STAILQ_FOREACH_FROM(impl, &g_net_impls, link) {
     369          29 :                 if (impl_name && strncmp(impl_name, impl->name, strlen(impl->name) + 1)) {
     370          18 :                         continue;
     371             :                 }
     372             : 
     373          11 :                 SPDK_DEBUGLOG(sock, "Creating a client socket using impl %s\n", impl->name);
     374          11 :                 sock_init_opts(&opts_local, opts);
     375          11 :                 sock = impl->connect(ip, port, &opts_local);
     376          11 :                 if (sock != NULL) {
     377             :                         /* Copy the contents, both the two structures are the same ABI version */
     378          11 :                         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          11 :                         sock->opts.impl_opts = NULL;
     382          11 :                         sock->net_impl = impl;
     383          11 :                         TAILQ_INIT(&sock->queued_reqs);
     384          11 :                         TAILQ_INIT(&sock->pending_reqs);
     385             : 
     386          11 :                         return sock;
     387             :                 }
     388             :         }
     389             : 
     390           0 :         return NULL;
     391             : }
     392             : 
     393             : struct spdk_sock *
     394           6 : spdk_sock_listen(const char *ip, int port, const char *impl_name)
     395             : {
     396             :         struct spdk_sock_opts opts;
     397             : 
     398           6 :         opts.opts_size = sizeof(opts);
     399           6 :         spdk_sock_get_default_opts(&opts);
     400           6 :         return spdk_sock_listen_ext(ip, port, impl_name, &opts);
     401             : }
     402             : 
     403             : struct spdk_sock *
     404           9 : spdk_sock_listen_ext(const char *ip, int port, const char *_impl_name, struct spdk_sock_opts *opts)
     405             : {
     406           9 :         struct spdk_net_impl *impl = NULL;
     407             :         struct spdk_sock *sock;
     408             :         struct spdk_sock_opts opts_local;
     409           9 :         const char *impl_name = NULL;
     410             : 
     411           9 :         if (opts == NULL) {
     412           0 :                 SPDK_ERRLOG("the opts should not be NULL pointer\n");
     413           0 :                 return NULL;
     414             :         }
     415             : 
     416           9 :         if (_impl_name) {
     417           9 :                 impl_name = _impl_name;
     418           0 :         } else if (g_default_impl) {
     419           0 :                 impl_name = g_default_impl->name;
     420             :         }
     421             : 
     422          23 :         STAILQ_FOREACH_FROM(impl, &g_net_impls, link) {
     423          23 :                 if (impl_name && strncmp(impl_name, impl->name, strlen(impl->name) + 1)) {
     424          14 :                         continue;
     425             :                 }
     426             : 
     427           9 :                 SPDK_DEBUGLOG(sock, "Creating a listening socket using impl %s\n", impl->name);
     428           9 :                 sock_init_opts(&opts_local, opts);
     429           9 :                 sock = impl->listen(ip, port, &opts_local);
     430           9 :                 if (sock != NULL) {
     431             :                         /* Copy the contents, both the two structures are the same ABI version */
     432           9 :                         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           9 :                         sock->opts.impl_opts = NULL;
     436           9 :                         sock->net_impl = impl;
     437             :                         /* Don't need to initialize the request queues for listen
     438             :                          * sockets. */
     439           9 :                         return sock;
     440             :                 }
     441             :         }
     442             : 
     443           0 :         return NULL;
     444             : }
     445             : 
     446             : struct spdk_sock *
     447          14 : spdk_sock_accept(struct spdk_sock *sock)
     448             : {
     449             :         struct spdk_sock *new_sock;
     450             : 
     451          14 :         new_sock = sock->net_impl->accept(sock);
     452          14 :         if (new_sock != NULL) {
     453             :                 /* Inherit the opts from the "accept sock" */
     454          10 :                 new_sock->opts = sock->opts;
     455          10 :                 memcpy(&new_sock->opts, &sock->opts, sizeof(new_sock->opts));
     456          10 :                 new_sock->net_impl = sock->net_impl;
     457          10 :                 TAILQ_INIT(&new_sock->queued_reqs);
     458          10 :                 TAILQ_INIT(&new_sock->pending_reqs);
     459             :         }
     460             : 
     461          14 :         return new_sock;
     462             : }
     463             : 
     464             : int
     465          33 : spdk_sock_close(struct spdk_sock **_sock)
     466             : {
     467          33 :         struct spdk_sock *sock = *_sock;
     468             : 
     469          33 :         if (sock == NULL) {
     470           0 :                 errno = EBADF;
     471           0 :                 return -1;
     472             :         }
     473             : 
     474          33 :         if (sock->cb_fn != NULL) {
     475             :                 /* This sock is still part of a sock_group. */
     476           2 :                 errno = EBUSY;
     477           2 :                 return -1;
     478             :         }
     479             : 
     480             :         /* Beyond this point the socket is considered closed. */
     481          31 :         *_sock = NULL;
     482             : 
     483          31 :         sock->flags.closed = true;
     484             : 
     485          31 :         if (sock->cb_cnt > 0) {
     486             :                 /* Let the callback unwind before destroying the socket */
     487           1 :                 return 0;
     488             :         }
     489             : 
     490          30 :         spdk_sock_abort_requests(sock);
     491             : 
     492          30 :         return sock->net_impl->close(sock);
     493             : }
     494             : 
     495             : ssize_t
     496          10 : spdk_sock_recv(struct spdk_sock *sock, void *buf, size_t len)
     497             : {
     498          10 :         if (sock == NULL || sock->flags.closed) {
     499           0 :                 errno = EBADF;
     500           0 :                 return -1;
     501             :         }
     502             : 
     503          10 :         return sock->net_impl->recv(sock, buf, len);
     504             : }
     505             : 
     506             : ssize_t
     507           4 : spdk_sock_readv(struct spdk_sock *sock, struct iovec *iov, int iovcnt)
     508             : {
     509           4 :         if (sock == NULL || sock->flags.closed) {
     510           0 :                 errno = EBADF;
     511           0 :                 return -1;
     512             :         }
     513             : 
     514           4 :         return sock->net_impl->readv(sock, iov, iovcnt);
     515             : }
     516             : 
     517             : ssize_t
     518          10 : spdk_sock_writev(struct spdk_sock *sock, struct iovec *iov, int iovcnt)
     519             : {
     520          10 :         if (sock == NULL || sock->flags.closed) {
     521           0 :                 errno = EBADF;
     522           0 :                 return -1;
     523             :         }
     524             : 
     525          10 :         return sock->net_impl->writev(sock, iov, iovcnt);
     526             : }
     527             : 
     528             : void
     529           2 : spdk_sock_writev_async(struct spdk_sock *sock, struct spdk_sock_request *req)
     530             : {
     531           2 :         assert(req->cb_fn != NULL);
     532             : 
     533           2 :         if (sock == NULL || sock->flags.closed) {
     534           0 :                 req->cb_fn(req->cb_arg, -EBADF);
     535           0 :                 return;
     536             :         }
     537             : 
     538           2 :         sock->net_impl->writev_async(sock, req);
     539             : }
     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             : }
     556             : 
     557             : int
     558           2 : spdk_sock_flush(struct spdk_sock *sock)
     559             : {
     560           2 :         if (sock == NULL || sock->flags.closed) {
     561           1 :                 errno = EBADF;
     562           1 :                 return -1;
     563             :         }
     564             : 
     565           1 :         return sock->net_impl->flush(sock);
     566             : }
     567             : 
     568             : int
     569           2 : spdk_sock_set_recvlowat(struct spdk_sock *sock, int nbytes)
     570             : {
     571           2 :         return sock->net_impl->set_recvlowat(sock, nbytes);
     572             : }
     573             : 
     574             : int
     575           2 : spdk_sock_set_recvbuf(struct spdk_sock *sock, int sz)
     576             : {
     577           2 :         return sock->net_impl->set_recvbuf(sock, sz);
     578             : }
     579             : 
     580             : int
     581           2 : spdk_sock_set_sendbuf(struct spdk_sock *sock, int sz)
     582             : {
     583           2 :         return sock->net_impl->set_sendbuf(sock, sz);
     584             : }
     585             : 
     586             : bool
     587           2 : spdk_sock_is_ipv6(struct spdk_sock *sock)
     588             : {
     589           2 :         return sock->net_impl->is_ipv6(sock);
     590             : }
     591             : 
     592             : bool
     593           2 : spdk_sock_is_ipv4(struct spdk_sock *sock)
     594             : {
     595           2 :         return sock->net_impl->is_ipv4(sock);
     596             : }
     597             : 
     598             : bool
     599           6 : spdk_sock_is_connected(struct spdk_sock *sock)
     600             : {
     601           6 :         return sock->net_impl->is_connected(sock);
     602             : }
     603             : 
     604             : struct spdk_sock_group *
     605           6 : spdk_sock_group_create(void *ctx)
     606             : {
     607           6 :         struct spdk_net_impl *impl = NULL;
     608             :         struct spdk_sock_group *group;
     609             :         struct spdk_sock_group_impl *group_impl;
     610             : 
     611           6 :         group = calloc(1, sizeof(*group));
     612           6 :         if (group == NULL) {
     613           0 :                 return NULL;
     614             :         }
     615             : 
     616           6 :         STAILQ_INIT(&group->group_impls);
     617           6 :         STAILQ_INIT(&group->pool);
     618             : 
     619          24 :         STAILQ_FOREACH_FROM(impl, &g_net_impls, link) {
     620          18 :                 group_impl = impl->group_impl_create();
     621          18 :                 if (group_impl != NULL) {
     622          18 :                         STAILQ_INSERT_TAIL(&group->group_impls, group_impl, link);
     623          18 :                         TAILQ_INIT(&group_impl->socks);
     624          18 :                         group_impl->net_impl = impl;
     625          18 :                         group_impl->group = group;
     626             :                 }
     627             :         }
     628             : 
     629           6 :         group->ctx = ctx;
     630             : 
     631           6 :         return group;
     632             : }
     633             : 
     634             : void *
     635           2 : spdk_sock_group_get_ctx(struct spdk_sock_group *group)
     636             : {
     637           2 :         if (group == NULL) {
     638           1 :                 return NULL;
     639             :         }
     640             : 
     641           1 :         return group->ctx;
     642             : }
     643             : 
     644             : int
     645          10 : 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          10 :         struct spdk_sock_group_impl *group_impl = NULL;
     649             :         int rc;
     650             : 
     651          10 :         if (cb_fn == NULL) {
     652           2 :                 errno = EINVAL;
     653           2 :                 return -1;
     654             :         }
     655             : 
     656           8 :         if (sock->group_impl != NULL) {
     657             :                 /*
     658             :                  * This sock is already part of a sock_group.
     659             :                  */
     660           2 :                 errno = EINVAL;
     661           2 :                 return -1;
     662             :         }
     663             : 
     664           6 :         group_impl = sock_get_group_impl_from_group(sock, group);
     665           6 :         if (group_impl == NULL) {
     666           0 :                 errno = EINVAL;
     667           0 :                 return -1;
     668             :         }
     669             : 
     670           6 :         rc = group_impl->net_impl->group_impl_add_sock(group_impl, sock);
     671           6 :         if (rc != 0) {
     672           0 :                 return rc;
     673             :         }
     674             : 
     675           6 :         TAILQ_INSERT_TAIL(&group_impl->socks, sock, link);
     676           6 :         sock->group_impl = group_impl;
     677           6 :         sock->cb_fn = cb_fn;
     678           6 :         sock->cb_arg = cb_arg;
     679             : 
     680           6 :         return 0;
     681             : }
     682             : 
     683             : int
     684           6 : spdk_sock_group_remove_sock(struct spdk_sock_group *group, struct spdk_sock *sock)
     685             : {
     686           6 :         struct spdk_sock_group_impl *group_impl = NULL;
     687             :         int rc;
     688             : 
     689           6 :         group_impl = sock_get_group_impl_from_group(sock, group);
     690           6 :         if (group_impl == NULL) {
     691           0 :                 errno = EINVAL;
     692           0 :                 return -1;
     693             :         }
     694             : 
     695           6 :         assert(group_impl == sock->group_impl);
     696             : 
     697           6 :         rc = group_impl->net_impl->group_impl_remove_sock(group_impl, sock);
     698           6 :         if (rc == 0) {
     699           6 :                 TAILQ_REMOVE(&group_impl->socks, sock, link);
     700           6 :                 sock->group_impl = NULL;
     701           6 :                 sock->cb_fn = NULL;
     702           6 :                 sock->cb_arg = NULL;
     703             :         }
     704             : 
     705           6 :         return rc;
     706             : }
     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             : }
     738             : 
     739             : int
     740           5 : spdk_sock_group_poll(struct spdk_sock_group *group)
     741             : {
     742           5 :         return spdk_sock_group_poll_count(group, MAX_EVENTS_PER_POLL);
     743             : }
     744             : 
     745             : static int
     746          27 : 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          27 :         if (TAILQ_EMPTY(&group_impl->socks)) {
     754          18 :                 return 0;
     755             :         }
     756             : 
     757           9 :         num_events = group_impl->net_impl->group_impl_poll(group_impl, max_events, socks);
     758           9 :         if (num_events == -1) {
     759           0 :                 return -1;
     760             :         }
     761             : 
     762          15 :         for (i = 0; i < num_events; i++) {
     763           6 :                 struct spdk_sock *sock = socks[i];
     764           6 :                 assert(sock->cb_fn != NULL);
     765           6 :                 sock->cb_fn(sock->cb_arg, group, sock);
     766             :         }
     767             : 
     768           9 :         return num_events;
     769             : }
     770             : 
     771             : int
     772           9 : spdk_sock_group_poll_count(struct spdk_sock_group *group, int max_events)
     773             : {
     774           9 :         struct spdk_sock_group_impl *group_impl = NULL;
     775           9 :         int rc, num_events = 0;
     776             : 
     777           9 :         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           9 :         if (max_events > MAX_EVENTS_PER_POLL) {
     787           0 :                 max_events = MAX_EVENTS_PER_POLL;
     788             :         }
     789             : 
     790          36 :         STAILQ_FOREACH_FROM(group_impl, &group->group_impls, link) {
     791          27 :                 rc = sock_group_impl_poll_count(group_impl, group, max_events);
     792          27 :                 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          27 :                 } else if (num_events >= 0) {
     797          27 :                         num_events += rc;
     798             :                 }
     799             :         }
     800             : 
     801           9 :         return num_events;
     802             : }
     803             : 
     804             : int
     805           8 : spdk_sock_group_close(struct spdk_sock_group **group)
     806             : {
     807           8 :         struct spdk_sock_group_impl *group_impl = NULL, *tmp;
     808             :         int rc;
     809             : 
     810           8 :         if (*group == NULL) {
     811           0 :                 errno = EBADF;
     812           0 :                 return -1;
     813             :         }
     814             : 
     815          28 :         STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) {
     816          22 :                 if (!TAILQ_EMPTY(&group_impl->socks)) {
     817           2 :                         errno = EBUSY;
     818           2 :                         return -1;
     819             :                 }
     820             :         }
     821             : 
     822          24 :         STAILQ_FOREACH_SAFE(group_impl, &(*group)->group_impls, link, tmp) {
     823          18 :                 rc = group_impl->net_impl->group_impl_close(group_impl);
     824          18 :                 if (rc != 0) {
     825           0 :                         SPDK_ERRLOG("group_impl_close for net failed\n");
     826             :                 }
     827             :         }
     828             : 
     829           6 :         free(*group);
     830           6 :         *group = NULL;
     831             : 
     832           6 :         return 0;
     833             : }
     834             : 
     835             : static inline struct spdk_net_impl *
     836          19 : sock_get_impl_by_name(const char *impl_name)
     837             : {
     838             :         struct spdk_net_impl *impl;
     839             : 
     840          19 :         assert(impl_name != NULL);
     841          49 :         STAILQ_FOREACH(impl, &g_net_impls, link) {
     842          49 :                 if (0 == strcmp(impl_name, impl->name)) {
     843          19 :                         return impl;
     844             :                 }
     845             :         }
     846             : 
     847           0 :         return NULL;
     848             : }
     849             : 
     850             : int
     851          16 : 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          16 :         if (!impl_name || !opts || !len) {
     856           4 :                 errno = EINVAL;
     857           4 :                 return -1;
     858             :         }
     859             : 
     860          12 :         impl = sock_get_impl_by_name(impl_name);
     861          12 :         if (!impl) {
     862           0 :                 errno = EINVAL;
     863           0 :                 return -1;
     864             :         }
     865             : 
     866          12 :         if (!impl->get_opts) {
     867           1 :                 errno = ENOTSUP;
     868           1 :                 return -1;
     869             :         }
     870             : 
     871          11 :         return impl->get_opts(opts, len);
     872             : }
     873             : 
     874             : int
     875           6 : 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           6 :         if (!impl_name || !opts) {
     880           2 :                 errno = EINVAL;
     881           2 :                 return -1;
     882             :         }
     883             : 
     884           4 :         impl = sock_get_impl_by_name(impl_name);
     885           4 :         if (!impl) {
     886           0 :                 errno = EINVAL;
     887           0 :                 return -1;
     888             :         }
     889             : 
     890           4 :         if (!impl->set_opts) {
     891           1 :                 errno = ENOTSUP;
     892           1 :                 return -1;
     893             :         }
     894             : 
     895           3 :         return impl->set_opts(opts, len);
     896             : }
     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             :         }
     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             :                 } else {
     942           0 :                         SPDK_ERRLOG("Failed to get socket options for socket implementation %s\n", impl->name);
     943             :                 }
     944             :         }
     945             : 
     946           0 :         spdk_json_write_array_end(w);
     947           0 : }
     948             : 
     949             : void
     950           3 : spdk_net_impl_register(struct spdk_net_impl *impl)
     951             : {
     952           3 :         STAILQ_INSERT_HEAD(&g_net_impls, impl, link);
     953           3 : }
     954             : 
     955             : int
     956           5 : spdk_sock_set_default_impl(const char *impl_name)
     957             : {
     958             :         struct spdk_net_impl *impl;
     959             : 
     960           5 :         if (!impl_name) {
     961           2 :                 errno = EINVAL;
     962           2 :                 return -1;
     963             :         }
     964             : 
     965           3 :         impl = sock_get_impl_by_name(impl_name);
     966           3 :         if (!impl) {
     967           0 :                 errno = EINVAL;
     968           0 :                 return -1;
     969             :         }
     970             : 
     971           3 :         if (impl == g_default_impl) {
     972           1 :                 return 0;
     973             :         }
     974             : 
     975           2 :         if (g_default_impl) {
     976           1 :                 SPDK_DEBUGLOG(sock, "Change the default sock impl from %s to %s\n", g_default_impl->name,
     977             :                               impl->name);
     978             :         } else {
     979           1 :                 SPDK_DEBUGLOG(sock, "Set default sock implementation to %s\n", impl_name);
     980             :         }
     981             : 
     982           2 :         g_default_impl = impl;
     983             : 
     984           2 :         return 0;
     985             : }
     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             : }
     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             :         }
    1014             : 
    1015           0 :         return 0;
    1016             : }
    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             :         }
    1028           0 : }
    1029             : 
    1030           1 : 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           1 : SPDK_TRACE_REGISTER_FN(sock_trace, "sock", TRACE_GROUP_SOCK)

Generated by: LCOV version 1.15