xref: /spdk/test/common/lib/test_env.c (revision c899854d0371a7cdb3e2fd8c07ccf3d1f0b8089a)
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 DEFINE_STUB(spdk_process_is_primary, bool, (void), true)
42 DEFINE_STUB(spdk_memzone_lookup, void *, (const char *name), NULL)
43 
44 /*
45  * These mocks don't use the DEFINE_STUB macros because
46  * their default implementation is more complex.
47  */
48 
49 DEFINE_RETURN_MOCK(spdk_memzone_reserve, void *);
50 void *
51 spdk_memzone_reserve(const char *name, size_t len, int socket_id, unsigned flags)
52 {
53 	HANDLE_RETURN_MOCK(spdk_memzone_reserve);
54 
55 	return malloc(len);
56 }
57 
58 DEFINE_RETURN_MOCK(spdk_memzone_reserve_aligned, void *);
59 void *
60 spdk_memzone_reserve_aligned(const char *name, size_t len, int socket_id,
61 			     unsigned flags, unsigned align)
62 {
63 	HANDLE_RETURN_MOCK(spdk_memzone_reserve_aligned);
64 
65 	return malloc(len);
66 }
67 
68 DEFINE_RETURN_MOCK(spdk_dma_malloc, void *);
69 void *
70 spdk_dma_malloc(size_t size, size_t align, uint64_t *phys_addr)
71 {
72 	HANDLE_RETURN_MOCK(spdk_dma_malloc);
73 
74 	void *buf = NULL;
75 	if (posix_memalign(&buf, align, size)) {
76 		return NULL;
77 	}
78 	if (phys_addr) {
79 		*phys_addr = (uint64_t)buf;
80 	}
81 
82 	return buf;
83 }
84 
85 DEFINE_RETURN_MOCK(spdk_dma_zmalloc, void *);
86 void *
87 spdk_dma_zmalloc(size_t size, size_t align, uint64_t *phys_addr)
88 {
89 	HANDLE_RETURN_MOCK(spdk_dma_zmalloc);
90 
91 	void *buf = spdk_dma_malloc(size, align, phys_addr);
92 
93 	if (buf != NULL) {
94 		memset(buf, 0, size);
95 	}
96 	return buf;
97 }
98 
99 DEFINE_RETURN_MOCK(spdk_dma_malloc_socket, void *);
100 void *
101 spdk_dma_malloc_socket(size_t size, size_t align, uint64_t *phys_addr, int socket_id)
102 {
103 	HANDLE_RETURN_MOCK(spdk_dma_malloc_socket);
104 
105 	return spdk_dma_malloc(size, align, phys_addr);
106 }
107 
108 DEFINE_RETURN_MOCK(spdk_dma_zmalloc_socket, void *);
109 void *
110 spdk_dma_zmalloc_socket(size_t size, size_t align, uint64_t *phys_addr, int socket_id)
111 {
112 	HANDLE_RETURN_MOCK(spdk_dma_zmalloc_socket);
113 
114 	return spdk_dma_zmalloc(size, align, phys_addr);
115 }
116 
117 DEFINE_RETURN_MOCK(spdk_dma_realloc, void *);
118 void *
119 spdk_dma_realloc(void *buf, size_t size, size_t align, uint64_t *phys_addr)
120 {
121 	HANDLE_RETURN_MOCK(spdk_dma_realloc);
122 
123 	return realloc(buf, size);
124 }
125 
126 void
127 spdk_dma_free(void *buf)
128 {
129 	free(buf);
130 }
131 
132 DEFINE_RETURN_MOCK(spdk_vtophys, uint64_t);
133 uint64_t
134 spdk_vtophys(void *buf)
135 {
136 	HANDLE_RETURN_MOCK(spdk_vtophys);
137 
138 	return (uintptr_t)buf;
139 }
140 
141 void
142 spdk_memzone_dump(FILE *f)
143 {
144 	return;
145 }
146 
147 DEFINE_RETURN_MOCK(spdk_memzone_free, int);
148 int
149 spdk_memzone_free(const char *name)
150 {
151 	HANDLE_RETURN_MOCK(spdk_memzone_free);
152 
153 	return 0;
154 }
155 
156 struct test_mempool {
157 	size_t	count;
158 };
159 
160 DEFINE_RETURN_MOCK(spdk_mempool_create, struct spdk_mempool *);
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 	HANDLE_RETURN_MOCK(spdk_mempool_create);
168 
169 	mp = calloc(1, sizeof(*mp));
170 	if (mp == NULL) {
171 		return NULL;
172 	}
173 
174 	mp->count = count;
175 
176 	return (struct spdk_mempool *)mp;
177 }
178 
179 void
180 spdk_mempool_free(struct spdk_mempool *_mp)
181 {
182 	struct test_mempool *mp = (struct test_mempool *)_mp;
183 
184 	free(mp);
185 }
186 
187 DEFINE_RETURN_MOCK(spdk_mempool_get, void *);
188 void *
189 spdk_mempool_get(struct spdk_mempool *_mp)
190 {
191 	struct test_mempool *mp = (struct test_mempool *)_mp;
192 	void *buf;
193 
194 	HANDLE_RETURN_MOCK(spdk_mempool_get);
195 
196 	if (mp && mp->count == 0) {
197 		return NULL;
198 	}
199 
200 	if (posix_memalign(&buf, 64, 0x1000)) {
201 		return NULL;
202 	} else {
203 		if (mp) {
204 			mp->count--;
205 		}
206 		return buf;
207 	}
208 }
209 
210 int
211 spdk_mempool_get_bulk(struct spdk_mempool *mp, void **ele_arr, size_t count)
212 {
213 	for (size_t i = 0; i < count; i++) {
214 		ele_arr[i] = spdk_mempool_get(mp);
215 		if (ele_arr[i] == NULL) {
216 			return -1;
217 		}
218 	}
219 	return 0;
220 }
221 
222 void
223 spdk_mempool_put(struct spdk_mempool *_mp, void *ele)
224 {
225 	struct test_mempool *mp = (struct test_mempool *)_mp;
226 
227 	if (mp) {
228 		mp->count++;
229 	}
230 	free(ele);
231 }
232 
233 void
234 spdk_mempool_put_bulk(struct spdk_mempool *mp, void **ele_arr, size_t count)
235 {
236 	for (size_t i = 0; i < count; i++) {
237 		spdk_mempool_put(mp, ele_arr[i]);
238 	}
239 }
240 
241 DEFINE_RETURN_MOCK(spdk_mempool_count, size_t);
242 size_t
243 spdk_mempool_count(const struct spdk_mempool *_mp)
244 {
245 	struct test_mempool *mp = (struct test_mempool *)_mp;
246 
247 	HANDLE_RETURN_MOCK(spdk_mempool_count);
248 
249 	if (mp) {
250 		return mp->count;
251 	} else {
252 		return 1024;
253 	}
254 }
255 
256 struct spdk_ring_ele {
257 	void *ele;
258 	TAILQ_ENTRY(spdk_ring_ele) link;
259 };
260 
261 struct spdk_ring {
262 	TAILQ_HEAD(, spdk_ring_ele) elements;
263 };
264 
265 DEFINE_RETURN_MOCK(spdk_ring_create, struct spdk_ring *);
266 struct spdk_ring *
267 spdk_ring_create(enum spdk_ring_type type, size_t count, int socket_id)
268 {
269 	struct spdk_ring *ring;
270 
271 	HANDLE_RETURN_MOCK(spdk_ring_create);
272 
273 	ring = calloc(1, sizeof(*ring));
274 	if (ring) {
275 		TAILQ_INIT(&ring->elements);
276 	}
277 
278 	return ring;
279 }
280 
281 void
282 spdk_ring_free(struct spdk_ring *ring)
283 {
284 	free(ring);
285 }
286 
287 DEFINE_RETURN_MOCK(spdk_ring_enqueue, size_t);
288 size_t
289 spdk_ring_enqueue(struct spdk_ring *ring, void **objs, size_t count)
290 {
291 	struct spdk_ring_ele *ele;
292 	size_t i;
293 
294 	HANDLE_RETURN_MOCK(spdk_ring_enqueue);
295 
296 	for (i = 0; i < count; i++) {
297 		ele = calloc(1, sizeof(*ele));
298 		if (!ele) {
299 			break;
300 		}
301 
302 		ele->ele = objs[i];
303 		TAILQ_INSERT_TAIL(&ring->elements, ele, link);
304 	}
305 
306 	return i;
307 }
308 
309 DEFINE_RETURN_MOCK(spdk_ring_dequeue, size_t);
310 size_t
311 spdk_ring_dequeue(struct spdk_ring *ring, void **objs, size_t count)
312 {
313 	struct spdk_ring_ele *ele, *tmp;
314 	size_t i = 0;
315 
316 	HANDLE_RETURN_MOCK(spdk_ring_dequeue);
317 
318 	if (count == 0) {
319 		return 0;
320 	}
321 
322 	TAILQ_FOREACH_SAFE(ele, &ring->elements, link, tmp) {
323 		TAILQ_REMOVE(&ring->elements, ele, link);
324 		objs[i] = ele->ele;
325 		free(ele);
326 		i++;
327 		if (i >= count) {
328 			break;
329 		}
330 	}
331 
332 	return i;
333 
334 }
335 
336 DEFINE_RETURN_MOCK(spdk_get_ticks, uint64_t);
337 uint64_t
338 spdk_get_ticks(void)
339 {
340 	HANDLE_RETURN_MOCK(spdk_get_ticks);
341 
342 	return ut_spdk_get_ticks;
343 }
344 
345 DEFINE_RETURN_MOCK(spdk_get_ticks_hz, uint64_t);
346 uint64_t
347 spdk_get_ticks_hz(void)
348 {
349 	HANDLE_RETURN_MOCK(spdk_get_ticks_hz);
350 
351 	return 1000000;
352 }
353 
354 void
355 spdk_delay_us(unsigned int us)
356 {
357 	ut_spdk_get_ticks += us;
358 }
359 
360 DEFINE_RETURN_MOCK(spdk_pci_addr_parse, int);
361 int
362 spdk_pci_addr_parse(struct spdk_pci_addr *addr, const char *bdf)
363 {
364 	unsigned domain, bus, dev, func;
365 
366 	HANDLE_RETURN_MOCK(spdk_pci_addr_parse);
367 
368 	if (addr == NULL || bdf == NULL) {
369 		return -EINVAL;
370 	}
371 
372 	if ((sscanf(bdf, "%x:%x:%x.%x", &domain, &bus, &dev, &func) == 4) ||
373 	    (sscanf(bdf, "%x.%x.%x.%x", &domain, &bus, &dev, &func) == 4)) {
374 		/* Matched a full address - all variables are initialized */
375 	} else if (sscanf(bdf, "%x:%x:%x", &domain, &bus, &dev) == 3) {
376 		func = 0;
377 	} else if ((sscanf(bdf, "%x:%x.%x", &bus, &dev, &func) == 3) ||
378 		   (sscanf(bdf, "%x.%x.%x", &bus, &dev, &func) == 3)) {
379 		domain = 0;
380 	} else if ((sscanf(bdf, "%x:%x", &bus, &dev) == 2) ||
381 		   (sscanf(bdf, "%x.%x", &bus, &dev) == 2)) {
382 		domain = 0;
383 		func = 0;
384 	} else {
385 		return -EINVAL;
386 	}
387 
388 	if (bus > 0xFF || dev > 0x1F || func > 7) {
389 		return -EINVAL;
390 	}
391 
392 	addr->domain = domain;
393 	addr->bus = bus;
394 	addr->dev = dev;
395 	addr->func = func;
396 
397 	return 0;
398 }
399 
400 DEFINE_RETURN_MOCK(spdk_pci_addr_fmt, int);
401 int
402 spdk_pci_addr_fmt(char *bdf, size_t sz, const struct spdk_pci_addr *addr)
403 {
404 	int rc;
405 
406 	HANDLE_RETURN_MOCK(spdk_pci_addr_fmt);
407 
408 	rc = snprintf(bdf, sz, "%04x:%02x:%02x.%x",
409 		      addr->domain, addr->bus,
410 		      addr->dev, addr->func);
411 
412 	if (rc > 0 && (size_t)rc < sz) {
413 		return 0;
414 	}
415 
416 	return -1;
417 }
418 
419 DEFINE_RETURN_MOCK(spdk_pci_addr_compare, int);
420 int
421 spdk_pci_addr_compare(const struct spdk_pci_addr *a1, const struct spdk_pci_addr *a2)
422 {
423 	HANDLE_RETURN_MOCK(spdk_pci_addr_compare);
424 
425 	if (a1->domain > a2->domain) {
426 		return 1;
427 	} else if (a1->domain < a2->domain) {
428 		return -1;
429 	} else if (a1->bus > a2->bus) {
430 		return 1;
431 	} else if (a1->bus < a2->bus) {
432 		return -1;
433 	} else if (a1->dev > a2->dev) {
434 		return 1;
435 	} else if (a1->dev < a2->dev) {
436 		return -1;
437 	} else if (a1->func > a2->func) {
438 		return 1;
439 	} else if (a1->func < a2->func) {
440 		return -1;
441 	}
442 
443 	return 0;
444 }
445