Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2019 6WIND S.A.
3 : : */
4 : :
5 : : #include <stdalign.h>
6 : : #include <sys/queue.h>
7 : : #include <stdint.h>
8 : : #include <limits.h>
9 : :
10 : : #include <eal_export.h>
11 : : #include <rte_common.h>
12 : : #include <rte_eal.h>
13 : : #include <rte_eal_memconfig.h>
14 : : #include <rte_tailq.h>
15 : : #include <rte_errno.h>
16 : : #include <rte_malloc.h>
17 : : #include <rte_string_fns.h>
18 : : #include <rte_bitops.h>
19 : : #include <rte_mbuf.h>
20 : : #include <rte_mbuf_dyn.h>
21 : :
22 : : #include "mbuf_log.h"
23 : :
24 : : #define RTE_MBUF_DYN_MZNAME "rte_mbuf_dyn"
25 : :
26 : : struct mbuf_dynfield_elt {
27 : : struct rte_mbuf_dynfield params;
28 : : size_t offset;
29 : : };
30 : : TAILQ_HEAD(mbuf_dynfield_list, rte_tailq_entry);
31 : :
32 : : static struct rte_tailq_elem mbuf_dynfield_tailq = {
33 : : .name = "RTE_MBUF_DYNFIELD",
34 : : };
35 [ - + ]: 252 : EAL_REGISTER_TAILQ(mbuf_dynfield_tailq);
36 : :
37 : : struct mbuf_dynflag_elt {
38 : : struct rte_mbuf_dynflag params;
39 : : unsigned int bitnum;
40 : : };
41 : : TAILQ_HEAD(mbuf_dynflag_list, rte_tailq_entry);
42 : :
43 : : static struct rte_tailq_elem mbuf_dynflag_tailq = {
44 : : .name = "RTE_MBUF_DYNFLAG",
45 : : };
46 [ - + ]: 252 : EAL_REGISTER_TAILQ(mbuf_dynflag_tailq);
47 : :
48 : : struct mbuf_dyn_shm {
49 : : /**
50 : : * For each mbuf byte, free_space[i] != 0 if space is free.
51 : : * The value is the size of the biggest aligned element that
52 : : * can fit in the zone.
53 : : */
54 : : uint8_t free_space[sizeof(struct rte_mbuf)];
55 : : /** Bitfield of available flags. */
56 : : uint64_t free_flags;
57 : : };
58 : : static struct mbuf_dyn_shm *shm;
59 : :
60 : : /* Set the value of free_space[] according to the size and alignment of
61 : : * the free areas. This helps to select the best place when reserving a
62 : : * dynamic field. Assume tailq is locked.
63 : : */
64 : : static void
65 : 14 : process_score(void)
66 : : {
67 : : size_t off, align, size, i;
68 : :
69 : : /* first, erase previous info */
70 [ + + ]: 1806 : for (i = 0; i < sizeof(struct rte_mbuf); i++) {
71 [ + + ]: 1792 : if (shm->free_space[i])
72 : 468 : shm->free_space[i] = 1;
73 : : }
74 : :
75 : : off = 0;
76 [ + + ]: 1370 : while (off < sizeof(struct rte_mbuf)) {
77 : : /* get the size of the free zone */
78 [ + + ]: 2212 : for (size = 0; (off + size) < sizeof(struct rte_mbuf) &&
79 [ + + ]: 2184 : shm->free_space[off + size]; size++)
80 : : ;
81 [ + + ]: 1356 : if (size == 0) {
82 : 1324 : off++;
83 : 1324 : continue;
84 : : }
85 : :
86 : : /* get the alignment of biggest object that can fit in
87 : : * the zone at this offset.
88 : : */
89 : : for (align = 1;
90 [ + + + - ]: 128 : (off % (align << 1)) == 0 && (align << 1) <= size;
91 : : align <<= 1)
92 : : ;
93 : :
94 : : /* save it in free_space[] */
95 [ + + ]: 500 : for (i = off; i < off + align; i++)
96 : 468 : shm->free_space[i] = RTE_MAX(align, shm->free_space[i]);
97 : :
98 : : off += align;
99 : : }
100 : 14 : }
101 : :
102 : : /* Mark the area occupied by a mbuf field as available in the shm. */
103 : : #define mark_free(field) \
104 : : memset(&shm->free_space[offsetof(struct rte_mbuf, field)], \
105 : : 1, sizeof(((struct rte_mbuf *)0)->field))
106 : :
107 : : /* Allocate and initialize the shared memory. Assume tailq is locked */
108 : : static int
109 : 6 : init_shared_mem(void)
110 : : {
111 : : const struct rte_memzone *mz;
112 : : uint64_t mask;
113 : :
114 [ + - ]: 6 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
115 : 6 : mz = rte_memzone_reserve_aligned(RTE_MBUF_DYN_MZNAME,
116 : : sizeof(struct mbuf_dyn_shm),
117 : : SOCKET_ID_ANY, 0,
118 : : RTE_CACHE_LINE_SIZE);
119 : : } else {
120 : 0 : mz = rte_memzone_lookup(RTE_MBUF_DYN_MZNAME);
121 : : }
122 [ - + ]: 6 : if (mz == NULL) {
123 : 0 : MBUF_LOG(ERR, "Failed to get mbuf dyn shared memory");
124 : 0 : return -1;
125 : : }
126 : :
127 : 6 : shm = mz->addr;
128 : :
129 [ + - ]: 6 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
130 : : /* init free_space, keep it sync'd with
131 : : * rte_mbuf_dynfield_copy().
132 : : */
133 : 6 : memset(shm, 0, sizeof(*shm));
134 : 6 : mark_free(dynfield1);
135 : : #if !RTE_IOVA_IN_MBUF
136 : : mark_free(dynfield2);
137 : : #endif
138 : :
139 : : /* init free_flags */
140 [ + + ]: 114 : for (mask = RTE_MBUF_F_FIRST_FREE; mask <= RTE_MBUF_F_LAST_FREE; mask <<= 1)
141 : 108 : shm->free_flags |= mask;
142 : :
143 : 6 : process_score();
144 : : }
145 : :
146 : : return 0;
147 : : }
148 : :
149 : : /* check if this offset can be used */
150 : : static int
151 : : check_offset(size_t offset, size_t size, size_t align)
152 : : {
153 : : size_t i;
154 : :
155 : 897 : if ((offset & (align - 1)) != 0)
156 : : return -1;
157 [ + - + - ]: 321 : if (offset + size > sizeof(struct rte_mbuf))
158 : : return -1;
159 : :
160 [ + + + + ]: 564 : for (i = 0; i < size; i++) {
161 [ + + + - ]: 475 : if (!shm->free_space[i + offset])
162 : : return -1;
163 : : }
164 : :
165 : : return 0;
166 : : }
167 : :
168 : : /* assume tailq is locked */
169 : : static struct mbuf_dynfield_elt *
170 : 15 : __mbuf_dynfield_lookup(const char *name)
171 : : {
172 : : struct mbuf_dynfield_list *mbuf_dynfield_list;
173 : : struct mbuf_dynfield_elt *mbuf_dynfield;
174 : : struct rte_tailq_entry *te;
175 : :
176 : 15 : mbuf_dynfield_list = RTE_TAILQ_CAST(
177 : : mbuf_dynfield_tailq.head, mbuf_dynfield_list);
178 : :
179 [ + + ]: 18 : TAILQ_FOREACH(te, mbuf_dynfield_list, next) {
180 : 10 : mbuf_dynfield = (struct mbuf_dynfield_elt *)te->data;
181 [ + + ]: 10 : if (strcmp(name, mbuf_dynfield->params.name) == 0)
182 : : break;
183 : : }
184 : :
185 [ + + ]: 15 : if (te == NULL || mbuf_dynfield == NULL) {
186 : 8 : rte_errno = ENOENT;
187 : 8 : return NULL;
188 : : }
189 : :
190 : : return mbuf_dynfield;
191 : : }
192 : :
193 : : RTE_EXPORT_SYMBOL(rte_mbuf_dynfield_lookup)
194 : : int
195 : 0 : rte_mbuf_dynfield_lookup(const char *name, struct rte_mbuf_dynfield *params)
196 : : {
197 : : struct mbuf_dynfield_elt *mbuf_dynfield;
198 : :
199 : 0 : rte_mcfg_tailq_read_lock();
200 [ # # # # ]: 0 : if (shm == NULL && init_shared_mem() < 0)
201 : : mbuf_dynfield = NULL;
202 : : else
203 : 0 : mbuf_dynfield = __mbuf_dynfield_lookup(name);
204 : 0 : rte_mcfg_tailq_read_unlock();
205 : :
206 [ # # ]: 0 : if (mbuf_dynfield == NULL)
207 : 0 : return -1;
208 : :
209 [ # # ]: 0 : if (params != NULL)
210 : 0 : memcpy(params, &mbuf_dynfield->params, sizeof(*params));
211 : :
212 : 0 : return mbuf_dynfield->offset;
213 : : }
214 : :
215 : 7 : static int mbuf_dynfield_cmp(const struct rte_mbuf_dynfield *params1,
216 : : const struct rte_mbuf_dynfield *params2)
217 : : {
218 [ + - ]: 7 : if (strcmp(params1->name, params2->name))
219 : : return -1;
220 [ + - ]: 7 : if (params1->size != params2->size)
221 : : return -1;
222 [ + - ]: 7 : if (params1->align != params2->align)
223 : : return -1;
224 [ - + ]: 7 : if (params1->flags != params2->flags)
225 : 0 : return -1;
226 : : return 0;
227 : : }
228 : :
229 : : /* assume tailq is locked */
230 : : static int
231 : 15 : __rte_mbuf_dynfield_register_offset(const struct rte_mbuf_dynfield *params,
232 : : size_t req)
233 : : {
234 : : struct mbuf_dynfield_list *mbuf_dynfield_list;
235 : : struct mbuf_dynfield_elt *mbuf_dynfield = NULL;
236 : : struct rte_tailq_entry *te = NULL;
237 : : unsigned int best_zone = UINT_MAX;
238 : : size_t i, offset;
239 : : int ret;
240 : :
241 [ + + + - ]: 15 : if (shm == NULL && init_shared_mem() < 0)
242 : : return -1;
243 : :
244 : 15 : mbuf_dynfield = __mbuf_dynfield_lookup(params->name);
245 [ + + ]: 15 : if (mbuf_dynfield != NULL) {
246 [ - + - - ]: 7 : if (req != SIZE_MAX && req != mbuf_dynfield->offset) {
247 : 0 : rte_errno = EEXIST;
248 : 0 : return -1;
249 : : }
250 [ - + ]: 7 : if (mbuf_dynfield_cmp(params, &mbuf_dynfield->params) < 0) {
251 : 0 : rte_errno = EEXIST;
252 : 0 : return -1;
253 : : }
254 : 7 : return mbuf_dynfield->offset;
255 : : }
256 : :
257 [ - + ]: 8 : if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
258 : 0 : rte_errno = EPERM;
259 : 0 : return -1;
260 : : }
261 : :
262 [ + + ]: 8 : if (req == SIZE_MAX) {
263 : : /* Find the best place to put this field: we search the
264 : : * lowest value of shm->free_space[offset]: the zones
265 : : * containing room for larger fields are kept for later.
266 : : */
267 : : for (offset = 0;
268 [ + + ]: 903 : offset < sizeof(struct rte_mbuf);
269 : 896 : offset++) {
270 [ + + ]: 320 : if (check_offset(offset, params->size,
271 [ + + ]: 896 : params->align) == 0 &&
272 [ + + ]: 88 : shm->free_space[offset] < best_zone) {
273 : : best_zone = shm->free_space[offset];
274 : : req = offset;
275 : : }
276 : : }
277 [ - + ]: 7 : if (req == SIZE_MAX) {
278 : 0 : rte_errno = ENOENT;
279 : 0 : return -1;
280 : : }
281 : : } else {
282 [ + - - + ]: 2 : if (check_offset(req, params->size, params->align) < 0) {
283 : 0 : rte_errno = EBUSY;
284 : 0 : return -1;
285 : : }
286 : : }
287 : :
288 : : offset = req;
289 : 8 : mbuf_dynfield_list = RTE_TAILQ_CAST(
290 : : mbuf_dynfield_tailq.head, mbuf_dynfield_list);
291 : :
292 : 8 : te = rte_zmalloc("MBUF_DYNFIELD_TAILQ_ENTRY", sizeof(*te), 0);
293 [ - + ]: 8 : if (te == NULL) {
294 : 0 : rte_errno = ENOMEM;
295 : 0 : return -1;
296 : : }
297 : :
298 : 8 : mbuf_dynfield = rte_zmalloc("mbuf_dynfield", sizeof(*mbuf_dynfield), 0);
299 [ - + ]: 8 : if (mbuf_dynfield == NULL) {
300 : 0 : rte_free(te);
301 : 0 : rte_errno = ENOMEM;
302 : 0 : return -1;
303 : : }
304 : :
305 [ - + ]: 8 : ret = strlcpy(mbuf_dynfield->params.name, params->name,
306 : : sizeof(mbuf_dynfield->params.name));
307 [ - + ]: 8 : if (ret < 0 || ret >= (int)sizeof(mbuf_dynfield->params.name)) {
308 : 0 : rte_errno = ENAMETOOLONG;
309 : 0 : rte_free(mbuf_dynfield);
310 : 0 : rte_free(te);
311 : 0 : return -1;
312 : : }
313 : 8 : memcpy(&mbuf_dynfield->params, params, sizeof(mbuf_dynfield->params));
314 : 8 : mbuf_dynfield->offset = offset;
315 : 8 : te->data = mbuf_dynfield;
316 : :
317 : 8 : TAILQ_INSERT_TAIL(mbuf_dynfield_list, te, next);
318 : :
319 [ + + ]: 40 : for (i = offset; i < offset + params->size; i++)
320 : 32 : shm->free_space[i] = 0;
321 : 8 : process_score();
322 : :
323 : 8 : MBUF_LOG(DEBUG, "Registered dynamic field %s (sz=%zu, al=%zu, fl=0x%x) -> %zd",
324 : : params->name, params->size, params->align, params->flags,
325 : : offset);
326 : :
327 : 8 : return offset;
328 : : }
329 : :
330 : : RTE_EXPORT_SYMBOL(rte_mbuf_dynfield_register_offset)
331 : : int
332 : 19 : rte_mbuf_dynfield_register_offset(const struct rte_mbuf_dynfield *params,
333 : : size_t req)
334 : : {
335 : : int ret;
336 : :
337 [ + + ]: 19 : if (params->size >= sizeof(struct rte_mbuf)) {
338 : 1 : rte_errno = EINVAL;
339 : 1 : return -1;
340 : : }
341 [ + - ]: 18 : if (!rte_is_power_of_2(params->align)) {
342 : 2 : rte_errno = EINVAL;
343 : 2 : return -1;
344 : : }
345 [ + + ]: 16 : if (params->flags != 0) {
346 : 1 : rte_errno = EINVAL;
347 : 1 : return -1;
348 : : }
349 : :
350 : 15 : rte_mcfg_tailq_write_lock();
351 : 15 : ret = __rte_mbuf_dynfield_register_offset(params, req);
352 : 15 : rte_mcfg_tailq_write_unlock();
353 : :
354 : 15 : return ret;
355 : : }
356 : :
357 : : RTE_EXPORT_SYMBOL(rte_mbuf_dynfield_register)
358 : : int
359 : 17 : rte_mbuf_dynfield_register(const struct rte_mbuf_dynfield *params)
360 : : {
361 : 17 : return rte_mbuf_dynfield_register_offset(params, SIZE_MAX);
362 : : }
363 : :
364 : : /* assume tailq is locked */
365 : : static struct mbuf_dynflag_elt *
366 : 5 : __mbuf_dynflag_lookup(const char *name)
367 : : {
368 : : struct mbuf_dynflag_list *mbuf_dynflag_list;
369 : : struct mbuf_dynflag_elt *mbuf_dynflag;
370 : : struct rte_tailq_entry *te;
371 : :
372 : 5 : mbuf_dynflag_list = RTE_TAILQ_CAST(
373 : : mbuf_dynflag_tailq.head, mbuf_dynflag_list);
374 : :
375 [ + + ]: 8 : TAILQ_FOREACH(te, mbuf_dynflag_list, next) {
376 : 4 : mbuf_dynflag = (struct mbuf_dynflag_elt *)te->data;
377 [ + + ]: 4 : if (strncmp(name, mbuf_dynflag->params.name,
378 : : RTE_MBUF_DYN_NAMESIZE) == 0)
379 : : break;
380 : : }
381 : :
382 [ + + ]: 5 : if (te == NULL) {
383 : 4 : rte_errno = ENOENT;
384 : 4 : return NULL;
385 : : }
386 : :
387 : : return mbuf_dynflag;
388 : : }
389 : :
390 : : RTE_EXPORT_SYMBOL(rte_mbuf_dynflag_lookup)
391 : : int
392 : 0 : rte_mbuf_dynflag_lookup(const char *name,
393 : : struct rte_mbuf_dynflag *params)
394 : : {
395 : : struct mbuf_dynflag_elt *mbuf_dynflag;
396 : :
397 : 0 : rte_mcfg_tailq_read_lock();
398 [ # # # # ]: 0 : if (shm == NULL && init_shared_mem() < 0)
399 : : mbuf_dynflag = NULL;
400 : : else
401 : 0 : mbuf_dynflag = __mbuf_dynflag_lookup(name);
402 : 0 : rte_mcfg_tailq_read_unlock();
403 : :
404 [ # # ]: 0 : if (mbuf_dynflag == NULL)
405 : 0 : return -1;
406 : :
407 [ # # ]: 0 : if (params != NULL)
408 : 0 : memcpy(params, &mbuf_dynflag->params, sizeof(*params));
409 : :
410 : 0 : return mbuf_dynflag->bitnum;
411 : : }
412 : :
413 : : static int mbuf_dynflag_cmp(const struct rte_mbuf_dynflag *params1,
414 : : const struct rte_mbuf_dynflag *params2)
415 : : {
416 [ + - ]: 1 : if (strcmp(params1->name, params2->name))
417 : : return -1;
418 [ + - ]: 1 : if (params1->flags != params2->flags)
419 : : return -1;
420 : : return 0;
421 : : }
422 : :
423 : : /* assume tailq is locked */
424 : : static int
425 : 5 : __rte_mbuf_dynflag_register_bitnum(const struct rte_mbuf_dynflag *params,
426 : : unsigned int req)
427 : : {
428 : : struct mbuf_dynflag_list *mbuf_dynflag_list;
429 : : struct mbuf_dynflag_elt *mbuf_dynflag = NULL;
430 : : struct rte_tailq_entry *te = NULL;
431 : : unsigned int bitnum;
432 : : int ret;
433 : :
434 [ - + - - ]: 5 : if (shm == NULL && init_shared_mem() < 0)
435 : : return -1;
436 : :
437 : 5 : mbuf_dynflag = __mbuf_dynflag_lookup(params->name);
438 [ + + ]: 5 : if (mbuf_dynflag != NULL) {
439 [ - + - - ]: 1 : if (req != UINT_MAX && req != mbuf_dynflag->bitnum) {
440 : 0 : rte_errno = EEXIST;
441 : 0 : return -1;
442 : : }
443 : : if (mbuf_dynflag_cmp(params, &mbuf_dynflag->params) < 0) {
444 : 0 : rte_errno = EEXIST;
445 : 0 : return -1;
446 : : }
447 : 1 : return mbuf_dynflag->bitnum;
448 : : }
449 : :
450 [ - + ]: 4 : if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
451 : 0 : rte_errno = EPERM;
452 : 0 : return -1;
453 : : }
454 : :
455 [ + + ]: 4 : if (req == UINT_MAX) {
456 [ - + ]: 3 : if (shm->free_flags == 0) {
457 : 0 : rte_errno = ENOENT;
458 : 0 : return -1;
459 : : }
460 : : bitnum = rte_bsf64(shm->free_flags);
461 : : } else {
462 [ - + ]: 1 : if ((shm->free_flags & (1ULL << req)) == 0) {
463 : 0 : rte_errno = EBUSY;
464 : 0 : return -1;
465 : : }
466 : : bitnum = req;
467 : : }
468 : :
469 : 4 : mbuf_dynflag_list = RTE_TAILQ_CAST(
470 : : mbuf_dynflag_tailq.head, mbuf_dynflag_list);
471 : :
472 : 4 : te = rte_zmalloc("MBUF_DYNFLAG_TAILQ_ENTRY", sizeof(*te), 0);
473 [ - + ]: 4 : if (te == NULL) {
474 : 0 : rte_errno = ENOMEM;
475 : 0 : return -1;
476 : : }
477 : :
478 : 4 : mbuf_dynflag = rte_zmalloc("mbuf_dynflag", sizeof(*mbuf_dynflag), 0);
479 [ - + ]: 4 : if (mbuf_dynflag == NULL) {
480 : 0 : rte_free(te);
481 : 0 : rte_errno = ENOMEM;
482 : 0 : return -1;
483 : : }
484 : :
485 [ - + ]: 4 : ret = strlcpy(mbuf_dynflag->params.name, params->name,
486 : : sizeof(mbuf_dynflag->params.name));
487 [ - + ]: 4 : if (ret < 0 || ret >= (int)sizeof(mbuf_dynflag->params.name)) {
488 : 0 : rte_free(mbuf_dynflag);
489 : 0 : rte_free(te);
490 : 0 : rte_errno = ENAMETOOLONG;
491 : 0 : return -1;
492 : : }
493 : 4 : mbuf_dynflag->bitnum = bitnum;
494 : 4 : te->data = mbuf_dynflag;
495 : :
496 : 4 : TAILQ_INSERT_TAIL(mbuf_dynflag_list, te, next);
497 : :
498 : 4 : shm->free_flags &= ~(1ULL << bitnum);
499 : :
500 : 4 : MBUF_LOG(DEBUG, "Registered dynamic flag %s (fl=0x%x) -> %u",
501 : : params->name, params->flags, bitnum);
502 : :
503 : 4 : return bitnum;
504 : : }
505 : :
506 : : RTE_EXPORT_SYMBOL(rte_mbuf_dynflag_register_bitnum)
507 : : int
508 : 6 : rte_mbuf_dynflag_register_bitnum(const struct rte_mbuf_dynflag *params,
509 : : unsigned int req)
510 : : {
511 : : int ret;
512 : :
513 [ + + ]: 6 : if (params->flags != 0) {
514 : 1 : rte_errno = EINVAL;
515 : 1 : return -1;
516 : : }
517 [ - + ]: 5 : if (req >= RTE_SIZEOF_FIELD(struct rte_mbuf, ol_flags) * CHAR_BIT &&
518 : : req != UINT_MAX) {
519 : 0 : rte_errno = EINVAL;
520 : 0 : return -1;
521 : : }
522 : :
523 : 5 : rte_mcfg_tailq_write_lock();
524 : 5 : ret = __rte_mbuf_dynflag_register_bitnum(params, req);
525 : 5 : rte_mcfg_tailq_write_unlock();
526 : :
527 : 5 : return ret;
528 : : }
529 : :
530 : : RTE_EXPORT_SYMBOL(rte_mbuf_dynflag_register)
531 : : int
532 : 5 : rte_mbuf_dynflag_register(const struct rte_mbuf_dynflag *params)
533 : : {
534 : 5 : return rte_mbuf_dynflag_register_bitnum(params, UINT_MAX);
535 : : }
536 : :
537 : : RTE_EXPORT_SYMBOL(rte_mbuf_dyn_dump)
538 : 2 : void rte_mbuf_dyn_dump(FILE *out)
539 : : {
540 : : struct mbuf_dynfield_list *mbuf_dynfield_list;
541 : : struct mbuf_dynfield_elt *dynfield;
542 : : struct mbuf_dynflag_list *mbuf_dynflag_list;
543 : : struct mbuf_dynflag_elt *dynflag;
544 : : struct rte_tailq_entry *te;
545 : : size_t i;
546 : :
547 : 2 : rte_mcfg_tailq_write_lock();
548 [ + + - + ]: 2 : if (shm == NULL && init_shared_mem() < 0) {
549 : 0 : rte_mcfg_tailq_write_unlock();
550 : 0 : return;
551 : : }
552 : :
553 : : fprintf(out, "Reserved fields:\n");
554 : 2 : mbuf_dynfield_list = RTE_TAILQ_CAST(
555 : : mbuf_dynfield_tailq.head, mbuf_dynfield_list);
556 [ + + ]: 5 : TAILQ_FOREACH(te, mbuf_dynfield_list, next) {
557 : 3 : dynfield = (struct mbuf_dynfield_elt *)te->data;
558 : 3 : fprintf(out, " name=%s offset=%zd size=%zd align=%zd flags=%x\n",
559 : 3 : dynfield->params.name, dynfield->offset,
560 : : dynfield->params.size, dynfield->params.align,
561 : : dynfield->params.flags);
562 : : }
563 : : fprintf(out, "Reserved flags:\n");
564 : 2 : mbuf_dynflag_list = RTE_TAILQ_CAST(
565 : : mbuf_dynflag_tailq.head, mbuf_dynflag_list);
566 [ + + ]: 5 : TAILQ_FOREACH(te, mbuf_dynflag_list, next) {
567 : 3 : dynflag = (struct mbuf_dynflag_elt *)te->data;
568 : 3 : fprintf(out, " name=%s bitnum=%u flags=%x\n",
569 : 3 : dynflag->params.name, dynflag->bitnum,
570 : : dynflag->params.flags);
571 : : }
572 : : fprintf(out, "Free space in mbuf (0 = occupied, value = free zone alignment):\n");
573 [ + + ]: 258 : for (i = 0; i < sizeof(struct rte_mbuf); i++) {
574 [ + + ]: 256 : if ((i % 8) == 0)
575 : : fprintf(out, " %4.4zx: ", i);
576 [ + + ]: 288 : fprintf(out, "%2.2x%s", shm->free_space[i],
577 : : (i % 8 != 7) ? " " : "\n");
578 : : }
579 : : fprintf(out, "Free bit in mbuf->ol_flags (0 = occupied, 1 = free):\n");
580 [ + + ]: 130 : for (i = 0; i < sizeof(uint64_t) * CHAR_BIT; i++) {
581 [ + + ]: 128 : if ((i % 8) == 0)
582 : : fprintf(out, " %4.4zx: ", i);
583 [ + + ]: 144 : fprintf(out, "%1.1x%s", (shm->free_flags & (1ULL << i)) ? 1 : 0,
584 : : (i % 8 != 7) ? " " : "\n");
585 : : }
586 : :
587 : 2 : rte_mcfg_tailq_write_unlock();
588 : : }
589 : :
590 : : static int
591 : 1 : rte_mbuf_dyn_timestamp_register(int *field_offset, uint64_t *flag,
592 : : const char *direction, const char *flag_name)
593 : : {
594 : : static const struct rte_mbuf_dynfield field_desc = {
595 : : .name = RTE_MBUF_DYNFIELD_TIMESTAMP_NAME,
596 : : .size = sizeof(rte_mbuf_timestamp_t),
597 : : .align = alignof(rte_mbuf_timestamp_t),
598 : : };
599 : 1 : struct rte_mbuf_dynflag flag_desc = {};
600 : : int offset;
601 : :
602 : 1 : offset = rte_mbuf_dynfield_register(&field_desc);
603 [ - + ]: 1 : if (offset < 0) {
604 : 0 : MBUF_LOG(ERR,
605 : : "Failed to register mbuf field for timestamp");
606 : 0 : return -1;
607 : : }
608 [ + - ]: 1 : if (field_offset != NULL)
609 : 1 : *field_offset = offset;
610 : :
611 : : strlcpy(flag_desc.name, flag_name, sizeof(flag_desc.name));
612 : 1 : offset = rte_mbuf_dynflag_register(&flag_desc);
613 [ - + ]: 1 : if (offset < 0) {
614 : 0 : MBUF_LOG(ERR,
615 : : "Failed to register mbuf flag for %s timestamp",
616 : : direction);
617 : 0 : return -1;
618 : : }
619 [ + - ]: 1 : if (flag != NULL)
620 : 1 : *flag = RTE_BIT64(offset);
621 : :
622 : : return 0;
623 : : }
624 : :
625 : : RTE_EXPORT_SYMBOL(rte_mbuf_dyn_rx_timestamp_register)
626 : : int
627 : 1 : rte_mbuf_dyn_rx_timestamp_register(int *field_offset, uint64_t *rx_flag)
628 : : {
629 : 1 : return rte_mbuf_dyn_timestamp_register(field_offset, rx_flag,
630 : : "Rx", RTE_MBUF_DYNFLAG_RX_TIMESTAMP_NAME);
631 : : }
632 : :
633 : : RTE_EXPORT_SYMBOL(rte_mbuf_dyn_tx_timestamp_register)
634 : : int
635 : 0 : rte_mbuf_dyn_tx_timestamp_register(int *field_offset, uint64_t *tx_flag)
636 : : {
637 : 0 : return rte_mbuf_dyn_timestamp_register(field_offset, tx_flag,
638 : : "Tx", RTE_MBUF_DYNFLAG_TX_TIMESTAMP_NAME);
639 : : }
|