DPDK  17.05.2
rte_mbuf.h
Go to the documentation of this file.
1 /*-
2  * BSD LICENSE
3  *
4  * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  * Copyright 2014 6WIND S.A.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in
16  * the documentation and/or other materials provided with the
17  * distribution.
18  * * Neither the name of Intel Corporation nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #ifndef _RTE_MBUF_H_
36 #define _RTE_MBUF_H_
37 
63 #include <stdint.h>
64 #include <rte_common.h>
65 #include <rte_mempool.h>
66 #include <rte_memory.h>
67 #include <rte_atomic.h>
68 #include <rte_prefetch.h>
69 #include <rte_branch_prediction.h>
70 #include <rte_mbuf_ptype.h>
71 
72 #ifdef __cplusplus
73 extern "C" {
74 #endif
75 
76 /*
77  * Packet Offload Features Flags. It also carry packet type information.
78  * Critical resources. Both rx/tx shared these bits. Be cautious on any change
79  *
80  * - RX flags start at bit position zero, and get added to the left of previous
81  * flags.
82  * - The most-significant 3 bits are reserved for generic mbuf flags
83  * - TX flags therefore start at bit position 60 (i.e. 63-3), and new flags get
84  * added to the right of the previously defined flags i.e. they should count
85  * downwards, not upwards.
86  *
87  * Keep these flags synchronized with rte_get_rx_ol_flag_name() and
88  * rte_get_tx_ol_flag_name().
89  */
90 
97 #define PKT_RX_VLAN_PKT (1ULL << 0)
98 
99 #define PKT_RX_RSS_HASH (1ULL << 1)
100 #define PKT_RX_FDIR (1ULL << 2)
109 #define PKT_RX_L4_CKSUM_BAD (1ULL << 3)
110 
118 #define PKT_RX_IP_CKSUM_BAD (1ULL << 4)
119 
120 #define PKT_RX_EIP_CKSUM_BAD (1ULL << 5)
127 #define PKT_RX_VLAN_STRIPPED (1ULL << 6)
128 
137 #define PKT_RX_IP_CKSUM_MASK ((1ULL << 4) | (1ULL << 7))
138 
139 #define PKT_RX_IP_CKSUM_UNKNOWN 0
140 #define PKT_RX_IP_CKSUM_BAD (1ULL << 4)
141 #define PKT_RX_IP_CKSUM_GOOD (1ULL << 7)
142 #define PKT_RX_IP_CKSUM_NONE ((1ULL << 4) | (1ULL << 7))
143 
152 #define PKT_RX_L4_CKSUM_MASK ((1ULL << 3) | (1ULL << 8))
153 
154 #define PKT_RX_L4_CKSUM_UNKNOWN 0
155 #define PKT_RX_L4_CKSUM_BAD (1ULL << 3)
156 #define PKT_RX_L4_CKSUM_GOOD (1ULL << 8)
157 #define PKT_RX_L4_CKSUM_NONE ((1ULL << 3) | (1ULL << 8))
158 
159 #define PKT_RX_IEEE1588_PTP (1ULL << 9)
160 #define PKT_RX_IEEE1588_TMST (1ULL << 10)
161 #define PKT_RX_FDIR_ID (1ULL << 13)
162 #define PKT_RX_FDIR_FLX (1ULL << 14)
171 #define PKT_RX_QINQ_STRIPPED (1ULL << 15)
172 
178 #define PKT_RX_QINQ_PKT PKT_RX_QINQ_STRIPPED
179 
185 #define PKT_RX_LRO (1ULL << 16)
186 
190 #define PKT_RX_TIMESTAMP (1ULL << 17)
191 
192 /* add new RX flags here */
193 
194 /* add new TX flags here */
195 
200 #define PKT_TX_MACSEC (1ULL << 44)
201 
207 #define PKT_TX_TUNNEL_VXLAN (0x1ULL << 45)
208 #define PKT_TX_TUNNEL_GRE (0x2ULL << 45)
209 #define PKT_TX_TUNNEL_IPIP (0x3ULL << 45)
210 #define PKT_TX_TUNNEL_GENEVE (0x4ULL << 45)
211 /* add new TX TUNNEL type here */
212 #define PKT_TX_TUNNEL_MASK (0xFULL << 45)
213 
217 #define PKT_TX_QINQ_PKT (1ULL << 49)
232 #define PKT_TX_TCP_SEG (1ULL << 50)
233 
234 #define PKT_TX_IEEE1588_TMST (1ULL << 51)
247 #define PKT_TX_L4_NO_CKSUM (0ULL << 52)
248 #define PKT_TX_TCP_CKSUM (1ULL << 52)
249 #define PKT_TX_SCTP_CKSUM (2ULL << 52)
250 #define PKT_TX_UDP_CKSUM (3ULL << 52)
251 #define PKT_TX_L4_MASK (3ULL << 52)
260 #define PKT_TX_IP_CKSUM (1ULL << 54)
261 
268 #define PKT_TX_IPV4 (1ULL << 55)
269 
276 #define PKT_TX_IPV6 (1ULL << 56)
277 
278 #define PKT_TX_VLAN_PKT (1ULL << 57)
288 #define PKT_TX_OUTER_IP_CKSUM (1ULL << 58)
289 
295 #define PKT_TX_OUTER_IPV4 (1ULL << 59)
296 
302 #define PKT_TX_OUTER_IPV6 (1ULL << 60)
303 
308 #define PKT_TX_OFFLOAD_MASK ( \
309  PKT_TX_IP_CKSUM | \
310  PKT_TX_L4_MASK | \
311  PKT_TX_OUTER_IP_CKSUM | \
312  PKT_TX_TCP_SEG | \
313  PKT_TX_IEEE1588_TMST | \
314  PKT_TX_QINQ_PKT | \
315  PKT_TX_VLAN_PKT | \
316  PKT_TX_TUNNEL_MASK | \
317  PKT_TX_MACSEC)
318 
319 #define __RESERVED (1ULL << 61)
321 #define IND_ATTACHED_MBUF (1ULL << 62)
323 /* Use final bit of flags to indicate a control mbuf */
324 #define CTRL_MBUF_FLAG (1ULL << 63)
327 #define RTE_MBUF_PRIV_ALIGN 8
328 
337 const char *rte_get_rx_ol_flag_name(uint64_t mask);
338 
351 int rte_get_rx_ol_flag_list(uint64_t mask, char *buf, size_t buflen);
352 
363 const char *rte_get_tx_ol_flag_name(uint64_t mask);
364 
377 int rte_get_tx_ol_flag_list(uint64_t mask, char *buf, size_t buflen);
378 
385 #define RTE_MBUF_DEFAULT_DATAROOM 2048
386 #define RTE_MBUF_DEFAULT_BUF_SIZE \
387  (RTE_MBUF_DEFAULT_DATAROOM + RTE_PKTMBUF_HEADROOM)
388 
389 /* define a set of marker types that can be used to refer to set points in the
390  * mbuf */
391 __extension__
392 typedef void *MARKER[0];
393 __extension__
394 typedef uint8_t MARKER8[0];
395 __extension__
396 typedef uint64_t MARKER64[0];
402 struct rte_mbuf {
403  MARKER cacheline0;
404 
405  void *buf_addr;
412  phys_addr_t buf_physaddr __rte_aligned(sizeof(phys_addr_t));
413 
414  /* next 8 bytes are initialised on RX descriptor rearm */
415  MARKER64 rearm_data;
416  uint16_t data_off;
417 
428  union {
430  uint16_t refcnt;
431  };
432  uint16_t nb_segs;
435  uint16_t port;
436 
437  uint64_t ol_flags;
439  /* remaining bytes are set on RX when pulling packet from descriptor */
440  MARKER rx_descriptor_fields1;
441 
442  /*
443  * The packet type, which is the combination of outer/inner L2, L3, L4
444  * and tunnel types. The packet_type is about data really present in the
445  * mbuf. Example: if vlan stripping is enabled, a received vlan packet
446  * would have RTE_PTYPE_L2_ETHER and not RTE_PTYPE_L2_VLAN because the
447  * vlan is stripped from the data.
448  */
450  union {
451  uint32_t packet_type;
452  struct {
453  uint32_t l2_type:4;
454  uint32_t l3_type:4;
455  uint32_t l4_type:4;
456  uint32_t tun_type:4;
457  uint32_t inner_l2_type:4;
458  uint32_t inner_l3_type:4;
459  uint32_t inner_l4_type:4;
460  };
461  };
462 
463  uint32_t pkt_len;
464  uint16_t data_len;
466  uint16_t vlan_tci;
467 
468  union {
469  uint32_t rss;
470  struct {
472  union {
473  struct {
474  uint16_t hash;
475  uint16_t id;
476  };
477  uint32_t lo;
479  };
480  uint32_t hi;
483  } fdir;
484  struct {
485  uint32_t lo;
486  uint32_t hi;
487  } sched;
488  uint32_t usr;
489  } hash;
492  uint16_t vlan_tci_outer;
493 
494  uint16_t buf_len;
499  uint64_t timestamp;
500 
501  /* second cache line - fields only used in slow path or on TX */
502  MARKER cacheline1 __rte_cache_min_aligned;
503 
505  union {
506  void *userdata;
507  uint64_t udata64;
508  };
509 
510  struct rte_mempool *pool;
511  struct rte_mbuf *next;
513  /* fields to support TX offloads */
515  union {
516  uint64_t tx_offload;
517  __extension__
518  struct {
519  uint64_t l2_len:7;
523  uint64_t l3_len:9;
524  uint64_t l4_len:8;
525  uint64_t tso_segsz:16;
527  /* fields for TX offloading of tunnels */
528  uint64_t outer_l3_len:9;
529  uint64_t outer_l2_len:7;
531  /* uint64_t unused:8; */
532  };
533  };
534 
537  uint16_t priv_size;
538 
540  uint16_t timesync;
541 
543  uint32_t seqn;
544 
546 
557 static inline void
559 {
560  rte_prefetch0(&m->cacheline0);
561 }
562 
574 static inline void
576 {
577 #if RTE_CACHE_LINE_SIZE == 64
578  rte_prefetch0(&m->cacheline1);
579 #else
580  RTE_SET_USED(m);
581 #endif
582 }
583 
584 
585 static inline uint16_t rte_pktmbuf_priv_size(struct rte_mempool *mp);
586 
595 static inline phys_addr_t
597 {
598  return mb->buf_physaddr + mb->data_off;
599 }
600 
613 static inline phys_addr_t
615 {
616  return mb->buf_physaddr + RTE_PKTMBUF_HEADROOM;
617 }
618 
627 static inline struct rte_mbuf *
629 {
630  return (struct rte_mbuf *)RTE_PTR_SUB(mi->buf_addr, sizeof(*mi) + mi->priv_size);
631 }
632 
641 static inline char *
643 {
644  char *buffer_addr;
645  buffer_addr = (char *)md + sizeof(*md) + rte_pktmbuf_priv_size(md->pool);
646  return buffer_addr;
647 }
648 
652 #define RTE_MBUF_INDIRECT(mb) ((mb)->ol_flags & IND_ATTACHED_MBUF)
653 
657 #define RTE_MBUF_DIRECT(mb) (!RTE_MBUF_INDIRECT(mb))
658 
667  uint16_t mbuf_priv_size;
668 };
669 
670 #ifdef RTE_LIBRTE_MBUF_DEBUG
671 
673 #define __rte_mbuf_sanity_check(m, is_h) rte_mbuf_sanity_check(m, is_h)
674 
675 #else /* RTE_LIBRTE_MBUF_DEBUG */
676 
678 #define __rte_mbuf_sanity_check(m, is_h) do { } while (0)
679 
680 #endif /* RTE_LIBRTE_MBUF_DEBUG */
681 
682 #ifdef RTE_MBUF_REFCNT_ATOMIC
683 
691 static inline uint16_t
692 rte_mbuf_refcnt_read(const struct rte_mbuf *m)
693 {
694  return (uint16_t)(rte_atomic16_read(&m->refcnt_atomic));
695 }
696 
704 static inline void
705 rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
706 {
707  rte_atomic16_set(&m->refcnt_atomic, new_value);
708 }
709 
719 static inline uint16_t
720 rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
721 {
722  /*
723  * The atomic_add is an expensive operation, so we don't want to
724  * call it in the case where we know we are the uniq holder of
725  * this mbuf (i.e. ref_cnt == 1). Otherwise, an atomic
726  * operation has to be used because concurrent accesses on the
727  * reference counter can occur.
728  */
729  if (likely(rte_mbuf_refcnt_read(m) == 1)) {
730  rte_mbuf_refcnt_set(m, 1 + value);
731  return 1 + value;
732  }
733 
734  return (uint16_t)(rte_atomic16_add_return(&m->refcnt_atomic, value));
735 }
736 
737 #else /* ! RTE_MBUF_REFCNT_ATOMIC */
738 
742 static inline uint16_t
743 rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
744 {
745  m->refcnt = (uint16_t)(m->refcnt + value);
746  return m->refcnt;
747 }
748 
752 static inline uint16_t
754 {
755  return m->refcnt;
756 }
757 
761 static inline void
762 rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
763 {
764  m->refcnt = new_value;
765 }
766 
767 #endif /* RTE_MBUF_REFCNT_ATOMIC */
768 
770 #define RTE_MBUF_PREFETCH_TO_FREE(m) do { \
771  if ((m) != NULL) \
772  rte_prefetch0(m); \
773 } while (0)
774 
775 
788 void
789 rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header);
790 
791 #define MBUF_RAW_ALLOC_CHECK(m) do { \
792  RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1); \
793  RTE_ASSERT((m)->next == NULL); \
794  RTE_ASSERT((m)->nb_segs == 1); \
795  __rte_mbuf_sanity_check(m, 0); \
796 } while (0)
797 
817 static inline struct rte_mbuf *rte_mbuf_raw_alloc(struct rte_mempool *mp)
818 {
819  struct rte_mbuf *m;
820  void *mb = NULL;
821 
822  if (rte_mempool_get(mp, &mb) < 0)
823  return NULL;
824  m = (struct rte_mbuf *)mb;
825  MBUF_RAW_ALLOC_CHECK(m);
826  return m;
827 }
828 
843 static inline void __attribute__((always_inline))
845 {
846  RTE_ASSERT(RTE_MBUF_DIRECT(m));
847  RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1);
848  RTE_ASSERT(m->next == NULL);
849  RTE_ASSERT(m->nb_segs == 1);
851  rte_mempool_put(m->pool, m);
852 }
853 
854 /* compat with older versions */
855 __rte_deprecated
856 static inline void
857 __rte_mbuf_raw_free(struct rte_mbuf *m)
858 {
860 }
861 
862 /* Operations on ctrl mbuf */
863 
883 void rte_ctrlmbuf_init(struct rte_mempool *mp, void *opaque_arg,
884  void *m, unsigned i);
885 
898 #define rte_ctrlmbuf_alloc(mp) rte_pktmbuf_alloc(mp)
899 
906 #define rte_ctrlmbuf_free(m) rte_pktmbuf_free(m)
907 
916 #define rte_ctrlmbuf_data(m) ((char *)((m)->buf_addr) + (m)->data_off)
917 
926 #define rte_ctrlmbuf_len(m) rte_pktmbuf_data_len(m)
927 
937 static inline int
939 {
940  return !!(m->ol_flags & CTRL_MBUF_FLAG);
941 }
942 
943 /* Operations on pkt mbuf */
944 
964 void rte_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg,
965  void *m, unsigned i);
966 
967 
985 void rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg);
986 
1021 struct rte_mempool *
1022 rte_pktmbuf_pool_create(const char *name, unsigned n,
1023  unsigned cache_size, uint16_t priv_size, uint16_t data_room_size,
1024  int socket_id);
1025 
1037 static inline uint16_t
1039 {
1040  struct rte_pktmbuf_pool_private *mbp_priv;
1041 
1042  mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
1043  return mbp_priv->mbuf_data_room_size;
1044 }
1045 
1058 static inline uint16_t
1060 {
1061  struct rte_pktmbuf_pool_private *mbp_priv;
1062 
1063  mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
1064  return mbp_priv->mbuf_priv_size;
1065 }
1066 
1075 static inline void rte_pktmbuf_reset_headroom(struct rte_mbuf *m)
1076 {
1077  m->data_off = RTE_MIN(RTE_PKTMBUF_HEADROOM, (uint16_t)m->buf_len);
1078 }
1079 
1088 static inline void rte_pktmbuf_reset(struct rte_mbuf *m)
1089 {
1090  m->next = NULL;
1091  m->pkt_len = 0;
1092  m->tx_offload = 0;
1093  m->vlan_tci = 0;
1094  m->vlan_tci_outer = 0;
1095  m->nb_segs = 1;
1096  m->port = 0xff;
1097 
1098  m->ol_flags = 0;
1099  m->packet_type = 0;
1101 
1102  m->data_len = 0;
1104 }
1105 
1119 static inline struct rte_mbuf *rte_pktmbuf_alloc(struct rte_mempool *mp)
1120 {
1121  struct rte_mbuf *m;
1122  if ((m = rte_mbuf_raw_alloc(mp)) != NULL)
1123  rte_pktmbuf_reset(m);
1124  return m;
1125 }
1126 
1141 static inline int rte_pktmbuf_alloc_bulk(struct rte_mempool *pool,
1142  struct rte_mbuf **mbufs, unsigned count)
1143 {
1144  unsigned idx = 0;
1145  int rc;
1146 
1147  rc = rte_mempool_get_bulk(pool, (void **)mbufs, count);
1148  if (unlikely(rc))
1149  return rc;
1150 
1151  /* To understand duff's device on loop unwinding optimization, see
1152  * https://en.wikipedia.org/wiki/Duff's_device.
1153  * Here while() loop is used rather than do() while{} to avoid extra
1154  * check if count is zero.
1155  */
1156  switch (count % 4) {
1157  case 0:
1158  while (idx != count) {
1159  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1160  rte_pktmbuf_reset(mbufs[idx]);
1161  idx++;
1162  /* fall-through */
1163  case 3:
1164  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1165  rte_pktmbuf_reset(mbufs[idx]);
1166  idx++;
1167  /* fall-through */
1168  case 2:
1169  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1170  rte_pktmbuf_reset(mbufs[idx]);
1171  idx++;
1172  /* fall-through */
1173  case 1:
1174  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1175  rte_pktmbuf_reset(mbufs[idx]);
1176  idx++;
1177  /* fall-through */
1178  }
1179  }
1180  return 0;
1181 }
1182 
1200 static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *m)
1201 {
1202  struct rte_mbuf *md;
1203 
1204  RTE_ASSERT(RTE_MBUF_DIRECT(mi) &&
1205  rte_mbuf_refcnt_read(mi) == 1);
1206 
1207  /* if m is not direct, get the mbuf that embeds the data */
1208  if (RTE_MBUF_DIRECT(m))
1209  md = m;
1210  else
1211  md = rte_mbuf_from_indirect(m);
1212 
1213  rte_mbuf_refcnt_update(md, 1);
1214  mi->priv_size = m->priv_size;
1215  mi->buf_physaddr = m->buf_physaddr;
1216  mi->buf_addr = m->buf_addr;
1217  mi->buf_len = m->buf_len;
1218 
1219  mi->data_off = m->data_off;
1220  mi->data_len = m->data_len;
1221  mi->port = m->port;
1222  mi->vlan_tci = m->vlan_tci;
1223  mi->vlan_tci_outer = m->vlan_tci_outer;
1224  mi->tx_offload = m->tx_offload;
1225  mi->hash = m->hash;
1226 
1227  mi->next = NULL;
1228  mi->pkt_len = mi->data_len;
1229  mi->nb_segs = 1;
1230  mi->ol_flags = m->ol_flags | IND_ATTACHED_MBUF;
1231  mi->packet_type = m->packet_type;
1232  mi->timestamp = m->timestamp;
1233 
1234  __rte_mbuf_sanity_check(mi, 1);
1236 }
1237 
1251 static inline void rte_pktmbuf_detach(struct rte_mbuf *m)
1252 {
1253  struct rte_mbuf *md = rte_mbuf_from_indirect(m);
1254  struct rte_mempool *mp = m->pool;
1255  uint32_t mbuf_size, buf_len, priv_size;
1256 
1257  priv_size = rte_pktmbuf_priv_size(mp);
1258  mbuf_size = sizeof(struct rte_mbuf) + priv_size;
1259  buf_len = rte_pktmbuf_data_room_size(mp);
1260 
1261  m->priv_size = priv_size;
1262  m->buf_addr = (char *)m + mbuf_size;
1263  m->buf_physaddr = rte_mempool_virt2phy(mp, m) + mbuf_size;
1264  m->buf_len = (uint16_t)buf_len;
1266  m->data_len = 0;
1267  m->ol_flags = 0;
1268 
1269  if (rte_mbuf_refcnt_update(md, -1) == 0) {
1270  md->next = NULL;
1271  md->nb_segs = 1;
1272  rte_mbuf_refcnt_set(md, 1);
1273  rte_mbuf_raw_free(md);
1274  }
1275 }
1276 
1291 __attribute__((always_inline))
1292 static inline struct rte_mbuf *
1294 {
1296 
1297  if (likely(rte_mbuf_refcnt_read(m) == 1)) {
1298 
1299  if (RTE_MBUF_INDIRECT(m))
1300  rte_pktmbuf_detach(m);
1301 
1302  if (m->next != NULL) {
1303  m->next = NULL;
1304  m->nb_segs = 1;
1305  }
1306 
1307  return m;
1308 
1309  } else if (rte_atomic16_add_return(&m->refcnt_atomic, -1) == 0) {
1310 
1311 
1312  if (RTE_MBUF_INDIRECT(m))
1313  rte_pktmbuf_detach(m);
1314 
1315  if (m->next != NULL) {
1316  m->next = NULL;
1317  m->nb_segs = 1;
1318  }
1319  rte_mbuf_refcnt_set(m, 1);
1320 
1321  return m;
1322  }
1323  return NULL;
1324 }
1325 
1326 /* deprecated, replaced by rte_pktmbuf_prefree_seg() */
1327 __rte_deprecated
1328 static inline struct rte_mbuf *
1329 __rte_pktmbuf_prefree_seg(struct rte_mbuf *m)
1330 {
1331  return rte_pktmbuf_prefree_seg(m);
1332 }
1333 
1343 static inline void __attribute__((always_inline))
1345 {
1346  m = rte_pktmbuf_prefree_seg(m);
1347  if (likely(m != NULL))
1348  rte_mbuf_raw_free(m);
1349 }
1350 
1360 static inline void rte_pktmbuf_free(struct rte_mbuf *m)
1361 {
1362  struct rte_mbuf *m_next;
1363 
1365 
1366  while (m != NULL) {
1367  m_next = m->next;
1369  m = m_next;
1370  }
1371 }
1372 
1390 static inline struct rte_mbuf *rte_pktmbuf_clone(struct rte_mbuf *md,
1391  struct rte_mempool *mp)
1392 {
1393  struct rte_mbuf *mc, *mi, **prev;
1394  uint32_t pktlen;
1395  uint8_t nseg;
1396 
1397  if (unlikely ((mc = rte_pktmbuf_alloc(mp)) == NULL))
1398  return NULL;
1399 
1400  mi = mc;
1401  prev = &mi->next;
1402  pktlen = md->pkt_len;
1403  nseg = 0;
1404 
1405  do {
1406  nseg++;
1407  rte_pktmbuf_attach(mi, md);
1408  *prev = mi;
1409  prev = &mi->next;
1410  } while ((md = md->next) != NULL &&
1411  (mi = rte_pktmbuf_alloc(mp)) != NULL);
1412 
1413  *prev = NULL;
1414  mc->nb_segs = nseg;
1415  mc->pkt_len = pktlen;
1416 
1417  /* Allocation of new indirect segment failed */
1418  if (unlikely (mi == NULL)) {
1419  rte_pktmbuf_free(mc);
1420  return NULL;
1421  }
1422 
1423  __rte_mbuf_sanity_check(mc, 1);
1424  return mc;
1425 }
1426 
1438 static inline void rte_pktmbuf_refcnt_update(struct rte_mbuf *m, int16_t v)
1439 {
1441 
1442  do {
1443  rte_mbuf_refcnt_update(m, v);
1444  } while ((m = m->next) != NULL);
1445 }
1446 
1455 static inline uint16_t rte_pktmbuf_headroom(const struct rte_mbuf *m)
1456 {
1458  return m->data_off;
1459 }
1460 
1469 static inline uint16_t rte_pktmbuf_tailroom(const struct rte_mbuf *m)
1470 {
1472  return (uint16_t)(m->buf_len - rte_pktmbuf_headroom(m) -
1473  m->data_len);
1474 }
1475 
1484 static inline struct rte_mbuf *rte_pktmbuf_lastseg(struct rte_mbuf *m)
1485 {
1486  struct rte_mbuf *m2 = (struct rte_mbuf *)m;
1487 
1489  while (m2->next != NULL)
1490  m2 = m2->next;
1491  return m2;
1492 }
1493 
1508 #define rte_pktmbuf_mtod_offset(m, t, o) \
1509  ((t)((char *)(m)->buf_addr + (m)->data_off + (o)))
1510 
1523 #define rte_pktmbuf_mtod(m, t) rte_pktmbuf_mtod_offset(m, t, 0)
1524 
1534 #define rte_pktmbuf_mtophys_offset(m, o) \
1535  (phys_addr_t)((m)->buf_physaddr + (m)->data_off + (o))
1536 
1544 #define rte_pktmbuf_mtophys(m) rte_pktmbuf_mtophys_offset(m, 0)
1545 
1554 #define rte_pktmbuf_pkt_len(m) ((m)->pkt_len)
1555 
1564 #define rte_pktmbuf_data_len(m) ((m)->data_len)
1565 
1581 static inline char *rte_pktmbuf_prepend(struct rte_mbuf *m,
1582  uint16_t len)
1583 {
1585 
1586  if (unlikely(len > rte_pktmbuf_headroom(m)))
1587  return NULL;
1588 
1589  m->data_off -= len;
1590  m->data_len = (uint16_t)(m->data_len + len);
1591  m->pkt_len = (m->pkt_len + len);
1592 
1593  return (char *)m->buf_addr + m->data_off;
1594 }
1595 
1611 static inline char *rte_pktmbuf_append(struct rte_mbuf *m, uint16_t len)
1612 {
1613  void *tail;
1614  struct rte_mbuf *m_last;
1615 
1617 
1618  m_last = rte_pktmbuf_lastseg(m);
1619  if (unlikely(len > rte_pktmbuf_tailroom(m_last)))
1620  return NULL;
1621 
1622  tail = (char *)m_last->buf_addr + m_last->data_off + m_last->data_len;
1623  m_last->data_len = (uint16_t)(m_last->data_len + len);
1624  m->pkt_len = (m->pkt_len + len);
1625  return (char*) tail;
1626 }
1627 
1642 static inline char *rte_pktmbuf_adj(struct rte_mbuf *m, uint16_t len)
1643 {
1645 
1646  if (unlikely(len > m->data_len))
1647  return NULL;
1648 
1649  m->data_len = (uint16_t)(m->data_len - len);
1650  m->data_off += len;
1651  m->pkt_len = (m->pkt_len - len);
1652  return (char *)m->buf_addr + m->data_off;
1653 }
1654 
1669 static inline int rte_pktmbuf_trim(struct rte_mbuf *m, uint16_t len)
1670 {
1671  struct rte_mbuf *m_last;
1672 
1674 
1675  m_last = rte_pktmbuf_lastseg(m);
1676  if (unlikely(len > m_last->data_len))
1677  return -1;
1678 
1679  m_last->data_len = (uint16_t)(m_last->data_len - len);
1680  m->pkt_len = (m->pkt_len - len);
1681  return 0;
1682 }
1683 
1693 static inline int rte_pktmbuf_is_contiguous(const struct rte_mbuf *m)
1694 {
1696  return !!(m->nb_segs == 1);
1697 }
1698 
1702 const void *__rte_pktmbuf_read(const struct rte_mbuf *m, uint32_t off,
1703  uint32_t len, void *buf);
1704 
1725 static inline const void *rte_pktmbuf_read(const struct rte_mbuf *m,
1726  uint32_t off, uint32_t len, void *buf)
1727 {
1728  if (likely(off + len <= rte_pktmbuf_data_len(m)))
1729  return rte_pktmbuf_mtod_offset(m, char *, off);
1730  else
1731  return __rte_pktmbuf_read(m, off, len, buf);
1732 }
1733 
1750 static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail)
1751 {
1752  struct rte_mbuf *cur_tail;
1753 
1754  /* Check for number-of-segments-overflow */
1755  if (head->nb_segs + tail->nb_segs >= 1 << (sizeof(head->nb_segs) * 8))
1756  return -EOVERFLOW;
1757 
1758  /* Chain 'tail' onto the old tail */
1759  cur_tail = rte_pktmbuf_lastseg(head);
1760  cur_tail->next = tail;
1761 
1762  /* accumulate number of segments and total length. */
1763  head->nb_segs = (uint8_t)(head->nb_segs + tail->nb_segs);
1764  head->pkt_len += tail->pkt_len;
1765 
1766  /* pkt_len is only set in the head */
1767  tail->pkt_len = tail->data_len;
1768 
1769  return 0;
1770 }
1771 
1782 static inline int
1784 {
1785  uint64_t ol_flags = m->ol_flags;
1786  uint64_t inner_l3_offset = m->l2_len;
1787 
1788  /* Does packet set any of available offloads? */
1789  if (!(ol_flags & PKT_TX_OFFLOAD_MASK))
1790  return 0;
1791 
1792  if (ol_flags & PKT_TX_OUTER_IP_CKSUM)
1793  inner_l3_offset += m->outer_l2_len + m->outer_l3_len;
1794 
1795  /* Headers are fragmented */
1796  if (rte_pktmbuf_data_len(m) < inner_l3_offset + m->l3_len + m->l4_len)
1797  return -ENOTSUP;
1798 
1799  /* IP checksum can be counted only for IPv4 packet */
1800  if ((ol_flags & PKT_TX_IP_CKSUM) && (ol_flags & PKT_TX_IPV6))
1801  return -EINVAL;
1802 
1803  /* IP type not set when required */
1804  if (ol_flags & (PKT_TX_L4_MASK | PKT_TX_TCP_SEG))
1805  if (!(ol_flags & (PKT_TX_IPV4 | PKT_TX_IPV6)))
1806  return -EINVAL;
1807 
1808  /* Check requirements for TSO packet */
1809  if (ol_flags & PKT_TX_TCP_SEG)
1810  if ((m->tso_segsz == 0) ||
1811  ((ol_flags & PKT_TX_IPV4) &&
1812  !(ol_flags & PKT_TX_IP_CKSUM)))
1813  return -EINVAL;
1814 
1815  /* PKT_TX_OUTER_IP_CKSUM set for non outer IPv4 packet. */
1816  if ((ol_flags & PKT_TX_OUTER_IP_CKSUM) &&
1817  !(ol_flags & PKT_TX_OUTER_IPV4))
1818  return -EINVAL;
1819 
1820  return 0;
1821 }
1822 
1835 static inline int
1837 {
1838  int seg_len, copy_len;
1839  struct rte_mbuf *m;
1840  struct rte_mbuf *m_next;
1841  char *buffer;
1842 
1843  if (rte_pktmbuf_is_contiguous(mbuf))
1844  return 0;
1845 
1846  /* Extend first segment to the total packet length */
1847  copy_len = rte_pktmbuf_pkt_len(mbuf) - rte_pktmbuf_data_len(mbuf);
1848 
1849  if (unlikely(copy_len > rte_pktmbuf_tailroom(mbuf)))
1850  return -1;
1851 
1852  buffer = rte_pktmbuf_mtod_offset(mbuf, char *, mbuf->data_len);
1853  mbuf->data_len = (uint16_t)(mbuf->pkt_len);
1854 
1855  /* Append data from next segments to the first one */
1856  m = mbuf->next;
1857  while (m != NULL) {
1858  m_next = m->next;
1859 
1860  seg_len = rte_pktmbuf_data_len(m);
1861  rte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), seg_len);
1862  buffer += seg_len;
1863 
1865  m = m_next;
1866  }
1867 
1868  mbuf->next = NULL;
1869  mbuf->nb_segs = 1;
1870 
1871  return 0;
1872 }
1873 
1888 void rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len);
1889 
1890 #ifdef __cplusplus
1891 }
1892 #endif
1893 
1894 #endif /* _RTE_MBUF_H_ */