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