LCOV - code coverage report
Current view: top level - spdk/test/unit/lib/nvmf/vfio_user.c - vfio_user_ut.c (source / functions) Hit Total Coverage
Test: Combined Lines: 153 175 87.4 %
Date: 2024-07-16 00:47:24 Functions: 6 46 13.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 7 44 15.9 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2021 Intel Corporation. All rights reserved.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include "spdk/stdinc.h"
       6                 :            : #include "spdk_internal/cunit.h"
       7                 :            : #include "common/lib/test_env.c"
       8                 :            : #include "nvmf/vfio_user.c"
       9                 :            : #include "nvmf/transport.c"
      10                 :            : 
      11         [ #  # ]:          0 : DEFINE_STUB(spdk_nvmf_ctrlr_get_regs, const struct spdk_nvmf_registers *,
      12                 :            :             (struct spdk_nvmf_ctrlr *ctrlr), NULL);
      13         [ #  # ]:          0 : DEFINE_STUB(spdk_mem_register, int, (void *vaddr, size_t len), 0);
      14         [ #  # ]:          0 : DEFINE_STUB(spdk_mem_unregister, int, (void *vaddr, size_t len), 0);
      15                 :          0 : DEFINE_STUB_V(spdk_nvmf_request_exec, (struct spdk_nvmf_request *req));
      16         [ #  # ]:          0 : DEFINE_STUB(spdk_nvmf_request_complete, int, (struct spdk_nvmf_request *req), 0);
      17                 :          0 : DEFINE_STUB_V(spdk_nvmf_tgt_new_qpair, (struct spdk_nvmf_tgt *tgt, struct spdk_nvmf_qpair *qpair));
      18         [ #  # ]:          0 : DEFINE_STUB(nvmf_ctrlr_abort_request, int, (struct spdk_nvmf_request *req), 0);
      19         [ #  # ]:          0 : DEFINE_STUB(spdk_nvmf_qpair_disconnect, int, (struct spdk_nvmf_qpair *qpair), 0);
      20         [ #  # ]:          0 : DEFINE_STUB(spdk_nvmf_subsystem_get_nqn, const char *,
      21                 :            :             (const struct spdk_nvmf_subsystem *subsystem), NULL);
      22         [ #  # ]:          0 : DEFINE_STUB(spdk_bdev_get_block_size, uint32_t, (const struct spdk_bdev *bdev), 512);
      23         [ #  # ]:          0 : DEFINE_STUB(spdk_nvmf_subsystem_pause, int, (struct spdk_nvmf_subsystem *subsystem,
      24                 :            :                 uint32_t nsid, spdk_nvmf_subsystem_state_change_done cb_fn, void *cb_arg), 0);
      25         [ #  # ]:          0 : DEFINE_STUB(spdk_nvmf_subsystem_resume, int, (struct spdk_nvmf_subsystem *subsystem,
      26                 :            :                 spdk_nvmf_subsystem_state_change_done cb_fn, void *cb_arg), 0);
      27                 :          0 : DEFINE_STUB_V(spdk_nvmf_ctrlr_abort_aer, (struct spdk_nvmf_ctrlr *ctrlr));
      28         [ #  # ]:          0 : DEFINE_STUB(spdk_nvmf_ctrlr_async_event_error_event, int, (struct spdk_nvmf_ctrlr *ctrlr,
      29                 :            :                 enum spdk_nvme_async_event_info_error info), 0);
      30         [ #  # ]:          0 : DEFINE_STUB(spdk_nvme_transport_id_adrfam_str, const char *, (enum spdk_nvmf_adrfam adrfam), NULL);
      31         [ #  # ]:          0 : DEFINE_STUB(spdk_nvmf_qpair_get_listen_trid, int, (struct spdk_nvmf_qpair *qpair,
      32                 :            :                 struct spdk_nvme_transport_id *trid), 0);
      33         [ #  # ]:          0 : DEFINE_STUB(spdk_nvme_transport_id_compare, int, (const struct spdk_nvme_transport_id *trid1,
      34                 :            :                 const struct spdk_nvme_transport_id *trid2), 0);
      35         [ #  # ]:          0 : DEFINE_STUB(nvmf_subsystem_get_ctrlr, struct spdk_nvmf_ctrlr *,
      36                 :            :             (struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid), NULL);
      37                 :          0 : DEFINE_STUB_V(nvmf_ctrlr_set_fatal_status, (struct spdk_nvmf_ctrlr *ctrlr));
      38         [ #  # ]:          0 : DEFINE_STUB(spdk_nvmf_ctrlr_save_migr_data, int, (struct spdk_nvmf_ctrlr *ctrlr,
      39                 :            :                 struct spdk_nvmf_ctrlr_migr_data *data), 0);
      40         [ #  # ]:          0 : DEFINE_STUB(spdk_nvmf_ctrlr_restore_migr_data, int, (struct spdk_nvmf_ctrlr *ctrlr,
      41                 :            :                 const struct spdk_nvmf_ctrlr_migr_data *data), 0);
      42         [ #  # ]:          0 : DEFINE_STUB(spdk_mempool_lookup, struct spdk_mempool *, (const char *name), NULL);
      43                 :            : 
      44                 :            : static void *
      45                 :         98 : gpa_to_vva(void *prv, uint64_t addr, uint64_t len, uint32_t flags)
      46                 :            : {
      47                 :         98 :         return (void *)(uintptr_t)addr;
      48                 :            : }
      49                 :            : 
      50                 :            : static void
      51                 :          2 : test_nvme_cmd_map_prps(void)
      52                 :            : {
      53                 :          2 :         struct spdk_nvme_cmd cmd = {};
      54                 :          1 :         struct iovec iovs[33];
      55                 :          1 :         uint64_t phy_addr, *prp;
      56                 :            :         uint32_t len;
      57                 :            :         void *buf, *prps;
      58                 :            :         int i, ret;
      59                 :          2 :         size_t mps = 4096;
      60                 :            : 
      61                 :          2 :         buf = spdk_zmalloc(132 * 1024, 4096, &phy_addr, 0, 0);
      62                 :          2 :         CU_ASSERT(buf != NULL);
      63                 :          2 :         prps = spdk_zmalloc(4096, 4096, &phy_addr, 0, 0);
      64                 :          2 :         CU_ASSERT(prps != NULL);
      65                 :            : 
      66                 :            :         /* test case 1: 4KiB with PRP1 only */
      67                 :          2 :         cmd.dptr.prp.prp1 = (uint64_t)(uintptr_t)buf;
      68                 :          2 :         len = 4096;
      69                 :          2 :         ret = nvme_cmd_map_prps(NULL, &cmd, iovs, 33, len, mps, gpa_to_vva);
      70                 :          2 :         CU_ASSERT(ret == 1);
      71                 :          2 :         CU_ASSERT(iovs[0].iov_base == (void *)(uintptr_t)cmd.dptr.prp.prp1);
      72                 :          2 :         CU_ASSERT(iovs[0].iov_len == len);
      73                 :            : 
      74                 :            :         /* test case 2: 4KiB with PRP1 and PRP2, 1KiB in first iov, and 3KiB in second iov */
      75                 :          2 :         cmd.dptr.prp.prp1 = (uint64_t)(uintptr_t)buf + 1024 * 3;
      76                 :          2 :         cmd.dptr.prp.prp2 = (uint64_t)(uintptr_t)buf + 4096;
      77                 :          2 :         len = 4096;
      78                 :          2 :         ret = nvme_cmd_map_prps(NULL, &cmd, iovs, 1, len, mps, gpa_to_vva);
      79                 :          2 :         CU_ASSERT(ret == -ERANGE);
      80                 :          2 :         ret = nvme_cmd_map_prps(NULL, &cmd, iovs, 33, len, mps, gpa_to_vva);
      81                 :          2 :         CU_ASSERT(ret == 2);
      82                 :          2 :         CU_ASSERT(iovs[0].iov_base == (void *)(uintptr_t)cmd.dptr.prp.prp1);
      83                 :          2 :         CU_ASSERT(iovs[0].iov_len == 1024);
      84                 :          2 :         CU_ASSERT(iovs[1].iov_base == (void *)(uintptr_t)cmd.dptr.prp.prp2);
      85                 :          2 :         CU_ASSERT(iovs[1].iov_len == 1024 * 3);
      86                 :            : 
      87                 :            :         /* test case 3: 128KiB with PRP list, 1KiB in first iov, 3KiB in last iov */
      88                 :          2 :         cmd.dptr.prp.prp1 = (uint64_t)(uintptr_t)buf + 1024 * 3;
      89                 :          2 :         cmd.dptr.prp.prp2 = (uint64_t)(uintptr_t)prps;
      90                 :          2 :         len = 128 * 1024;
      91                 :          2 :         prp = prps;
      92         [ +  + ]:         66 :         for (i = 1; i < 33; i++) {
      93                 :         64 :                 *prp = (uint64_t)(uintptr_t)buf + i * 4096;
      94                 :         64 :                 prp++;
      95                 :            :         }
      96                 :          2 :         ret = nvme_cmd_map_prps(NULL, &cmd, iovs, 33, len, mps, gpa_to_vva);
      97                 :          2 :         CU_ASSERT(ret == 33);
      98                 :          2 :         CU_ASSERT(iovs[0].iov_base == (void *)(uintptr_t)cmd.dptr.prp.prp1);
      99                 :          2 :         CU_ASSERT(iovs[0].iov_len == 1024);
     100         [ +  + ]:         64 :         for (i = 1; i < 32; i++) {
     101                 :         62 :                 CU_ASSERT(iovs[i].iov_base == (void *)((uintptr_t)buf + i * 4096));
     102                 :         62 :                 CU_ASSERT(iovs[i].iov_len == 4096);
     103                 :            :         }
     104                 :          2 :         CU_ASSERT(iovs[32].iov_base == (void *)((uintptr_t)buf + 32 * 4096));
     105                 :          2 :         CU_ASSERT(iovs[32].iov_len == 1024 * 3);
     106                 :            : 
     107                 :            :         /* test case 4: 256KiB with PRP list, not enough iovs */
     108                 :          2 :         cmd.dptr.prp.prp1 = (uint64_t)(uintptr_t)buf + 1024 * 3;
     109                 :          2 :         cmd.dptr.prp.prp2 = (uint64_t)(uintptr_t)prps;
     110                 :          2 :         len = 256 * 1024;
     111                 :          2 :         ret = nvme_cmd_map_prps(NULL, &cmd, iovs, 33, len, mps, gpa_to_vva);
     112                 :          2 :         CU_ASSERT(ret == -ERANGE);
     113                 :            : 
     114                 :          2 :         spdk_free(buf);
     115                 :          2 :         spdk_free(prps);
     116                 :          2 : }
     117                 :            : 
     118                 :            : static void
     119                 :          2 : test_nvme_cmd_map_sgls(void)
     120                 :            : {
     121                 :          2 :         struct spdk_nvme_cmd cmd = {};
     122                 :          1 :         struct iovec iovs[33];
     123                 :          1 :         uint64_t phy_addr;
     124                 :            :         uint32_t len;
     125                 :            :         void *buf, *sgls;
     126                 :            :         struct spdk_nvme_sgl_descriptor *sgl;
     127                 :            :         int i, ret;
     128                 :          2 :         size_t mps = 4096;
     129                 :            : 
     130                 :          2 :         buf = spdk_zmalloc(132 * 1024, 4096, &phy_addr, 0, 0);
     131                 :          2 :         CU_ASSERT(buf != NULL);
     132                 :          2 :         sgls = spdk_zmalloc(4096, 4096, &phy_addr, 0, 0);
     133                 :          2 :         CU_ASSERT(sgls != NULL);
     134                 :            : 
     135                 :            :         /* test case 1: 8KiB with 1 data block */
     136                 :          2 :         len = 8192;
     137                 :          2 :         cmd.dptr.sgl1.unkeyed.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK;
     138                 :          2 :         cmd.dptr.sgl1.unkeyed.length = len;
     139                 :          2 :         cmd.dptr.sgl1.address = (uint64_t)(uintptr_t)buf;
     140                 :            : 
     141                 :          2 :         ret = nvme_cmd_map_sgls(NULL, &cmd, iovs, 33, len, mps, gpa_to_vva);
     142                 :          2 :         CU_ASSERT(ret == 1);
     143                 :          2 :         CU_ASSERT(iovs[0].iov_base == buf);
     144                 :          2 :         CU_ASSERT(iovs[0].iov_len == 8192);
     145                 :            : 
     146                 :            :         /* test case 2: 8KiB with 2 data blocks and 1 last segment */
     147                 :          2 :         sgl = (struct spdk_nvme_sgl_descriptor *)sgls;
     148                 :          2 :         sgl[0].unkeyed.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK;
     149                 :          2 :         sgl[0].unkeyed.length = 2048;
     150                 :          2 :         sgl[0].address = (uint64_t)(uintptr_t)buf;
     151                 :          2 :         sgl[1].unkeyed.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK;
     152                 :          2 :         sgl[1].unkeyed.length = len - 2048;
     153                 :          2 :         sgl[1].address = (uint64_t)(uintptr_t)buf + 16 * 1024;
     154                 :            : 
     155                 :          2 :         cmd.dptr.sgl1.unkeyed.type = SPDK_NVME_SGL_TYPE_LAST_SEGMENT;
     156                 :          2 :         cmd.dptr.sgl1.unkeyed.length = 2 * sizeof(*sgl);
     157                 :          2 :         cmd.dptr.sgl1.address = (uint64_t)(uintptr_t)sgls;
     158                 :            : 
     159                 :          2 :         ret = nvme_cmd_map_sgls(NULL, &cmd, iovs, 33, len, mps, gpa_to_vva);
     160                 :          2 :         CU_ASSERT(ret == 2);
     161                 :          2 :         CU_ASSERT(iovs[0].iov_base == (void *)(uintptr_t)buf);
     162                 :          2 :         CU_ASSERT(iovs[0].iov_len == 2048);
     163                 :          2 :         CU_ASSERT(iovs[1].iov_base == (void *)((uintptr_t)buf + 16 * 1024));
     164                 :          2 :         CU_ASSERT(iovs[1].iov_len == len - 2048);
     165                 :            : 
     166                 :            :         /* test case 3: 8KiB with 1 segment, 1 last segment and 3 data blocks */
     167                 :          2 :         sgl[0].unkeyed.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK;
     168                 :          2 :         sgl[0].unkeyed.length = 2048;
     169                 :          2 :         sgl[0].address = (uint64_t)(uintptr_t)buf;
     170                 :          2 :         sgl[1].unkeyed.type = SPDK_NVME_SGL_TYPE_LAST_SEGMENT;
     171                 :          2 :         sgl[1].unkeyed.length = 2 * sizeof(*sgl);
     172                 :          2 :         sgl[1].address = (uint64_t)(uintptr_t)&sgl[9];
     173                 :            : 
     174                 :          2 :         sgl[9].unkeyed.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK;
     175                 :          2 :         sgl[9].unkeyed.length = 4096;
     176                 :          2 :         sgl[9].address = (uint64_t)(uintptr_t)buf + 4 * 1024;
     177                 :          2 :         sgl[10].unkeyed.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK;
     178                 :          2 :         sgl[10].unkeyed.length = 2048;
     179                 :          2 :         sgl[10].address = (uint64_t)(uintptr_t)buf + 16 * 1024;
     180                 :            : 
     181                 :          2 :         cmd.dptr.sgl1.unkeyed.type = SPDK_NVME_SGL_TYPE_SEGMENT;
     182                 :          2 :         cmd.dptr.sgl1.unkeyed.length = 2 * sizeof(*sgl);
     183                 :          2 :         cmd.dptr.sgl1.address = (uint64_t)(uintptr_t)&sgl[0];
     184                 :            : 
     185                 :          2 :         ret = nvme_cmd_map_sgls(NULL, &cmd, iovs, 33, len, mps, gpa_to_vva);
     186                 :          2 :         CU_ASSERT(ret == 3);
     187                 :          2 :         CU_ASSERT(iovs[0].iov_base == (void *)(uintptr_t)buf);
     188                 :          2 :         CU_ASSERT(iovs[0].iov_len == 2048);
     189                 :          2 :         CU_ASSERT(iovs[1].iov_base == (void *)((uintptr_t)buf + 4 * 1024));
     190                 :          2 :         CU_ASSERT(iovs[1].iov_len == 4096);
     191                 :          2 :         CU_ASSERT(iovs[2].iov_base == (void *)((uintptr_t)buf + 16 * 1024));
     192                 :          2 :         CU_ASSERT(iovs[2].iov_len == 2048);
     193                 :            : 
     194                 :            :         /* test case 4: not enough iovs */
     195                 :          2 :         len = 12 * 1024;
     196         [ +  + ]:         14 :         for (i = 0; i < 6; i++) {
     197                 :         12 :                 sgl[0].unkeyed.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK;
     198                 :         12 :                 sgl[0].unkeyed.length = 2048;
     199                 :         12 :                 sgl[0].address = (uint64_t)(uintptr_t)buf + i * 4096;
     200                 :            :         }
     201                 :            : 
     202                 :          2 :         cmd.dptr.sgl1.unkeyed.type = SPDK_NVME_SGL_TYPE_LAST_SEGMENT;
     203                 :          2 :         cmd.dptr.sgl1.unkeyed.length = 6 * sizeof(*sgl);
     204                 :          2 :         cmd.dptr.sgl1.address = (uint64_t)(uintptr_t)sgls;
     205                 :            : 
     206                 :          2 :         ret = nvme_cmd_map_sgls(NULL, &cmd, iovs, 4, len, mps, gpa_to_vva);
     207                 :          2 :         CU_ASSERT(ret == -ERANGE);
     208                 :            : 
     209                 :          2 :         spdk_free(buf);
     210                 :          2 :         spdk_free(sgls);
     211                 :          2 : }
     212                 :            : 
     213                 :            : static void
     214                 :          2 : ut_transport_destroy_done_cb(void *cb_arg)
     215                 :            : {
     216                 :          2 :         int *done = cb_arg;
     217                 :          2 :         *done = 1;
     218                 :          2 : }
     219                 :            : 
     220                 :            : static void
     221                 :          2 : test_nvmf_vfio_user_create_destroy(void)
     222                 :            : {
     223                 :          2 :         struct spdk_nvmf_transport *transport = NULL;
     224                 :          2 :         struct nvmf_vfio_user_transport *vu_transport = NULL;
     225                 :          2 :         struct nvmf_vfio_user_endpoint *endpoint = NULL;
     226                 :          2 :         struct spdk_nvmf_transport_opts opts = {};
     227                 :            :         int rc;
     228                 :          1 :         int done;
     229                 :            : 
     230                 :            :         /* Initialize transport_specific NULL to avoid decoding json */
     231                 :          2 :         opts.transport_specific = NULL;
     232                 :            : 
     233                 :          2 :         transport = nvmf_vfio_user_create(&opts);
     234                 :          2 :         CU_ASSERT(transport != NULL);
     235                 :            : 
     236                 :          2 :         vu_transport = SPDK_CONTAINEROF(transport, struct nvmf_vfio_user_transport,
     237                 :            :                                         transport);
     238                 :            :         /* Allocate a endpoint for destroy */
     239                 :          2 :         endpoint = calloc(1, sizeof(*endpoint));
     240         [ -  + ]:          2 :         pthread_mutex_init(&endpoint->lock, NULL);
     241                 :          2 :         TAILQ_INSERT_TAIL(&vu_transport->endpoints, endpoint, link);
     242                 :          2 :         done = 0;
     243                 :            : 
     244                 :          2 :         rc = nvmf_vfio_user_destroy(transport, ut_transport_destroy_done_cb, &done);
     245                 :          2 :         CU_ASSERT(rc == 0);
     246                 :          2 :         CU_ASSERT(done == 1);
     247                 :          2 : }
     248                 :            : 
     249                 :            : int
     250                 :          2 : main(int argc, char **argv)
     251                 :            : {
     252                 :          2 :         CU_pSuite       suite = NULL;
     253                 :            :         unsigned int    num_failures;
     254                 :            : 
     255                 :          2 :         CU_initialize_registry();
     256                 :            : 
     257                 :          2 :         suite = CU_add_suite("vfio_user", NULL, NULL);
     258                 :            : 
     259                 :          2 :         CU_ADD_TEST(suite, test_nvme_cmd_map_prps);
     260                 :          2 :         CU_ADD_TEST(suite, test_nvme_cmd_map_sgls);
     261                 :          2 :         CU_ADD_TEST(suite, test_nvmf_vfio_user_create_destroy);
     262                 :            : 
     263                 :          2 :         num_failures = spdk_ut_run_tests(argc, argv, NULL);
     264                 :          2 :         CU_cleanup_registry();
     265                 :          2 :         return num_failures;
     266                 :            : }

Generated by: LCOV version 1.14