Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation.
3 : : * Copyright 2014 6WIND S.A.
4 : : */
5 : :
6 : : #include <string.h>
7 : : #include <stdio.h>
8 : : #include <stdint.h>
9 : : #include <inttypes.h>
10 : : #include <errno.h>
11 : :
12 : : #include <eal_export.h>
13 : : #include <rte_debug.h>
14 : : #include <rte_common.h>
15 : : #include <rte_branch_prediction.h>
16 : : #include <rte_mempool.h>
17 : : #include <rte_mbuf.h>
18 : : #include <rte_mbuf_pool_ops.h>
19 : : #include <rte_hexdump.h>
20 : : #include <rte_errno.h>
21 : : #include <rte_memcpy.h>
22 : :
23 : : #include "mbuf_log.h"
24 : :
25 [ - + ]: 253 : RTE_LOG_REGISTER_DEFAULT(mbuf_logtype, INFO);
26 : :
27 : : /*
28 : : * pktmbuf pool constructor, given as a callback function to
29 : : * rte_mempool_create(), or called directly if using
30 : : * rte_mempool_create_empty()/rte_mempool_populate()
31 : : */
32 : : RTE_EXPORT_SYMBOL(rte_pktmbuf_pool_init)
33 : : void
34 : 24 : rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg)
35 : : {
36 : : struct rte_pktmbuf_pool_private *user_mbp_priv, *mbp_priv;
37 : : struct rte_pktmbuf_pool_private default_mbp_priv;
38 : : uint16_t roomsz;
39 : :
40 : : RTE_ASSERT(mp->private_data_size >=
41 : : sizeof(struct rte_pktmbuf_pool_private));
42 : : RTE_ASSERT(mp->elt_size >= sizeof(struct rte_mbuf));
43 : :
44 : 24 : rte_mbuf_history_init();
45 : :
46 : : /* if no structure is provided, assume no mbuf private area */
47 : : user_mbp_priv = opaque_arg;
48 [ - + ]: 24 : if (user_mbp_priv == NULL) {
49 : : memset(&default_mbp_priv, 0, sizeof(default_mbp_priv));
50 [ # # ]: 0 : if (mp->elt_size > sizeof(struct rte_mbuf))
51 : 0 : roomsz = mp->elt_size - sizeof(struct rte_mbuf);
52 : : else
53 : : roomsz = 0;
54 : 0 : default_mbp_priv.mbuf_data_room_size = roomsz;
55 : : user_mbp_priv = &default_mbp_priv;
56 : : }
57 : :
58 : : RTE_ASSERT(mp->elt_size >= sizeof(struct rte_mbuf) +
59 : : ((user_mbp_priv->flags & RTE_PKTMBUF_POOL_F_PINNED_EXT_BUF) ?
60 : : sizeof(struct rte_mbuf_ext_shared_info) :
61 : : user_mbp_priv->mbuf_data_room_size) +
62 : : user_mbp_priv->mbuf_priv_size);
63 : : RTE_ASSERT((user_mbp_priv->flags &
64 : : ~RTE_PKTMBUF_POOL_F_PINNED_EXT_BUF) == 0);
65 : :
66 : : mbp_priv = rte_mempool_get_priv(mp);
67 : : memcpy(mbp_priv, user_mbp_priv, sizeof(*mbp_priv));
68 : 24 : }
69 : :
70 : : /*
71 : : * pktmbuf constructor, given as a callback function to
72 : : * rte_mempool_obj_iter() or rte_mempool_create().
73 : : * Set the fields of a packet mbuf to their default values.
74 : : */
75 : : RTE_EXPORT_SYMBOL(rte_pktmbuf_init)
76 : : void
77 [ + + ]: 85602 : rte_pktmbuf_init(struct rte_mempool *mp,
78 : : __rte_unused void *opaque_arg,
79 : : void *_m,
80 : : __rte_unused unsigned i)
81 : : {
82 : : struct rte_mbuf *m = _m;
83 : : uint32_t mbuf_size, buf_len, priv_size;
84 : :
85 : : RTE_ASSERT(mp->private_data_size >=
86 : : sizeof(struct rte_pktmbuf_pool_private));
87 : :
88 : 85602 : priv_size = rte_pktmbuf_priv_size(mp);
89 : 85602 : mbuf_size = sizeof(struct rte_mbuf) + priv_size;
90 : : buf_len = rte_pktmbuf_data_room_size(mp);
91 : :
92 : : RTE_ASSERT(RTE_ALIGN(priv_size, RTE_MBUF_PRIV_ALIGN) == priv_size);
93 : : RTE_ASSERT(mp->elt_size >= mbuf_size);
94 : : RTE_ASSERT(buf_len <= UINT16_MAX);
95 : :
96 : 85602 : memset(m, 0, mbuf_size);
97 : : /* start of buffer is after mbuf structure and priv data */
98 : 85602 : m->priv_size = priv_size;
99 : 85602 : m->buf_addr = (char *)m + mbuf_size;
100 : 85602 : rte_mbuf_iova_set(m, rte_mempool_virt2iova(m) + mbuf_size);
101 : 85602 : m->buf_len = (uint16_t)buf_len;
102 : :
103 : : /* keep some headroom between start of buffer and data */
104 : 85602 : m->data_off = RTE_MIN(RTE_PKTMBUF_HEADROOM, (uint16_t)m->buf_len);
105 : :
106 : : /* init some constant fields */
107 : 85602 : m->pool = mp;
108 : 85602 : m->nb_segs = 1;
109 : 85602 : m->port = RTE_MBUF_PORT_INVALID;
110 : : rte_mbuf_refcnt_set(m, 1);
111 : 85602 : m->next = NULL;
112 : 85602 : }
113 : :
114 : : /*
115 : : * @internal The callback routine called when reference counter in shinfo
116 : : * for mbufs with pinned external buffer reaches zero. It means there is
117 : : * no more reference to buffer backing mbuf and this one should be freed.
118 : : * This routine is called for the regular (not with pinned external or
119 : : * indirect buffer) mbufs on detaching from the mbuf with pinned external
120 : : * buffer.
121 : : */
122 : : static void
123 : 2 : rte_pktmbuf_free_pinned_extmem(void *addr, void *opaque)
124 : : {
125 : : struct rte_mbuf *m = opaque;
126 : :
127 : : RTE_SET_USED(addr);
128 : : RTE_ASSERT(RTE_MBUF_HAS_EXTBUF(m));
129 : : RTE_ASSERT(RTE_MBUF_HAS_PINNED_EXTBUF(m));
130 : : RTE_ASSERT(m->shinfo->fcb_opaque == m);
131 : :
132 [ + + ]: 2 : rte_mbuf_ext_refcnt_set(m->shinfo, 1);
133 : 2 : m->ol_flags = RTE_MBUF_F_EXTERNAL;
134 [ + + ]: 2 : if (m->next != NULL)
135 : 1 : m->next = NULL;
136 [ + + ]: 2 : if (m->nb_segs != 1)
137 : 1 : m->nb_segs = 1;
138 : : rte_mbuf_raw_free(m);
139 : 2 : }
140 : :
141 : : /** The context to initialize the mbufs with pinned external buffers. */
142 : : struct rte_pktmbuf_extmem_init_ctx {
143 : : const struct rte_pktmbuf_extmem *ext_mem; /* descriptor array. */
144 : : unsigned int ext_num; /* number of descriptors in array. */
145 : : unsigned int ext; /* loop descriptor index. */
146 : : size_t off; /* loop buffer offset. */
147 : : };
148 : :
149 : : /**
150 : : * @internal Packet mbuf constructor for pools with pinned external memory.
151 : : *
152 : : * This function initializes some fields in the mbuf structure that are
153 : : * not modified by the user once created (origin pool, buffer start
154 : : * address, and so on). This function is given as a callback function to
155 : : * rte_mempool_obj_iter() called from rte_mempool_create_extmem().
156 : : *
157 : : * @param mp
158 : : * The mempool from which mbufs originate.
159 : : * @param opaque_arg
160 : : * A pointer to the rte_pktmbuf_extmem_init_ctx - initialization
161 : : * context structure
162 : : * @param m
163 : : * The mbuf to initialize.
164 : : * @param i
165 : : * The index of the mbuf in the pool table.
166 : : */
167 : : static void
168 [ + - ]: 128 : __rte_pktmbuf_init_extmem(struct rte_mempool *mp,
169 : : void *opaque_arg,
170 : : void *_m,
171 : : __rte_unused unsigned int i)
172 : : {
173 : : struct rte_mbuf *m = _m;
174 : : struct rte_pktmbuf_extmem_init_ctx *ctx = opaque_arg;
175 : : const struct rte_pktmbuf_extmem *ext_mem;
176 : : uint32_t mbuf_size, buf_len, priv_size;
177 : : struct rte_mbuf_ext_shared_info *shinfo;
178 : :
179 : 128 : priv_size = rte_pktmbuf_priv_size(mp);
180 [ + - ]: 128 : mbuf_size = sizeof(struct rte_mbuf) + priv_size;
181 : : buf_len = rte_pktmbuf_data_room_size(mp);
182 : :
183 : : RTE_ASSERT(RTE_ALIGN(priv_size, RTE_MBUF_PRIV_ALIGN) == priv_size);
184 : : RTE_ASSERT(mp->elt_size >= mbuf_size);
185 : : RTE_ASSERT(buf_len <= UINT16_MAX);
186 : :
187 [ + - ]: 128 : memset(m, 0, mbuf_size);
188 : 128 : m->priv_size = priv_size;
189 : 128 : m->buf_len = (uint16_t)buf_len;
190 : :
191 : : /* set the data buffer pointers to external memory */
192 : 128 : ext_mem = ctx->ext_mem + ctx->ext;
193 : :
194 : : RTE_ASSERT(ctx->ext < ctx->ext_num);
195 : : RTE_ASSERT(ctx->off + ext_mem->elt_size <= ext_mem->buf_len);
196 : :
197 : 128 : m->buf_addr = RTE_PTR_ADD(ext_mem->buf_ptr, ctx->off);
198 [ + - ]: 128 : rte_mbuf_iova_set(m, ext_mem->buf_iova == RTE_BAD_IOVA ? RTE_BAD_IOVA :
199 : : (ext_mem->buf_iova + ctx->off));
200 : :
201 : 128 : ctx->off += ext_mem->elt_size;
202 [ + + ]: 128 : if (ctx->off + ext_mem->elt_size > ext_mem->buf_len) {
203 : 1 : ctx->off = 0;
204 : 1 : ++ctx->ext;
205 : : }
206 : : /* keep some headroom between start of buffer and data */
207 : 128 : m->data_off = RTE_MIN(RTE_PKTMBUF_HEADROOM, (uint16_t)m->buf_len);
208 : :
209 : : /* init some constant fields */
210 : 128 : m->pool = mp;
211 : 128 : m->nb_segs = 1;
212 : 128 : m->port = RTE_MBUF_PORT_INVALID;
213 : 128 : m->ol_flags = RTE_MBUF_F_EXTERNAL;
214 : : rte_mbuf_refcnt_set(m, 1);
215 : 128 : m->next = NULL;
216 : :
217 : : /* init external buffer shared info items */
218 : 128 : shinfo = RTE_PTR_ADD(m, mbuf_size);
219 : 128 : m->shinfo = shinfo;
220 : 128 : shinfo->free_cb = rte_pktmbuf_free_pinned_extmem;
221 : 128 : shinfo->fcb_opaque = m;
222 : : rte_mbuf_ext_refcnt_set(shinfo, 1);
223 : 128 : }
224 : :
225 : : /* Helper to create a mbuf pool with given mempool ops name*/
226 : : RTE_EXPORT_SYMBOL(rte_pktmbuf_pool_create_by_ops)
227 : : struct rte_mempool *
228 : 23 : rte_pktmbuf_pool_create_by_ops(const char *name, unsigned int n,
229 : : unsigned int cache_size, uint16_t priv_size, uint16_t data_room_size,
230 : : int socket_id, const char *ops_name)
231 : : {
232 : : struct rte_mempool *mp;
233 : : struct rte_pktmbuf_pool_private mbp_priv;
234 : : const char *mp_ops_name = ops_name;
235 : : unsigned elt_size;
236 : : int ret;
237 : :
238 [ - + ]: 23 : if (RTE_ALIGN(priv_size, RTE_MBUF_PRIV_ALIGN) != priv_size) {
239 : 0 : MBUF_LOG(ERR, "mbuf priv_size=%u is not aligned",
240 : : priv_size);
241 : 0 : rte_errno = EINVAL;
242 : 0 : return NULL;
243 : : }
244 : 23 : elt_size = sizeof(struct rte_mbuf) + (unsigned)priv_size +
245 : : (unsigned)data_room_size;
246 : : memset(&mbp_priv, 0, sizeof(mbp_priv));
247 : 23 : mbp_priv.mbuf_data_room_size = data_room_size;
248 : 23 : mbp_priv.mbuf_priv_size = priv_size;
249 : :
250 : 23 : mp = rte_mempool_create_empty(name, n, elt_size, cache_size,
251 : : sizeof(struct rte_pktmbuf_pool_private), socket_id, 0);
252 [ + - ]: 23 : if (mp == NULL)
253 : : return NULL;
254 : :
255 [ + + ]: 23 : if (mp_ops_name == NULL)
256 : 22 : mp_ops_name = rte_mbuf_best_mempool_ops();
257 : 23 : ret = rte_mempool_set_ops_byname(mp, mp_ops_name, NULL);
258 [ - + ]: 23 : if (ret != 0) {
259 : 0 : MBUF_LOG(ERR, "error setting mempool handler");
260 : 0 : rte_mempool_free(mp);
261 : 0 : rte_errno = -ret;
262 : 0 : return NULL;
263 : : }
264 : 23 : rte_pktmbuf_pool_init(mp, &mbp_priv);
265 : :
266 : 23 : ret = rte_mempool_populate_default(mp);
267 [ - + ]: 23 : if (ret < 0) {
268 : 0 : rte_mempool_free(mp);
269 : 0 : rte_errno = -ret;
270 : 0 : return NULL;
271 : : }
272 : :
273 : 23 : rte_mempool_obj_iter(mp, rte_pktmbuf_init, NULL);
274 : :
275 : 23 : return mp;
276 : : }
277 : :
278 : : /* helper to create a mbuf pool */
279 : : RTE_EXPORT_SYMBOL(rte_pktmbuf_pool_create)
280 : : struct rte_mempool *
281 : 22 : rte_pktmbuf_pool_create(const char *name, unsigned int n,
282 : : unsigned int cache_size, uint16_t priv_size, uint16_t data_room_size,
283 : : int socket_id)
284 : : {
285 : 22 : return rte_pktmbuf_pool_create_by_ops(name, n, cache_size, priv_size,
286 : : data_room_size, socket_id, NULL);
287 : : }
288 : :
289 : : /* Helper to create a mbuf pool with pinned external data buffers. */
290 : : RTE_EXPORT_SYMBOL(rte_pktmbuf_pool_create_extbuf)
291 : : struct rte_mempool *
292 : 1 : rte_pktmbuf_pool_create_extbuf(const char *name, unsigned int n,
293 : : unsigned int cache_size, uint16_t priv_size,
294 : : uint16_t data_room_size, int socket_id,
295 : : const struct rte_pktmbuf_extmem *ext_mem,
296 : : unsigned int ext_num)
297 : : {
298 : : struct rte_mempool *mp;
299 : : struct rte_pktmbuf_pool_private mbp_priv;
300 : : struct rte_pktmbuf_extmem_init_ctx init_ctx;
301 : : const char *mp_ops_name;
302 : : unsigned int elt_size;
303 : : unsigned int i, n_elts = 0;
304 : : int ret;
305 : :
306 [ - + ]: 1 : if (RTE_ALIGN(priv_size, RTE_MBUF_PRIV_ALIGN) != priv_size) {
307 : 0 : MBUF_LOG(ERR, "mbuf priv_size=%u is not aligned",
308 : : priv_size);
309 : 0 : rte_errno = EINVAL;
310 : 0 : return NULL;
311 : : }
312 : : /* Check the external memory descriptors. */
313 [ + + ]: 2 : for (i = 0; i < ext_num; i++) {
314 : 1 : const struct rte_pktmbuf_extmem *extm = ext_mem + i;
315 : :
316 [ + - + - : 1 : if (!extm->elt_size || !extm->buf_len || !extm->buf_ptr) {
- + ]
317 : 0 : MBUF_LOG(ERR, "invalid extmem descriptor");
318 : 0 : rte_errno = EINVAL;
319 : 0 : return NULL;
320 : : }
321 [ - + ]: 1 : if (data_room_size > extm->elt_size) {
322 : 0 : MBUF_LOG(ERR, "ext elt_size=%u is too small",
323 : : priv_size);
324 : 0 : rte_errno = EINVAL;
325 : 0 : return NULL;
326 : : }
327 : 1 : n_elts += extm->buf_len / extm->elt_size;
328 : : }
329 : : /* Check whether enough external memory provided. */
330 [ - + ]: 1 : if (n_elts < n) {
331 : 0 : MBUF_LOG(ERR, "not enough extmem");
332 : 0 : rte_errno = ENOMEM;
333 : 0 : return NULL;
334 : : }
335 : 1 : elt_size = sizeof(struct rte_mbuf) +
336 : 1 : (unsigned int)priv_size +
337 : : sizeof(struct rte_mbuf_ext_shared_info);
338 : :
339 : : memset(&mbp_priv, 0, sizeof(mbp_priv));
340 : 1 : mbp_priv.mbuf_data_room_size = data_room_size;
341 : 1 : mbp_priv.mbuf_priv_size = priv_size;
342 : 1 : mbp_priv.flags = RTE_PKTMBUF_POOL_F_PINNED_EXT_BUF;
343 : :
344 : 1 : mp = rte_mempool_create_empty(name, n, elt_size, cache_size,
345 : : sizeof(struct rte_pktmbuf_pool_private), socket_id, 0);
346 [ + - ]: 1 : if (mp == NULL)
347 : : return NULL;
348 : :
349 : 1 : mp_ops_name = rte_mbuf_best_mempool_ops();
350 : 1 : ret = rte_mempool_set_ops_byname(mp, mp_ops_name, NULL);
351 [ - + ]: 1 : if (ret != 0) {
352 : 0 : MBUF_LOG(ERR, "error setting mempool handler");
353 : 0 : rte_mempool_free(mp);
354 : 0 : rte_errno = -ret;
355 : 0 : return NULL;
356 : : }
357 : 1 : rte_pktmbuf_pool_init(mp, &mbp_priv);
358 : :
359 : 1 : ret = rte_mempool_populate_default(mp);
360 [ - + ]: 1 : if (ret < 0) {
361 : 0 : rte_mempool_free(mp);
362 : 0 : rte_errno = -ret;
363 : 0 : return NULL;
364 : : }
365 : :
366 : 1 : init_ctx = (struct rte_pktmbuf_extmem_init_ctx){
367 : : .ext_mem = ext_mem,
368 : : .ext_num = ext_num,
369 : : .ext = 0,
370 : : .off = 0,
371 : : };
372 : 1 : rte_mempool_obj_iter(mp, __rte_pktmbuf_init_extmem, &init_ctx);
373 : :
374 : 1 : return mp;
375 : : }
376 : :
377 : : /* do some sanity checks on a reinitialized mbuf: panic if it fails */
378 : : RTE_EXPORT_SYMBOL(rte_mbuf_raw_sanity_check)
379 : : void
380 : 0 : rte_mbuf_raw_sanity_check(const struct rte_mbuf *m, const struct rte_mempool *mp)
381 : : {
382 : : const char *reason;
383 : :
384 [ # # ]: 0 : if (rte_mbuf_raw_check(m, mp, &reason))
385 : 0 : rte_panic("%s\n", reason);
386 : 0 : }
387 : :
388 : : RTE_EXPORT_SYMBOL(rte_mbuf_raw_check)
389 : 0 : int rte_mbuf_raw_check(const struct rte_mbuf *m, const struct rte_mempool *mp,
390 : : const char **reason)
391 : : {
392 : : /* check sanity */
393 [ # # ]: 0 : if (rte_mbuf_check(m, 0, reason) == -1)
394 : : return -1;
395 : :
396 : : /* check initialized */
397 [ # # ]: 0 : if (rte_mbuf_refcnt_read(m) != 1) {
398 : 0 : *reason = "uninitialized ref cnt";
399 : 0 : return -1;
400 : : }
401 [ # # ]: 0 : if (m->next != NULL) {
402 : 0 : *reason = "uninitialized next ptr";
403 : 0 : return -1;
404 : : }
405 [ # # ]: 0 : if (m->nb_segs != 1) {
406 : 0 : *reason = "uninitialized nb_segs";
407 : 0 : return -1;
408 : : }
409 [ # # ]: 0 : if (RTE_MBUF_CLONED(m)) {
410 : 0 : *reason = "cloned";
411 : 0 : return -1;
412 : : }
413 [ # # ]: 0 : if (RTE_MBUF_HAS_EXTBUF(m)) {
414 [ # # # # ]: 0 : if (!RTE_MBUF_HAS_PINNED_EXTBUF(m)) {
415 : 0 : *reason = "external buffer not pinned";
416 : 0 : return -1;
417 : : }
418 : :
419 [ # # ]: 0 : uint16_t cnt = rte_mbuf_ext_refcnt_read(m->shinfo);
420 [ # # ]: 0 : if ((cnt == 0) || (cnt == UINT16_MAX)) {
421 : 0 : *reason = "pinned external buffer bad ref cnt";
422 : 0 : return -1;
423 : : }
424 [ # # ]: 0 : if (cnt != 1) {
425 : 0 : *reason = "pinned external buffer uninitialized ref cnt";
426 : 0 : return -1;
427 : : }
428 : : }
429 : :
430 [ # # # # ]: 0 : if (mp != NULL && m->pool != mp) {
431 : 0 : *reason = "wrong mbuf pool";
432 : 0 : return -1;
433 : : }
434 : :
435 : : return 0;
436 : : }
437 : :
438 : : /* do some sanity checks on a mbuf: panic if it fails */
439 : : RTE_EXPORT_SYMBOL(rte_mbuf_sanity_check)
440 : : void
441 : 66 : rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header)
442 : : {
443 : : const char *reason;
444 : :
445 [ - + ]: 66 : if (rte_mbuf_check(m, is_header, &reason))
446 : 0 : rte_panic("%s\n", reason);
447 : 66 : }
448 : :
449 : : RTE_EXPORT_SYMBOL(rte_mbuf_check)
450 : 80 : int rte_mbuf_check(const struct rte_mbuf *m, int is_header,
451 : : const char **reason)
452 : : {
453 : : unsigned int nb_segs, pkt_len;
454 : :
455 [ + + ]: 80 : if (m == NULL) {
456 : 2 : *reason = "mbuf is NULL";
457 : 2 : return -1;
458 : : }
459 : :
460 : : /* generic checks */
461 [ + + ]: 78 : if (m->pool == NULL) {
462 : 2 : *reason = "bad mbuf pool";
463 : 2 : return -1;
464 : : }
465 [ + + ]: 76 : if (RTE_IOVA_IN_MBUF && rte_mbuf_iova_get(m) == 0) {
466 : 2 : *reason = "bad IO addr";
467 : 2 : return -1;
468 : : }
469 [ + + ]: 74 : if (m->buf_addr == NULL) {
470 : 2 : *reason = "bad virt addr";
471 : 2 : return -1;
472 : : }
473 : :
474 : : uint16_t cnt = rte_mbuf_refcnt_read(m);
475 [ + + ]: 72 : if ((cnt == 0) || (cnt == UINT16_MAX)) {
476 : 4 : *reason = "bad ref cnt";
477 : 4 : return -1;
478 : : }
479 : :
480 : : /* nothing to check for sub-segments */
481 [ + + ]: 68 : if (is_header == 0)
482 : : return 0;
483 : :
484 : : /* data_len is supposed to be not more than pkt_len */
485 [ - + ]: 4 : if (m->data_len > m->pkt_len) {
486 : 0 : *reason = "bad data_len";
487 : 0 : return -1;
488 : : }
489 : :
490 : 4 : nb_segs = m->nb_segs;
491 : : pkt_len = m->pkt_len;
492 : :
493 : : do {
494 [ - + ]: 4 : if (m->data_off > m->buf_len) {
495 : 0 : *reason = "data offset too big in mbuf segment";
496 : 0 : return -1;
497 : : }
498 [ - + ]: 4 : if (m->data_off + m->data_len > m->buf_len) {
499 : 0 : *reason = "data length too big in mbuf segment";
500 : 0 : return -1;
501 : : }
502 : 4 : nb_segs -= 1;
503 : 4 : pkt_len -= m->data_len;
504 [ - + ]: 4 : } while ((m = m->next) != NULL);
505 : :
506 [ - + ]: 4 : if (nb_segs) {
507 : 0 : *reason = "bad nb_segs";
508 : 0 : return -1;
509 : : }
510 [ - + ]: 4 : if (pkt_len) {
511 : 0 : *reason = "bad pkt_len";
512 : 0 : return -1;
513 : : }
514 : :
515 : : return 0;
516 : : }
517 : :
518 : : /**
519 : : * @internal helper function for freeing a bulk of packet mbuf segments
520 : : * via an array holding the packet mbuf segments from the same mempool
521 : : * pending to be freed.
522 : : *
523 : : * @param m
524 : : * The packet mbuf segment to be freed.
525 : : * @param pending
526 : : * Pointer to the array of packet mbuf segments pending to be freed.
527 : : * @param nb_pending
528 : : * Pointer to the number of elements held in the array.
529 : : * @param pending_sz
530 : : * Number of elements the array can hold.
531 : : * Note: The compiler should optimize this parameter away when using a
532 : : * constant value, such as RTE_PKTMBUF_FREE_PENDING_SZ.
533 : : */
534 : : static void
535 : 8842 : __rte_pktmbuf_free_seg_via_array(struct rte_mbuf *m,
536 : : struct rte_mbuf ** const pending, unsigned int * const nb_pending,
537 : : const unsigned int pending_sz)
538 : : {
539 : : m = rte_pktmbuf_prefree_seg(m);
540 [ + - ]: 8842 : if (likely(m != NULL)) {
541 [ + + + + ]: 8842 : if (*nb_pending == pending_sz ||
542 [ + + ]: 8640 : (*nb_pending > 0 && m->pool != pending[0]->pool)) {
543 [ - + ]: 126 : rte_mempool_put_bulk(pending[0]->pool,
544 : : (void **)pending, *nb_pending);
545 : 126 : *nb_pending = 0;
546 : : }
547 : :
548 : 8842 : pending[(*nb_pending)++] = m;
549 : : }
550 : 8842 : }
551 : :
552 : : /**
553 : : * Size of the array holding mbufs from the same mempool pending to be freed
554 : : * in bulk.
555 : : */
556 : : #define RTE_PKTMBUF_FREE_PENDING_SZ 64
557 : :
558 : : /* Free a bulk of packet mbufs back into their original mempools. */
559 : : RTE_EXPORT_SYMBOL(rte_pktmbuf_free_bulk)
560 : 138 : void rte_pktmbuf_free_bulk(struct rte_mbuf **mbufs, unsigned int count)
561 : : {
562 : : struct rte_mbuf *m, *m_next, *pending[RTE_PKTMBUF_FREE_PENDING_SZ];
563 : 138 : unsigned int idx, nb_pending = 0;
564 : :
565 : : rte_mbuf_history_mark_bulk(mbufs, count, RTE_MBUF_HISTORY_OP_LIB_FREE);
566 : :
567 [ + + ]: 4512 : for (idx = 0; idx < count; idx++) {
568 : 4374 : m = mbufs[idx];
569 [ - + ]: 4374 : if (unlikely(m == NULL))
570 : 0 : continue;
571 : :
572 : : __rte_mbuf_sanity_check(m, 1);
573 : :
574 : : do {
575 : 8842 : m_next = m->next;
576 : 8842 : __rte_pktmbuf_free_seg_via_array(m,
577 : : pending, &nb_pending,
578 : : RTE_PKTMBUF_FREE_PENDING_SZ);
579 : : m = m_next;
580 [ + + ]: 8842 : } while (m != NULL);
581 : : }
582 : :
583 [ + - ]: 138 : if (nb_pending > 0)
584 [ - + ]: 138 : rte_mempool_put_bulk(pending[0]->pool, (void **)pending, nb_pending);
585 : 138 : }
586 : :
587 : : /* Creates a shallow copy of mbuf */
588 : : RTE_EXPORT_SYMBOL(rte_pktmbuf_clone)
589 : : struct rte_mbuf *
590 : 13 : rte_pktmbuf_clone(struct rte_mbuf *md, struct rte_mempool *mp)
591 : : {
592 : : struct rte_mbuf *mc, *mi, **prev;
593 : : uint32_t pktlen;
594 : : uint16_t nseg;
595 : :
596 : 13 : mc = rte_pktmbuf_alloc(mp);
597 [ + + ]: 13 : if (unlikely(mc == NULL))
598 : : return NULL;
599 : :
600 : : mi = mc;
601 : 9 : prev = &mi->next;
602 : 9 : pktlen = md->pkt_len;
603 : : nseg = 0;
604 : :
605 : : do {
606 : 13 : nseg++;
607 : 13 : rte_pktmbuf_attach(mi, md);
608 : 13 : *prev = mi;
609 : 13 : prev = &mi->next;
610 [ + + + - ]: 17 : } while ((md = md->next) != NULL &&
611 : 4 : (mi = rte_pktmbuf_alloc(mp)) != NULL);
612 : :
613 : 9 : *prev = NULL;
614 : 9 : mc->nb_segs = nseg;
615 : 9 : mc->pkt_len = pktlen;
616 : :
617 : : /* Allocation of new indirect segment failed */
618 [ - + ]: 9 : if (unlikely(mi == NULL)) {
619 : 0 : rte_pktmbuf_free(mc);
620 : 0 : return NULL;
621 : : }
622 : :
623 : : __rte_mbuf_sanity_check(mc, 1);
624 : : return mc;
625 : : }
626 : :
627 : : /* convert multi-segment mbuf to single mbuf */
628 : : RTE_EXPORT_SYMBOL(__rte_pktmbuf_linearize)
629 : : int
630 : 8 : __rte_pktmbuf_linearize(struct rte_mbuf *mbuf)
631 : : {
632 : : size_t seg_len, copy_len;
633 : : struct rte_mbuf *m;
634 : : struct rte_mbuf *m_next;
635 : : char *buffer;
636 : :
637 : : /* Extend first segment to the total packet length */
638 [ + - ]: 8 : copy_len = rte_pktmbuf_pkt_len(mbuf) - rte_pktmbuf_data_len(mbuf);
639 : :
640 [ + - ]: 8 : if (unlikely(copy_len > rte_pktmbuf_tailroom(mbuf)))
641 : : return -1;
642 : :
643 : 8 : buffer = rte_pktmbuf_mtod_offset(mbuf, char *, mbuf->data_len);
644 : 8 : mbuf->data_len = (uint16_t)(mbuf->pkt_len);
645 : :
646 : : /* Append data from next segments to the first one */
647 : 8 : m = mbuf->next;
648 [ + + ]: 192 : while (m != NULL) {
649 : 184 : m_next = m->next;
650 : :
651 : 184 : seg_len = rte_pktmbuf_data_len(m);
652 [ + + ]: 184 : rte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), seg_len);
653 [ - + ]: 184 : buffer += seg_len;
654 : :
655 : : rte_pktmbuf_free_seg(m);
656 : : m = m_next;
657 : : }
658 : :
659 : 8 : mbuf->next = NULL;
660 : 8 : mbuf->nb_segs = 1;
661 : :
662 : 8 : return 0;
663 : : }
664 : :
665 : : /* Create a deep copy of mbuf */
666 : : RTE_EXPORT_SYMBOL(rte_pktmbuf_copy)
667 : : struct rte_mbuf *
668 : 4111 : rte_pktmbuf_copy(const struct rte_mbuf *m, struct rte_mempool *mp,
669 : : uint32_t off, uint32_t len)
670 : : {
671 : : const struct rte_mbuf *seg = m;
672 : : struct rte_mbuf *mc, *m_last, **prev;
673 : :
674 : : /* garbage in check */
675 : : __rte_mbuf_sanity_check(m, 1);
676 : :
677 : : /* check for request to copy at offset past end of mbuf */
678 [ + - ]: 4111 : if (unlikely(off >= m->pkt_len))
679 : : return NULL;
680 : :
681 : 4111 : mc = rte_pktmbuf_alloc(mp);
682 [ + - ]: 4111 : if (unlikely(mc == NULL))
683 : : return NULL;
684 : :
685 : : /* truncate requested length to available data */
686 : 4111 : if (len > m->pkt_len - off)
687 : : len = m->pkt_len - off;
688 : :
689 : 4111 : __rte_pktmbuf_copy_hdr(mc, m);
690 : :
691 : : /* copied mbuf is not indirect or external */
692 : 4111 : mc->ol_flags = m->ol_flags & ~(RTE_MBUF_F_INDIRECT|RTE_MBUF_F_EXTERNAL);
693 : :
694 : 4111 : prev = &mc->next;
695 : : m_last = mc;
696 [ + + ]: 20527 : while (len > 0) {
697 : : uint32_t copy_len;
698 : :
699 : : /* skip leading mbuf segments */
700 [ + + ]: 24620 : while (off >= seg->data_len) {
701 : 8204 : off -= seg->data_len;
702 : 8204 : seg = seg->next;
703 : : }
704 : :
705 : : /* current buffer is full, chain a new one */
706 [ + + ]: 16416 : if (rte_pktmbuf_tailroom(m_last) == 0) {
707 : 4101 : m_last = rte_pktmbuf_alloc(mp);
708 [ - + ]: 4101 : if (unlikely(m_last == NULL)) {
709 : 0 : rte_pktmbuf_free(mc);
710 : 0 : return NULL;
711 : : }
712 : 4101 : ++mc->nb_segs;
713 : 4101 : *prev = m_last;
714 : 4101 : prev = &m_last->next;
715 : : }
716 : :
717 : : /*
718 : : * copy the min of data in input segment (seg)
719 : : * vs space available in output (m_last)
720 : : */
721 [ + + ]: 16416 : copy_len = RTE_MIN(seg->data_len - off, len);
722 : 16416 : if (copy_len > rte_pktmbuf_tailroom(m_last))
723 : : copy_len = rte_pktmbuf_tailroom(m_last);
724 : :
725 : : /* append from seg to m_last */
726 : 16416 : rte_memcpy(rte_pktmbuf_mtod_offset(m_last, char *,
727 : : m_last->data_len),
728 [ + + ]: 16416 : rte_pktmbuf_mtod_offset(seg, char *, off),
729 : : copy_len);
730 : :
731 : : /* update offsets and lengths */
732 : 16416 : m_last->data_len += copy_len;
733 : 16416 : mc->pkt_len += copy_len;
734 : 16416 : off += copy_len;
735 : 16416 : len -= copy_len;
736 : : }
737 : :
738 : : /* garbage out check */
739 : : __rte_mbuf_sanity_check(mc, 1);
740 : : return mc;
741 : : }
742 : :
743 : : /* dump a mbuf on console */
744 : : RTE_EXPORT_SYMBOL(rte_pktmbuf_dump)
745 : : void
746 : 26 : rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len)
747 : : {
748 : : unsigned int len;
749 : : unsigned int nb_segs;
750 : :
751 : : __rte_mbuf_sanity_check(m, 1);
752 : :
753 : 26 : fprintf(f, "dump mbuf at %p, iova=%#" PRIx64 ", buf_len=%u\n", m, rte_mbuf_iova_get(m),
754 : 26 : m->buf_len);
755 : 26 : fprintf(f, " pkt_len=%u, ol_flags=%#"PRIx64", nb_segs=%u, port=%u",
756 : 26 : m->pkt_len, m->ol_flags, m->nb_segs, m->port);
757 : :
758 [ - + ]: 26 : if (m->ol_flags & (RTE_MBUF_F_RX_QINQ | RTE_MBUF_F_TX_QINQ))
759 : 0 : fprintf(f, ", vlan_tci_outer=%u", m->vlan_tci_outer);
760 : :
761 [ - + ]: 26 : if (m->ol_flags & (RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_TX_VLAN))
762 : 0 : fprintf(f, ", vlan_tci=%u", m->vlan_tci);
763 : :
764 : 26 : fprintf(f, ", ptype=%#"PRIx32"\n", m->packet_type);
765 : :
766 : 26 : nb_segs = m->nb_segs;
767 : :
768 [ + + ]: 72 : while (m && nb_segs != 0) {
769 : : __rte_mbuf_sanity_check(m, 0);
770 : :
771 : 46 : fprintf(f, " segment at %p, data=%p, len=%u, off=%u, refcnt=%u\n",
772 : 46 : m, rte_pktmbuf_mtod(m, void *),
773 : 46 : m->data_len, m->data_off, rte_mbuf_refcnt_read(m));
774 : :
775 : : len = dump_len;
776 : 46 : if (len > m->data_len)
777 : : len = m->data_len;
778 [ + + ]: 46 : if (len != 0)
779 : 42 : rte_hexdump(f, NULL, rte_pktmbuf_mtod(m, void *), len);
780 : 46 : dump_len -= len;
781 : 46 : m = m->next;
782 : 46 : nb_segs --;
783 : : }
784 : 26 : }
785 : :
786 : : /* read len data bytes in a mbuf at specified offset (internal) */
787 : : RTE_EXPORT_SYMBOL(__rte_pktmbuf_read)
788 : 50 : const void *__rte_pktmbuf_read(const struct rte_mbuf *m, uint32_t off,
789 : : uint32_t len, void *buf)
790 : : {
791 : : const struct rte_mbuf *seg = m;
792 : : uint32_t buf_off = 0, copy_len;
793 : :
794 [ + + ]: 50 : if (off + len > rte_pktmbuf_pkt_len(m))
795 : : return NULL;
796 : :
797 [ + + ]: 63 : while (off >= rte_pktmbuf_data_len(seg)) {
798 : 25 : off -= rte_pktmbuf_data_len(seg);
799 : 25 : seg = seg->next;
800 : : }
801 : :
802 [ + + ]: 38 : if (off + len <= rte_pktmbuf_data_len(seg))
803 : 9 : return rte_pktmbuf_mtod_offset(seg, char *, off);
804 : :
805 : : /* rare case: header is split among several segments */
806 [ + + ]: 159 : while (len > 0) {
807 : 130 : copy_len = rte_pktmbuf_data_len(seg) - off;
808 : : if (copy_len > len)
809 : : copy_len = len;
810 : 130 : rte_memcpy((char *)buf + buf_off,
811 [ + + ]: 130 : rte_pktmbuf_mtod_offset(seg, char *, off), copy_len);
812 : : off = 0;
813 : 130 : buf_off += copy_len;
814 : 130 : len -= copy_len;
815 : 130 : seg = seg->next;
816 : : }
817 : :
818 : : return buf;
819 : : }
820 : :
821 : : /*
822 : : * Get the name of a RX offload flag. Must be kept synchronized with flag
823 : : * definitions in rte_mbuf.h.
824 : : */
825 : : RTE_EXPORT_SYMBOL(rte_get_rx_ol_flag_name)
826 : 31 : const char *rte_get_rx_ol_flag_name(uint64_t mask)
827 : : {
828 [ + + + + : 31 : switch (mask) {
+ + + + +
+ + + + +
+ - + + +
+ + + +
+ ]
829 : : case RTE_MBUF_F_RX_VLAN: return "RTE_MBUF_F_RX_VLAN";
830 : 1 : case RTE_MBUF_F_RX_RSS_HASH: return "RTE_MBUF_F_RX_RSS_HASH";
831 : 1 : case RTE_MBUF_F_RX_FDIR: return "RTE_MBUF_F_RX_FDIR";
832 : 1 : case RTE_MBUF_F_RX_L4_CKSUM_BAD: return "RTE_MBUF_F_RX_L4_CKSUM_BAD";
833 : 1 : case RTE_MBUF_F_RX_L4_CKSUM_GOOD: return "RTE_MBUF_F_RX_L4_CKSUM_GOOD";
834 : 1 : case RTE_MBUF_F_RX_L4_CKSUM_NONE: return "RTE_MBUF_F_RX_L4_CKSUM_NONE";
835 : 1 : case RTE_MBUF_F_RX_IP_CKSUM_BAD: return "RTE_MBUF_F_RX_IP_CKSUM_BAD";
836 : 1 : case RTE_MBUF_F_RX_IP_CKSUM_GOOD: return "RTE_MBUF_F_RX_IP_CKSUM_GOOD";
837 : 1 : case RTE_MBUF_F_RX_IP_CKSUM_NONE: return "RTE_MBUF_F_RX_IP_CKSUM_NONE";
838 : 1 : case RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD: return "RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD";
839 : 1 : case RTE_MBUF_F_RX_VLAN_STRIPPED: return "RTE_MBUF_F_RX_VLAN_STRIPPED";
840 : 1 : case RTE_MBUF_F_RX_IEEE1588_PTP: return "RTE_MBUF_F_RX_IEEE1588_PTP";
841 : 1 : case RTE_MBUF_F_RX_IEEE1588_TMST: return "RTE_MBUF_F_RX_IEEE1588_TMST";
842 : 1 : case RTE_MBUF_F_RX_FDIR_ID: return "RTE_MBUF_F_RX_FDIR_ID";
843 : 1 : case RTE_MBUF_F_RX_FDIR_FLX: return "RTE_MBUF_F_RX_FDIR_FLX";
844 : 1 : case RTE_MBUF_F_RX_QINQ_STRIPPED: return "RTE_MBUF_F_RX_QINQ_STRIPPED";
845 : 0 : case RTE_MBUF_F_RX_QINQ: return "RTE_MBUF_F_RX_QINQ";
846 : 1 : case RTE_MBUF_F_RX_LRO: return "RTE_MBUF_F_RX_LRO";
847 : 2 : case RTE_MBUF_F_RX_SEC_OFFLOAD: return "RTE_MBUF_F_RX_SEC_OFFLOAD";
848 : 1 : case RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED: return "RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED";
849 : 1 : case RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD: return "RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD";
850 : 1 : case RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD: return "RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD";
851 : 1 : case RTE_MBUF_F_RX_OUTER_L4_CKSUM_INVALID:
852 : 1 : return "RTE_MBUF_F_RX_OUTER_L4_CKSUM_INVALID";
853 : :
854 : 8 : default: return NULL;
855 : : }
856 : : }
857 : :
858 : : struct flag_mask {
859 : : uint64_t flag;
860 : : uint64_t mask;
861 : : const char *default_name;
862 : : };
863 : :
864 : : /* write the list of rx ol flags in buffer buf */
865 : : RTE_EXPORT_SYMBOL(rte_get_rx_ol_flag_list)
866 : : int
867 : 5 : rte_get_rx_ol_flag_list(uint64_t mask, char *buf, size_t buflen)
868 : : {
869 : 5 : const struct flag_mask rx_flags[] = {
870 : : { RTE_MBUF_F_RX_VLAN, RTE_MBUF_F_RX_VLAN, NULL },
871 : : { RTE_MBUF_F_RX_RSS_HASH, RTE_MBUF_F_RX_RSS_HASH, NULL },
872 : : { RTE_MBUF_F_RX_FDIR, RTE_MBUF_F_RX_FDIR, NULL },
873 : : { RTE_MBUF_F_RX_L4_CKSUM_BAD, RTE_MBUF_F_RX_L4_CKSUM_MASK, NULL },
874 : : { RTE_MBUF_F_RX_L4_CKSUM_GOOD, RTE_MBUF_F_RX_L4_CKSUM_MASK, NULL },
875 : : { RTE_MBUF_F_RX_L4_CKSUM_NONE, RTE_MBUF_F_RX_L4_CKSUM_MASK, NULL },
876 : : { RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN, RTE_MBUF_F_RX_L4_CKSUM_MASK,
877 : : "RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN" },
878 : : { RTE_MBUF_F_RX_IP_CKSUM_BAD, RTE_MBUF_F_RX_IP_CKSUM_MASK, NULL },
879 : : { RTE_MBUF_F_RX_IP_CKSUM_GOOD, RTE_MBUF_F_RX_IP_CKSUM_MASK, NULL },
880 : : { RTE_MBUF_F_RX_IP_CKSUM_NONE, RTE_MBUF_F_RX_IP_CKSUM_MASK, NULL },
881 : : { RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN, RTE_MBUF_F_RX_IP_CKSUM_MASK,
882 : : "RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN" },
883 : : { RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD, RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD, NULL },
884 : : { RTE_MBUF_F_RX_VLAN_STRIPPED, RTE_MBUF_F_RX_VLAN_STRIPPED, NULL },
885 : : { RTE_MBUF_F_RX_IEEE1588_PTP, RTE_MBUF_F_RX_IEEE1588_PTP, NULL },
886 : : { RTE_MBUF_F_RX_IEEE1588_TMST, RTE_MBUF_F_RX_IEEE1588_TMST, NULL },
887 : : { RTE_MBUF_F_RX_FDIR_ID, RTE_MBUF_F_RX_FDIR_ID, NULL },
888 : : { RTE_MBUF_F_RX_FDIR_FLX, RTE_MBUF_F_RX_FDIR_FLX, NULL },
889 : : { RTE_MBUF_F_RX_QINQ_STRIPPED, RTE_MBUF_F_RX_QINQ_STRIPPED, NULL },
890 : : { RTE_MBUF_F_RX_LRO, RTE_MBUF_F_RX_LRO, NULL },
891 : : { RTE_MBUF_F_RX_SEC_OFFLOAD, RTE_MBUF_F_RX_SEC_OFFLOAD, NULL },
892 : : { RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED, RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED, NULL },
893 : : { RTE_MBUF_F_RX_QINQ, RTE_MBUF_F_RX_QINQ, NULL },
894 : : { RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD, RTE_MBUF_F_RX_OUTER_L4_CKSUM_MASK, NULL },
895 : : { RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD, RTE_MBUF_F_RX_OUTER_L4_CKSUM_MASK,
896 : : NULL },
897 : : { RTE_MBUF_F_RX_OUTER_L4_CKSUM_INVALID, RTE_MBUF_F_RX_OUTER_L4_CKSUM_MASK,
898 : : NULL },
899 : : { RTE_MBUF_F_RX_OUTER_L4_CKSUM_UNKNOWN, RTE_MBUF_F_RX_OUTER_L4_CKSUM_MASK,
900 : : "RTE_MBUF_F_RX_OUTER_L4_CKSUM_UNKNOWN" },
901 : : };
902 : : const char *name;
903 : : unsigned int i;
904 : : int ret;
905 : :
906 [ + + ]: 5 : if (buflen == 0)
907 : : return -1;
908 : :
909 : 3 : buf[0] = '\0';
910 [ + + ]: 61 : for (i = 0; i < RTE_DIM(rx_flags); i++) {
911 [ + + ]: 59 : if ((mask & rx_flags[i].mask) != rx_flags[i].flag)
912 : 51 : continue;
913 : 8 : name = rte_get_rx_ol_flag_name(rx_flags[i].flag);
914 [ + + ]: 8 : if (name == NULL)
915 : 7 : name = rx_flags[i].default_name;
916 : : ret = snprintf(buf, buflen, "%s ", name);
917 [ + - ]: 8 : if (ret < 0)
918 : : return -1;
919 [ + + ]: 8 : if ((size_t)ret >= buflen)
920 : : return -1;
921 : 7 : buf += ret;
922 : 7 : buflen -= ret;
923 : : }
924 : :
925 : : return 0;
926 : : }
927 : :
928 : : /*
929 : : * Get the name of a TX offload flag. Must be kept synchronized with flag
930 : : * definitions in rte_mbuf.h.
931 : : */
932 : : RTE_EXPORT_SYMBOL(rte_get_tx_ol_flag_name)
933 : 29 : const char *rte_get_tx_ol_flag_name(uint64_t mask)
934 : : {
935 [ + + + + : 29 : switch (mask) {
+ + + + +
+ + + - +
+ + + + +
+ + + + +
+ + + ]
936 : : case RTE_MBUF_F_TX_VLAN: return "RTE_MBUF_F_TX_VLAN";
937 : 1 : case RTE_MBUF_F_TX_IP_CKSUM: return "RTE_MBUF_F_TX_IP_CKSUM";
938 : 1 : case RTE_MBUF_F_TX_TCP_CKSUM: return "RTE_MBUF_F_TX_TCP_CKSUM";
939 : 1 : case RTE_MBUF_F_TX_SCTP_CKSUM: return "RTE_MBUF_F_TX_SCTP_CKSUM";
940 : 2 : case RTE_MBUF_F_TX_UDP_CKSUM: return "RTE_MBUF_F_TX_UDP_CKSUM";
941 : 1 : case RTE_MBUF_F_TX_IEEE1588_TMST: return "RTE_MBUF_F_TX_IEEE1588_TMST";
942 : 1 : case RTE_MBUF_F_TX_TCP_SEG: return "RTE_MBUF_F_TX_TCP_SEG";
943 : 1 : case RTE_MBUF_F_TX_IPV4: return "RTE_MBUF_F_TX_IPV4";
944 : 1 : case RTE_MBUF_F_TX_IPV6: return "RTE_MBUF_F_TX_IPV6";
945 : 1 : case RTE_MBUF_F_TX_OUTER_IP_CKSUM: return "RTE_MBUF_F_TX_OUTER_IP_CKSUM";
946 : 1 : case RTE_MBUF_F_TX_OUTER_IPV4: return "RTE_MBUF_F_TX_OUTER_IPV4";
947 : 1 : case RTE_MBUF_F_TX_OUTER_IPV6: return "RTE_MBUF_F_TX_OUTER_IPV6";
948 : 1 : case RTE_MBUF_F_TX_TUNNEL_VXLAN: return "RTE_MBUF_F_TX_TUNNEL_VXLAN";
949 : 0 : case RTE_MBUF_F_TX_TUNNEL_GTP: return "RTE_MBUF_F_TX_TUNNEL_GTP";
950 : 1 : case RTE_MBUF_F_TX_TUNNEL_GRE: return "RTE_MBUF_F_TX_TUNNEL_GRE";
951 : 1 : case RTE_MBUF_F_TX_TUNNEL_IPIP: return "RTE_MBUF_F_TX_TUNNEL_IPIP";
952 : 1 : case RTE_MBUF_F_TX_TUNNEL_GENEVE: return "RTE_MBUF_F_TX_TUNNEL_GENEVE";
953 : 1 : case RTE_MBUF_F_TX_TUNNEL_MPLSINUDP: return "RTE_MBUF_F_TX_TUNNEL_MPLSINUDP";
954 : 1 : case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE: return "RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE";
955 : 1 : case RTE_MBUF_F_TX_TUNNEL_IP: return "RTE_MBUF_F_TX_TUNNEL_IP";
956 : 1 : case RTE_MBUF_F_TX_TUNNEL_UDP: return "RTE_MBUF_F_TX_TUNNEL_UDP";
957 : 1 : case RTE_MBUF_F_TX_QINQ: return "RTE_MBUF_F_TX_QINQ";
958 : 1 : case RTE_MBUF_F_TX_MACSEC: return "RTE_MBUF_F_TX_MACSEC";
959 : 1 : case RTE_MBUF_F_TX_SEC_OFFLOAD: return "RTE_MBUF_F_TX_SEC_OFFLOAD";
960 : 1 : case RTE_MBUF_F_TX_UDP_SEG: return "RTE_MBUF_F_TX_UDP_SEG";
961 : 1 : case RTE_MBUF_F_TX_OUTER_UDP_CKSUM: return "RTE_MBUF_F_TX_OUTER_UDP_CKSUM";
962 : 3 : default: return NULL;
963 : : }
964 : : }
965 : :
966 : : /* write the list of tx ol flags in buffer buf */
967 : : RTE_EXPORT_SYMBOL(rte_get_tx_ol_flag_list)
968 : : int
969 : 5 : rte_get_tx_ol_flag_list(uint64_t mask, char *buf, size_t buflen)
970 : : {
971 : 5 : const struct flag_mask tx_flags[] = {
972 : : { RTE_MBUF_F_TX_VLAN, RTE_MBUF_F_TX_VLAN, NULL },
973 : : { RTE_MBUF_F_TX_IP_CKSUM, RTE_MBUF_F_TX_IP_CKSUM, NULL },
974 : : { RTE_MBUF_F_TX_TCP_CKSUM, RTE_MBUF_F_TX_L4_MASK, NULL },
975 : : { RTE_MBUF_F_TX_SCTP_CKSUM, RTE_MBUF_F_TX_L4_MASK, NULL },
976 : : { RTE_MBUF_F_TX_UDP_CKSUM, RTE_MBUF_F_TX_L4_MASK, NULL },
977 : : { RTE_MBUF_F_TX_L4_NO_CKSUM, RTE_MBUF_F_TX_L4_MASK, "RTE_MBUF_F_TX_L4_NO_CKSUM" },
978 : : { RTE_MBUF_F_TX_IEEE1588_TMST, RTE_MBUF_F_TX_IEEE1588_TMST, NULL },
979 : : { RTE_MBUF_F_TX_TCP_SEG, RTE_MBUF_F_TX_TCP_SEG, NULL },
980 : : { RTE_MBUF_F_TX_IPV4, RTE_MBUF_F_TX_IPV4, NULL },
981 : : { RTE_MBUF_F_TX_IPV6, RTE_MBUF_F_TX_IPV6, NULL },
982 : : { RTE_MBUF_F_TX_OUTER_IP_CKSUM, RTE_MBUF_F_TX_OUTER_IP_CKSUM, NULL },
983 : : { RTE_MBUF_F_TX_OUTER_IPV4, RTE_MBUF_F_TX_OUTER_IPV4, NULL },
984 : : { RTE_MBUF_F_TX_OUTER_IPV6, RTE_MBUF_F_TX_OUTER_IPV6, NULL },
985 : : { RTE_MBUF_F_TX_TUNNEL_VXLAN, RTE_MBUF_F_TX_TUNNEL_MASK, NULL },
986 : : { RTE_MBUF_F_TX_TUNNEL_GTP, RTE_MBUF_F_TX_TUNNEL_MASK, NULL },
987 : : { RTE_MBUF_F_TX_TUNNEL_GRE, RTE_MBUF_F_TX_TUNNEL_MASK, NULL },
988 : : { RTE_MBUF_F_TX_TUNNEL_IPIP, RTE_MBUF_F_TX_TUNNEL_MASK, NULL },
989 : : { RTE_MBUF_F_TX_TUNNEL_GENEVE, RTE_MBUF_F_TX_TUNNEL_MASK, NULL },
990 : : { RTE_MBUF_F_TX_TUNNEL_MPLSINUDP, RTE_MBUF_F_TX_TUNNEL_MASK, NULL },
991 : : { RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE, RTE_MBUF_F_TX_TUNNEL_MASK, NULL },
992 : : { RTE_MBUF_F_TX_TUNNEL_IP, RTE_MBUF_F_TX_TUNNEL_MASK, NULL },
993 : : { RTE_MBUF_F_TX_TUNNEL_UDP, RTE_MBUF_F_TX_TUNNEL_MASK, NULL },
994 : : { RTE_MBUF_F_TX_QINQ, RTE_MBUF_F_TX_QINQ, NULL },
995 : : { RTE_MBUF_F_TX_MACSEC, RTE_MBUF_F_TX_MACSEC, NULL },
996 : : { RTE_MBUF_F_TX_SEC_OFFLOAD, RTE_MBUF_F_TX_SEC_OFFLOAD, NULL },
997 : : { RTE_MBUF_F_TX_UDP_SEG, RTE_MBUF_F_TX_UDP_SEG, NULL },
998 : : { RTE_MBUF_F_TX_OUTER_UDP_CKSUM, RTE_MBUF_F_TX_OUTER_UDP_CKSUM, NULL },
999 : : };
1000 : : const char *name;
1001 : : unsigned int i;
1002 : : int ret;
1003 : :
1004 [ + + ]: 5 : if (buflen == 0)
1005 : : return -1;
1006 : :
1007 : 3 : buf[0] = '\0';
1008 [ + + ]: 62 : for (i = 0; i < RTE_DIM(tx_flags); i++) {
1009 [ + + ]: 60 : if ((mask & tx_flags[i].mask) != tx_flags[i].flag)
1010 : 57 : continue;
1011 : 3 : name = rte_get_tx_ol_flag_name(tx_flags[i].flag);
1012 [ + + ]: 3 : if (name == NULL)
1013 : 2 : name = tx_flags[i].default_name;
1014 : : ret = snprintf(buf, buflen, "%s ", name);
1015 [ + - ]: 3 : if (ret < 0)
1016 : : return -1;
1017 [ + + ]: 3 : if ((size_t)ret >= buflen)
1018 : : return -1;
1019 : 2 : buf += ret;
1020 : 2 : buflen -= ret;
1021 : : }
1022 : :
1023 : : return 0;
1024 : : }
|