xref: /spdk/test/common/lib/test_env.c (revision 2fac05e919e1940137e4502f01beabb81ebbef9c)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #include "spdk_internal/mock.h"
37 
38 #include "spdk/env.h"
39 #include "spdk/queue.h"
40 
41 /*
42  * NOTE:
43  * Functions in this file are mocks for SPDK based functions
44  * and work conceptually in the same way that mocks work in
45  * /lib/ut_mock. However, the globals that control the behavior
46  * of the mock are defined here, with each function, as
47  * opposed to being defined as part of the macro that defines
48  * the stub or wrapper for other types of functions. Be sure
49  * to use the correct global variable naming convention when
50  * working with these functions. See /lib/ut_mock for details.
51  */
52 
53 /*
54  * these stubs have a return value set with one of the MOCK_SET macros
55  */
56 DEFINE_STUB(spdk_process_is_primary, bool, (void), true)
57 
58 DEFINE_STUB_VP(spdk_memzone_lookup, (const char *name), NULL)
59 
60 /*
61  * these mocks don't fit well with the library macro model because
62  * they do 'something' other than just return a pre-set value
63  */
64 
65 /* setup the mock control to pass thru by default */
66 void *ut_p_spdk_memzone_reserve = MOCK_PASS_THRU_P;
67 void *
68 spdk_memzone_reserve(const char *name, size_t len, int socket_id, unsigned flags)
69 {
70 	if (ut_p_spdk_memzone_reserve &&
71 	    ut_p_spdk_memzone_reserve == MOCK_PASS_THRU_P) {
72 		return malloc(len);
73 	} else {
74 		return ut_p_spdk_memzone_reserve;
75 	}
76 }
77 
78 void *
79 spdk_dma_malloc(size_t size, size_t align, uint64_t *phys_addr)
80 {
81 	void *buf = NULL;
82 	if (posix_memalign(&buf, align, size)) {
83 		return NULL;
84 	}
85 	if (phys_addr) {
86 		*phys_addr = (uint64_t)buf;
87 	}
88 	return buf;
89 }
90 
91 int ut_spdk_dma_zmalloc = (int)MOCK_PASS_THRU;
92 void *ut_p_spdk_dma_zmalloc = &ut_spdk_dma_zmalloc;
93 void *
94 spdk_dma_zmalloc(size_t size, size_t align, uint64_t *phys_addr)
95 {
96 	if (ut_p_spdk_dma_zmalloc &&
97 	    ut_spdk_dma_zmalloc == (int)MOCK_PASS_THRU) {
98 		void *buf = spdk_dma_malloc(size, align, phys_addr);
99 
100 		if (buf != NULL) {
101 			memset(buf, 0, size);
102 		}
103 		return buf;
104 	} else {
105 		return ut_p_spdk_dma_zmalloc;
106 	}
107 }
108 
109 void *
110 spdk_dma_malloc_socket(size_t size, size_t align, uint64_t *phys_addr, int socket_id)
111 {
112 	return spdk_dma_malloc(size, align, phys_addr);
113 }
114 
115 void *
116 spdk_dma_zmalloc_socket(size_t size, size_t align, uint64_t *phys_addr, int socket_id)
117 {
118 	return spdk_dma_zmalloc(size, align, phys_addr);
119 }
120 
121 void *
122 spdk_dma_realloc(void *buf, size_t size, size_t align, uint64_t *phys_addr)
123 {
124 	return realloc(buf, size);
125 }
126 
127 void spdk_dma_free(void *buf)
128 {
129 	if (ut_p_spdk_dma_zmalloc &&
130 	    ut_spdk_dma_zmalloc == (int)MOCK_PASS_THRU) {
131 		free(buf);
132 	}
133 }
134 
135 bool ut_fail_vtophys = false;
136 uint64_t spdk_vtophys(void *buf)
137 {
138 	if (ut_fail_vtophys) {
139 		return (uint64_t) - 1;
140 	} else {
141 		return (uintptr_t)buf;
142 	}
143 }
144 
145 void
146 spdk_memzone_dump(FILE *f)
147 {
148 	return;
149 }
150 
151 int
152 spdk_memzone_free(const char *name)
153 {
154 	return 0;
155 }
156 
157 struct test_mempool {
158 	size_t	count;
159 };
160 
161 struct spdk_mempool *
162 spdk_mempool_create(const char *name, size_t count,
163 		    size_t ele_size, size_t cache_size, int socket_id)
164 {
165 	struct test_mempool *mp;
166 
167 	mp = calloc(1, sizeof(*mp));
168 	if (mp == NULL) {
169 		return NULL;
170 	}
171 
172 	mp->count = count;
173 
174 	return (struct spdk_mempool *)mp;
175 }
176 
177 void
178 spdk_mempool_free(struct spdk_mempool *_mp)
179 {
180 	struct test_mempool *mp = (struct test_mempool *)_mp;
181 
182 	free(mp);
183 }
184 
185 void *
186 spdk_mempool_get(struct spdk_mempool *_mp)
187 {
188 	struct test_mempool *mp = (struct test_mempool *)_mp;
189 	void *buf;
190 
191 	if (mp && mp->count == 0) {
192 		return NULL;
193 	}
194 
195 	if (posix_memalign(&buf, 64, 0x1000)) {
196 		return NULL;
197 	} else {
198 		if (mp) {
199 			mp->count--;
200 		}
201 		return buf;
202 	}
203 }
204 
205 void
206 spdk_mempool_put(struct spdk_mempool *_mp, void *ele)
207 {
208 	struct test_mempool *mp = (struct test_mempool *)_mp;
209 
210 	if (mp) {
211 		mp->count++;
212 	}
213 	free(ele);
214 }
215 
216 void
217 spdk_mempool_put_bulk(struct spdk_mempool *mp, void **ele_arr, size_t count)
218 {
219 	for (size_t i = 0; i < count; i++) {
220 		spdk_mempool_put(mp, ele_arr[i]);
221 	}
222 }
223 
224 size_t
225 spdk_mempool_count(const struct spdk_mempool *_mp)
226 {
227 	struct test_mempool *mp = (struct test_mempool *)_mp;
228 
229 	if (mp) {
230 		return mp->count;
231 	} else {
232 		return 1024;
233 	}
234 }
235 
236 struct spdk_ring_ele {
237 	void *ele;
238 	TAILQ_ENTRY(spdk_ring_ele) link;
239 };
240 
241 struct spdk_ring {
242 	TAILQ_HEAD(, spdk_ring_ele) elements;
243 };
244 
245 struct spdk_ring *
246 spdk_ring_create(enum spdk_ring_type type, size_t count, int socket_id)
247 {
248 	struct spdk_ring *ring;
249 
250 	ring = calloc(1, sizeof(*ring));
251 	if (ring) {
252 		TAILQ_INIT(&ring->elements);
253 	}
254 
255 	return ring;
256 }
257 
258 
259 void
260 spdk_ring_free(struct spdk_ring *ring)
261 {
262 	free(ring);
263 }
264 
265 size_t
266 spdk_ring_enqueue(struct spdk_ring *ring, void **objs, size_t count)
267 {
268 	struct spdk_ring_ele *ele;
269 	size_t i;
270 
271 	for (i = 0; i < count; i++) {
272 		ele = calloc(1, sizeof(*ele));
273 		if (!ele) {
274 			break;
275 		}
276 
277 		ele->ele = objs[i];
278 		TAILQ_INSERT_TAIL(&ring->elements, ele, link);
279 	}
280 
281 	return i;
282 }
283 
284 size_t
285 spdk_ring_dequeue(struct spdk_ring *ring, void **objs, size_t count)
286 {
287 	struct spdk_ring_ele *ele, *tmp;
288 	size_t i = 0;
289 
290 	if (count == 0) {
291 		return 0;
292 	}
293 
294 	TAILQ_FOREACH_SAFE(ele, &ring->elements, link, tmp) {
295 		TAILQ_REMOVE(&ring->elements, ele, link);
296 		objs[i] = ele->ele;
297 		free(ele);
298 		i++;
299 		if (i >= count) {
300 			break;
301 		}
302 	}
303 
304 	return i;
305 
306 }
307 
308 uint64_t ut_tsc = 0;
309 uint64_t spdk_get_ticks(void)
310 {
311 	return ut_tsc;
312 }
313 
314 uint64_t spdk_get_ticks_hz(void)
315 {
316 	return 1000000;
317 }
318 
319 void spdk_delay_us(unsigned int us)
320 {
321 	ut_tsc += us;
322 }
323 
324 int
325 spdk_pci_addr_parse(struct spdk_pci_addr *addr, const char *bdf)
326 {
327 	unsigned domain, bus, dev, func;
328 
329 	if (addr == NULL || bdf == NULL) {
330 		return -EINVAL;
331 	}
332 
333 	if ((sscanf(bdf, "%x:%x:%x.%x", &domain, &bus, &dev, &func) == 4) ||
334 	    (sscanf(bdf, "%x.%x.%x.%x", &domain, &bus, &dev, &func) == 4)) {
335 		/* Matched a full address - all variables are initialized */
336 	} else if (sscanf(bdf, "%x:%x:%x", &domain, &bus, &dev) == 3) {
337 		func = 0;
338 	} else if ((sscanf(bdf, "%x:%x.%x", &bus, &dev, &func) == 3) ||
339 		   (sscanf(bdf, "%x.%x.%x", &bus, &dev, &func) == 3)) {
340 		domain = 0;
341 	} else if ((sscanf(bdf, "%x:%x", &bus, &dev) == 2) ||
342 		   (sscanf(bdf, "%x.%x", &bus, &dev) == 2)) {
343 		domain = 0;
344 		func = 0;
345 	} else {
346 		return -EINVAL;
347 	}
348 
349 	if (bus > 0xFF || dev > 0x1F || func > 7) {
350 		return -EINVAL;
351 	}
352 
353 	addr->domain = domain;
354 	addr->bus = bus;
355 	addr->dev = dev;
356 	addr->func = func;
357 
358 	return 0;
359 }
360 
361 int
362 spdk_pci_addr_fmt(char *bdf, size_t sz, const struct spdk_pci_addr *addr)
363 {
364 	int rc;
365 
366 	rc = snprintf(bdf, sz, "%04x:%02x:%02x.%x",
367 		      addr->domain, addr->bus,
368 		      addr->dev, addr->func);
369 
370 	if (rc > 0 && (size_t)rc < sz) {
371 		return 0;
372 	}
373 
374 	return -1;
375 }
376 
377 int
378 spdk_pci_addr_compare(const struct spdk_pci_addr *a1, const struct spdk_pci_addr *a2)
379 {
380 	if (a1->domain > a2->domain) {
381 		return 1;
382 	} else if (a1->domain < a2->domain) {
383 		return -1;
384 	} else if (a1->bus > a2->bus) {
385 		return 1;
386 	} else if (a1->bus < a2->bus) {
387 		return -1;
388 	} else if (a1->dev > a2->dev) {
389 		return 1;
390 	} else if (a1->dev < a2->dev) {
391 		return -1;
392 	} else if (a1->func > a2->func) {
393 		return 1;
394 	} else if (a1->func < a2->func) {
395 		return -1;
396 	}
397 
398 	return 0;
399 }
400