Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 : : */
4 : :
5 : : #include "spdk/stdinc.h"
6 : : #include "spdk_internal/cunit.h"
7 : : #include "spdk_internal/mock.h"
8 : : #include "common/lib/test_env.c"
9 : : #include "rdma_utils/rdma_utils.c"
10 : :
11 [ # # ]: 0 : DEFINE_STUB(spdk_mem_map_alloc, struct spdk_mem_map *, (uint64_t default_translation,
12 : : const struct spdk_mem_map_ops *ops, void *cb_ctx), NULL);
13 : 0 : DEFINE_STUB_V(spdk_mem_map_free, (struct spdk_mem_map **pmap));
14 [ # # ]: 0 : DEFINE_STUB(spdk_mem_map_set_translation, int, (struct spdk_mem_map *map, uint64_t vaddr,
15 : : uint64_t size, uint64_t translation), 0);
16 [ # # ]: 0 : DEFINE_STUB(spdk_mem_map_clear_translation, int, (struct spdk_mem_map *map, uint64_t vaddr,
17 : : uint64_t size), 0);
18 [ # # ]: 0 : DEFINE_STUB(spdk_mem_map_translate, uint64_t, (const struct spdk_mem_map *map, uint64_t vaddr,
19 : : uint64_t *size), 0);
20 [ # # ]: 0 : DEFINE_STUB(spdk_memory_domain_create, int, (struct spdk_memory_domain **_domain,
21 : : enum spdk_dma_device_type type,
22 : : struct spdk_memory_domain_ctx *ctx, const char *id), 0);
23 : 0 : DEFINE_STUB_V(spdk_memory_domain_destroy, (struct spdk_memory_domain *domain));
24 : :
25 : : struct ut_rdma_device {
26 : : struct ibv_context *context;
27 : : bool removed;
28 : : TAILQ_ENTRY(ut_rdma_device) tailq;
29 : : };
30 : :
31 : : static TAILQ_HEAD(, ut_rdma_device) g_ut_dev_list = TAILQ_HEAD_INITIALIZER(g_ut_dev_list);
32 : :
33 : : struct ibv_context **
34 : : rdma_get_devices(int *num_devices)
35 : : {
36 : : struct ibv_context **ctx_list;
37 : : struct ut_rdma_device *ut_dev;
38 : 24 : int num_ut_devs = 0;
39 : 24 : int i = 0;
40 : :
41 [ + + ]: 96 : TAILQ_FOREACH(ut_dev, &g_ut_dev_list, tailq) {
42 [ + + + + ]: 72 : if (!ut_dev->removed) {
43 : 32 : num_ut_devs++;
44 : : }
45 : : }
46 : :
47 : 24 : ctx_list = malloc(sizeof(*ctx_list) * (num_ut_devs + 1));
48 [ - + ]: 24 : SPDK_CU_ASSERT_FATAL(ctx_list);
49 : :
50 [ + + ]: 96 : TAILQ_FOREACH(ut_dev, &g_ut_dev_list, tailq) {
51 [ + + + + ]: 72 : if (!ut_dev->removed) {
52 : 32 : ctx_list[i++] = ut_dev->context;
53 : : }
54 : : }
55 : 24 : ctx_list[i] = NULL;
56 : :
57 [ + - ]: 24 : if (num_devices) {
58 : 24 : *num_devices = num_ut_devs;
59 : : }
60 : :
61 : 24 : return ctx_list;
62 : : }
63 : :
64 : : void
65 : : rdma_free_devices(struct ibv_context **list)
66 : : {
67 : 24 : free(list);
68 : 24 : }
69 : :
70 : : struct ibv_pd *
71 : : ibv_alloc_pd(struct ibv_context *context)
72 : : {
73 : : struct ibv_pd *pd;
74 : : struct ut_rdma_device *ut_dev;
75 : :
76 [ + - ]: 24 : TAILQ_FOREACH(ut_dev, &g_ut_dev_list, tailq) {
77 [ + + + + : 24 : if (ut_dev->context == context && !ut_dev->removed) {
+ - ]
78 : 12 : break;
79 : : }
80 : : }
81 : :
82 [ - + ]: 12 : if (!ut_dev) {
83 : 0 : return NULL;
84 : : }
85 : :
86 : 12 : pd = calloc(1, sizeof(*pd));
87 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(pd);
88 : :
89 : 12 : pd->context = context;
90 : :
91 : 12 : return pd;
92 : : }
93 : :
94 : : int
95 : : ibv_dealloc_pd(struct ibv_pd *pd)
96 : : {
97 : 12 : free(pd);
98 : :
99 : 12 : return 0;
100 : : }
101 : :
102 : : static struct ut_rdma_device *
103 : 12 : ut_rdma_add_dev(struct ibv_context *context)
104 : : {
105 : : struct ut_rdma_device *ut_dev;
106 : :
107 : 12 : ut_dev = calloc(1, sizeof(*ut_dev));
108 [ - + ]: 12 : if (!ut_dev) {
109 : 0 : return NULL;
110 : : }
111 : :
112 : 12 : ut_dev->context = context;
113 : 12 : TAILQ_INSERT_TAIL(&g_ut_dev_list, ut_dev, tailq);
114 : :
115 : 12 : return ut_dev;
116 : : }
117 : :
118 : : static void
119 : 12 : ut_rdma_remove_dev(struct ut_rdma_device *ut_dev)
120 : : {
121 [ + + ]: 12 : TAILQ_REMOVE(&g_ut_dev_list, ut_dev, tailq);
122 : 12 : free(ut_dev);
123 : 12 : }
124 : :
125 : : static struct rdma_utils_device *
126 : 60 : _rdma_get_dev(struct ibv_context *context)
127 : : {
128 : : struct rdma_utils_device *dev;
129 : :
130 [ + + ]: 112 : TAILQ_FOREACH(dev, &g_dev_list, tailq) {
131 [ + + ]: 84 : if (dev->context == context) {
132 : 32 : break;
133 : : }
134 : : }
135 : :
136 : 60 : return dev;
137 : : }
138 : :
139 : : static void
140 : 4 : test_spdk_rdma_pd(void)
141 : : {
142 : : struct ut_rdma_device *ut_dev0, *ut_dev1, *ut_dev2;
143 : : struct ibv_pd *pd1, *pd1_1, *pd2;
144 : :
145 : 4 : ut_dev0 = ut_rdma_add_dev((struct ibv_context *)0xface);
146 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(ut_dev0 != NULL);
147 : :
148 : 4 : ut_dev1 = ut_rdma_add_dev((struct ibv_context *)0xc0ffee);
149 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(ut_dev1 != NULL);
150 : :
151 : 4 : ut_dev2 = ut_rdma_add_dev((struct ibv_context *)0xf00d);
152 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(ut_dev2 != NULL);
153 : :
154 : : /* There are ut_dev0 and ut_dev1. */
155 : 4 : ut_dev2->removed = true;
156 : :
157 : : /* Call spdk_rdma_get_pd() to non-existent ut_dev2. */
158 : 4 : pd2 = spdk_rdma_utils_get_pd(ut_dev2->context);
159 : :
160 : : /* Then, spdk_rdma_utils_get_pd() should return NULL and g_dev_list should have dev0 and dev1. */
161 : 4 : CU_ASSERT(pd2 == NULL);
162 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev0->context) != NULL);
163 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev1->context) != NULL);
164 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev2->context) == NULL);
165 : :
166 : : /* Remove ut_dev0 and add ut_dev2. */
167 : 4 : ut_dev0->removed = true;
168 : 4 : ut_dev2->removed = false;
169 : :
170 : : /* Call spdk_rdma_utils_get_pd() to ut_dev1. */
171 : 4 : pd1 = spdk_rdma_utils_get_pd(ut_dev1->context);
172 : :
173 : : /* Then, spdk_rdma_utils_get_pd() should return pd1 and g_dev_list should have dev1 and dev2. */
174 : 4 : CU_ASSERT(pd1 != NULL);
175 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev0->context) == NULL);
176 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev1->context) != NULL);
177 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev2->context) != NULL);
178 : :
179 : : /* Remove ut_dev1. */
180 : 4 : ut_dev1->removed = true;
181 : :
182 : : /* Call spdk_rdma_utils_get_pd() again to ut_dev1 which does not exist anymore. */
183 : 4 : pd1_1 = spdk_rdma_utils_get_pd(ut_dev1->context);
184 : :
185 : : /* Then, spdk_rdma_utils_get_pd() should return NULL and g_dev_list should still have dev1. */
186 : 4 : CU_ASSERT(pd1_1 == NULL);
187 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev0->context) == NULL);
188 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev1->context) != NULL);
189 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev2->context) != NULL);
190 : :
191 : : /* Call spdk_rdma_utils_put_pd() to pd1. */
192 : 4 : spdk_rdma_utils_put_pd(pd1);
193 : :
194 : : /* Then, dev1 should be removed from g_dev_list. */
195 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev0->context) == NULL);
196 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev1->context) == NULL);
197 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev2->context) != NULL);
198 : :
199 : : /* Call spdk_rdma_utils_get_pd() to ut_dev2. */
200 : 4 : pd2 = spdk_rdma_utils_get_pd(ut_dev2->context);
201 : :
202 : : /* spdk_rdma_utils_get_pd() should succeed and g_dev_list should still have dev2
203 : : * even after spdk_rdma_utils_put_pd() is called to pd2.
204 : : */
205 : 4 : CU_ASSERT(pd2 != NULL);
206 : :
207 : 4 : spdk_rdma_utils_put_pd(pd2);
208 : :
209 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev0->context) == NULL);
210 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev1->context) == NULL);
211 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev2->context) != NULL);
212 : :
213 : 4 : _rdma_utils_fini();
214 : :
215 : 4 : ut_rdma_remove_dev(ut_dev0);
216 : 4 : ut_rdma_remove_dev(ut_dev1);
217 : 4 : ut_rdma_remove_dev(ut_dev2);
218 : 4 : }
219 : :
220 : : int
221 : 4 : main(int argc, char **argv)
222 : : {
223 : 4 : CU_pSuite suite = NULL;
224 : : unsigned int num_failures;
225 : :
226 : 4 : CU_initialize_registry();
227 : :
228 : 4 : suite = CU_add_suite("rdma_common", NULL, NULL);
229 : 4 : CU_ADD_TEST(suite, test_spdk_rdma_pd);
230 : :
231 : 4 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
232 : 4 : CU_cleanup_registry();
233 : 4 : return num_failures;
234 : : }
|