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