DPDK  19.02.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_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 
179 #define PKT_RX_QINQ (1ULL << 20)
180 
193 #define PKT_RX_OUTER_L4_CKSUM_MASK ((1ULL << 21) | (1ULL << 22))
194 
195 #define PKT_RX_OUTER_L4_CKSUM_UNKNOWN 0
196 #define PKT_RX_OUTER_L4_CKSUM_BAD (1ULL << 21)
197 #define PKT_RX_OUTER_L4_CKSUM_GOOD (1ULL << 22)
198 #define PKT_RX_OUTER_L4_CKSUM_INVALID ((1ULL << 21) | (1ULL << 22))
199 
200 /* add new RX flags here */
201 
202 /* add new TX flags here */
203 
207 #define PKT_TX_METADATA (1ULL << 40)
208 
218 #define PKT_TX_OUTER_UDP_CKSUM (1ULL << 41)
219 
225 #define PKT_TX_UDP_SEG (1ULL << 42)
226 
230 #define PKT_TX_SEC_OFFLOAD (1ULL << 43)
231 
236 #define PKT_TX_MACSEC (1ULL << 44)
237 
246 #define PKT_TX_TUNNEL_VXLAN (0x1ULL << 45)
247 #define PKT_TX_TUNNEL_GRE (0x2ULL << 45)
248 #define PKT_TX_TUNNEL_IPIP (0x3ULL << 45)
249 #define PKT_TX_TUNNEL_GENEVE (0x4ULL << 45)
250 
251 #define PKT_TX_TUNNEL_MPLSINUDP (0x5ULL << 45)
252 #define PKT_TX_TUNNEL_VXLAN_GPE (0x6ULL << 45)
253 
264 #define PKT_TX_TUNNEL_IP (0xDULL << 45)
265 
277 #define PKT_TX_TUNNEL_UDP (0xEULL << 45)
278 /* add new TX TUNNEL type here */
279 #define PKT_TX_TUNNEL_MASK (0xFULL << 45)
280 
284 #define PKT_TX_QINQ (1ULL << 49)
285 /* this old name is deprecated */
286 #define PKT_TX_QINQ_PKT PKT_TX_QINQ
287 
297 #define PKT_TX_TCP_SEG (1ULL << 50)
298 
299 #define PKT_TX_IEEE1588_TMST (1ULL << 51)
309 #define PKT_TX_L4_NO_CKSUM (0ULL << 52)
310 #define PKT_TX_TCP_CKSUM (1ULL << 52)
311 #define PKT_TX_SCTP_CKSUM (2ULL << 52)
312 #define PKT_TX_UDP_CKSUM (3ULL << 52)
313 #define PKT_TX_L4_MASK (3ULL << 52)
321 #define PKT_TX_IP_CKSUM (1ULL << 54)
322 
329 #define PKT_TX_IPV4 (1ULL << 55)
330 
337 #define PKT_TX_IPV6 (1ULL << 56)
338 
342 #define PKT_TX_VLAN (1ULL << 57)
343 /* this old name is deprecated */
344 #define PKT_TX_VLAN_PKT PKT_TX_VLAN
345 
352 #define PKT_TX_OUTER_IP_CKSUM (1ULL << 58)
353 
359 #define PKT_TX_OUTER_IPV4 (1ULL << 59)
360 
366 #define PKT_TX_OUTER_IPV6 (1ULL << 60)
367 
372 #define PKT_TX_OFFLOAD_MASK ( \
373  PKT_TX_OUTER_IPV6 | \
374  PKT_TX_OUTER_IPV4 | \
375  PKT_TX_OUTER_IP_CKSUM | \
376  PKT_TX_VLAN_PKT | \
377  PKT_TX_IPV6 | \
378  PKT_TX_IPV4 | \
379  PKT_TX_IP_CKSUM | \
380  PKT_TX_L4_MASK | \
381  PKT_TX_IEEE1588_TMST | \
382  PKT_TX_TCP_SEG | \
383  PKT_TX_QINQ_PKT | \
384  PKT_TX_TUNNEL_MASK | \
385  PKT_TX_MACSEC | \
386  PKT_TX_SEC_OFFLOAD | \
387  PKT_TX_UDP_SEG | \
388  PKT_TX_OUTER_UDP_CKSUM | \
389  PKT_TX_METADATA)
390 
394 #define EXT_ATTACHED_MBUF (1ULL << 61)
395 
396 #define IND_ATTACHED_MBUF (1ULL << 62)
399 #define RTE_MBUF_PRIV_ALIGN 8
400 
409 const char *rte_get_rx_ol_flag_name(uint64_t mask);
410 
423 int rte_get_rx_ol_flag_list(uint64_t mask, char *buf, size_t buflen);
424 
435 const char *rte_get_tx_ol_flag_name(uint64_t mask);
436 
449 int rte_get_tx_ol_flag_list(uint64_t mask, char *buf, size_t buflen);
450 
457 #define RTE_MBUF_DEFAULT_DATAROOM 2048
458 #define RTE_MBUF_DEFAULT_BUF_SIZE \
459  (RTE_MBUF_DEFAULT_DATAROOM + RTE_PKTMBUF_HEADROOM)
460 
461 /* define a set of marker types that can be used to refer to set points in the
462  * mbuf */
463 __extension__
464 typedef void *MARKER[0];
465 __extension__
466 typedef uint8_t MARKER8[0];
467 __extension__
468 typedef uint64_t MARKER64[0];
472  uint32_t queue_id;
473  uint8_t traffic_class;
477  uint8_t color;
479  uint16_t reserved;
480 };
485 struct rte_mbuf {
486  MARKER cacheline0;
487 
488  void *buf_addr;
496  union {
497  rte_iova_t buf_iova;
499  } __rte_aligned(sizeof(rte_iova_t));
500 
501  /* next 8 bytes are initialised on RX descriptor rearm */
502  MARKER64 rearm_data;
503  uint16_t data_off;
504 
515  union {
517  uint16_t refcnt;
518  };
519  uint16_t nb_segs;
524  uint16_t port;
525 
526  uint64_t ol_flags;
528  /* remaining bytes are set on RX when pulling packet from descriptor */
529  MARKER rx_descriptor_fields1;
530 
531  /*
532  * The packet type, which is the combination of outer/inner L2, L3, L4
533  * and tunnel types. The packet_type is about data really present in the
534  * mbuf. Example: if vlan stripping is enabled, a received vlan packet
535  * would have RTE_PTYPE_L2_ETHER and not RTE_PTYPE_L2_VLAN because the
536  * vlan is stripped from the data.
537  */
539  union {
540  uint32_t packet_type;
541  struct {
542  uint32_t l2_type:4;
543  uint32_t l3_type:4;
544  uint32_t l4_type:4;
545  uint32_t tun_type:4;
547  union {
548  uint8_t inner_esp_next_proto;
553  __extension__
554  struct {
555  uint8_t inner_l2_type:4;
557  uint8_t inner_l3_type:4;
559  };
560  };
561  uint32_t inner_l4_type:4;
562  };
563  };
564 
565  uint32_t pkt_len;
566  uint16_t data_len;
568  uint16_t vlan_tci;
569 
571  union {
572  union {
573  uint32_t rss;
574  struct {
575  union {
576  struct {
577  uint16_t hash;
578  uint16_t id;
579  };
580  uint32_t lo;
582  };
583  uint32_t hi;
587  } fdir;
590  struct {
591  uint32_t reserved1;
592  uint16_t reserved2;
593  uint16_t txq;
598  } txadapter;
600  uint32_t usr;
601  } hash;
602  struct {
610  uint32_t tx_metadata;
611  uint32_t reserved;
612  };
613  };
614 
616  uint16_t vlan_tci_outer;
617 
618  uint16_t buf_len;
623  uint64_t timestamp;
624 
625  /* second cache line - fields only used in slow path or on TX */
626  MARKER cacheline1 __rte_cache_min_aligned;
627 
629  union {
630  void *userdata;
631  uint64_t udata64;
632  };
633 
634  struct rte_mempool *pool;
635  struct rte_mbuf *next;
637  /* fields to support TX offloads */
639  union {
640  uint64_t tx_offload;
641  __extension__
642  struct {
643  uint64_t l2_len:7;
647  uint64_t l3_len:9;
648  uint64_t l4_len:8;
649  uint64_t tso_segsz:16;
651  /* fields for TX offloading of tunnels */
652  uint64_t outer_l3_len:9;
653  uint64_t outer_l2_len:7;
655  /* uint64_t unused:8; */
656  };
657  };
658 
661  uint16_t priv_size;
662 
664  uint16_t timesync;
665 
667  uint32_t seqn;
668 
673 
675 
679 typedef void (*rte_mbuf_extbuf_free_callback_t)(void *addr, void *opaque);
680 
686  void *fcb_opaque;
688 };
689 
691 #define RTE_MBUF_MAX_NB_SEGS UINT16_MAX
692 
703 static inline void
705 {
706  rte_prefetch0(&m->cacheline0);
707 }
708 
720 static inline void
722 {
723 #if RTE_CACHE_LINE_SIZE == 64
724  rte_prefetch0(&m->cacheline1);
725 #else
726  RTE_SET_USED(m);
727 #endif
728 }
729 
730 
731 static inline uint16_t rte_pktmbuf_priv_size(struct rte_mempool *mp);
732 
741 static inline rte_iova_t
742 rte_mbuf_data_iova(const struct rte_mbuf *mb)
743 {
744  return mb->buf_iova + mb->data_off;
745 }
746 
747 __rte_deprecated
748 static inline phys_addr_t
749 rte_mbuf_data_dma_addr(const struct rte_mbuf *mb)
750 {
751  return rte_mbuf_data_iova(mb);
752 }
753 
766 static inline rte_iova_t
768 {
769  return mb->buf_iova + RTE_PKTMBUF_HEADROOM;
770 }
771 
772 __rte_deprecated
773 static inline phys_addr_t
774 rte_mbuf_data_dma_addr_default(const struct rte_mbuf *mb)
775 {
776  return rte_mbuf_data_iova_default(mb);
777 }
778 
787 static inline struct rte_mbuf *
789 {
790  return (struct rte_mbuf *)RTE_PTR_SUB(mi->buf_addr, sizeof(*mi) + mi->priv_size);
791 }
792 
813 static inline char * __rte_experimental
814 rte_mbuf_buf_addr(struct rte_mbuf *mb, struct rte_mempool *mp)
815 {
816  return (char *)mb + sizeof(*mb) + rte_pktmbuf_priv_size(mp);
817 }
818 
830 static inline char * __rte_experimental
832 {
833  return rte_mbuf_buf_addr(mb, mb->pool) + RTE_PKTMBUF_HEADROOM;
834 }
835 
849 static inline char *
851 {
852 #ifdef ALLOW_EXPERIMENTAL_API
853  return rte_mbuf_buf_addr(md, md->pool);
854 #else
855  char *buffer_addr;
856  buffer_addr = (char *)md + sizeof(*md) + rte_pktmbuf_priv_size(md->pool);
857  return buffer_addr;
858 #endif
859 }
860 
873 static inline void * __rte_experimental
875 {
876  return RTE_PTR_ADD(m, sizeof(struct rte_mbuf));
877 }
878 
886 #define RTE_MBUF_CLONED(mb) ((mb)->ol_flags & IND_ATTACHED_MBUF)
887 
893 #define RTE_MBUF_HAS_EXTBUF(mb) ((mb)->ol_flags & EXT_ATTACHED_MBUF)
894 
901 #define RTE_MBUF_DIRECT(mb) \
902  (!((mb)->ol_flags & (IND_ATTACHED_MBUF | EXT_ATTACHED_MBUF)))
903 
912  uint16_t mbuf_priv_size;
913 };
914 
915 #ifdef RTE_LIBRTE_MBUF_DEBUG
916 
918 #define __rte_mbuf_sanity_check(m, is_h) rte_mbuf_sanity_check(m, is_h)
919 
920 #else /* RTE_LIBRTE_MBUF_DEBUG */
921 
923 #define __rte_mbuf_sanity_check(m, is_h) do { } while (0)
924 
925 #endif /* RTE_LIBRTE_MBUF_DEBUG */
926 
927 #ifdef RTE_MBUF_REFCNT_ATOMIC
928 
936 static inline uint16_t
937 rte_mbuf_refcnt_read(const struct rte_mbuf *m)
938 {
939  return (uint16_t)(rte_atomic16_read(&m->refcnt_atomic));
940 }
941 
949 static inline void
950 rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
951 {
952  rte_atomic16_set(&m->refcnt_atomic, (int16_t)new_value);
953 }
954 
955 /* internal */
956 static inline uint16_t
957 __rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
958 {
959  return (uint16_t)(rte_atomic16_add_return(&m->refcnt_atomic, value));
960 }
961 
971 static inline uint16_t
972 rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
973 {
974  /*
975  * The atomic_add is an expensive operation, so we don't want to
976  * call it in the case where we know we are the uniq holder of
977  * this mbuf (i.e. ref_cnt == 1). Otherwise, an atomic
978  * operation has to be used because concurrent accesses on the
979  * reference counter can occur.
980  */
981  if (likely(rte_mbuf_refcnt_read(m) == 1)) {
982  ++value;
983  rte_mbuf_refcnt_set(m, (uint16_t)value);
984  return (uint16_t)value;
985  }
986 
987  return __rte_mbuf_refcnt_update(m, value);
988 }
989 
990 #else /* ! RTE_MBUF_REFCNT_ATOMIC */
991 
992 /* internal */
993 static inline uint16_t
994 __rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
995 {
996  m->refcnt = (uint16_t)(m->refcnt + value);
997  return m->refcnt;
998 }
999 
1003 static inline uint16_t
1004 rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
1005 {
1006  return __rte_mbuf_refcnt_update(m, value);
1007 }
1008 
1012 static inline uint16_t
1014 {
1015  return m->refcnt;
1016 }
1017 
1021 static inline void
1022 rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
1023 {
1024  m->refcnt = new_value;
1025 }
1026 
1027 #endif /* RTE_MBUF_REFCNT_ATOMIC */
1028 
1037 static inline uint16_t
1039 {
1040  return (uint16_t)(rte_atomic16_read(&shinfo->refcnt_atomic));
1041 }
1042 
1051 static inline void
1053  uint16_t new_value)
1054 {
1055  rte_atomic16_set(&shinfo->refcnt_atomic, (int16_t)new_value);
1056 }
1057 
1069 static inline uint16_t
1071  int16_t value)
1072 {
1073  if (likely(rte_mbuf_ext_refcnt_read(shinfo) == 1)) {
1074  ++value;
1075  rte_mbuf_ext_refcnt_set(shinfo, (uint16_t)value);
1076  return (uint16_t)value;
1077  }
1078 
1079  return (uint16_t)rte_atomic16_add_return(&shinfo->refcnt_atomic, value);
1080 }
1081 
1083 #define RTE_MBUF_PREFETCH_TO_FREE(m) do { \
1084  if ((m) != NULL) \
1085  rte_prefetch0(m); \
1086 } while (0)
1087 
1088 
1101 void
1102 rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header);
1103 
1123 __rte_experimental
1124 int rte_mbuf_check(const struct rte_mbuf *m, int is_header,
1125  const char **reason);
1126 
1127 #define MBUF_RAW_ALLOC_CHECK(m) do { \
1128  RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1); \
1129  RTE_ASSERT((m)->next == NULL); \
1130  RTE_ASSERT((m)->nb_segs == 1); \
1131  __rte_mbuf_sanity_check(m, 0); \
1132 } while (0)
1133 
1153 static inline struct rte_mbuf *rte_mbuf_raw_alloc(struct rte_mempool *mp)
1154 {
1155  struct rte_mbuf *m;
1156 
1157  if (rte_mempool_get(mp, (void **)&m) < 0)
1158  return NULL;
1159  MBUF_RAW_ALLOC_CHECK(m);
1160  return m;
1161 }
1162 
1177 static __rte_always_inline void
1179 {
1180  RTE_ASSERT(RTE_MBUF_DIRECT(m));
1181  RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1);
1182  RTE_ASSERT(m->next == NULL);
1183  RTE_ASSERT(m->nb_segs == 1);
1185  rte_mempool_put(m->pool, m);
1186 }
1187 
1207 void rte_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg,
1208  void *m, unsigned i);
1209 
1210 
1228 void rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg);
1229 
1264 struct rte_mempool *
1265 rte_pktmbuf_pool_create(const char *name, unsigned n,
1266  unsigned cache_size, uint16_t priv_size, uint16_t data_room_size,
1267  int socket_id);
1268 
1306 struct rte_mempool *
1307 rte_pktmbuf_pool_create_by_ops(const char *name, unsigned int n,
1308  unsigned int cache_size, uint16_t priv_size, uint16_t data_room_size,
1309  int socket_id, const char *ops_name);
1310 
1322 static inline uint16_t
1324 {
1325  struct rte_pktmbuf_pool_private *mbp_priv;
1326 
1327  mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
1328  return mbp_priv->mbuf_data_room_size;
1329 }
1330 
1343 static inline uint16_t
1345 {
1346  struct rte_pktmbuf_pool_private *mbp_priv;
1347 
1348  mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
1349  return mbp_priv->mbuf_priv_size;
1350 }
1351 
1360 static inline void rte_pktmbuf_reset_headroom(struct rte_mbuf *m)
1361 {
1362  m->data_off = (uint16_t)RTE_MIN((uint16_t)RTE_PKTMBUF_HEADROOM,
1363  (uint16_t)m->buf_len);
1364 }
1365 
1374 #define MBUF_INVALID_PORT UINT16_MAX
1375 
1376 static inline void rte_pktmbuf_reset(struct rte_mbuf *m)
1377 {
1378  m->next = NULL;
1379  m->pkt_len = 0;
1380  m->tx_offload = 0;
1381  m->vlan_tci = 0;
1382  m->vlan_tci_outer = 0;
1383  m->nb_segs = 1;
1384  m->port = MBUF_INVALID_PORT;
1385 
1386  m->ol_flags = 0;
1387  m->packet_type = 0;
1389 
1390  m->data_len = 0;
1392 }
1393 
1407 static inline struct rte_mbuf *rte_pktmbuf_alloc(struct rte_mempool *mp)
1408 {
1409  struct rte_mbuf *m;
1410  if ((m = rte_mbuf_raw_alloc(mp)) != NULL)
1411  rte_pktmbuf_reset(m);
1412  return m;
1413 }
1414 
1429 static inline int rte_pktmbuf_alloc_bulk(struct rte_mempool *pool,
1430  struct rte_mbuf **mbufs, unsigned count)
1431 {
1432  unsigned idx = 0;
1433  int rc;
1434 
1435  rc = rte_mempool_get_bulk(pool, (void **)mbufs, count);
1436  if (unlikely(rc))
1437  return rc;
1438 
1439  /* To understand duff's device on loop unwinding optimization, see
1440  * https://en.wikipedia.org/wiki/Duff's_device.
1441  * Here while() loop is used rather than do() while{} to avoid extra
1442  * check if count is zero.
1443  */
1444  switch (count % 4) {
1445  case 0:
1446  while (idx != count) {
1447  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1448  rte_pktmbuf_reset(mbufs[idx]);
1449  idx++;
1450  /* fall-through */
1451  case 3:
1452  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1453  rte_pktmbuf_reset(mbufs[idx]);
1454  idx++;
1455  /* fall-through */
1456  case 2:
1457  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1458  rte_pktmbuf_reset(mbufs[idx]);
1459  idx++;
1460  /* fall-through */
1461  case 1:
1462  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1463  rte_pktmbuf_reset(mbufs[idx]);
1464  idx++;
1465  /* fall-through */
1466  }
1467  }
1468  return 0;
1469 }
1470 
1503 static inline struct rte_mbuf_ext_shared_info *
1504 rte_pktmbuf_ext_shinfo_init_helper(void *buf_addr, uint16_t *buf_len,
1506 {
1507  struct rte_mbuf_ext_shared_info *shinfo;
1508  void *buf_end = RTE_PTR_ADD(buf_addr, *buf_len);
1509  void *addr;
1510 
1511  addr = RTE_PTR_ALIGN_FLOOR(RTE_PTR_SUB(buf_end, sizeof(*shinfo)),
1512  sizeof(uintptr_t));
1513  if (addr <= buf_addr)
1514  return NULL;
1515 
1516  shinfo = (struct rte_mbuf_ext_shared_info *)addr;
1517  shinfo->free_cb = free_cb;
1518  shinfo->fcb_opaque = fcb_opaque;
1519  rte_mbuf_ext_refcnt_set(shinfo, 1);
1520 
1521  *buf_len = (uint16_t)RTE_PTR_DIFF(shinfo, buf_addr);
1522  return shinfo;
1523 }
1524 
1581 static inline void
1582 rte_pktmbuf_attach_extbuf(struct rte_mbuf *m, void *buf_addr,
1583  rte_iova_t buf_iova, uint16_t buf_len,
1584  struct rte_mbuf_ext_shared_info *shinfo)
1585 {
1586  /* mbuf should not be read-only */
1587  RTE_ASSERT(RTE_MBUF_DIRECT(m) && rte_mbuf_refcnt_read(m) == 1);
1588  RTE_ASSERT(shinfo->free_cb != NULL);
1589 
1590  m->buf_addr = buf_addr;
1591  m->buf_iova = buf_iova;
1592  m->buf_len = buf_len;
1593 
1594  m->data_len = 0;
1595  m->data_off = 0;
1596 
1598  m->shinfo = shinfo;
1599 }
1600 
1608 #define rte_pktmbuf_detach_extbuf(m) rte_pktmbuf_detach(m)
1609 
1631 static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *m)
1632 {
1633  RTE_ASSERT(RTE_MBUF_DIRECT(mi) &&
1634  rte_mbuf_refcnt_read(mi) == 1);
1635 
1636  if (RTE_MBUF_HAS_EXTBUF(m)) {
1638  mi->ol_flags = m->ol_flags;
1639  mi->shinfo = m->shinfo;
1640  } else {
1641  /* if m is not direct, get the mbuf that embeds the data */
1643  mi->priv_size = m->priv_size;
1644  mi->ol_flags = m->ol_flags | IND_ATTACHED_MBUF;
1645  }
1646 
1647  mi->buf_iova = m->buf_iova;
1648  mi->buf_addr = m->buf_addr;
1649  mi->buf_len = m->buf_len;
1650 
1651  mi->data_off = m->data_off;
1652  mi->data_len = m->data_len;
1653  mi->port = m->port;
1654  mi->vlan_tci = m->vlan_tci;
1655  mi->vlan_tci_outer = m->vlan_tci_outer;
1656  mi->tx_offload = m->tx_offload;
1657  mi->hash = m->hash;
1658 
1659  mi->next = NULL;
1660  mi->pkt_len = mi->data_len;
1661  mi->nb_segs = 1;
1662  mi->packet_type = m->packet_type;
1663  mi->timestamp = m->timestamp;
1664 
1665  __rte_mbuf_sanity_check(mi, 1);
1667 }
1668 
1676 static inline void
1677 __rte_pktmbuf_free_extbuf(struct rte_mbuf *m)
1678 {
1679  RTE_ASSERT(RTE_MBUF_HAS_EXTBUF(m));
1680  RTE_ASSERT(m->shinfo != NULL);
1681 
1682  if (rte_mbuf_ext_refcnt_update(m->shinfo, -1) == 0)
1683  m->shinfo->free_cb(m->buf_addr, m->shinfo->fcb_opaque);
1684 }
1685 
1692 static inline void
1693 __rte_pktmbuf_free_direct(struct rte_mbuf *m)
1694 {
1695  struct rte_mbuf *md;
1696 
1697  RTE_ASSERT(RTE_MBUF_CLONED(m));
1698 
1699  md = rte_mbuf_from_indirect(m);
1700 
1701  if (rte_mbuf_refcnt_update(md, -1) == 0) {
1702  md->next = NULL;
1703  md->nb_segs = 1;
1704  rte_mbuf_refcnt_set(md, 1);
1705  rte_mbuf_raw_free(md);
1706  }
1707 }
1708 
1722 static inline void rte_pktmbuf_detach(struct rte_mbuf *m)
1723 {
1724  struct rte_mempool *mp = m->pool;
1725  uint32_t mbuf_size, buf_len;
1726  uint16_t priv_size;
1727 
1728  if (RTE_MBUF_HAS_EXTBUF(m))
1729  __rte_pktmbuf_free_extbuf(m);
1730  else
1731  __rte_pktmbuf_free_direct(m);
1732 
1733  priv_size = rte_pktmbuf_priv_size(mp);
1734  mbuf_size = (uint32_t)(sizeof(struct rte_mbuf) + priv_size);
1735  buf_len = rte_pktmbuf_data_room_size(mp);
1736 
1737  m->priv_size = priv_size;
1738  m->buf_addr = (char *)m + mbuf_size;
1739  m->buf_iova = rte_mempool_virt2iova(m) + mbuf_size;
1740  m->buf_len = (uint16_t)buf_len;
1742  m->data_len = 0;
1743  m->ol_flags = 0;
1744 }
1745 
1760 static __rte_always_inline struct rte_mbuf *
1762 {
1764 
1765  if (likely(rte_mbuf_refcnt_read(m) == 1)) {
1766 
1767  if (!RTE_MBUF_DIRECT(m))
1768  rte_pktmbuf_detach(m);
1769 
1770  if (m->next != NULL) {
1771  m->next = NULL;
1772  m->nb_segs = 1;
1773  }
1774 
1775  return m;
1776 
1777  } else if (__rte_mbuf_refcnt_update(m, -1) == 0) {
1778 
1779  if (!RTE_MBUF_DIRECT(m))
1780  rte_pktmbuf_detach(m);
1781 
1782  if (m->next != NULL) {
1783  m->next = NULL;
1784  m->nb_segs = 1;
1785  }
1786  rte_mbuf_refcnt_set(m, 1);
1787 
1788  return m;
1789  }
1790  return NULL;
1791 }
1792 
1802 static __rte_always_inline void
1804 {
1805  m = rte_pktmbuf_prefree_seg(m);
1806  if (likely(m != NULL))
1807  rte_mbuf_raw_free(m);
1808 }
1809 
1819 static inline void rte_pktmbuf_free(struct rte_mbuf *m)
1820 {
1821  struct rte_mbuf *m_next;
1822 
1823  if (m != NULL)
1825 
1826  while (m != NULL) {
1827  m_next = m->next;
1829  m = m_next;
1830  }
1831 }
1832 
1850 static inline struct rte_mbuf *rte_pktmbuf_clone(struct rte_mbuf *md,
1851  struct rte_mempool *mp)
1852 {
1853  struct rte_mbuf *mc, *mi, **prev;
1854  uint32_t pktlen;
1855  uint16_t nseg;
1856 
1857  if (unlikely ((mc = rte_pktmbuf_alloc(mp)) == NULL))
1858  return NULL;
1859 
1860  mi = mc;
1861  prev = &mi->next;
1862  pktlen = md->pkt_len;
1863  nseg = 0;
1864 
1865  do {
1866  nseg++;
1867  rte_pktmbuf_attach(mi, md);
1868  *prev = mi;
1869  prev = &mi->next;
1870  } while ((md = md->next) != NULL &&
1871  (mi = rte_pktmbuf_alloc(mp)) != NULL);
1872 
1873  *prev = NULL;
1874  mc->nb_segs = nseg;
1875  mc->pkt_len = pktlen;
1876 
1877  /* Allocation of new indirect segment failed */
1878  if (unlikely (mi == NULL)) {
1879  rte_pktmbuf_free(mc);
1880  return NULL;
1881  }
1882 
1883  __rte_mbuf_sanity_check(mc, 1);
1884  return mc;
1885 }
1886 
1898 static inline void rte_pktmbuf_refcnt_update(struct rte_mbuf *m, int16_t v)
1899 {
1901 
1902  do {
1903  rte_mbuf_refcnt_update(m, v);
1904  } while ((m = m->next) != NULL);
1905 }
1906 
1915 static inline uint16_t rte_pktmbuf_headroom(const struct rte_mbuf *m)
1916 {
1918  return m->data_off;
1919 }
1920 
1929 static inline uint16_t rte_pktmbuf_tailroom(const struct rte_mbuf *m)
1930 {
1932  return (uint16_t)(m->buf_len - rte_pktmbuf_headroom(m) -
1933  m->data_len);
1934 }
1935 
1944 static inline struct rte_mbuf *rte_pktmbuf_lastseg(struct rte_mbuf *m)
1945 {
1947  while (m->next != NULL)
1948  m = m->next;
1949  return m;
1950 }
1951 
1966 #define rte_pktmbuf_mtod_offset(m, t, o) \
1967  ((t)((char *)(m)->buf_addr + (m)->data_off + (o)))
1968 
1981 #define rte_pktmbuf_mtod(m, t) rte_pktmbuf_mtod_offset(m, t, 0)
1982 
1992 #define rte_pktmbuf_iova_offset(m, o) \
1993  (rte_iova_t)((m)->buf_iova + (m)->data_off + (o))
1994 
1995 /* deprecated */
1996 #define rte_pktmbuf_mtophys_offset(m, o) \
1997  rte_pktmbuf_iova_offset(m, o)
1998 
2006 #define rte_pktmbuf_iova(m) rte_pktmbuf_iova_offset(m, 0)
2007 
2008 /* deprecated */
2009 #define rte_pktmbuf_mtophys(m) rte_pktmbuf_iova(m)
2010 
2019 #define rte_pktmbuf_pkt_len(m) ((m)->pkt_len)
2020 
2029 #define rte_pktmbuf_data_len(m) ((m)->data_len)
2030 
2046 static inline char *rte_pktmbuf_prepend(struct rte_mbuf *m,
2047  uint16_t len)
2048 {
2050 
2051  if (unlikely(len > rte_pktmbuf_headroom(m)))
2052  return NULL;
2053 
2054  /* NB: elaborating the subtraction like this instead of using
2055  * -= allows us to ensure the result type is uint16_t
2056  * avoiding compiler warnings on gcc 8.1 at least */
2057  m->data_off = (uint16_t)(m->data_off - len);
2058  m->data_len = (uint16_t)(m->data_len + len);
2059  m->pkt_len = (m->pkt_len + len);
2060 
2061  return (char *)m->buf_addr + m->data_off;
2062 }
2063 
2079 static inline char *rte_pktmbuf_append(struct rte_mbuf *m, uint16_t len)
2080 {
2081  void *tail;
2082  struct rte_mbuf *m_last;
2083 
2085 
2086  m_last = rte_pktmbuf_lastseg(m);
2087  if (unlikely(len > rte_pktmbuf_tailroom(m_last)))
2088  return NULL;
2089 
2090  tail = (char *)m_last->buf_addr + m_last->data_off + m_last->data_len;
2091  m_last->data_len = (uint16_t)(m_last->data_len + len);
2092  m->pkt_len = (m->pkt_len + len);
2093  return (char*) tail;
2094 }
2095 
2110 static inline char *rte_pktmbuf_adj(struct rte_mbuf *m, uint16_t len)
2111 {
2113 
2114  if (unlikely(len > m->data_len))
2115  return NULL;
2116 
2117  /* NB: elaborating the addition like this instead of using
2118  * += allows us to ensure the result type is uint16_t
2119  * avoiding compiler warnings on gcc 8.1 at least */
2120  m->data_len = (uint16_t)(m->data_len - len);
2121  m->data_off = (uint16_t)(m->data_off + len);
2122  m->pkt_len = (m->pkt_len - len);
2123  return (char *)m->buf_addr + m->data_off;
2124 }
2125 
2140 static inline int rte_pktmbuf_trim(struct rte_mbuf *m, uint16_t len)
2141 {
2142  struct rte_mbuf *m_last;
2143 
2145 
2146  m_last = rte_pktmbuf_lastseg(m);
2147  if (unlikely(len > m_last->data_len))
2148  return -1;
2149 
2150  m_last->data_len = (uint16_t)(m_last->data_len - len);
2151  m->pkt_len = (m->pkt_len - len);
2152  return 0;
2153 }
2154 
2164 static inline int rte_pktmbuf_is_contiguous(const struct rte_mbuf *m)
2165 {
2167  return !!(m->nb_segs == 1);
2168 }
2169 
2173 const void *__rte_pktmbuf_read(const struct rte_mbuf *m, uint32_t off,
2174  uint32_t len, void *buf);
2175 
2196 static inline const void *rte_pktmbuf_read(const struct rte_mbuf *m,
2197  uint32_t off, uint32_t len, void *buf)
2198 {
2199  if (likely(off + len <= rte_pktmbuf_data_len(m)))
2200  return rte_pktmbuf_mtod_offset(m, char *, off);
2201  else
2202  return __rte_pktmbuf_read(m, off, len, buf);
2203 }
2204 
2221 static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail)
2222 {
2223  struct rte_mbuf *cur_tail;
2224 
2225  /* Check for number-of-segments-overflow */
2226  if (head->nb_segs + tail->nb_segs > RTE_MBUF_MAX_NB_SEGS)
2227  return -EOVERFLOW;
2228 
2229  /* Chain 'tail' onto the old tail */
2230  cur_tail = rte_pktmbuf_lastseg(head);
2231  cur_tail->next = tail;
2232 
2233  /* accumulate number of segments and total length.
2234  * NB: elaborating the addition like this instead of using
2235  * -= allows us to ensure the result type is uint16_t
2236  * avoiding compiler warnings on gcc 8.1 at least */
2237  head->nb_segs = (uint16_t)(head->nb_segs + tail->nb_segs);
2238  head->pkt_len += tail->pkt_len;
2239 
2240  /* pkt_len is only set in the head */
2241  tail->pkt_len = tail->data_len;
2242 
2243  return 0;
2244 }
2245 
2256 static inline int
2258 {
2259  uint64_t ol_flags = m->ol_flags;
2260  uint64_t inner_l3_offset = m->l2_len;
2261 
2262  /* Does packet set any of available offloads? */
2263  if (!(ol_flags & PKT_TX_OFFLOAD_MASK))
2264  return 0;
2265 
2266  if (ol_flags & PKT_TX_OUTER_IP_CKSUM)
2267  /* NB: elaborating the addition like this instead of using
2268  * += gives the result uint64_t type instead of int,
2269  * avoiding compiler warnings on gcc 8.1 at least */
2270  inner_l3_offset = inner_l3_offset + m->outer_l2_len +
2271  m->outer_l3_len;
2272 
2273  /* Headers are fragmented */
2274  if (rte_pktmbuf_data_len(m) < inner_l3_offset + m->l3_len + m->l4_len)
2275  return -ENOTSUP;
2276 
2277  /* IP checksum can be counted only for IPv4 packet */
2278  if ((ol_flags & PKT_TX_IP_CKSUM) && (ol_flags & PKT_TX_IPV6))
2279  return -EINVAL;
2280 
2281  /* IP type not set when required */
2282  if (ol_flags & (PKT_TX_L4_MASK | PKT_TX_TCP_SEG))
2283  if (!(ol_flags & (PKT_TX_IPV4 | PKT_TX_IPV6)))
2284  return -EINVAL;
2285 
2286  /* Check requirements for TSO packet */
2287  if (ol_flags & PKT_TX_TCP_SEG)
2288  if ((m->tso_segsz == 0) ||
2289  ((ol_flags & PKT_TX_IPV4) &&
2290  !(ol_flags & PKT_TX_IP_CKSUM)))
2291  return -EINVAL;
2292 
2293  /* PKT_TX_OUTER_IP_CKSUM set for non outer IPv4 packet. */
2294  if ((ol_flags & PKT_TX_OUTER_IP_CKSUM) &&
2295  !(ol_flags & PKT_TX_OUTER_IPV4))
2296  return -EINVAL;
2297 
2298  return 0;
2299 }
2300 
2313 static inline int
2315 {
2316  size_t seg_len, copy_len;
2317  struct rte_mbuf *m;
2318  struct rte_mbuf *m_next;
2319  char *buffer;
2320 
2321  if (rte_pktmbuf_is_contiguous(mbuf))
2322  return 0;
2323 
2324  /* Extend first segment to the total packet length */
2325  copy_len = rte_pktmbuf_pkt_len(mbuf) - rte_pktmbuf_data_len(mbuf);
2326 
2327  if (unlikely(copy_len > rte_pktmbuf_tailroom(mbuf)))
2328  return -1;
2329 
2330  buffer = rte_pktmbuf_mtod_offset(mbuf, char *, mbuf->data_len);
2331  mbuf->data_len = (uint16_t)(mbuf->pkt_len);
2332 
2333  /* Append data from next segments to the first one */
2334  m = mbuf->next;
2335  while (m != NULL) {
2336  m_next = m->next;
2337 
2338  seg_len = rte_pktmbuf_data_len(m);
2339  rte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), seg_len);
2340  buffer += seg_len;
2341 
2343  m = m_next;
2344  }
2345 
2346  mbuf->next = NULL;
2347  mbuf->nb_segs = 1;
2348 
2349  return 0;
2350 }
2351 
2366 void rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len);
2367 
2371 static inline uint32_t
2373 {
2374  return m->hash.sched.queue_id;
2375 }
2376 
2380 static inline uint8_t
2382 {
2383  return m->hash.sched.traffic_class;
2384 }
2385 
2389 static inline uint8_t
2391 {
2392  return m->hash.sched.color;
2393 }
2394 
2407 static inline void
2408 rte_mbuf_sched_get(const struct rte_mbuf *m, uint32_t *queue_id,
2409  uint8_t *traffic_class,
2410  uint8_t *color)
2411 {
2412  struct rte_mbuf_sched sched = m->hash.sched;
2413 
2414  *queue_id = sched.queue_id;
2415  *traffic_class = sched.traffic_class;
2416  *color = sched.color;
2417 }
2418 
2422 static inline void
2424 {
2425  m->hash.sched.queue_id = queue_id;
2426 }
2427 
2431 static inline void
2433 {
2434  m->hash.sched.traffic_class = traffic_class;
2435 }
2436 
2440 static inline void
2442 {
2443  m->hash.sched.color = color;
2444 }
2445 
2458 static inline void
2460  uint8_t traffic_class,
2461  uint8_t color)
2462 {
2463  m->hash.sched = (struct rte_mbuf_sched){
2464  .queue_id = queue_id,
2465  .traffic_class = traffic_class,
2466  .color = color,
2467  .reserved = 0,
2468  };
2469 }
2470 
2471 #ifdef __cplusplus
2472 }
2473 #endif
2474 
2475 #endif /* _RTE_MBUF_H_ */