DPDK  19.05.0
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_byteorder.h>
44 #include <rte_mbuf_ptype.h>
45 
46 #ifdef __cplusplus
47 extern "C" {
48 #endif
49 
50 /*
51  * Packet Offload Features Flags. It also carry packet type information.
52  * Critical resources. Both rx/tx shared these bits. Be cautious on any change
53  *
54  * - RX flags start at bit position zero, and get added to the left of previous
55  * flags.
56  * - The most-significant 3 bits are reserved for generic mbuf flags
57  * - TX flags therefore start at bit position 60 (i.e. 63-3), and new flags get
58  * added to the right of the previously defined flags i.e. they should count
59  * downwards, not upwards.
60  *
61  * Keep these flags synchronized with rte_get_rx_ol_flag_name() and
62  * rte_get_tx_ol_flag_name().
63  */
64 
72 #define PKT_RX_VLAN (1ULL << 0)
73 
74 #define PKT_RX_RSS_HASH (1ULL << 1)
75 #define PKT_RX_FDIR (1ULL << 2)
84 #define PKT_RX_L4_CKSUM_BAD (1ULL << 3)
85 
93 #define PKT_RX_IP_CKSUM_BAD (1ULL << 4)
94 
95 #define PKT_RX_EIP_CKSUM_BAD (1ULL << 5)
103 #define PKT_RX_VLAN_STRIPPED (1ULL << 6)
104 
113 #define PKT_RX_IP_CKSUM_MASK ((1ULL << 4) | (1ULL << 7))
114 
115 #define PKT_RX_IP_CKSUM_UNKNOWN 0
116 #define PKT_RX_IP_CKSUM_BAD (1ULL << 4)
117 #define PKT_RX_IP_CKSUM_GOOD (1ULL << 7)
118 #define PKT_RX_IP_CKSUM_NONE ((1ULL << 4) | (1ULL << 7))
119 
128 #define PKT_RX_L4_CKSUM_MASK ((1ULL << 3) | (1ULL << 8))
129 
130 #define PKT_RX_L4_CKSUM_UNKNOWN 0
131 #define PKT_RX_L4_CKSUM_BAD (1ULL << 3)
132 #define PKT_RX_L4_CKSUM_GOOD (1ULL << 8)
133 #define PKT_RX_L4_CKSUM_NONE ((1ULL << 3) | (1ULL << 8))
134 
135 #define PKT_RX_IEEE1588_PTP (1ULL << 9)
136 #define PKT_RX_IEEE1588_TMST (1ULL << 10)
137 #define PKT_RX_FDIR_ID (1ULL << 13)
138 #define PKT_RX_FDIR_FLX (1ULL << 14)
148 #define PKT_RX_QINQ_STRIPPED (1ULL << 15)
149 
155 #define PKT_RX_LRO (1ULL << 16)
156 
160 #define PKT_RX_TIMESTAMP (1ULL << 17)
161 
165 #define PKT_RX_SEC_OFFLOAD (1ULL << 18)
166 
170 #define PKT_RX_SEC_OFFLOAD_FAILED (1ULL << 19)
171 
180 #define PKT_RX_QINQ (1ULL << 20)
181 
194 #define PKT_RX_OUTER_L4_CKSUM_MASK ((1ULL << 21) | (1ULL << 22))
195 
196 #define PKT_RX_OUTER_L4_CKSUM_UNKNOWN 0
197 #define PKT_RX_OUTER_L4_CKSUM_BAD (1ULL << 21)
198 #define PKT_RX_OUTER_L4_CKSUM_GOOD (1ULL << 22)
199 #define PKT_RX_OUTER_L4_CKSUM_INVALID ((1ULL << 21) | (1ULL << 22))
200 
201 /* add new RX flags here */
202 
203 /* add new TX flags here */
204 
208 #define PKT_TX_METADATA (1ULL << 40)
209 
219 #define PKT_TX_OUTER_UDP_CKSUM (1ULL << 41)
220 
226 #define PKT_TX_UDP_SEG (1ULL << 42)
227 
231 #define PKT_TX_SEC_OFFLOAD (1ULL << 43)
232 
237 #define PKT_TX_MACSEC (1ULL << 44)
238 
247 #define PKT_TX_TUNNEL_VXLAN (0x1ULL << 45)
248 #define PKT_TX_TUNNEL_GRE (0x2ULL << 45)
249 #define PKT_TX_TUNNEL_IPIP (0x3ULL << 45)
250 #define PKT_TX_TUNNEL_GENEVE (0x4ULL << 45)
251 
252 #define PKT_TX_TUNNEL_MPLSINUDP (0x5ULL << 45)
253 #define PKT_TX_TUNNEL_VXLAN_GPE (0x6ULL << 45)
254 
265 #define PKT_TX_TUNNEL_IP (0xDULL << 45)
266 
278 #define PKT_TX_TUNNEL_UDP (0xEULL << 45)
279 /* add new TX TUNNEL type here */
280 #define PKT_TX_TUNNEL_MASK (0xFULL << 45)
281 
287 #define PKT_TX_QINQ (1ULL << 49)
288 /* this old name is deprecated */
289 #define PKT_TX_QINQ_PKT PKT_TX_QINQ
290 
300 #define PKT_TX_TCP_SEG (1ULL << 50)
301 
302 #define PKT_TX_IEEE1588_TMST (1ULL << 51)
312 #define PKT_TX_L4_NO_CKSUM (0ULL << 52)
313 #define PKT_TX_TCP_CKSUM (1ULL << 52)
314 #define PKT_TX_SCTP_CKSUM (2ULL << 52)
315 #define PKT_TX_UDP_CKSUM (3ULL << 52)
316 #define PKT_TX_L4_MASK (3ULL << 52)
324 #define PKT_TX_IP_CKSUM (1ULL << 54)
325 
332 #define PKT_TX_IPV4 (1ULL << 55)
333 
340 #define PKT_TX_IPV6 (1ULL << 56)
341 
347 #define PKT_TX_VLAN (1ULL << 57)
348 /* this old name is deprecated */
349 #define PKT_TX_VLAN_PKT PKT_TX_VLAN
350 
357 #define PKT_TX_OUTER_IP_CKSUM (1ULL << 58)
358 
364 #define PKT_TX_OUTER_IPV4 (1ULL << 59)
365 
371 #define PKT_TX_OUTER_IPV6 (1ULL << 60)
372 
377 #define PKT_TX_OFFLOAD_MASK ( \
378  PKT_TX_OUTER_IPV6 | \
379  PKT_TX_OUTER_IPV4 | \
380  PKT_TX_OUTER_IP_CKSUM | \
381  PKT_TX_VLAN_PKT | \
382  PKT_TX_IPV6 | \
383  PKT_TX_IPV4 | \
384  PKT_TX_IP_CKSUM | \
385  PKT_TX_L4_MASK | \
386  PKT_TX_IEEE1588_TMST | \
387  PKT_TX_TCP_SEG | \
388  PKT_TX_QINQ_PKT | \
389  PKT_TX_TUNNEL_MASK | \
390  PKT_TX_MACSEC | \
391  PKT_TX_SEC_OFFLOAD | \
392  PKT_TX_UDP_SEG | \
393  PKT_TX_OUTER_UDP_CKSUM | \
394  PKT_TX_METADATA)
395 
399 #define EXT_ATTACHED_MBUF (1ULL << 61)
400 
401 #define IND_ATTACHED_MBUF (1ULL << 62)
404 #define RTE_MBUF_PRIV_ALIGN 8
405 
414 const char *rte_get_rx_ol_flag_name(uint64_t mask);
415 
428 int rte_get_rx_ol_flag_list(uint64_t mask, char *buf, size_t buflen);
429 
440 const char *rte_get_tx_ol_flag_name(uint64_t mask);
441 
454 int rte_get_tx_ol_flag_list(uint64_t mask, char *buf, size_t buflen);
455 
462 #define RTE_MBUF_DEFAULT_DATAROOM 2048
463 #define RTE_MBUF_DEFAULT_BUF_SIZE \
464  (RTE_MBUF_DEFAULT_DATAROOM + RTE_PKTMBUF_HEADROOM)
465 
466 /* define a set of marker types that can be used to refer to set points in the
467  * mbuf */
468 __extension__
469 typedef void *MARKER[0];
470 __extension__
471 typedef uint8_t MARKER8[0];
472 __extension__
473 typedef uint64_t MARKER64[0];
477  uint32_t queue_id;
478  uint8_t traffic_class;
482  uint8_t color;
484  uint16_t reserved;
485 };
491 enum {
492  RTE_MBUF_L2_LEN_BITS = 7,
493  RTE_MBUF_L3_LEN_BITS = 9,
494  RTE_MBUF_L4_LEN_BITS = 8,
495  RTE_MBUF_TSO_SEGSZ_BITS = 16,
496  RTE_MBUF_OUTL3_LEN_BITS = 9,
497  RTE_MBUF_OUTL2_LEN_BITS = 7,
498  RTE_MBUF_TXOFLD_UNUSED_BITS = sizeof(uint64_t) * CHAR_BIT -
499  RTE_MBUF_L2_LEN_BITS -
500  RTE_MBUF_L3_LEN_BITS -
501  RTE_MBUF_L4_LEN_BITS -
502  RTE_MBUF_TSO_SEGSZ_BITS -
503  RTE_MBUF_OUTL3_LEN_BITS -
504  RTE_MBUF_OUTL2_LEN_BITS,
505 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
506  RTE_MBUF_L2_LEN_OFS =
507  sizeof(uint64_t) * CHAR_BIT - RTE_MBUF_L2_LEN_BITS,
508  RTE_MBUF_L3_LEN_OFS = RTE_MBUF_L2_LEN_OFS - RTE_MBUF_L3_LEN_BITS,
509  RTE_MBUF_L4_LEN_OFS = RTE_MBUF_L3_LEN_OFS - RTE_MBUF_L4_LEN_BITS,
510  RTE_MBUF_TSO_SEGSZ_OFS = RTE_MBUF_L4_LEN_OFS - RTE_MBUF_TSO_SEGSZ_BITS,
511  RTE_MBUF_OUTL3_LEN_OFS =
512  RTE_MBUF_TSO_SEGSZ_OFS - RTE_MBUF_OUTL3_LEN_BITS,
513  RTE_MBUF_OUTL2_LEN_OFS =
514  RTE_MBUF_OUTL3_LEN_OFS - RTE_MBUF_OUTL2_LEN_BITS,
515  RTE_MBUF_TXOFLD_UNUSED_OFS =
516  RTE_MBUF_OUTL2_LEN_OFS - RTE_MBUF_TXOFLD_UNUSED_BITS,
517 #else
518  RTE_MBUF_L2_LEN_OFS = 0,
519  RTE_MBUF_L3_LEN_OFS = RTE_MBUF_L2_LEN_OFS + RTE_MBUF_L2_LEN_BITS,
520  RTE_MBUF_L4_LEN_OFS = RTE_MBUF_L3_LEN_OFS + RTE_MBUF_L3_LEN_BITS,
521  RTE_MBUF_TSO_SEGSZ_OFS = RTE_MBUF_L4_LEN_OFS + RTE_MBUF_L4_LEN_BITS,
522  RTE_MBUF_OUTL3_LEN_OFS =
523  RTE_MBUF_TSO_SEGSZ_OFS + RTE_MBUF_TSO_SEGSZ_BITS,
524  RTE_MBUF_OUTL2_LEN_OFS =
525  RTE_MBUF_OUTL3_LEN_OFS + RTE_MBUF_OUTL3_LEN_BITS,
526  RTE_MBUF_TXOFLD_UNUSED_OFS =
527  RTE_MBUF_OUTL2_LEN_OFS + RTE_MBUF_OUTL2_LEN_BITS,
528 #endif
529 };
530 
534 struct rte_mbuf {
535  MARKER cacheline0;
536 
537  void *buf_addr;
545  union {
546  rte_iova_t buf_iova;
548  } __rte_aligned(sizeof(rte_iova_t));
549 
550  /* next 8 bytes are initialised on RX descriptor rearm */
551  MARKER64 rearm_data;
552  uint16_t data_off;
553 
564  union {
566  uint16_t refcnt;
567  };
568  uint16_t nb_segs;
573  uint16_t port;
574 
575  uint64_t ol_flags;
577  /* remaining bytes are set on RX when pulling packet from descriptor */
578  MARKER rx_descriptor_fields1;
579 
580  /*
581  * The packet type, which is the combination of outer/inner L2, L3, L4
582  * and tunnel types. The packet_type is about data really present in the
583  * mbuf. Example: if vlan stripping is enabled, a received vlan packet
584  * would have RTE_PTYPE_L2_ETHER and not RTE_PTYPE_L2_VLAN because the
585  * vlan is stripped from the data.
586  */
588  union {
589  uint32_t packet_type;
590  struct {
591  uint32_t l2_type:4;
592  uint32_t l3_type:4;
593  uint32_t l4_type:4;
594  uint32_t tun_type:4;
596  union {
597  uint8_t inner_esp_next_proto;
602  __extension__
603  struct {
604  uint8_t inner_l2_type:4;
606  uint8_t inner_l3_type:4;
608  };
609  };
610  uint32_t inner_l4_type:4;
611  };
612  };
613 
614  uint32_t pkt_len;
615  uint16_t data_len;
617  uint16_t vlan_tci;
618 
620  union {
621  union {
622  uint32_t rss;
623  struct {
624  union {
625  struct {
626  uint16_t hash;
627  uint16_t id;
628  };
629  uint32_t lo;
631  };
632  uint32_t hi;
636  } fdir;
639  struct {
640  uint32_t reserved1;
641  uint16_t reserved2;
642  uint16_t txq;
647  } txadapter;
649  uint32_t usr;
650  } hash;
651  struct {
659  uint32_t tx_metadata;
660  uint32_t reserved;
661  };
662  };
663 
665  uint16_t vlan_tci_outer;
666 
667  uint16_t buf_len;
672  uint64_t timestamp;
673 
674  /* second cache line - fields only used in slow path or on TX */
675  MARKER cacheline1 __rte_cache_min_aligned;
676 
678  union {
679  void *userdata;
680  uint64_t udata64;
681  };
682 
683  struct rte_mempool *pool;
684  struct rte_mbuf *next;
686  /* fields to support TX offloads */
688  union {
689  uint64_t tx_offload;
690  __extension__
691  struct {
692  uint64_t l2_len:RTE_MBUF_L2_LEN_BITS;
696  uint64_t l3_len:RTE_MBUF_L3_LEN_BITS;
698  uint64_t l4_len:RTE_MBUF_L4_LEN_BITS;
700  uint64_t tso_segsz:RTE_MBUF_TSO_SEGSZ_BITS;
703  /* fields for TX offloading of tunnels */
704  uint64_t outer_l3_len:RTE_MBUF_OUTL3_LEN_BITS;
706  uint64_t outer_l2_len:RTE_MBUF_OUTL2_LEN_BITS;
709  /* uint64_t unused:RTE_MBUF_TXOFLD_UNUSED_BITS; */
710  };
711  };
712 
715  uint16_t priv_size;
716 
718  uint16_t timesync;
719 
721  uint32_t seqn;
722 
727 
729 
733 typedef void (*rte_mbuf_extbuf_free_callback_t)(void *addr, void *opaque);
734 
740  void *fcb_opaque;
742 };
743 
745 #define RTE_MBUF_MAX_NB_SEGS UINT16_MAX
746 
757 static inline void
759 {
760  rte_prefetch0(&m->cacheline0);
761 }
762 
774 static inline void
776 {
777 #if RTE_CACHE_LINE_SIZE == 64
778  rte_prefetch0(&m->cacheline1);
779 #else
780  RTE_SET_USED(m);
781 #endif
782 }
783 
784 
785 static inline uint16_t rte_pktmbuf_priv_size(struct rte_mempool *mp);
786 
795 static inline rte_iova_t
796 rte_mbuf_data_iova(const struct rte_mbuf *mb)
797 {
798  return mb->buf_iova + mb->data_off;
799 }
800 
801 __rte_deprecated
802 static inline phys_addr_t
803 rte_mbuf_data_dma_addr(const struct rte_mbuf *mb)
804 {
805  return rte_mbuf_data_iova(mb);
806 }
807 
820 static inline rte_iova_t
822 {
823  return mb->buf_iova + RTE_PKTMBUF_HEADROOM;
824 }
825 
826 __rte_deprecated
827 static inline phys_addr_t
828 rte_mbuf_data_dma_addr_default(const struct rte_mbuf *mb)
829 {
830  return rte_mbuf_data_iova_default(mb);
831 }
832 
841 static inline struct rte_mbuf *
843 {
844  return (struct rte_mbuf *)RTE_PTR_SUB(mi->buf_addr, sizeof(*mi) + mi->priv_size);
845 }
846 
867 static inline char * __rte_experimental
868 rte_mbuf_buf_addr(struct rte_mbuf *mb, struct rte_mempool *mp)
869 {
870  return (char *)mb + sizeof(*mb) + rte_pktmbuf_priv_size(mp);
871 }
872 
884 static inline char * __rte_experimental
886 {
887  return rte_mbuf_buf_addr(mb, mb->pool) + RTE_PKTMBUF_HEADROOM;
888 }
889 
903 static inline char *
905 {
906 #ifdef ALLOW_EXPERIMENTAL_API
907  return rte_mbuf_buf_addr(md, md->pool);
908 #else
909  char *buffer_addr;
910  buffer_addr = (char *)md + sizeof(*md) + rte_pktmbuf_priv_size(md->pool);
911  return buffer_addr;
912 #endif
913 }
914 
927 static inline void * __rte_experimental
929 {
930  return RTE_PTR_ADD(m, sizeof(struct rte_mbuf));
931 }
932 
940 #define RTE_MBUF_CLONED(mb) ((mb)->ol_flags & IND_ATTACHED_MBUF)
941 
947 #define RTE_MBUF_HAS_EXTBUF(mb) ((mb)->ol_flags & EXT_ATTACHED_MBUF)
948 
955 #define RTE_MBUF_DIRECT(mb) \
956  (!((mb)->ol_flags & (IND_ATTACHED_MBUF | EXT_ATTACHED_MBUF)))
957 
966  uint16_t mbuf_priv_size;
967 };
968 
969 #ifdef RTE_LIBRTE_MBUF_DEBUG
970 
972 #define __rte_mbuf_sanity_check(m, is_h) rte_mbuf_sanity_check(m, is_h)
973 
974 #else /* RTE_LIBRTE_MBUF_DEBUG */
975 
977 #define __rte_mbuf_sanity_check(m, is_h) do { } while (0)
978 
979 #endif /* RTE_LIBRTE_MBUF_DEBUG */
980 
981 #ifdef RTE_MBUF_REFCNT_ATOMIC
982 
990 static inline uint16_t
991 rte_mbuf_refcnt_read(const struct rte_mbuf *m)
992 {
993  return (uint16_t)(rte_atomic16_read(&m->refcnt_atomic));
994 }
995 
1003 static inline void
1004 rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
1005 {
1006  rte_atomic16_set(&m->refcnt_atomic, (int16_t)new_value);
1007 }
1008 
1009 /* internal */
1010 static inline uint16_t
1011 __rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
1012 {
1013  return (uint16_t)(rte_atomic16_add_return(&m->refcnt_atomic, value));
1014 }
1015 
1025 static inline uint16_t
1026 rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
1027 {
1028  /*
1029  * The atomic_add is an expensive operation, so we don't want to
1030  * call it in the case where we know we are the unique holder of
1031  * this mbuf (i.e. ref_cnt == 1). Otherwise, an atomic
1032  * operation has to be used because concurrent accesses on the
1033  * reference counter can occur.
1034  */
1035  if (likely(rte_mbuf_refcnt_read(m) == 1)) {
1036  ++value;
1037  rte_mbuf_refcnt_set(m, (uint16_t)value);
1038  return (uint16_t)value;
1039  }
1040 
1041  return __rte_mbuf_refcnt_update(m, value);
1042 }
1043 
1044 #else /* ! RTE_MBUF_REFCNT_ATOMIC */
1045 
1046 /* internal */
1047 static inline uint16_t
1048 __rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
1049 {
1050  m->refcnt = (uint16_t)(m->refcnt + value);
1051  return m->refcnt;
1052 }
1053 
1057 static inline uint16_t
1058 rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
1059 {
1060  return __rte_mbuf_refcnt_update(m, value);
1061 }
1062 
1066 static inline uint16_t
1068 {
1069  return m->refcnt;
1070 }
1071 
1075 static inline void
1076 rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
1077 {
1078  m->refcnt = new_value;
1079 }
1080 
1081 #endif /* RTE_MBUF_REFCNT_ATOMIC */
1082 
1091 static inline uint16_t
1093 {
1094  return (uint16_t)(rte_atomic16_read(&shinfo->refcnt_atomic));
1095 }
1096 
1105 static inline void
1107  uint16_t new_value)
1108 {
1109  rte_atomic16_set(&shinfo->refcnt_atomic, (int16_t)new_value);
1110 }
1111 
1123 static inline uint16_t
1125  int16_t value)
1126 {
1127  if (likely(rte_mbuf_ext_refcnt_read(shinfo) == 1)) {
1128  ++value;
1129  rte_mbuf_ext_refcnt_set(shinfo, (uint16_t)value);
1130  return (uint16_t)value;
1131  }
1132 
1133  return (uint16_t)rte_atomic16_add_return(&shinfo->refcnt_atomic, value);
1134 }
1135 
1137 #define RTE_MBUF_PREFETCH_TO_FREE(m) do { \
1138  if ((m) != NULL) \
1139  rte_prefetch0(m); \
1140 } while (0)
1141 
1142 
1155 void
1156 rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header);
1157 
1177 __rte_experimental
1178 int rte_mbuf_check(const struct rte_mbuf *m, int is_header,
1179  const char **reason);
1180 
1181 #define MBUF_RAW_ALLOC_CHECK(m) do { \
1182  RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1); \
1183  RTE_ASSERT((m)->next == NULL); \
1184  RTE_ASSERT((m)->nb_segs == 1); \
1185  __rte_mbuf_sanity_check(m, 0); \
1186 } while (0)
1187 
1207 static inline struct rte_mbuf *rte_mbuf_raw_alloc(struct rte_mempool *mp)
1208 {
1209  struct rte_mbuf *m;
1210 
1211  if (rte_mempool_get(mp, (void **)&m) < 0)
1212  return NULL;
1213  MBUF_RAW_ALLOC_CHECK(m);
1214  return m;
1215 }
1216 
1231 static __rte_always_inline void
1233 {
1234  RTE_ASSERT(RTE_MBUF_DIRECT(m));
1235  RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1);
1236  RTE_ASSERT(m->next == NULL);
1237  RTE_ASSERT(m->nb_segs == 1);
1239  rte_mempool_put(m->pool, m);
1240 }
1241 
1261 void rte_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg,
1262  void *m, unsigned i);
1263 
1264 
1282 void rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg);
1283 
1318 struct rte_mempool *
1319 rte_pktmbuf_pool_create(const char *name, unsigned n,
1320  unsigned cache_size, uint16_t priv_size, uint16_t data_room_size,
1321  int socket_id);
1322 
1360 struct rte_mempool *
1361 rte_pktmbuf_pool_create_by_ops(const char *name, unsigned int n,
1362  unsigned int cache_size, uint16_t priv_size, uint16_t data_room_size,
1363  int socket_id, const char *ops_name);
1364 
1376 static inline uint16_t
1378 {
1379  struct rte_pktmbuf_pool_private *mbp_priv;
1380 
1381  mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
1382  return mbp_priv->mbuf_data_room_size;
1383 }
1384 
1397 static inline uint16_t
1399 {
1400  struct rte_pktmbuf_pool_private *mbp_priv;
1401 
1402  mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
1403  return mbp_priv->mbuf_priv_size;
1404 }
1405 
1414 static inline void rte_pktmbuf_reset_headroom(struct rte_mbuf *m)
1415 {
1416  m->data_off = (uint16_t)RTE_MIN((uint16_t)RTE_PKTMBUF_HEADROOM,
1417  (uint16_t)m->buf_len);
1418 }
1419 
1428 #define MBUF_INVALID_PORT UINT16_MAX
1429 
1430 static inline void rte_pktmbuf_reset(struct rte_mbuf *m)
1431 {
1432  m->next = NULL;
1433  m->pkt_len = 0;
1434  m->tx_offload = 0;
1435  m->vlan_tci = 0;
1436  m->vlan_tci_outer = 0;
1437  m->nb_segs = 1;
1438  m->port = MBUF_INVALID_PORT;
1439 
1440  m->ol_flags = 0;
1441  m->packet_type = 0;
1443 
1444  m->data_len = 0;
1446 }
1447 
1461 static inline struct rte_mbuf *rte_pktmbuf_alloc(struct rte_mempool *mp)
1462 {
1463  struct rte_mbuf *m;
1464  if ((m = rte_mbuf_raw_alloc(mp)) != NULL)
1465  rte_pktmbuf_reset(m);
1466  return m;
1467 }
1468 
1483 static inline int rte_pktmbuf_alloc_bulk(struct rte_mempool *pool,
1484  struct rte_mbuf **mbufs, unsigned count)
1485 {
1486  unsigned idx = 0;
1487  int rc;
1488 
1489  rc = rte_mempool_get_bulk(pool, (void **)mbufs, count);
1490  if (unlikely(rc))
1491  return rc;
1492 
1493  /* To understand duff's device on loop unwinding optimization, see
1494  * https://en.wikipedia.org/wiki/Duff's_device.
1495  * Here while() loop is used rather than do() while{} to avoid extra
1496  * check if count is zero.
1497  */
1498  switch (count % 4) {
1499  case 0:
1500  while (idx != count) {
1501  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1502  rte_pktmbuf_reset(mbufs[idx]);
1503  idx++;
1504  /* fall-through */
1505  case 3:
1506  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1507  rte_pktmbuf_reset(mbufs[idx]);
1508  idx++;
1509  /* fall-through */
1510  case 2:
1511  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1512  rte_pktmbuf_reset(mbufs[idx]);
1513  idx++;
1514  /* fall-through */
1515  case 1:
1516  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1517  rte_pktmbuf_reset(mbufs[idx]);
1518  idx++;
1519  /* fall-through */
1520  }
1521  }
1522  return 0;
1523 }
1524 
1557 static inline struct rte_mbuf_ext_shared_info *
1558 rte_pktmbuf_ext_shinfo_init_helper(void *buf_addr, uint16_t *buf_len,
1560 {
1561  struct rte_mbuf_ext_shared_info *shinfo;
1562  void *buf_end = RTE_PTR_ADD(buf_addr, *buf_len);
1563  void *addr;
1564 
1565  addr = RTE_PTR_ALIGN_FLOOR(RTE_PTR_SUB(buf_end, sizeof(*shinfo)),
1566  sizeof(uintptr_t));
1567  if (addr <= buf_addr)
1568  return NULL;
1569 
1570  shinfo = (struct rte_mbuf_ext_shared_info *)addr;
1571  shinfo->free_cb = free_cb;
1572  shinfo->fcb_opaque = fcb_opaque;
1573  rte_mbuf_ext_refcnt_set(shinfo, 1);
1574 
1575  *buf_len = (uint16_t)RTE_PTR_DIFF(shinfo, buf_addr);
1576  return shinfo;
1577 }
1578 
1635 static inline void
1636 rte_pktmbuf_attach_extbuf(struct rte_mbuf *m, void *buf_addr,
1637  rte_iova_t buf_iova, uint16_t buf_len,
1638  struct rte_mbuf_ext_shared_info *shinfo)
1639 {
1640  /* mbuf should not be read-only */
1641  RTE_ASSERT(RTE_MBUF_DIRECT(m) && rte_mbuf_refcnt_read(m) == 1);
1642  RTE_ASSERT(shinfo->free_cb != NULL);
1643 
1644  m->buf_addr = buf_addr;
1645  m->buf_iova = buf_iova;
1646  m->buf_len = buf_len;
1647 
1648  m->data_len = 0;
1649  m->data_off = 0;
1650 
1652  m->shinfo = shinfo;
1653 }
1654 
1662 #define rte_pktmbuf_detach_extbuf(m) rte_pktmbuf_detach(m)
1663 
1685 static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *m)
1686 {
1687  RTE_ASSERT(RTE_MBUF_DIRECT(mi) &&
1688  rte_mbuf_refcnt_read(mi) == 1);
1689 
1690  if (RTE_MBUF_HAS_EXTBUF(m)) {
1692  mi->ol_flags = m->ol_flags;
1693  mi->shinfo = m->shinfo;
1694  } else {
1695  /* if m is not direct, get the mbuf that embeds the data */
1697  mi->priv_size = m->priv_size;
1698  mi->ol_flags = m->ol_flags | IND_ATTACHED_MBUF;
1699  }
1700 
1701  mi->buf_iova = m->buf_iova;
1702  mi->buf_addr = m->buf_addr;
1703  mi->buf_len = m->buf_len;
1704 
1705  mi->data_off = m->data_off;
1706  mi->data_len = m->data_len;
1707  mi->port = m->port;
1708  mi->vlan_tci = m->vlan_tci;
1709  mi->vlan_tci_outer = m->vlan_tci_outer;
1710  mi->tx_offload = m->tx_offload;
1711  mi->hash = m->hash;
1712 
1713  mi->next = NULL;
1714  mi->pkt_len = mi->data_len;
1715  mi->nb_segs = 1;
1716  mi->packet_type = m->packet_type;
1717  mi->timestamp = m->timestamp;
1718 
1719  __rte_mbuf_sanity_check(mi, 1);
1721 }
1722 
1730 static inline void
1731 __rte_pktmbuf_free_extbuf(struct rte_mbuf *m)
1732 {
1733  RTE_ASSERT(RTE_MBUF_HAS_EXTBUF(m));
1734  RTE_ASSERT(m->shinfo != NULL);
1735 
1736  if (rte_mbuf_ext_refcnt_update(m->shinfo, -1) == 0)
1737  m->shinfo->free_cb(m->buf_addr, m->shinfo->fcb_opaque);
1738 }
1739 
1746 static inline void
1747 __rte_pktmbuf_free_direct(struct rte_mbuf *m)
1748 {
1749  struct rte_mbuf *md;
1750 
1751  RTE_ASSERT(RTE_MBUF_CLONED(m));
1752 
1753  md = rte_mbuf_from_indirect(m);
1754 
1755  if (rte_mbuf_refcnt_update(md, -1) == 0) {
1756  md->next = NULL;
1757  md->nb_segs = 1;
1758  rte_mbuf_refcnt_set(md, 1);
1759  rte_mbuf_raw_free(md);
1760  }
1761 }
1762 
1776 static inline void rte_pktmbuf_detach(struct rte_mbuf *m)
1777 {
1778  struct rte_mempool *mp = m->pool;
1779  uint32_t mbuf_size, buf_len;
1780  uint16_t priv_size;
1781 
1782  if (RTE_MBUF_HAS_EXTBUF(m))
1783  __rte_pktmbuf_free_extbuf(m);
1784  else
1785  __rte_pktmbuf_free_direct(m);
1786 
1787  priv_size = rte_pktmbuf_priv_size(mp);
1788  mbuf_size = (uint32_t)(sizeof(struct rte_mbuf) + priv_size);
1789  buf_len = rte_pktmbuf_data_room_size(mp);
1790 
1791  m->priv_size = priv_size;
1792  m->buf_addr = (char *)m + mbuf_size;
1793  m->buf_iova = rte_mempool_virt2iova(m) + mbuf_size;
1794  m->buf_len = (uint16_t)buf_len;
1796  m->data_len = 0;
1797  m->ol_flags = 0;
1798 }
1799 
1814 static __rte_always_inline struct rte_mbuf *
1816 {
1818 
1819  if (likely(rte_mbuf_refcnt_read(m) == 1)) {
1820 
1821  if (!RTE_MBUF_DIRECT(m))
1822  rte_pktmbuf_detach(m);
1823 
1824  if (m->next != NULL) {
1825  m->next = NULL;
1826  m->nb_segs = 1;
1827  }
1828 
1829  return m;
1830 
1831  } else if (__rte_mbuf_refcnt_update(m, -1) == 0) {
1832 
1833  if (!RTE_MBUF_DIRECT(m))
1834  rte_pktmbuf_detach(m);
1835 
1836  if (m->next != NULL) {
1837  m->next = NULL;
1838  m->nb_segs = 1;
1839  }
1840  rte_mbuf_refcnt_set(m, 1);
1841 
1842  return m;
1843  }
1844  return NULL;
1845 }
1846 
1856 static __rte_always_inline void
1858 {
1859  m = rte_pktmbuf_prefree_seg(m);
1860  if (likely(m != NULL))
1861  rte_mbuf_raw_free(m);
1862 }
1863 
1873 static inline void rte_pktmbuf_free(struct rte_mbuf *m)
1874 {
1875  struct rte_mbuf *m_next;
1876 
1877  if (m != NULL)
1879 
1880  while (m != NULL) {
1881  m_next = m->next;
1883  m = m_next;
1884  }
1885 }
1886 
1904 static inline struct rte_mbuf *rte_pktmbuf_clone(struct rte_mbuf *md,
1905  struct rte_mempool *mp)
1906 {
1907  struct rte_mbuf *mc, *mi, **prev;
1908  uint32_t pktlen;
1909  uint16_t nseg;
1910 
1911  if (unlikely ((mc = rte_pktmbuf_alloc(mp)) == NULL))
1912  return NULL;
1913 
1914  mi = mc;
1915  prev = &mi->next;
1916  pktlen = md->pkt_len;
1917  nseg = 0;
1918 
1919  do {
1920  nseg++;
1921  rte_pktmbuf_attach(mi, md);
1922  *prev = mi;
1923  prev = &mi->next;
1924  } while ((md = md->next) != NULL &&
1925  (mi = rte_pktmbuf_alloc(mp)) != NULL);
1926 
1927  *prev = NULL;
1928  mc->nb_segs = nseg;
1929  mc->pkt_len = pktlen;
1930 
1931  /* Allocation of new indirect segment failed */
1932  if (unlikely (mi == NULL)) {
1933  rte_pktmbuf_free(mc);
1934  return NULL;
1935  }
1936 
1937  __rte_mbuf_sanity_check(mc, 1);
1938  return mc;
1939 }
1940 
1952 static inline void rte_pktmbuf_refcnt_update(struct rte_mbuf *m, int16_t v)
1953 {
1955 
1956  do {
1957  rte_mbuf_refcnt_update(m, v);
1958  } while ((m = m->next) != NULL);
1959 }
1960 
1969 static inline uint16_t rte_pktmbuf_headroom(const struct rte_mbuf *m)
1970 {
1972  return m->data_off;
1973 }
1974 
1983 static inline uint16_t rte_pktmbuf_tailroom(const struct rte_mbuf *m)
1984 {
1986  return (uint16_t)(m->buf_len - rte_pktmbuf_headroom(m) -
1987  m->data_len);
1988 }
1989 
1998 static inline struct rte_mbuf *rte_pktmbuf_lastseg(struct rte_mbuf *m)
1999 {
2001  while (m->next != NULL)
2002  m = m->next;
2003  return m;
2004 }
2005 
2020 #define rte_pktmbuf_mtod_offset(m, t, o) \
2021  ((t)((char *)(m)->buf_addr + (m)->data_off + (o)))
2022 
2035 #define rte_pktmbuf_mtod(m, t) rte_pktmbuf_mtod_offset(m, t, 0)
2036 
2046 #define rte_pktmbuf_iova_offset(m, o) \
2047  (rte_iova_t)((m)->buf_iova + (m)->data_off + (o))
2048 
2049 /* deprecated */
2050 #define rte_pktmbuf_mtophys_offset(m, o) \
2051  rte_pktmbuf_iova_offset(m, o)
2052 
2060 #define rte_pktmbuf_iova(m) rte_pktmbuf_iova_offset(m, 0)
2061 
2062 /* deprecated */
2063 #define rte_pktmbuf_mtophys(m) rte_pktmbuf_iova(m)
2064 
2073 #define rte_pktmbuf_pkt_len(m) ((m)->pkt_len)
2074 
2083 #define rte_pktmbuf_data_len(m) ((m)->data_len)
2084 
2100 static inline char *rte_pktmbuf_prepend(struct rte_mbuf *m,
2101  uint16_t len)
2102 {
2104 
2105  if (unlikely(len > rte_pktmbuf_headroom(m)))
2106  return NULL;
2107 
2108  /* NB: elaborating the subtraction like this instead of using
2109  * -= allows us to ensure the result type is uint16_t
2110  * avoiding compiler warnings on gcc 8.1 at least */
2111  m->data_off = (uint16_t)(m->data_off - len);
2112  m->data_len = (uint16_t)(m->data_len + len);
2113  m->pkt_len = (m->pkt_len + len);
2114 
2115  return (char *)m->buf_addr + m->data_off;
2116 }
2117 
2133 static inline char *rte_pktmbuf_append(struct rte_mbuf *m, uint16_t len)
2134 {
2135  void *tail;
2136  struct rte_mbuf *m_last;
2137 
2139 
2140  m_last = rte_pktmbuf_lastseg(m);
2141  if (unlikely(len > rte_pktmbuf_tailroom(m_last)))
2142  return NULL;
2143 
2144  tail = (char *)m_last->buf_addr + m_last->data_off + m_last->data_len;
2145  m_last->data_len = (uint16_t)(m_last->data_len + len);
2146  m->pkt_len = (m->pkt_len + len);
2147  return (char*) tail;
2148 }
2149 
2164 static inline char *rte_pktmbuf_adj(struct rte_mbuf *m, uint16_t len)
2165 {
2167 
2168  if (unlikely(len > m->data_len))
2169  return NULL;
2170 
2171  /* NB: elaborating the addition like this instead of using
2172  * += allows us to ensure the result type is uint16_t
2173  * avoiding compiler warnings on gcc 8.1 at least */
2174  m->data_len = (uint16_t)(m->data_len - len);
2175  m->data_off = (uint16_t)(m->data_off + len);
2176  m->pkt_len = (m->pkt_len - len);
2177  return (char *)m->buf_addr + m->data_off;
2178 }
2179 
2194 static inline int rte_pktmbuf_trim(struct rte_mbuf *m, uint16_t len)
2195 {
2196  struct rte_mbuf *m_last;
2197 
2199 
2200  m_last = rte_pktmbuf_lastseg(m);
2201  if (unlikely(len > m_last->data_len))
2202  return -1;
2203 
2204  m_last->data_len = (uint16_t)(m_last->data_len - len);
2205  m->pkt_len = (m->pkt_len - len);
2206  return 0;
2207 }
2208 
2218 static inline int rte_pktmbuf_is_contiguous(const struct rte_mbuf *m)
2219 {
2221  return !!(m->nb_segs == 1);
2222 }
2223 
2227 const void *__rte_pktmbuf_read(const struct rte_mbuf *m, uint32_t off,
2228  uint32_t len, void *buf);
2229 
2250 static inline const void *rte_pktmbuf_read(const struct rte_mbuf *m,
2251  uint32_t off, uint32_t len, void *buf)
2252 {
2253  if (likely(off + len <= rte_pktmbuf_data_len(m)))
2254  return rte_pktmbuf_mtod_offset(m, char *, off);
2255  else
2256  return __rte_pktmbuf_read(m, off, len, buf);
2257 }
2258 
2275 static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail)
2276 {
2277  struct rte_mbuf *cur_tail;
2278 
2279  /* Check for number-of-segments-overflow */
2280  if (head->nb_segs + tail->nb_segs > RTE_MBUF_MAX_NB_SEGS)
2281  return -EOVERFLOW;
2282 
2283  /* Chain 'tail' onto the old tail */
2284  cur_tail = rte_pktmbuf_lastseg(head);
2285  cur_tail->next = tail;
2286 
2287  /* accumulate number of segments and total length.
2288  * NB: elaborating the addition like this instead of using
2289  * -= allows us to ensure the result type is uint16_t
2290  * avoiding compiler warnings on gcc 8.1 at least */
2291  head->nb_segs = (uint16_t)(head->nb_segs + tail->nb_segs);
2292  head->pkt_len += tail->pkt_len;
2293 
2294  /* pkt_len is only set in the head */
2295  tail->pkt_len = tail->data_len;
2296 
2297  return 0;
2298 }
2299 
2300 /*
2301  * @warning
2302  * @b EXPERIMENTAL: This API may change without prior notice.
2303  *
2304  * For given input values generate raw tx_offload value.
2305  * Note that it is caller responsibility to make sure that input parameters
2306  * don't exceed maximum bit-field values.
2307  * @param il2
2308  * l2_len value.
2309  * @param il3
2310  * l3_len value.
2311  * @param il4
2312  * l4_len value.
2313  * @param tso
2314  * tso_segsz value.
2315  * @param ol3
2316  * outer_l3_len value.
2317  * @param ol2
2318  * outer_l2_len value.
2319  * @param unused
2320  * unused value.
2321  * @return
2322  * raw tx_offload value.
2323  */
2324 static __rte_always_inline uint64_t
2325 rte_mbuf_tx_offload(uint64_t il2, uint64_t il3, uint64_t il4, uint64_t tso,
2326  uint64_t ol3, uint64_t ol2, uint64_t unused)
2327 {
2328  return il2 << RTE_MBUF_L2_LEN_OFS |
2329  il3 << RTE_MBUF_L3_LEN_OFS |
2330  il4 << RTE_MBUF_L4_LEN_OFS |
2331  tso << RTE_MBUF_TSO_SEGSZ_OFS |
2332  ol3 << RTE_MBUF_OUTL3_LEN_OFS |
2333  ol2 << RTE_MBUF_OUTL2_LEN_OFS |
2334  unused << RTE_MBUF_TXOFLD_UNUSED_OFS;
2335 }
2336 
2347 static inline int
2349 {
2350  uint64_t ol_flags = m->ol_flags;
2351 
2352  /* Does packet set any of available offloads? */
2353  if (!(ol_flags & PKT_TX_OFFLOAD_MASK))
2354  return 0;
2355 
2356  /* IP checksum can be counted only for IPv4 packet */
2357  if ((ol_flags & PKT_TX_IP_CKSUM) && (ol_flags & PKT_TX_IPV6))
2358  return -EINVAL;
2359 
2360  /* IP type not set when required */
2361  if (ol_flags & (PKT_TX_L4_MASK | PKT_TX_TCP_SEG))
2362  if (!(ol_flags & (PKT_TX_IPV4 | PKT_TX_IPV6)))
2363  return -EINVAL;
2364 
2365  /* Check requirements for TSO packet */
2366  if (ol_flags & PKT_TX_TCP_SEG)
2367  if ((m->tso_segsz == 0) ||
2368  ((ol_flags & PKT_TX_IPV4) &&
2369  !(ol_flags & PKT_TX_IP_CKSUM)))
2370  return -EINVAL;
2371 
2372  /* PKT_TX_OUTER_IP_CKSUM set for non outer IPv4 packet. */
2373  if ((ol_flags & PKT_TX_OUTER_IP_CKSUM) &&
2374  !(ol_flags & PKT_TX_OUTER_IPV4))
2375  return -EINVAL;
2376 
2377  return 0;
2378 }
2379 
2392 static inline int
2394 {
2395  size_t seg_len, copy_len;
2396  struct rte_mbuf *m;
2397  struct rte_mbuf *m_next;
2398  char *buffer;
2399 
2400  if (rte_pktmbuf_is_contiguous(mbuf))
2401  return 0;
2402 
2403  /* Extend first segment to the total packet length */
2404  copy_len = rte_pktmbuf_pkt_len(mbuf) - rte_pktmbuf_data_len(mbuf);
2405 
2406  if (unlikely(copy_len > rte_pktmbuf_tailroom(mbuf)))
2407  return -1;
2408 
2409  buffer = rte_pktmbuf_mtod_offset(mbuf, char *, mbuf->data_len);
2410  mbuf->data_len = (uint16_t)(mbuf->pkt_len);
2411 
2412  /* Append data from next segments to the first one */
2413  m = mbuf->next;
2414  while (m != NULL) {
2415  m_next = m->next;
2416 
2417  seg_len = rte_pktmbuf_data_len(m);
2418  rte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), seg_len);
2419  buffer += seg_len;
2420 
2422  m = m_next;
2423  }
2424 
2425  mbuf->next = NULL;
2426  mbuf->nb_segs = 1;
2427 
2428  return 0;
2429 }
2430 
2445 void rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len);
2446 
2450 static inline uint32_t
2452 {
2453  return m->hash.sched.queue_id;
2454 }
2455 
2459 static inline uint8_t
2461 {
2462  return m->hash.sched.traffic_class;
2463 }
2464 
2468 static inline uint8_t
2470 {
2471  return m->hash.sched.color;
2472 }
2473 
2486 static inline void
2487 rte_mbuf_sched_get(const struct rte_mbuf *m, uint32_t *queue_id,
2488  uint8_t *traffic_class,
2489  uint8_t *color)
2490 {
2491  struct rte_mbuf_sched sched = m->hash.sched;
2492 
2493  *queue_id = sched.queue_id;
2494  *traffic_class = sched.traffic_class;
2495  *color = sched.color;
2496 }
2497 
2501 static inline void
2503 {
2504  m->hash.sched.queue_id = queue_id;
2505 }
2506 
2510 static inline void
2512 {
2513  m->hash.sched.traffic_class = traffic_class;
2514 }
2515 
2519 static inline void
2521 {
2522  m->hash.sched.color = color;
2523 }
2524 
2537 static inline void
2539  uint8_t traffic_class,
2540  uint8_t color)
2541 {
2542  m->hash.sched = (struct rte_mbuf_sched){
2543  .queue_id = queue_id,
2544  .traffic_class = traffic_class,
2545  .color = color,
2546  .reserved = 0,
2547  };
2548 }
2549 
2550 #ifdef __cplusplus
2551 }
2552 #endif
2553 
2554 #endif /* _RTE_MBUF_H_ */