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 176 86.9 %
Date: 2024-07-14 20:59:18 Functions: 6 29 20.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 7 8 87.5 %

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

Generated by: LCOV version 1.14