DPDK  18.08.1
rte_mbuf.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation.
3  * Copyright 2014 6WIND S.A.
4  */
5 
6 #ifndef _RTE_MBUF_H_
7 #define _RTE_MBUF_H_
8 
34 #include <stdint.h>
35 #include <rte_compat.h>
36 #include <rte_common.h>
37 #include <rte_config.h>
38 #include <rte_mempool.h>
39 #include <rte_memory.h>
40 #include <rte_atomic.h>
41 #include <rte_prefetch.h>
42 #include <rte_branch_prediction.h>
43 #include <rte_mbuf_ptype.h>
44 
45 #ifdef __cplusplus
46 extern "C" {
47 #endif
48 
49 /*
50  * Packet Offload Features Flags. It also carry packet type information.
51  * Critical resources. Both rx/tx shared these bits. Be cautious on any change
52  *
53  * - RX flags start at bit position zero, and get added to the left of previous
54  * flags.
55  * - The most-significant 3 bits are reserved for generic mbuf flags
56  * - TX flags therefore start at bit position 60 (i.e. 63-3), and new flags get
57  * added to the right of the previously defined flags i.e. they should count
58  * downwards, not upwards.
59  *
60  * Keep these flags synchronized with rte_get_rx_ol_flag_name() and
61  * rte_get_tx_ol_flag_name().
62  */
63 
71 #define PKT_RX_VLAN (1ULL << 0)
72 
73 #define PKT_RX_RSS_HASH (1ULL << 1)
74 #define PKT_RX_FDIR (1ULL << 2)
83 #define PKT_RX_L4_CKSUM_BAD (1ULL << 3)
84 
92 #define PKT_RX_IP_CKSUM_BAD (1ULL << 4)
93 
94 #define PKT_RX_EIP_CKSUM_BAD (1ULL << 5)
102 #define PKT_RX_VLAN_STRIPPED (1ULL << 6)
103 
112 #define PKT_RX_IP_CKSUM_MASK ((1ULL << 4) | (1ULL << 7))
113 
114 #define PKT_RX_IP_CKSUM_UNKNOWN 0
115 #define PKT_RX_IP_CKSUM_BAD (1ULL << 4)
116 #define PKT_RX_IP_CKSUM_GOOD (1ULL << 7)
117 #define PKT_RX_IP_CKSUM_NONE ((1ULL << 4) | (1ULL << 7))
118 
127 #define PKT_RX_L4_CKSUM_MASK ((1ULL << 3) | (1ULL << 8))
128 
129 #define PKT_RX_L4_CKSUM_UNKNOWN 0
130 #define PKT_RX_L4_CKSUM_BAD (1ULL << 3)
131 #define PKT_RX_L4_CKSUM_GOOD (1ULL << 8)
132 #define PKT_RX_L4_CKSUM_NONE ((1ULL << 3) | (1ULL << 8))
133 
134 #define PKT_RX_IEEE1588_PTP (1ULL << 9)
135 #define PKT_RX_IEEE1588_TMST (1ULL << 10)
136 #define PKT_RX_FDIR_ID (1ULL << 13)
137 #define PKT_RX_FDIR_FLX (1ULL << 14)
147 #define PKT_RX_QINQ_STRIPPED (1ULL << 15)
148 
154 #define PKT_RX_LRO (1ULL << 16)
155 
159 #define PKT_RX_TIMESTAMP (1ULL << 17)
160 
164 #define PKT_RX_SEC_OFFLOAD (1ULL << 18)
165 
169 #define PKT_RX_SEC_OFFLOAD_FAILED (1ULL << 19)
170 
178 #define PKT_RX_QINQ (1ULL << 20)
179 
180 /* add new RX flags here */
181 
182 /* add new TX flags here */
183 
189 #define PKT_TX_UDP_SEG (1ULL << 42)
190 
194 #define PKT_TX_SEC_OFFLOAD (1ULL << 43)
195 
200 #define PKT_TX_MACSEC (1ULL << 44)
201 
210 #define PKT_TX_TUNNEL_VXLAN (0x1ULL << 45)
211 #define PKT_TX_TUNNEL_GRE (0x2ULL << 45)
212 #define PKT_TX_TUNNEL_IPIP (0x3ULL << 45)
213 #define PKT_TX_TUNNEL_GENEVE (0x4ULL << 45)
214 
215 #define PKT_TX_TUNNEL_MPLSINUDP (0x5ULL << 45)
216 #define PKT_TX_TUNNEL_VXLAN_GPE (0x6ULL << 45)
217 
228 #define PKT_TX_TUNNEL_IP (0xDULL << 45)
229 
241 #define PKT_TX_TUNNEL_UDP (0xEULL << 45)
242 /* add new TX TUNNEL type here */
243 #define PKT_TX_TUNNEL_MASK (0xFULL << 45)
244 
248 #define PKT_TX_QINQ (1ULL << 49)
249 /* this old name is deprecated */
250 #define PKT_TX_QINQ_PKT PKT_TX_QINQ
251 
261 #define PKT_TX_TCP_SEG (1ULL << 50)
262 
263 #define PKT_TX_IEEE1588_TMST (1ULL << 51)
273 #define PKT_TX_L4_NO_CKSUM (0ULL << 52)
274 #define PKT_TX_TCP_CKSUM (1ULL << 52)
275 #define PKT_TX_SCTP_CKSUM (2ULL << 52)
276 #define PKT_TX_UDP_CKSUM (3ULL << 52)
277 #define PKT_TX_L4_MASK (3ULL << 52)
285 #define PKT_TX_IP_CKSUM (1ULL << 54)
286 
293 #define PKT_TX_IPV4 (1ULL << 55)
294 
301 #define PKT_TX_IPV6 (1ULL << 56)
302 
306 #define PKT_TX_VLAN (1ULL << 57)
307 /* this old name is deprecated */
308 #define PKT_TX_VLAN_PKT PKT_TX_VLAN
309 
316 #define PKT_TX_OUTER_IP_CKSUM (1ULL << 58)
317 
323 #define PKT_TX_OUTER_IPV4 (1ULL << 59)
324 
330 #define PKT_TX_OUTER_IPV6 (1ULL << 60)
331 
336 #define PKT_TX_OFFLOAD_MASK ( \
337  PKT_TX_OUTER_IPV6 | \
338  PKT_TX_OUTER_IPV4 | \
339  PKT_TX_OUTER_IP_CKSUM | \
340  PKT_TX_VLAN_PKT | \
341  PKT_TX_IPV6 | \
342  PKT_TX_IPV4 | \
343  PKT_TX_IP_CKSUM | \
344  PKT_TX_L4_MASK | \
345  PKT_TX_IEEE1588_TMST | \
346  PKT_TX_TCP_SEG | \
347  PKT_TX_QINQ_PKT | \
348  PKT_TX_TUNNEL_MASK | \
349  PKT_TX_MACSEC | \
350  PKT_TX_SEC_OFFLOAD | \
351  PKT_TX_UDP_SEG)
352 
356 #define EXT_ATTACHED_MBUF (1ULL << 61)
357 
358 #define IND_ATTACHED_MBUF (1ULL << 62)
361 #define RTE_MBUF_PRIV_ALIGN 8
362 
371 const char *rte_get_rx_ol_flag_name(uint64_t mask);
372 
385 int rte_get_rx_ol_flag_list(uint64_t mask, char *buf, size_t buflen);
386 
397 const char *rte_get_tx_ol_flag_name(uint64_t mask);
398 
411 int rte_get_tx_ol_flag_list(uint64_t mask, char *buf, size_t buflen);
412 
419 #define RTE_MBUF_DEFAULT_DATAROOM 2048
420 #define RTE_MBUF_DEFAULT_BUF_SIZE \
421  (RTE_MBUF_DEFAULT_DATAROOM + RTE_PKTMBUF_HEADROOM)
422 
423 /* define a set of marker types that can be used to refer to set points in the
424  * mbuf */
425 __extension__
426 typedef void *MARKER[0];
427 __extension__
428 typedef uint8_t MARKER8[0];
429 __extension__
430 typedef uint64_t MARKER64[0];
436 struct rte_mbuf {
437  MARKER cacheline0;
438 
439  void *buf_addr;
447  union {
448  rte_iova_t buf_iova;
450  } __rte_aligned(sizeof(rte_iova_t));
451 
452  /* next 8 bytes are initialised on RX descriptor rearm */
453  MARKER64 rearm_data;
454  uint16_t data_off;
455 
466  union {
468  uint16_t refcnt;
469  };
470  uint16_t nb_segs;
473  uint16_t port;
474 
475  uint64_t ol_flags;
477  /* remaining bytes are set on RX when pulling packet from descriptor */
478  MARKER rx_descriptor_fields1;
479 
480  /*
481  * The packet type, which is the combination of outer/inner L2, L3, L4
482  * and tunnel types. The packet_type is about data really present in the
483  * mbuf. Example: if vlan stripping is enabled, a received vlan packet
484  * would have RTE_PTYPE_L2_ETHER and not RTE_PTYPE_L2_VLAN because the
485  * vlan is stripped from the data.
486  */
488  union {
489  uint32_t packet_type;
490  struct {
491  uint32_t l2_type:4;
492  uint32_t l3_type:4;
493  uint32_t l4_type:4;
494  uint32_t tun_type:4;
496  union {
497  uint8_t inner_esp_next_proto;
502  __extension__
503  struct {
504  uint8_t inner_l2_type:4;
506  uint8_t inner_l3_type:4;
508  };
509  };
510  uint32_t inner_l4_type:4;
511  };
512  };
513 
514  uint32_t pkt_len;
515  uint16_t data_len;
517  uint16_t vlan_tci;
518 
519  union {
520  uint32_t rss;
521  struct {
523  union {
524  struct {
525  uint16_t hash;
526  uint16_t id;
527  };
528  uint32_t lo;
530  };
531  uint32_t hi;
534  } fdir;
535  struct {
536  uint32_t lo;
537  uint32_t hi;
538  } sched;
539  uint32_t usr;
540  } hash;
543  uint16_t vlan_tci_outer;
544 
545  uint16_t buf_len;
550  uint64_t timestamp;
551 
552  /* second cache line - fields only used in slow path or on TX */
553  MARKER cacheline1 __rte_cache_min_aligned;
554 
556  union {
557  void *userdata;
558  uint64_t udata64;
559  };
560 
561  struct rte_mempool *pool;
562  struct rte_mbuf *next;
564  /* fields to support TX offloads */
566  union {
567  uint64_t tx_offload;
568  __extension__
569  struct {
570  uint64_t l2_len:7;
574  uint64_t l3_len:9;
575  uint64_t l4_len:8;
576  uint64_t tso_segsz:16;
578  /* fields for TX offloading of tunnels */
579  uint64_t outer_l3_len:9;
580  uint64_t outer_l2_len:7;
582  /* uint64_t unused:8; */
583  };
584  };
585 
588  uint16_t priv_size;
589 
591  uint16_t timesync;
592 
594  uint32_t seqn;
595 
600 
602 
606 typedef void (*rte_mbuf_extbuf_free_callback_t)(void *addr, void *opaque);
607 
613  void *fcb_opaque;
615 };
616 
618 #define RTE_MBUF_MAX_NB_SEGS UINT16_MAX
619 
630 static inline void
632 {
633  rte_prefetch0(&m->cacheline0);
634 }
635 
647 static inline void
649 {
650 #if RTE_CACHE_LINE_SIZE == 64
651  rte_prefetch0(&m->cacheline1);
652 #else
653  RTE_SET_USED(m);
654 #endif
655 }
656 
657 
658 static inline uint16_t rte_pktmbuf_priv_size(struct rte_mempool *mp);
659 
668 static inline rte_iova_t
669 rte_mbuf_data_iova(const struct rte_mbuf *mb)
670 {
671  return mb->buf_iova + mb->data_off;
672 }
673 
674 __rte_deprecated
675 static inline phys_addr_t
676 rte_mbuf_data_dma_addr(const struct rte_mbuf *mb)
677 {
678  return rte_mbuf_data_iova(mb);
679 }
680 
693 static inline rte_iova_t
695 {
696  return mb->buf_iova + RTE_PKTMBUF_HEADROOM;
697 }
698 
699 __rte_deprecated
700 static inline phys_addr_t
701 rte_mbuf_data_dma_addr_default(const struct rte_mbuf *mb)
702 {
703  return rte_mbuf_data_iova_default(mb);
704 }
705 
714 static inline struct rte_mbuf *
716 {
717  return (struct rte_mbuf *)RTE_PTR_SUB(mi->buf_addr, sizeof(*mi) + mi->priv_size);
718 }
719 
728 static inline char *
730 {
731  char *buffer_addr;
732  buffer_addr = (char *)md + sizeof(*md) + rte_pktmbuf_priv_size(md->pool);
733  return buffer_addr;
734 }
735 
748 static inline void * __rte_experimental
750 {
751  return RTE_PTR_ADD(m, sizeof(struct rte_mbuf));
752 }
753 
761 #define RTE_MBUF_CLONED(mb) ((mb)->ol_flags & IND_ATTACHED_MBUF)
762 
767 #define RTE_MBUF_INDIRECT(mb) RTE_MBUF_CLONED(mb)
768 
774 #define RTE_MBUF_HAS_EXTBUF(mb) ((mb)->ol_flags & EXT_ATTACHED_MBUF)
775 
782 #define RTE_MBUF_DIRECT(mb) \
783  (!((mb)->ol_flags & (IND_ATTACHED_MBUF | EXT_ATTACHED_MBUF)))
784 
793  uint16_t mbuf_priv_size;
794 };
795 
796 #ifdef RTE_LIBRTE_MBUF_DEBUG
797 
799 #define __rte_mbuf_sanity_check(m, is_h) rte_mbuf_sanity_check(m, is_h)
800 
801 #else /* RTE_LIBRTE_MBUF_DEBUG */
802 
804 #define __rte_mbuf_sanity_check(m, is_h) do { } while (0)
805 
806 #endif /* RTE_LIBRTE_MBUF_DEBUG */
807 
808 #ifdef RTE_MBUF_REFCNT_ATOMIC
809 
817 static inline uint16_t
818 rte_mbuf_refcnt_read(const struct rte_mbuf *m)
819 {
820  return (uint16_t)(rte_atomic16_read(&m->refcnt_atomic));
821 }
822 
830 static inline void
831 rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
832 {
833  rte_atomic16_set(&m->refcnt_atomic, (int16_t)new_value);
834 }
835 
836 /* internal */
837 static inline uint16_t
838 __rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
839 {
840  return (uint16_t)(rte_atomic16_add_return(&m->refcnt_atomic, value));
841 }
842 
852 static inline uint16_t
853 rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
854 {
855  /*
856  * The atomic_add is an expensive operation, so we don't want to
857  * call it in the case where we know we are the uniq holder of
858  * this mbuf (i.e. ref_cnt == 1). Otherwise, an atomic
859  * operation has to be used because concurrent accesses on the
860  * reference counter can occur.
861  */
862  if (likely(rte_mbuf_refcnt_read(m) == 1)) {
863  ++value;
864  rte_mbuf_refcnt_set(m, (uint16_t)value);
865  return (uint16_t)value;
866  }
867 
868  return __rte_mbuf_refcnt_update(m, value);
869 }
870 
871 #else /* ! RTE_MBUF_REFCNT_ATOMIC */
872 
873 /* internal */
874 static inline uint16_t
875 __rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
876 {
877  m->refcnt = (uint16_t)(m->refcnt + value);
878  return m->refcnt;
879 }
880 
884 static inline uint16_t
885 rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
886 {
887  return __rte_mbuf_refcnt_update(m, value);
888 }
889 
893 static inline uint16_t
895 {
896  return m->refcnt;
897 }
898 
902 static inline void
903 rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
904 {
905  m->refcnt = new_value;
906 }
907 
908 #endif /* RTE_MBUF_REFCNT_ATOMIC */
909 
918 static inline uint16_t
920 {
921  return (uint16_t)(rte_atomic16_read(&shinfo->refcnt_atomic));
922 }
923 
932 static inline void
934  uint16_t new_value)
935 {
936  rte_atomic16_set(&shinfo->refcnt_atomic, (int16_t)new_value);
937 }
938 
950 static inline uint16_t
952  int16_t value)
953 {
954  if (likely(rte_mbuf_ext_refcnt_read(shinfo) == 1)) {
955  ++value;
956  rte_mbuf_ext_refcnt_set(shinfo, (uint16_t)value);
957  return (uint16_t)value;
958  }
959 
960  return (uint16_t)rte_atomic16_add_return(&shinfo->refcnt_atomic, value);
961 }
962 
964 #define RTE_MBUF_PREFETCH_TO_FREE(m) do { \
965  if ((m) != NULL) \
966  rte_prefetch0(m); \
967 } while (0)
968 
969 
982 void
983 rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header);
984 
985 #define MBUF_RAW_ALLOC_CHECK(m) do { \
986  RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1); \
987  RTE_ASSERT((m)->next == NULL); \
988  RTE_ASSERT((m)->nb_segs == 1); \
989  __rte_mbuf_sanity_check(m, 0); \
990 } while (0)
991 
1011 static inline struct rte_mbuf *rte_mbuf_raw_alloc(struct rte_mempool *mp)
1012 {
1013  struct rte_mbuf *m;
1014 
1015  if (rte_mempool_get(mp, (void **)&m) < 0)
1016  return NULL;
1017  MBUF_RAW_ALLOC_CHECK(m);
1018  return m;
1019 }
1020 
1035 static __rte_always_inline void
1037 {
1038  RTE_ASSERT(RTE_MBUF_DIRECT(m));
1039  RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1);
1040  RTE_ASSERT(m->next == NULL);
1041  RTE_ASSERT(m->nb_segs == 1);
1043  rte_mempool_put(m->pool, m);
1044 }
1045 
1046 /* compat with older versions */
1047 __rte_deprecated
1048 static inline void
1049 __rte_mbuf_raw_free(struct rte_mbuf *m)
1050 {
1051  rte_mbuf_raw_free(m);
1052 }
1053 
1073 void rte_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg,
1074  void *m, unsigned i);
1075 
1076 
1094 void rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg);
1095 
1130 struct rte_mempool *
1131 rte_pktmbuf_pool_create(const char *name, unsigned n,
1132  unsigned cache_size, uint16_t priv_size, uint16_t data_room_size,
1133  int socket_id);
1134 
1172 struct rte_mempool *
1173 rte_pktmbuf_pool_create_by_ops(const char *name, unsigned int n,
1174  unsigned int cache_size, uint16_t priv_size, uint16_t data_room_size,
1175  int socket_id, const char *ops_name);
1176 
1188 static inline uint16_t
1190 {
1191  struct rte_pktmbuf_pool_private *mbp_priv;
1192 
1193  mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
1194  return mbp_priv->mbuf_data_room_size;
1195 }
1196 
1209 static inline uint16_t
1211 {
1212  struct rte_pktmbuf_pool_private *mbp_priv;
1213 
1214  mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
1215  return mbp_priv->mbuf_priv_size;
1216 }
1217 
1226 static inline void rte_pktmbuf_reset_headroom(struct rte_mbuf *m)
1227 {
1228  m->data_off = (uint16_t)RTE_MIN((uint16_t)RTE_PKTMBUF_HEADROOM,
1229  (uint16_t)m->buf_len);
1230 }
1231 
1240 #define MBUF_INVALID_PORT UINT16_MAX
1241 
1242 static inline void rte_pktmbuf_reset(struct rte_mbuf *m)
1243 {
1244  m->next = NULL;
1245  m->pkt_len = 0;
1246  m->tx_offload = 0;
1247  m->vlan_tci = 0;
1248  m->vlan_tci_outer = 0;
1249  m->nb_segs = 1;
1250  m->port = MBUF_INVALID_PORT;
1251 
1252  m->ol_flags = 0;
1253  m->packet_type = 0;
1255 
1256  m->data_len = 0;
1258 }
1259 
1273 static inline struct rte_mbuf *rte_pktmbuf_alloc(struct rte_mempool *mp)
1274 {
1275  struct rte_mbuf *m;
1276  if ((m = rte_mbuf_raw_alloc(mp)) != NULL)
1277  rte_pktmbuf_reset(m);
1278  return m;
1279 }
1280 
1295 static inline int rte_pktmbuf_alloc_bulk(struct rte_mempool *pool,
1296  struct rte_mbuf **mbufs, unsigned count)
1297 {
1298  unsigned idx = 0;
1299  int rc;
1300 
1301  rc = rte_mempool_get_bulk(pool, (void **)mbufs, count);
1302  if (unlikely(rc))
1303  return rc;
1304 
1305  /* To understand duff's device on loop unwinding optimization, see
1306  * https://en.wikipedia.org/wiki/Duff's_device.
1307  * Here while() loop is used rather than do() while{} to avoid extra
1308  * check if count is zero.
1309  */
1310  switch (count % 4) {
1311  case 0:
1312  while (idx != count) {
1313  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1314  rte_pktmbuf_reset(mbufs[idx]);
1315  idx++;
1316  /* fall-through */
1317  case 3:
1318  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1319  rte_pktmbuf_reset(mbufs[idx]);
1320  idx++;
1321  /* fall-through */
1322  case 2:
1323  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1324  rte_pktmbuf_reset(mbufs[idx]);
1325  idx++;
1326  /* fall-through */
1327  case 1:
1328  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1329  rte_pktmbuf_reset(mbufs[idx]);
1330  idx++;
1331  /* fall-through */
1332  }
1333  }
1334  return 0;
1335 }
1336 
1369 static inline struct rte_mbuf_ext_shared_info *
1370 rte_pktmbuf_ext_shinfo_init_helper(void *buf_addr, uint16_t *buf_len,
1372 {
1373  struct rte_mbuf_ext_shared_info *shinfo;
1374  void *buf_end = RTE_PTR_ADD(buf_addr, *buf_len);
1375  void *addr;
1376 
1377  addr = RTE_PTR_ALIGN_FLOOR(RTE_PTR_SUB(buf_end, sizeof(*shinfo)),
1378  sizeof(uintptr_t));
1379  if (addr <= buf_addr)
1380  return NULL;
1381 
1382  shinfo = (struct rte_mbuf_ext_shared_info *)addr;
1383  shinfo->free_cb = free_cb;
1384  shinfo->fcb_opaque = fcb_opaque;
1385  rte_mbuf_ext_refcnt_set(shinfo, 1);
1386 
1387  *buf_len = (uint16_t)RTE_PTR_DIFF(shinfo, buf_addr);
1388  return shinfo;
1389 }
1390 
1454 static inline void __rte_experimental
1455 rte_pktmbuf_attach_extbuf(struct rte_mbuf *m, void *buf_addr,
1456  rte_iova_t buf_iova, uint16_t buf_len,
1457  struct rte_mbuf_ext_shared_info *shinfo)
1458 {
1459  /* mbuf should not be read-only */
1460  RTE_ASSERT(RTE_MBUF_DIRECT(m) && rte_mbuf_refcnt_read(m) == 1);
1461  RTE_ASSERT(shinfo->free_cb != NULL);
1462 
1463  m->buf_addr = buf_addr;
1464  m->buf_iova = buf_iova;
1465  m->buf_len = buf_len;
1466 
1467  m->data_len = 0;
1468  m->data_off = 0;
1469 
1471  m->shinfo = shinfo;
1472 }
1473 
1481 #define rte_pktmbuf_detach_extbuf(m) rte_pktmbuf_detach(m)
1482 
1504 static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *m)
1505 {
1506  RTE_ASSERT(RTE_MBUF_DIRECT(mi) &&
1507  rte_mbuf_refcnt_read(mi) == 1);
1508 
1509  if (RTE_MBUF_HAS_EXTBUF(m)) {
1511  mi->ol_flags = m->ol_flags;
1512  mi->shinfo = m->shinfo;
1513  } else {
1514  /* if m is not direct, get the mbuf that embeds the data */
1516  mi->priv_size = m->priv_size;
1517  mi->ol_flags = m->ol_flags | IND_ATTACHED_MBUF;
1518  }
1519 
1520  mi->buf_iova = m->buf_iova;
1521  mi->buf_addr = m->buf_addr;
1522  mi->buf_len = m->buf_len;
1523 
1524  mi->data_off = m->data_off;
1525  mi->data_len = m->data_len;
1526  mi->port = m->port;
1527  mi->vlan_tci = m->vlan_tci;
1528  mi->vlan_tci_outer = m->vlan_tci_outer;
1529  mi->tx_offload = m->tx_offload;
1530  mi->hash = m->hash;
1531 
1532  mi->next = NULL;
1533  mi->pkt_len = mi->data_len;
1534  mi->nb_segs = 1;
1535  mi->packet_type = m->packet_type;
1536  mi->timestamp = m->timestamp;
1537 
1538  __rte_mbuf_sanity_check(mi, 1);
1540 }
1541 
1549 static inline void
1550 __rte_pktmbuf_free_extbuf(struct rte_mbuf *m)
1551 {
1552  RTE_ASSERT(RTE_MBUF_HAS_EXTBUF(m));
1553  RTE_ASSERT(m->shinfo != NULL);
1554 
1555  if (rte_mbuf_ext_refcnt_update(m->shinfo, -1) == 0)
1556  m->shinfo->free_cb(m->buf_addr, m->shinfo->fcb_opaque);
1557 }
1558 
1565 static inline void
1566 __rte_pktmbuf_free_direct(struct rte_mbuf *m)
1567 {
1568  struct rte_mbuf *md;
1569 
1570  RTE_ASSERT(RTE_MBUF_INDIRECT(m));
1571 
1572  md = rte_mbuf_from_indirect(m);
1573 
1574  if (rte_mbuf_refcnt_update(md, -1) == 0) {
1575  md->next = NULL;
1576  md->nb_segs = 1;
1577  rte_mbuf_refcnt_set(md, 1);
1578  rte_mbuf_raw_free(md);
1579  }
1580 }
1581 
1595 static inline void rte_pktmbuf_detach(struct rte_mbuf *m)
1596 {
1597  struct rte_mempool *mp = m->pool;
1598  uint32_t mbuf_size, buf_len;
1599  uint16_t priv_size;
1600 
1601  if (RTE_MBUF_HAS_EXTBUF(m))
1602  __rte_pktmbuf_free_extbuf(m);
1603  else
1604  __rte_pktmbuf_free_direct(m);
1605 
1606  priv_size = rte_pktmbuf_priv_size(mp);
1607  mbuf_size = (uint32_t)(sizeof(struct rte_mbuf) + priv_size);
1608  buf_len = rte_pktmbuf_data_room_size(mp);
1609 
1610  m->priv_size = priv_size;
1611  m->buf_addr = (char *)m + mbuf_size;
1612  m->buf_iova = rte_mempool_virt2iova(m) + mbuf_size;
1613  m->buf_len = (uint16_t)buf_len;
1615  m->data_len = 0;
1616  m->ol_flags = 0;
1617 }
1618 
1633 static __rte_always_inline struct rte_mbuf *
1635 {
1637 
1638  if (likely(rte_mbuf_refcnt_read(m) == 1)) {
1639 
1640  if (!RTE_MBUF_DIRECT(m))
1641  rte_pktmbuf_detach(m);
1642 
1643  if (m->next != NULL) {
1644  m->next = NULL;
1645  m->nb_segs = 1;
1646  }
1647 
1648  return m;
1649 
1650  } else if (__rte_mbuf_refcnt_update(m, -1) == 0) {
1651 
1652  if (!RTE_MBUF_DIRECT(m))
1653  rte_pktmbuf_detach(m);
1654 
1655  if (m->next != NULL) {
1656  m->next = NULL;
1657  m->nb_segs = 1;
1658  }
1659  rte_mbuf_refcnt_set(m, 1);
1660 
1661  return m;
1662  }
1663  return NULL;
1664 }
1665 
1666 /* deprecated, replaced by rte_pktmbuf_prefree_seg() */
1667 __rte_deprecated
1668 static inline struct rte_mbuf *
1669 __rte_pktmbuf_prefree_seg(struct rte_mbuf *m)
1670 {
1671  return rte_pktmbuf_prefree_seg(m);
1672 }
1673 
1683 static __rte_always_inline void
1685 {
1686  m = rte_pktmbuf_prefree_seg(m);
1687  if (likely(m != NULL))
1688  rte_mbuf_raw_free(m);
1689 }
1690 
1700 static inline void rte_pktmbuf_free(struct rte_mbuf *m)
1701 {
1702  struct rte_mbuf *m_next;
1703 
1704  if (m != NULL)
1706 
1707  while (m != NULL) {
1708  m_next = m->next;
1710  m = m_next;
1711  }
1712 }
1713 
1731 static inline struct rte_mbuf *rte_pktmbuf_clone(struct rte_mbuf *md,
1732  struct rte_mempool *mp)
1733 {
1734  struct rte_mbuf *mc, *mi, **prev;
1735  uint32_t pktlen;
1736  uint16_t nseg;
1737 
1738  if (unlikely ((mc = rte_pktmbuf_alloc(mp)) == NULL))
1739  return NULL;
1740 
1741  mi = mc;
1742  prev = &mi->next;
1743  pktlen = md->pkt_len;
1744  nseg = 0;
1745 
1746  do {
1747  nseg++;
1748  rte_pktmbuf_attach(mi, md);
1749  *prev = mi;
1750  prev = &mi->next;
1751  } while ((md = md->next) != NULL &&
1752  (mi = rte_pktmbuf_alloc(mp)) != NULL);
1753 
1754  *prev = NULL;
1755  mc->nb_segs = nseg;
1756  mc->pkt_len = pktlen;
1757 
1758  /* Allocation of new indirect segment failed */
1759  if (unlikely (mi == NULL)) {
1760  rte_pktmbuf_free(mc);
1761  return NULL;
1762  }
1763 
1764  __rte_mbuf_sanity_check(mc, 1);
1765  return mc;
1766 }
1767 
1779 static inline void rte_pktmbuf_refcnt_update(struct rte_mbuf *m, int16_t v)
1780 {
1782 
1783  do {
1784  rte_mbuf_refcnt_update(m, v);
1785  } while ((m = m->next) != NULL);
1786 }
1787 
1796 static inline uint16_t rte_pktmbuf_headroom(const struct rte_mbuf *m)
1797 {
1799  return m->data_off;
1800 }
1801 
1810 static inline uint16_t rte_pktmbuf_tailroom(const struct rte_mbuf *m)
1811 {
1813  return (uint16_t)(m->buf_len - rte_pktmbuf_headroom(m) -
1814  m->data_len);
1815 }
1816 
1825 static inline struct rte_mbuf *rte_pktmbuf_lastseg(struct rte_mbuf *m)
1826 {
1828  while (m->next != NULL)
1829  m = m->next;
1830  return m;
1831 }
1832 
1847 #define rte_pktmbuf_mtod_offset(m, t, o) \
1848  ((t)((char *)(m)->buf_addr + (m)->data_off + (o)))
1849 
1862 #define rte_pktmbuf_mtod(m, t) rte_pktmbuf_mtod_offset(m, t, 0)
1863 
1873 #define rte_pktmbuf_iova_offset(m, o) \
1874  (rte_iova_t)((m)->buf_iova + (m)->data_off + (o))
1875 
1876 /* deprecated */
1877 #define rte_pktmbuf_mtophys_offset(m, o) \
1878  rte_pktmbuf_iova_offset(m, o)
1879 
1887 #define rte_pktmbuf_iova(m) rte_pktmbuf_iova_offset(m, 0)
1888 
1889 /* deprecated */
1890 #define rte_pktmbuf_mtophys(m) rte_pktmbuf_iova(m)
1891 
1900 #define rte_pktmbuf_pkt_len(m) ((m)->pkt_len)
1901 
1910 #define rte_pktmbuf_data_len(m) ((m)->data_len)
1911 
1927 static inline char *rte_pktmbuf_prepend(struct rte_mbuf *m,
1928  uint16_t len)
1929 {
1931 
1932  if (unlikely(len > rte_pktmbuf_headroom(m)))
1933  return NULL;
1934 
1935  /* NB: elaborating the subtraction like this instead of using
1936  * -= allows us to ensure the result type is uint16_t
1937  * avoiding compiler warnings on gcc 8.1 at least */
1938  m->data_off = (uint16_t)(m->data_off - len);
1939  m->data_len = (uint16_t)(m->data_len + len);
1940  m->pkt_len = (m->pkt_len + len);
1941 
1942  return (char *)m->buf_addr + m->data_off;
1943 }
1944 
1960 static inline char *rte_pktmbuf_append(struct rte_mbuf *m, uint16_t len)
1961 {
1962  void *tail;
1963  struct rte_mbuf *m_last;
1964 
1966 
1967  m_last = rte_pktmbuf_lastseg(m);
1968  if (unlikely(len > rte_pktmbuf_tailroom(m_last)))
1969  return NULL;
1970 
1971  tail = (char *)m_last->buf_addr + m_last->data_off + m_last->data_len;
1972  m_last->data_len = (uint16_t)(m_last->data_len + len);
1973  m->pkt_len = (m->pkt_len + len);
1974  return (char*) tail;
1975 }
1976 
1991 static inline char *rte_pktmbuf_adj(struct rte_mbuf *m, uint16_t len)
1992 {
1994 
1995  if (unlikely(len > m->data_len))
1996  return NULL;
1997 
1998  /* NB: elaborating the addition like this instead of using
1999  * += allows us to ensure the result type is uint16_t
2000  * avoiding compiler warnings on gcc 8.1 at least */
2001  m->data_len = (uint16_t)(m->data_len - len);
2002  m->data_off = (uint16_t)(m->data_off + len);
2003  m->pkt_len = (m->pkt_len - len);
2004  return (char *)m->buf_addr + m->data_off;
2005 }
2006 
2021 static inline int rte_pktmbuf_trim(struct rte_mbuf *m, uint16_t len)
2022 {
2023  struct rte_mbuf *m_last;
2024 
2026 
2027  m_last = rte_pktmbuf_lastseg(m);
2028  if (unlikely(len > m_last->data_len))
2029  return -1;
2030 
2031  m_last->data_len = (uint16_t)(m_last->data_len - len);
2032  m->pkt_len = (m->pkt_len - len);
2033  return 0;
2034 }
2035 
2045 static inline int rte_pktmbuf_is_contiguous(const struct rte_mbuf *m)
2046 {
2048  return !!(m->nb_segs == 1);
2049 }
2050 
2054 const void *__rte_pktmbuf_read(const struct rte_mbuf *m, uint32_t off,
2055  uint32_t len, void *buf);
2056 
2077 static inline const void *rte_pktmbuf_read(const struct rte_mbuf *m,
2078  uint32_t off, uint32_t len, void *buf)
2079 {
2080  if (likely(off + len <= rte_pktmbuf_data_len(m)))
2081  return rte_pktmbuf_mtod_offset(m, char *, off);
2082  else
2083  return __rte_pktmbuf_read(m, off, len, buf);
2084 }
2085 
2102 static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail)
2103 {
2104  struct rte_mbuf *cur_tail;
2105 
2106  /* Check for number-of-segments-overflow */
2107  if (head->nb_segs + tail->nb_segs > RTE_MBUF_MAX_NB_SEGS)
2108  return -EOVERFLOW;
2109 
2110  /* Chain 'tail' onto the old tail */
2111  cur_tail = rte_pktmbuf_lastseg(head);
2112  cur_tail->next = tail;
2113 
2114  /* accumulate number of segments and total length.
2115  * NB: elaborating the addition like this instead of using
2116  * -= allows us to ensure the result type is uint16_t
2117  * avoiding compiler warnings on gcc 8.1 at least */
2118  head->nb_segs = (uint16_t)(head->nb_segs + tail->nb_segs);
2119  head->pkt_len += tail->pkt_len;
2120 
2121  /* pkt_len is only set in the head */
2122  tail->pkt_len = tail->data_len;
2123 
2124  return 0;
2125 }
2126 
2137 static inline int
2139 {
2140  uint64_t ol_flags = m->ol_flags;
2141  uint64_t inner_l3_offset = m->l2_len;
2142 
2143  /* Does packet set any of available offloads? */
2144  if (!(ol_flags & PKT_TX_OFFLOAD_MASK))
2145  return 0;
2146 
2147  if (ol_flags & PKT_TX_OUTER_IP_CKSUM)
2148  /* NB: elaborating the addition like this instead of using
2149  * += gives the result uint64_t type instead of int,
2150  * avoiding compiler warnings on gcc 8.1 at least */
2151  inner_l3_offset = inner_l3_offset + m->outer_l2_len +
2152  m->outer_l3_len;
2153 
2154  /* Headers are fragmented */
2155  if (rte_pktmbuf_data_len(m) < inner_l3_offset + m->l3_len + m->l4_len)
2156  return -ENOTSUP;
2157 
2158  /* IP checksum can be counted only for IPv4 packet */
2159  if ((ol_flags & PKT_TX_IP_CKSUM) && (ol_flags & PKT_TX_IPV6))
2160  return -EINVAL;
2161 
2162  /* IP type not set when required */
2163  if (ol_flags & (PKT_TX_L4_MASK | PKT_TX_TCP_SEG))
2164  if (!(ol_flags & (PKT_TX_IPV4 | PKT_TX_IPV6)))
2165  return -EINVAL;
2166 
2167  /* Check requirements for TSO packet */
2168  if (ol_flags & PKT_TX_TCP_SEG)
2169  if ((m->tso_segsz == 0) ||
2170  ((ol_flags & PKT_TX_IPV4) &&
2171  !(ol_flags & PKT_TX_IP_CKSUM)))
2172  return -EINVAL;
2173 
2174  /* PKT_TX_OUTER_IP_CKSUM set for non outer IPv4 packet. */
2175  if ((ol_flags & PKT_TX_OUTER_IP_CKSUM) &&
2176  !(ol_flags & PKT_TX_OUTER_IPV4))
2177  return -EINVAL;
2178 
2179  return 0;
2180 }
2181 
2194 static inline int
2196 {
2197  size_t seg_len, copy_len;
2198  struct rte_mbuf *m;
2199  struct rte_mbuf *m_next;
2200  char *buffer;
2201 
2202  if (rte_pktmbuf_is_contiguous(mbuf))
2203  return 0;
2204 
2205  /* Extend first segment to the total packet length */
2206  copy_len = rte_pktmbuf_pkt_len(mbuf) - rte_pktmbuf_data_len(mbuf);
2207 
2208  if (unlikely(copy_len > rte_pktmbuf_tailroom(mbuf)))
2209  return -1;
2210 
2211  buffer = rte_pktmbuf_mtod_offset(mbuf, char *, mbuf->data_len);
2212  mbuf->data_len = (uint16_t)(mbuf->pkt_len);
2213 
2214  /* Append data from next segments to the first one */
2215  m = mbuf->next;
2216  while (m != NULL) {
2217  m_next = m->next;
2218 
2219  seg_len = rte_pktmbuf_data_len(m);
2220  rte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), seg_len);
2221  buffer += seg_len;
2222 
2224  m = m_next;
2225  }
2226 
2227  mbuf->next = NULL;
2228  mbuf->nb_segs = 1;
2229 
2230  return 0;
2231 }
2232 
2247 void rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len);
2248 
2249 #ifdef __cplusplus
2250 }
2251 #endif
2252 
2253 #endif /* _RTE_MBUF_H_ */