xref: /spdk/test/unit/lib/rdma/common.c/common_ut.c (revision 95d6c9fac17572b107042103439aafd696d60b0e)
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 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 DEFINE_STUB_V(spdk_mem_map_free, (struct spdk_mem_map **pmap));
14 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 DEFINE_STUB(spdk_mem_map_clear_translation, int, (struct spdk_mem_map *map, uint64_t vaddr,
17 		uint64_t size), 0);
18 DEFINE_STUB(spdk_mem_map_translate, uint64_t, (const struct spdk_mem_map *map, uint64_t vaddr,
19 		uint64_t *size), 0);
20 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 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 	int num_ut_devs = 0;
39 	int i = 0;
40 
41 	TAILQ_FOREACH(ut_dev, &g_ut_dev_list, tailq) {
42 		if (!ut_dev->removed) {
43 			num_ut_devs++;
44 		}
45 	}
46 
47 	ctx_list = malloc(sizeof(*ctx_list) * (num_ut_devs + 1));
48 	SPDK_CU_ASSERT_FATAL(ctx_list);
49 
50 	TAILQ_FOREACH(ut_dev, &g_ut_dev_list, tailq) {
51 		if (!ut_dev->removed) {
52 			ctx_list[i++] = ut_dev->context;
53 		}
54 	}
55 	ctx_list[i] = NULL;
56 
57 	if (num_devices) {
58 		*num_devices = num_ut_devs;
59 	}
60 
61 	return ctx_list;
62 }
63 
64 void
65 rdma_free_devices(struct ibv_context **list)
66 {
67 	free(list);
68 }
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 	TAILQ_FOREACH(ut_dev, &g_ut_dev_list, tailq) {
77 		if (ut_dev->context == context && !ut_dev->removed) {
78 			break;
79 		}
80 	}
81 
82 	if (!ut_dev) {
83 		return NULL;
84 	}
85 
86 	pd = calloc(1, sizeof(*pd));
87 	SPDK_CU_ASSERT_FATAL(pd);
88 
89 	pd->context = context;
90 
91 	return pd;
92 }
93 
94 int
95 ibv_dealloc_pd(struct ibv_pd *pd)
96 {
97 	free(pd);
98 
99 	return 0;
100 }
101 
102 static struct ut_rdma_device *
103 ut_rdma_add_dev(struct ibv_context *context)
104 {
105 	struct ut_rdma_device *ut_dev;
106 
107 	ut_dev = calloc(1, sizeof(*ut_dev));
108 	if (!ut_dev) {
109 		return NULL;
110 	}
111 
112 	ut_dev->context = context;
113 	TAILQ_INSERT_TAIL(&g_ut_dev_list, ut_dev, tailq);
114 
115 	return ut_dev;
116 }
117 
118 static void
119 ut_rdma_remove_dev(struct ut_rdma_device *ut_dev)
120 {
121 	TAILQ_REMOVE(&g_ut_dev_list, ut_dev, tailq);
122 	free(ut_dev);
123 }
124 
125 static struct rdma_utils_device *
126 _rdma_get_dev(struct ibv_context *context)
127 {
128 	struct rdma_utils_device *dev;
129 
130 	TAILQ_FOREACH(dev, &g_dev_list, tailq) {
131 		if (dev->context == context) {
132 			break;
133 		}
134 	}
135 
136 	return dev;
137 }
138 
139 static void
140 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 	ut_dev0 = ut_rdma_add_dev((struct ibv_context *)0xface);
146 	SPDK_CU_ASSERT_FATAL(ut_dev0 != NULL);
147 
148 	ut_dev1 = ut_rdma_add_dev((struct ibv_context *)0xc0ffee);
149 	SPDK_CU_ASSERT_FATAL(ut_dev1 != NULL);
150 
151 	ut_dev2 = ut_rdma_add_dev((struct ibv_context *)0xf00d);
152 	SPDK_CU_ASSERT_FATAL(ut_dev2 != NULL);
153 
154 	/* There are ut_dev0 and ut_dev1. */
155 	ut_dev2->removed = true;
156 
157 	/* Call spdk_rdma_get_pd() to non-existent ut_dev2. */
158 	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 	CU_ASSERT(pd2 == NULL);
162 	CU_ASSERT(_rdma_get_dev(ut_dev0->context) != NULL);
163 	CU_ASSERT(_rdma_get_dev(ut_dev1->context) != NULL);
164 	CU_ASSERT(_rdma_get_dev(ut_dev2->context) == NULL);
165 
166 	/* Remove ut_dev0 and add ut_dev2. */
167 	ut_dev0->removed = true;
168 	ut_dev2->removed = false;
169 
170 	/* Call spdk_rdma_utils_get_pd() to ut_dev1. */
171 	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 	CU_ASSERT(pd1 != NULL);
175 	CU_ASSERT(_rdma_get_dev(ut_dev0->context) == NULL);
176 	CU_ASSERT(_rdma_get_dev(ut_dev1->context) != NULL);
177 	CU_ASSERT(_rdma_get_dev(ut_dev2->context) != NULL);
178 
179 	/* Remove ut_dev1. */
180 	ut_dev1->removed = true;
181 
182 	/* Call spdk_rdma_utils_get_pd() again to ut_dev1 which does not exist anymore. */
183 	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 	CU_ASSERT(pd1_1 == NULL);
187 	CU_ASSERT(_rdma_get_dev(ut_dev0->context) == NULL);
188 	CU_ASSERT(_rdma_get_dev(ut_dev1->context) != NULL);
189 	CU_ASSERT(_rdma_get_dev(ut_dev2->context) != NULL);
190 
191 	/* Call spdk_rdma_utils_put_pd() to pd1. */
192 	spdk_rdma_utils_put_pd(pd1);
193 
194 	/* Then, dev1 should be removed from g_dev_list. */
195 	CU_ASSERT(_rdma_get_dev(ut_dev0->context) == NULL);
196 	CU_ASSERT(_rdma_get_dev(ut_dev1->context) == NULL);
197 	CU_ASSERT(_rdma_get_dev(ut_dev2->context) != NULL);
198 
199 	/* Call spdk_rdma_utils_get_pd() to ut_dev2. */
200 	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 	CU_ASSERT(pd2 != NULL);
206 
207 	spdk_rdma_utils_put_pd(pd2);
208 
209 	CU_ASSERT(_rdma_get_dev(ut_dev0->context) == NULL);
210 	CU_ASSERT(_rdma_get_dev(ut_dev1->context) == NULL);
211 	CU_ASSERT(_rdma_get_dev(ut_dev2->context) != NULL);
212 
213 	_rdma_utils_fini();
214 
215 	ut_rdma_remove_dev(ut_dev0);
216 	ut_rdma_remove_dev(ut_dev1);
217 	ut_rdma_remove_dev(ut_dev2);
218 }
219 
220 int
221 main(int argc, char **argv)
222 {
223 	CU_pSuite suite = NULL;
224 	unsigned int num_failures;
225 
226 	CU_initialize_registry();
227 
228 	suite = CU_add_suite("rdma_common", NULL, NULL);
229 	CU_ADD_TEST(suite, test_spdk_rdma_pd);
230 
231 	num_failures = spdk_ut_run_tests(argc, argv, NULL);
232 	CU_cleanup_registry();
233 	return num_failures;
234 }
235