xref: /spdk/test/unit/lib/rdma/common.c/common_ut.c (revision 45a053c5777494f4e8ce4bc1191c9de3920377f7)
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/common.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 
21 struct ut_rdma_device {
22 	struct ibv_context		*context;
23 	bool				removed;
24 	TAILQ_ENTRY(ut_rdma_device)	tailq;
25 };
26 
27 static TAILQ_HEAD(, ut_rdma_device) g_ut_dev_list = TAILQ_HEAD_INITIALIZER(g_ut_dev_list);
28 
29 struct ibv_context **
30 rdma_get_devices(int *num_devices)
31 {
32 	struct ibv_context **ctx_list;
33 	struct ut_rdma_device *ut_dev;
34 	int num_ut_devs = 0;
35 	int i = 0;
36 
37 	TAILQ_FOREACH(ut_dev, &g_ut_dev_list, tailq) {
38 		if (!ut_dev->removed) {
39 			num_ut_devs++;
40 		}
41 	}
42 
43 	ctx_list = malloc(sizeof(*ctx_list) * (num_ut_devs + 1));
44 	SPDK_CU_ASSERT_FATAL(ctx_list);
45 
46 	TAILQ_FOREACH(ut_dev, &g_ut_dev_list, tailq) {
47 		if (!ut_dev->removed) {
48 			ctx_list[i++] = ut_dev->context;
49 		}
50 	}
51 	ctx_list[i] = NULL;
52 
53 	if (num_devices) {
54 		*num_devices = num_ut_devs;
55 	}
56 
57 	return ctx_list;
58 }
59 
60 void
61 rdma_free_devices(struct ibv_context **list)
62 {
63 	free(list);
64 }
65 
66 struct ibv_pd *
67 ibv_alloc_pd(struct ibv_context *context)
68 {
69 	struct ibv_pd *pd;
70 	struct ut_rdma_device *ut_dev;
71 
72 	TAILQ_FOREACH(ut_dev, &g_ut_dev_list, tailq) {
73 		if (ut_dev->context == context && !ut_dev->removed) {
74 			break;
75 		}
76 	}
77 
78 	if (!ut_dev) {
79 		return NULL;
80 	}
81 
82 	pd = calloc(1, sizeof(*pd));
83 	SPDK_CU_ASSERT_FATAL(pd);
84 
85 	pd->context = context;
86 
87 	return pd;
88 }
89 
90 int
91 ibv_dealloc_pd(struct ibv_pd *pd)
92 {
93 	free(pd);
94 
95 	return 0;
96 }
97 
98 static struct ut_rdma_device *
99 ut_rdma_add_dev(struct ibv_context *context)
100 {
101 	struct ut_rdma_device *ut_dev;
102 
103 	ut_dev = calloc(1, sizeof(*ut_dev));
104 	if (!ut_dev) {
105 		return NULL;
106 	}
107 
108 	ut_dev->context = context;
109 	TAILQ_INSERT_TAIL(&g_ut_dev_list, ut_dev, tailq);
110 
111 	return ut_dev;
112 }
113 
114 static void
115 ut_rdma_remove_dev(struct ut_rdma_device *ut_dev)
116 {
117 	TAILQ_REMOVE(&g_ut_dev_list, ut_dev, tailq);
118 	free(ut_dev);
119 }
120 
121 static struct spdk_rdma_device *
122 _rdma_get_dev(struct ibv_context *context)
123 {
124 	struct spdk_rdma_device *dev;
125 
126 	TAILQ_FOREACH(dev, &g_dev_list, tailq) {
127 		if (dev->context == context) {
128 			break;
129 		}
130 	}
131 
132 	return dev;
133 }
134 
135 static void
136 test_spdk_rdma_pd(void)
137 {
138 	struct ut_rdma_device *ut_dev0, *ut_dev1, *ut_dev2;
139 	struct ibv_pd *pd1, *pd1_1, *pd2;
140 
141 	ut_dev0 = ut_rdma_add_dev((struct ibv_context *)0xface);
142 	SPDK_CU_ASSERT_FATAL(ut_dev0 != NULL);
143 
144 	ut_dev1 = ut_rdma_add_dev((struct ibv_context *)0xc0ffee);
145 	SPDK_CU_ASSERT_FATAL(ut_dev1 != NULL);
146 
147 	ut_dev2 = ut_rdma_add_dev((struct ibv_context *)0xf00d);
148 	SPDK_CU_ASSERT_FATAL(ut_dev2 != NULL);
149 
150 	/* There are ut_dev0 and ut_dev1. */
151 	ut_dev2->removed = true;
152 
153 	/* Call spdk_rdma_get_pd() to non-existent ut_dev2. */
154 	pd2 = spdk_rdma_get_pd(ut_dev2->context);
155 
156 	/* Then, spdk_rdma_get_pd() should return NULL and g_dev_list should have dev0 and dev1. */
157 	CU_ASSERT(pd2 == NULL);
158 	CU_ASSERT(_rdma_get_dev(ut_dev0->context) != NULL);
159 	CU_ASSERT(_rdma_get_dev(ut_dev1->context) != NULL);
160 	CU_ASSERT(_rdma_get_dev(ut_dev2->context) == NULL);
161 
162 	/* Remove ut_dev0 and add ut_dev2. */
163 	ut_dev0->removed = true;
164 	ut_dev2->removed = false;
165 
166 	/* Call spdk_rdma_get_pd() to ut_dev1. */
167 	pd1 = spdk_rdma_get_pd(ut_dev1->context);
168 
169 	/* Then, spdk_rdma_get_pd() should return pd1 and g_dev_list should have dev1 and dev2. */
170 	CU_ASSERT(pd1 != NULL);
171 	CU_ASSERT(_rdma_get_dev(ut_dev0->context) == NULL);
172 	CU_ASSERT(_rdma_get_dev(ut_dev1->context) != NULL);
173 	CU_ASSERT(_rdma_get_dev(ut_dev2->context) != NULL);
174 
175 	/* Remove ut_dev1. */
176 	ut_dev1->removed = true;
177 
178 	/* Call spdk_rdma_get_pd() again to ut_dev1 which does not exist anymore. */
179 	pd1_1 = spdk_rdma_get_pd(ut_dev1->context);
180 
181 	/* Then, spdk_rdma_get_pd() should return NULL and g_dev_list should still have dev1. */
182 	CU_ASSERT(pd1_1 == NULL);
183 	CU_ASSERT(_rdma_get_dev(ut_dev0->context) == NULL);
184 	CU_ASSERT(_rdma_get_dev(ut_dev1->context) != NULL);
185 	CU_ASSERT(_rdma_get_dev(ut_dev2->context) != NULL);
186 
187 	/* Call spdk_rdma_put_pd() to pd1. */
188 	spdk_rdma_put_pd(pd1);
189 
190 	/* Then, dev1 should be removed from g_dev_list. */
191 	CU_ASSERT(_rdma_get_dev(ut_dev0->context) == NULL);
192 	CU_ASSERT(_rdma_get_dev(ut_dev1->context) == NULL);
193 	CU_ASSERT(_rdma_get_dev(ut_dev2->context) != NULL);
194 
195 	/* Call spdk_rdma_get_pd() to ut_dev2. */
196 	pd2 = spdk_rdma_get_pd(ut_dev2->context);
197 
198 	/* spdk_rdma_get_pd() should succeed and g_dev_list should still have dev2
199 	 * even after spdk_rdma_put_pd() is called to pd2.
200 	 */
201 	CU_ASSERT(pd2 != NULL);
202 
203 	spdk_rdma_put_pd(pd2);
204 
205 	CU_ASSERT(_rdma_get_dev(ut_dev0->context) == NULL);
206 	CU_ASSERT(_rdma_get_dev(ut_dev1->context) == NULL);
207 	CU_ASSERT(_rdma_get_dev(ut_dev2->context) != NULL);
208 
209 	_rdma_fini();
210 
211 	ut_rdma_remove_dev(ut_dev0);
212 	ut_rdma_remove_dev(ut_dev1);
213 	ut_rdma_remove_dev(ut_dev2);
214 }
215 
216 int
217 main(int argc, char **argv)
218 {
219 	CU_pSuite suite = NULL;
220 	unsigned int num_failures;
221 
222 	CU_initialize_registry();
223 
224 	suite = CU_add_suite("rdma_common", NULL, NULL);
225 	CU_ADD_TEST(suite, test_spdk_rdma_pd);
226 
227 	num_failures = spdk_ut_run_tests(argc, argv, NULL);
228 	CU_cleanup_registry();
229 	return num_failures;
230 }
231