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-08-12 07:19:58 Functions: 6 48 12.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 7 46 15.2 %

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

Generated by: LCOV version 1.14