DPDK  17.08.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 
212 #define PKT_TX_TUNNEL_MPLSINUDP (0x5ULL << 45)
213 /* add new TX TUNNEL type here */
214 #define PKT_TX_TUNNEL_MASK (0xFULL << 45)
215 
219 #define PKT_TX_QINQ_PKT (1ULL << 49)
234 #define PKT_TX_TCP_SEG (1ULL << 50)
235 
236 #define PKT_TX_IEEE1588_TMST (1ULL << 51)
249 #define PKT_TX_L4_NO_CKSUM (0ULL << 52)
250 #define PKT_TX_TCP_CKSUM (1ULL << 52)
251 #define PKT_TX_SCTP_CKSUM (2ULL << 52)
252 #define PKT_TX_UDP_CKSUM (3ULL << 52)
253 #define PKT_TX_L4_MASK (3ULL << 52)
262 #define PKT_TX_IP_CKSUM (1ULL << 54)
263 
270 #define PKT_TX_IPV4 (1ULL << 55)
271 
278 #define PKT_TX_IPV6 (1ULL << 56)
279 
280 #define PKT_TX_VLAN_PKT (1ULL << 57)
290 #define PKT_TX_OUTER_IP_CKSUM (1ULL << 58)
291 
297 #define PKT_TX_OUTER_IPV4 (1ULL << 59)
298 
304 #define PKT_TX_OUTER_IPV6 (1ULL << 60)
305 
310 #define PKT_TX_OFFLOAD_MASK ( \
311  PKT_TX_IP_CKSUM | \
312  PKT_TX_L4_MASK | \
313  PKT_TX_OUTER_IP_CKSUM | \
314  PKT_TX_TCP_SEG | \
315  PKT_TX_IEEE1588_TMST | \
316  PKT_TX_QINQ_PKT | \
317  PKT_TX_VLAN_PKT | \
318  PKT_TX_TUNNEL_MASK | \
319  PKT_TX_MACSEC)
320 
321 #define __RESERVED (1ULL << 61)
323 #define IND_ATTACHED_MBUF (1ULL << 62)
325 /* Use final bit of flags to indicate a control mbuf */
326 #define CTRL_MBUF_FLAG (1ULL << 63)
329 #define RTE_MBUF_PRIV_ALIGN 8
330 
339 const char *rte_get_rx_ol_flag_name(uint64_t mask);
340 
353 int rte_get_rx_ol_flag_list(uint64_t mask, char *buf, size_t buflen);
354 
365 const char *rte_get_tx_ol_flag_name(uint64_t mask);
366 
379 int rte_get_tx_ol_flag_list(uint64_t mask, char *buf, size_t buflen);
380 
387 #define RTE_MBUF_DEFAULT_DATAROOM 2048
388 #define RTE_MBUF_DEFAULT_BUF_SIZE \
389  (RTE_MBUF_DEFAULT_DATAROOM + RTE_PKTMBUF_HEADROOM)
390 
391 /* define a set of marker types that can be used to refer to set points in the
392  * mbuf */
393 __extension__
394 typedef void *MARKER[0];
395 __extension__
396 typedef uint8_t MARKER8[0];
397 __extension__
398 typedef uint64_t MARKER64[0];
404 struct rte_mbuf {
405  MARKER cacheline0;
406 
407  void *buf_addr;
414  phys_addr_t buf_physaddr __rte_aligned(sizeof(phys_addr_t));
415 
416  /* next 8 bytes are initialised on RX descriptor rearm */
417  MARKER64 rearm_data;
418  uint16_t data_off;
419 
430  union {
432  uint16_t refcnt;
433  };
434  uint16_t nb_segs;
437  uint16_t port;
438 
439  uint64_t ol_flags;
441  /* remaining bytes are set on RX when pulling packet from descriptor */
442  MARKER rx_descriptor_fields1;
443 
444  /*
445  * The packet type, which is the combination of outer/inner L2, L3, L4
446  * and tunnel types. The packet_type is about data really present in the
447  * mbuf. Example: if vlan stripping is enabled, a received vlan packet
448  * would have RTE_PTYPE_L2_ETHER and not RTE_PTYPE_L2_VLAN because the
449  * vlan is stripped from the data.
450  */
452  union {
453  uint32_t packet_type;
454  struct {
455  uint32_t l2_type:4;
456  uint32_t l3_type:4;
457  uint32_t l4_type:4;
458  uint32_t tun_type:4;
459  uint32_t inner_l2_type:4;
460  uint32_t inner_l3_type:4;
461  uint32_t inner_l4_type:4;
462  };
463  };
464 
465  uint32_t pkt_len;
466  uint16_t data_len;
468  uint16_t vlan_tci;
469 
470  union {
471  uint32_t rss;
472  struct {
474  union {
475  struct {
476  uint16_t hash;
477  uint16_t id;
478  };
479  uint32_t lo;
481  };
482  uint32_t hi;
485  } fdir;
486  struct {
487  uint32_t lo;
488  uint32_t hi;
489  } sched;
490  uint32_t usr;
491  } hash;
494  uint16_t vlan_tci_outer;
495 
496  uint16_t buf_len;
501  uint64_t timestamp;
502 
503  /* second cache line - fields only used in slow path or on TX */
504  MARKER cacheline1 __rte_cache_min_aligned;
505 
507  union {
508  void *userdata;
509  uint64_t udata64;
510  };
511 
512  struct rte_mempool *pool;
513  struct rte_mbuf *next;
515  /* fields to support TX offloads */
517  union {
518  uint64_t tx_offload;
519  __extension__
520  struct {
521  uint64_t l2_len:7;
525  uint64_t l3_len:9;
526  uint64_t l4_len:8;
527  uint64_t tso_segsz:16;
529  /* fields for TX offloading of tunnels */
530  uint64_t outer_l3_len:9;
531  uint64_t outer_l2_len:7;
533  /* uint64_t unused:8; */
534  };
535  };
536 
539  uint16_t priv_size;
540 
542  uint16_t timesync;
543 
545  uint32_t seqn;
546 
548 
559 static inline void
561 {
562  rte_prefetch0(&m->cacheline0);
563 }
564 
576 static inline void
578 {
579 #if RTE_CACHE_LINE_SIZE == 64
580  rte_prefetch0(&m->cacheline1);
581 #else
582  RTE_SET_USED(m);
583 #endif
584 }
585 
586 
587 static inline uint16_t rte_pktmbuf_priv_size(struct rte_mempool *mp);
588 
597 static inline phys_addr_t
599 {
600  return mb->buf_physaddr + mb->data_off;
601 }
602 
615 static inline phys_addr_t
617 {
618  return mb->buf_physaddr + RTE_PKTMBUF_HEADROOM;
619 }
620 
629 static inline struct rte_mbuf *
631 {
632  return (struct rte_mbuf *)RTE_PTR_SUB(mi->buf_addr, sizeof(*mi) + mi->priv_size);
633 }
634 
643 static inline char *
645 {
646  char *buffer_addr;
647  buffer_addr = (char *)md + sizeof(*md) + rte_pktmbuf_priv_size(md->pool);
648  return buffer_addr;
649 }
650 
654 #define RTE_MBUF_INDIRECT(mb) ((mb)->ol_flags & IND_ATTACHED_MBUF)
655 
659 #define RTE_MBUF_DIRECT(mb) (!RTE_MBUF_INDIRECT(mb))
660 
669  uint16_t mbuf_priv_size;
670 };
671 
672 #ifdef RTE_LIBRTE_MBUF_DEBUG
673 
675 #define __rte_mbuf_sanity_check(m, is_h) rte_mbuf_sanity_check(m, is_h)
676 
677 #else /* RTE_LIBRTE_MBUF_DEBUG */
678 
680 #define __rte_mbuf_sanity_check(m, is_h) do { } while (0)
681 
682 #endif /* RTE_LIBRTE_MBUF_DEBUG */
683 
684 #ifdef RTE_MBUF_REFCNT_ATOMIC
685 
693 static inline uint16_t
694 rte_mbuf_refcnt_read(const struct rte_mbuf *m)
695 {
696  return (uint16_t)(rte_atomic16_read(&m->refcnt_atomic));
697 }
698 
706 static inline void
707 rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
708 {
709  rte_atomic16_set(&m->refcnt_atomic, new_value);
710 }
711 
721 static inline uint16_t
722 rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
723 {
724  /*
725  * The atomic_add is an expensive operation, so we don't want to
726  * call it in the case where we know we are the uniq holder of
727  * this mbuf (i.e. ref_cnt == 1). Otherwise, an atomic
728  * operation has to be used because concurrent accesses on the
729  * reference counter can occur.
730  */
731  if (likely(rte_mbuf_refcnt_read(m) == 1)) {
732  rte_mbuf_refcnt_set(m, 1 + value);
733  return 1 + value;
734  }
735 
736  return (uint16_t)(rte_atomic16_add_return(&m->refcnt_atomic, value));
737 }
738 
739 #else /* ! RTE_MBUF_REFCNT_ATOMIC */
740 
744 static inline uint16_t
745 rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
746 {
747  m->refcnt = (uint16_t)(m->refcnt + value);
748  return m->refcnt;
749 }
750 
754 static inline uint16_t
756 {
757  return m->refcnt;
758 }
759 
763 static inline void
764 rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
765 {
766  m->refcnt = new_value;
767 }
768 
769 #endif /* RTE_MBUF_REFCNT_ATOMIC */
770 
772 #define RTE_MBUF_PREFETCH_TO_FREE(m) do { \
773  if ((m) != NULL) \
774  rte_prefetch0(m); \
775 } while (0)
776 
777 
790 void
791 rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header);
792 
793 #define MBUF_RAW_ALLOC_CHECK(m) do { \
794  RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1); \
795  RTE_ASSERT((m)->next == NULL); \
796  RTE_ASSERT((m)->nb_segs == 1); \
797  __rte_mbuf_sanity_check(m, 0); \
798 } while (0)
799 
819 static inline struct rte_mbuf *rte_mbuf_raw_alloc(struct rte_mempool *mp)
820 {
821  struct rte_mbuf *m;
822  void *mb = NULL;
823 
824  if (rte_mempool_get(mp, &mb) < 0)
825  return NULL;
826  m = (struct rte_mbuf *)mb;
827  MBUF_RAW_ALLOC_CHECK(m);
828  return m;
829 }
830 
845 static __rte_always_inline void
847 {
848  RTE_ASSERT(RTE_MBUF_DIRECT(m));
849  RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1);
850  RTE_ASSERT(m->next == NULL);
851  RTE_ASSERT(m->nb_segs == 1);
853  rte_mempool_put(m->pool, m);
854 }
855 
856 /* compat with older versions */
857 __rte_deprecated
858 static inline void
859 __rte_mbuf_raw_free(struct rte_mbuf *m)
860 {
862 }
863 
864 /* Operations on ctrl mbuf */
865 
885 void rte_ctrlmbuf_init(struct rte_mempool *mp, void *opaque_arg,
886  void *m, unsigned i);
887 
900 #define rte_ctrlmbuf_alloc(mp) rte_pktmbuf_alloc(mp)
901 
908 #define rte_ctrlmbuf_free(m) rte_pktmbuf_free(m)
909 
918 #define rte_ctrlmbuf_data(m) ((char *)((m)->buf_addr) + (m)->data_off)
919 
928 #define rte_ctrlmbuf_len(m) rte_pktmbuf_data_len(m)
929 
939 static inline int
941 {
942  return !!(m->ol_flags & CTRL_MBUF_FLAG);
943 }
944 
945 /* Operations on pkt mbuf */
946 
966 void rte_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg,
967  void *m, unsigned i);
968 
969 
987 void rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg);
988 
1023 struct rte_mempool *
1024 rte_pktmbuf_pool_create(const char *name, unsigned n,
1025  unsigned cache_size, uint16_t priv_size, uint16_t data_room_size,
1026  int socket_id);
1027 
1039 static inline uint16_t
1041 {
1042  struct rte_pktmbuf_pool_private *mbp_priv;
1043 
1044  mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
1045  return mbp_priv->mbuf_data_room_size;
1046 }
1047 
1060 static inline uint16_t
1062 {
1063  struct rte_pktmbuf_pool_private *mbp_priv;
1064 
1065  mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
1066  return mbp_priv->mbuf_priv_size;
1067 }
1068 
1077 static inline void rte_pktmbuf_reset_headroom(struct rte_mbuf *m)
1078 {
1079  m->data_off = RTE_MIN(RTE_PKTMBUF_HEADROOM, (uint16_t)m->buf_len);
1080 }
1081 
1090 static inline void rte_pktmbuf_reset(struct rte_mbuf *m)
1091 {
1092  m->next = NULL;
1093  m->pkt_len = 0;
1094  m->tx_offload = 0;
1095  m->vlan_tci = 0;
1096  m->vlan_tci_outer = 0;
1097  m->nb_segs = 1;
1098  m->port = 0xff;
1099 
1100  m->ol_flags = 0;
1101  m->packet_type = 0;
1103 
1104  m->data_len = 0;
1106 }
1107 
1121 static inline struct rte_mbuf *rte_pktmbuf_alloc(struct rte_mempool *mp)
1122 {
1123  struct rte_mbuf *m;
1124  if ((m = rte_mbuf_raw_alloc(mp)) != NULL)
1125  rte_pktmbuf_reset(m);
1126  return m;
1127 }
1128 
1143 static inline int rte_pktmbuf_alloc_bulk(struct rte_mempool *pool,
1144  struct rte_mbuf **mbufs, unsigned count)
1145 {
1146  unsigned idx = 0;
1147  int rc;
1148 
1149  rc = rte_mempool_get_bulk(pool, (void **)mbufs, count);
1150  if (unlikely(rc))
1151  return rc;
1152 
1153  /* To understand duff's device on loop unwinding optimization, see
1154  * https://en.wikipedia.org/wiki/Duff's_device.
1155  * Here while() loop is used rather than do() while{} to avoid extra
1156  * check if count is zero.
1157  */
1158  switch (count % 4) {
1159  case 0:
1160  while (idx != count) {
1161  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1162  rte_pktmbuf_reset(mbufs[idx]);
1163  idx++;
1164  /* fall-through */
1165  case 3:
1166  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1167  rte_pktmbuf_reset(mbufs[idx]);
1168  idx++;
1169  /* fall-through */
1170  case 2:
1171  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1172  rte_pktmbuf_reset(mbufs[idx]);
1173  idx++;
1174  /* fall-through */
1175  case 1:
1176  MBUF_RAW_ALLOC_CHECK(mbufs[idx]);
1177  rte_pktmbuf_reset(mbufs[idx]);
1178  idx++;
1179  /* fall-through */
1180  }
1181  }
1182  return 0;
1183 }
1184 
1202 static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *m)
1203 {
1204  struct rte_mbuf *md;
1205 
1206  RTE_ASSERT(RTE_MBUF_DIRECT(mi) &&
1207  rte_mbuf_refcnt_read(mi) == 1);
1208 
1209  /* if m is not direct, get the mbuf that embeds the data */
1210  if (RTE_MBUF_DIRECT(m))
1211  md = m;
1212  else
1213  md = rte_mbuf_from_indirect(m);
1214 
1215  rte_mbuf_refcnt_update(md, 1);
1216  mi->priv_size = m->priv_size;
1217  mi->buf_physaddr = m->buf_physaddr;
1218  mi->buf_addr = m->buf_addr;
1219  mi->buf_len = m->buf_len;
1220 
1221  mi->data_off = m->data_off;
1222  mi->data_len = m->data_len;
1223  mi->port = m->port;
1224  mi->vlan_tci = m->vlan_tci;
1225  mi->vlan_tci_outer = m->vlan_tci_outer;
1226  mi->tx_offload = m->tx_offload;
1227  mi->hash = m->hash;
1228 
1229  mi->next = NULL;
1230  mi->pkt_len = mi->data_len;
1231  mi->nb_segs = 1;
1232  mi->ol_flags = m->ol_flags | IND_ATTACHED_MBUF;
1233  mi->packet_type = m->packet_type;
1234  mi->timestamp = m->timestamp;
1235 
1236  __rte_mbuf_sanity_check(mi, 1);
1238 }
1239 
1253 static inline void rte_pktmbuf_detach(struct rte_mbuf *m)
1254 {
1255  struct rte_mbuf *md = rte_mbuf_from_indirect(m);
1256  struct rte_mempool *mp = m->pool;
1257  uint32_t mbuf_size, buf_len, priv_size;
1258 
1259  priv_size = rte_pktmbuf_priv_size(mp);
1260  mbuf_size = sizeof(struct rte_mbuf) + priv_size;
1261  buf_len = rte_pktmbuf_data_room_size(mp);
1262 
1263  m->priv_size = priv_size;
1264  m->buf_addr = (char *)m + mbuf_size;
1265  m->buf_physaddr = rte_mempool_virt2phy(mp, m) + mbuf_size;
1266  m->buf_len = (uint16_t)buf_len;
1268  m->data_len = 0;
1269  m->ol_flags = 0;
1270 
1271  if (rte_mbuf_refcnt_update(md, -1) == 0) {
1272  md->next = NULL;
1273  md->nb_segs = 1;
1274  rte_mbuf_refcnt_set(md, 1);
1275  rte_mbuf_raw_free(md);
1276  }
1277 }
1278 
1293 static __rte_always_inline struct rte_mbuf *
1295 {
1297 
1298  if (likely(rte_mbuf_refcnt_read(m) == 1)) {
1299 
1300  if (RTE_MBUF_INDIRECT(m))
1301  rte_pktmbuf_detach(m);
1302 
1303  if (m->next != NULL) {
1304  m->next = NULL;
1305  m->nb_segs = 1;
1306  }
1307 
1308  return m;
1309 
1310  } else if (rte_atomic16_add_return(&m->refcnt_atomic, -1) == 0) {
1311 
1312 
1313  if (RTE_MBUF_INDIRECT(m))
1314  rte_pktmbuf_detach(m);
1315 
1316  if (m->next != NULL) {
1317  m->next = NULL;
1318  m->nb_segs = 1;
1319  }
1320  rte_mbuf_refcnt_set(m, 1);
1321 
1322  return m;
1323  }
1324  return NULL;
1325 }
1326 
1327 /* deprecated, replaced by rte_pktmbuf_prefree_seg() */
1328 __rte_deprecated
1329 static inline struct rte_mbuf *
1330 __rte_pktmbuf_prefree_seg(struct rte_mbuf *m)
1331 {
1332  return rte_pktmbuf_prefree_seg(m);
1333 }
1334 
1344 static __rte_always_inline void
1346 {
1347  m = rte_pktmbuf_prefree_seg(m);
1348  if (likely(m != NULL))
1349  rte_mbuf_raw_free(m);
1350 }
1351 
1361 static inline void rte_pktmbuf_free(struct rte_mbuf *m)
1362 {
1363  struct rte_mbuf *m_next;
1364 
1366 
1367  while (m != NULL) {
1368  m_next = m->next;
1370  m = m_next;
1371  }
1372 }
1373 
1391 static inline struct rte_mbuf *rte_pktmbuf_clone(struct rte_mbuf *md,
1392  struct rte_mempool *mp)
1393 {
1394  struct rte_mbuf *mc, *mi, **prev;
1395  uint32_t pktlen;
1396  uint8_t nseg;
1397 
1398  if (unlikely ((mc = rte_pktmbuf_alloc(mp)) == NULL))
1399  return NULL;
1400 
1401  mi = mc;
1402  prev = &mi->next;
1403  pktlen = md->pkt_len;
1404  nseg = 0;
1405 
1406  do {
1407  nseg++;
1408  rte_pktmbuf_attach(mi, md);
1409  *prev = mi;
1410  prev = &mi->next;
1411  } while ((md = md->next) != NULL &&
1412  (mi = rte_pktmbuf_alloc(mp)) != NULL);
1413 
1414  *prev = NULL;
1415  mc->nb_segs = nseg;
1416  mc->pkt_len = pktlen;
1417 
1418  /* Allocation of new indirect segment failed */
1419  if (unlikely (mi == NULL)) {
1420  rte_pktmbuf_free(mc);
1421  return NULL;
1422  }
1423 
1424  __rte_mbuf_sanity_check(mc, 1);
1425  return mc;
1426 }
1427 
1439 static inline void rte_pktmbuf_refcnt_update(struct rte_mbuf *m, int16_t v)
1440 {
1442 
1443  do {
1444  rte_mbuf_refcnt_update(m, v);
1445  } while ((m = m->next) != NULL);
1446 }
1447 
1456 static inline uint16_t rte_pktmbuf_headroom(const struct rte_mbuf *m)
1457 {
1459  return m->data_off;
1460 }
1461 
1470 static inline uint16_t rte_pktmbuf_tailroom(const struct rte_mbuf *m)
1471 {
1473  return (uint16_t)(m->buf_len - rte_pktmbuf_headroom(m) -
1474  m->data_len);
1475 }
1476 
1485 static inline struct rte_mbuf *rte_pktmbuf_lastseg(struct rte_mbuf *m)
1486 {
1487  struct rte_mbuf *m2 = (struct rte_mbuf *)m;
1488 
1490  while (m2->next != NULL)
1491  m2 = m2->next;
1492  return m2;
1493 }
1494 
1509 #define rte_pktmbuf_mtod_offset(m, t, o) \
1510  ((t)((char *)(m)->buf_addr + (m)->data_off + (o)))
1511 
1524 #define rte_pktmbuf_mtod(m, t) rte_pktmbuf_mtod_offset(m, t, 0)
1525 
1535 #define rte_pktmbuf_mtophys_offset(m, o) \
1536  (phys_addr_t)((m)->buf_physaddr + (m)->data_off + (o))
1537 
1545 #define rte_pktmbuf_mtophys(m) rte_pktmbuf_mtophys_offset(m, 0)
1546 
1555 #define rte_pktmbuf_pkt_len(m) ((m)->pkt_len)
1556 
1565 #define rte_pktmbuf_data_len(m) ((m)->data_len)
1566 
1582 static inline char *rte_pktmbuf_prepend(struct rte_mbuf *m,
1583  uint16_t len)
1584 {
1586 
1587  if (unlikely(len > rte_pktmbuf_headroom(m)))
1588  return NULL;
1589 
1590  m->data_off -= len;
1591  m->data_len = (uint16_t)(m->data_len + len);
1592  m->pkt_len = (m->pkt_len + len);
1593 
1594  return (char *)m->buf_addr + m->data_off;
1595 }
1596 
1612 static inline char *rte_pktmbuf_append(struct rte_mbuf *m, uint16_t len)
1613 {
1614  void *tail;
1615  struct rte_mbuf *m_last;
1616 
1618 
1619  m_last = rte_pktmbuf_lastseg(m);
1620  if (unlikely(len > rte_pktmbuf_tailroom(m_last)))
1621  return NULL;
1622 
1623  tail = (char *)m_last->buf_addr + m_last->data_off + m_last->data_len;
1624  m_last->data_len = (uint16_t)(m_last->data_len + len);
1625  m->pkt_len = (m->pkt_len + len);
1626  return (char*) tail;
1627 }
1628 
1643 static inline char *rte_pktmbuf_adj(struct rte_mbuf *m, uint16_t len)
1644 {
1646 
1647  if (unlikely(len > m->data_len))
1648  return NULL;
1649 
1650  m->data_len = (uint16_t)(m->data_len - len);
1651  m->data_off += len;
1652  m->pkt_len = (m->pkt_len - len);
1653  return (char *)m->buf_addr + m->data_off;
1654 }
1655 
1670 static inline int rte_pktmbuf_trim(struct rte_mbuf *m, uint16_t len)
1671 {
1672  struct rte_mbuf *m_last;
1673 
1675 
1676  m_last = rte_pktmbuf_lastseg(m);
1677  if (unlikely(len > m_last->data_len))
1678  return -1;
1679 
1680  m_last->data_len = (uint16_t)(m_last->data_len - len);
1681  m->pkt_len = (m->pkt_len - len);
1682  return 0;
1683 }
1684 
1694 static inline int rte_pktmbuf_is_contiguous(const struct rte_mbuf *m)
1695 {
1697  return !!(m->nb_segs == 1);
1698 }
1699 
1703 const void *__rte_pktmbuf_read(const struct rte_mbuf *m, uint32_t off,
1704  uint32_t len, void *buf);
1705 
1726 static inline const void *rte_pktmbuf_read(const struct rte_mbuf *m,
1727  uint32_t off, uint32_t len, void *buf)
1728 {
1729  if (likely(off + len <= rte_pktmbuf_data_len(m)))
1730  return rte_pktmbuf_mtod_offset(m, char *, off);
1731  else
1732  return __rte_pktmbuf_read(m, off, len, buf);
1733 }
1734 
1751 static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail)
1752 {
1753  struct rte_mbuf *cur_tail;
1754 
1755  /* Check for number-of-segments-overflow */
1756  if (head->nb_segs + tail->nb_segs >= 1 << (sizeof(head->nb_segs) * 8))
1757  return -EOVERFLOW;
1758 
1759  /* Chain 'tail' onto the old tail */
1760  cur_tail = rte_pktmbuf_lastseg(head);
1761  cur_tail->next = tail;
1762 
1763  /* accumulate number of segments and total length. */
1764  head->nb_segs = (uint8_t)(head->nb_segs + tail->nb_segs);
1765  head->pkt_len += tail->pkt_len;
1766 
1767  /* pkt_len is only set in the head */
1768  tail->pkt_len = tail->data_len;
1769 
1770  return 0;
1771 }
1772 
1783 static inline int
1785 {
1786  uint64_t ol_flags = m->ol_flags;
1787  uint64_t inner_l3_offset = m->l2_len;
1788 
1789  /* Does packet set any of available offloads? */
1790  if (!(ol_flags & PKT_TX_OFFLOAD_MASK))
1791  return 0;
1792 
1793  if (ol_flags & PKT_TX_OUTER_IP_CKSUM)
1794  inner_l3_offset += m->outer_l2_len + m->outer_l3_len;
1795 
1796  /* Headers are fragmented */
1797  if (rte_pktmbuf_data_len(m) < inner_l3_offset + m->l3_len + m->l4_len)
1798  return -ENOTSUP;
1799 
1800  /* IP checksum can be counted only for IPv4 packet */
1801  if ((ol_flags & PKT_TX_IP_CKSUM) && (ol_flags & PKT_TX_IPV6))
1802  return -EINVAL;
1803 
1804  /* IP type not set when required */
1805  if (ol_flags & (PKT_TX_L4_MASK | PKT_TX_TCP_SEG))
1806  if (!(ol_flags & (PKT_TX_IPV4 | PKT_TX_IPV6)))
1807  return -EINVAL;
1808 
1809  /* Check requirements for TSO packet */
1810  if (ol_flags & PKT_TX_TCP_SEG)
1811  if ((m->tso_segsz == 0) ||
1812  ((ol_flags & PKT_TX_IPV4) &&
1813  !(ol_flags & PKT_TX_IP_CKSUM)))
1814  return -EINVAL;
1815 
1816  /* PKT_TX_OUTER_IP_CKSUM set for non outer IPv4 packet. */
1817  if ((ol_flags & PKT_TX_OUTER_IP_CKSUM) &&
1818  !(ol_flags & PKT_TX_OUTER_IPV4))
1819  return -EINVAL;
1820 
1821  return 0;
1822 }
1823 
1836 static inline int
1838 {
1839  int seg_len, copy_len;
1840  struct rte_mbuf *m;
1841  struct rte_mbuf *m_next;
1842  char *buffer;
1843 
1844  if (rte_pktmbuf_is_contiguous(mbuf))
1845  return 0;
1846 
1847  /* Extend first segment to the total packet length */
1848  copy_len = rte_pktmbuf_pkt_len(mbuf) - rte_pktmbuf_data_len(mbuf);
1849 
1850  if (unlikely(copy_len > rte_pktmbuf_tailroom(mbuf)))
1851  return -1;
1852 
1853  buffer = rte_pktmbuf_mtod_offset(mbuf, char *, mbuf->data_len);
1854  mbuf->data_len = (uint16_t)(mbuf->pkt_len);
1855 
1856  /* Append data from next segments to the first one */
1857  m = mbuf->next;
1858  while (m != NULL) {
1859  m_next = m->next;
1860 
1861  seg_len = rte_pktmbuf_data_len(m);
1862  rte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), seg_len);
1863  buffer += seg_len;
1864 
1866  m = m_next;
1867  }
1868 
1869  mbuf->next = NULL;
1870  mbuf->nb_segs = 1;
1871 
1872  return 0;
1873 }
1874 
1889 void rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len);
1890 
1891 #ifdef __cplusplus
1892 }
1893 #endif
1894 
1895 #endif /* _RTE_MBUF_H_ */