DPDK  17.02.1
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 
56 #include <stdint.h>
57 #include <rte_common.h>
58 #include <rte_mempool.h>
59 #include <rte_memory.h>
60 #include <rte_atomic.h>
61 #include <rte_prefetch.h>
62 #include <rte_branch_prediction.h>
63 #include <rte_mbuf_ptype.h>
64 
65 #ifdef __cplusplus
66 extern "C" {
67 #endif
68 
69 /*
70  * Packet Offload Features Flags. It also carry packet type information.
71  * Critical resources. Both rx/tx shared these bits. Be cautious on any change
72  *
73  * - RX flags start at bit position zero, and get added to the left of previous
74  * flags.
75  * - The most-significant 3 bits are reserved for generic mbuf flags
76  * - TX flags therefore start at bit position 60 (i.e. 63-3), and new flags get
77  * added to the right of the previously defined flags i.e. they should count
78  * downwards, not upwards.
79  *
80  * Keep these flags synchronized with rte_get_rx_ol_flag_name() and
81  * rte_get_tx_ol_flag_name().
82  */
83 
90 #define PKT_RX_VLAN_PKT (1ULL << 0)
91 
92 #define PKT_RX_RSS_HASH (1ULL << 1)
93 #define PKT_RX_FDIR (1ULL << 2)
102 #define PKT_RX_L4_CKSUM_BAD (1ULL << 3)
103 
111 #define PKT_RX_IP_CKSUM_BAD (1ULL << 4)
112 
113 #define PKT_RX_EIP_CKSUM_BAD (1ULL << 5)
120 #define PKT_RX_VLAN_STRIPPED (1ULL << 6)
121 
130 #define PKT_RX_IP_CKSUM_MASK ((1ULL << 4) | (1ULL << 7))
131 
132 #define PKT_RX_IP_CKSUM_UNKNOWN 0
133 #define PKT_RX_IP_CKSUM_BAD (1ULL << 4)
134 #define PKT_RX_IP_CKSUM_GOOD (1ULL << 7)
135 #define PKT_RX_IP_CKSUM_NONE ((1ULL << 4) | (1ULL << 7))
136 
145 #define PKT_RX_L4_CKSUM_MASK ((1ULL << 3) | (1ULL << 8))
146 
147 #define PKT_RX_L4_CKSUM_UNKNOWN 0
148 #define PKT_RX_L4_CKSUM_BAD (1ULL << 3)
149 #define PKT_RX_L4_CKSUM_GOOD (1ULL << 8)
150 #define PKT_RX_L4_CKSUM_NONE ((1ULL << 3) | (1ULL << 8))
151 
152 #define PKT_RX_IEEE1588_PTP (1ULL << 9)
153 #define PKT_RX_IEEE1588_TMST (1ULL << 10)
154 #define PKT_RX_FDIR_ID (1ULL << 13)
155 #define PKT_RX_FDIR_FLX (1ULL << 14)
164 #define PKT_RX_QINQ_STRIPPED (1ULL << 15)
165 
171 #define PKT_RX_QINQ_PKT PKT_RX_QINQ_STRIPPED
172 
178 #define PKT_RX_LRO (1ULL << 16)
179 
180 /* add new RX flags here */
181 
182 /* add new TX flags here */
183 
188 #define PKT_TX_MACSEC (1ULL << 44)
189 
195 #define PKT_TX_TUNNEL_VXLAN (0x1ULL << 45)
196 #define PKT_TX_TUNNEL_GRE (0x2ULL << 45)
197 #define PKT_TX_TUNNEL_IPIP (0x3ULL << 45)
198 #define PKT_TX_TUNNEL_GENEVE (0x4ULL << 45)
199 /* add new TX TUNNEL type here */
200 #define PKT_TX_TUNNEL_MASK (0xFULL << 45)
201 
205 #define PKT_TX_QINQ_PKT (1ULL << 49)
220 #define PKT_TX_TCP_SEG (1ULL << 50)
221 
222 #define PKT_TX_IEEE1588_TMST (1ULL << 51)
235 #define PKT_TX_L4_NO_CKSUM (0ULL << 52)
236 #define PKT_TX_TCP_CKSUM (1ULL << 52)
237 #define PKT_TX_SCTP_CKSUM (2ULL << 52)
238 #define PKT_TX_UDP_CKSUM (3ULL << 52)
239 #define PKT_TX_L4_MASK (3ULL << 52)
248 #define PKT_TX_IP_CKSUM (1ULL << 54)
249 
256 #define PKT_TX_IPV4 (1ULL << 55)
257 
264 #define PKT_TX_IPV6 (1ULL << 56)
265 
266 #define PKT_TX_VLAN_PKT (1ULL << 57)
276 #define PKT_TX_OUTER_IP_CKSUM (1ULL << 58)
277 
283 #define PKT_TX_OUTER_IPV4 (1ULL << 59)
284 
290 #define PKT_TX_OUTER_IPV6 (1ULL << 60)
291 
296 #define PKT_TX_OFFLOAD_MASK ( \
297  PKT_TX_IP_CKSUM | \
298  PKT_TX_L4_MASK | \
299  PKT_TX_OUTER_IP_CKSUM | \
300  PKT_TX_TCP_SEG | \
301  PKT_TX_IEEE1588_TMST | \
302  PKT_TX_QINQ_PKT | \
303  PKT_TX_VLAN_PKT | \
304  PKT_TX_TUNNEL_MASK | \
305  PKT_TX_MACSEC)
306 
307 #define __RESERVED (1ULL << 61)
309 #define IND_ATTACHED_MBUF (1ULL << 62)
311 /* Use final bit of flags to indicate a control mbuf */
312 #define CTRL_MBUF_FLAG (1ULL << 63)
315 #define RTE_MBUF_PRIV_ALIGN 8
316 
325 const char *rte_get_rx_ol_flag_name(uint64_t mask);
326 
339 int rte_get_rx_ol_flag_list(uint64_t mask, char *buf, size_t buflen);
340 
351 const char *rte_get_tx_ol_flag_name(uint64_t mask);
352 
365 int rte_get_tx_ol_flag_list(uint64_t mask, char *buf, size_t buflen);
366 
373 #define RTE_MBUF_DEFAULT_DATAROOM 2048
374 #define RTE_MBUF_DEFAULT_BUF_SIZE \
375  (RTE_MBUF_DEFAULT_DATAROOM + RTE_PKTMBUF_HEADROOM)
376 
377 /* define a set of marker types that can be used to refer to set points in the
378  * mbuf */
379 __extension__
380 typedef void *MARKER[0];
381 __extension__
382 typedef uint8_t MARKER8[0];
383 __extension__
384 typedef uint64_t MARKER64[0];
390 struct rte_mbuf {
391  MARKER cacheline0;
392 
393  void *buf_addr;
396  uint16_t buf_len;
398  /* next 6 bytes are initialised on RX descriptor rearm */
399  MARKER8 rearm_data;
400  uint16_t data_off;
401 
411  union {
413  uint16_t refcnt;
414  };
415  uint8_t nb_segs;
416  uint8_t port;
418  uint64_t ol_flags;
420  /* remaining bytes are set on RX when pulling packet from descriptor */
421  MARKER rx_descriptor_fields1;
422 
423  /*
424  * The packet type, which is the combination of outer/inner L2, L3, L4
425  * and tunnel types. The packet_type is about data really present in the
426  * mbuf. Example: if vlan stripping is enabled, a received vlan packet
427  * would have RTE_PTYPE_L2_ETHER and not RTE_PTYPE_L2_VLAN because the
428  * vlan is stripped from the data.
429  */
431  union {
432  uint32_t packet_type;
433  struct {
434  uint32_t l2_type:4;
435  uint32_t l3_type:4;
436  uint32_t l4_type:4;
437  uint32_t tun_type:4;
438  uint32_t inner_l2_type:4;
439  uint32_t inner_l3_type:4;
440  uint32_t inner_l4_type:4;
441  };
442  };
443 
444  uint32_t pkt_len;
445  uint16_t data_len;
447  uint16_t vlan_tci;
448 
449  union {
450  uint32_t rss;
451  struct {
453  union {
454  struct {
455  uint16_t hash;
456  uint16_t id;
457  };
458  uint32_t lo;
460  };
461  uint32_t hi;
464  } fdir;
465  struct {
466  uint32_t lo;
467  uint32_t hi;
468  } sched;
469  uint32_t usr;
470  } hash;
472  uint32_t seqn;
475  uint16_t vlan_tci_outer;
476 
477  /* second cache line - fields only used in slow path or on TX */
478  MARKER cacheline1 __rte_cache_min_aligned;
479 
481  union {
482  void *userdata;
483  uint64_t udata64;
484  };
485 
486  struct rte_mempool *pool;
487  struct rte_mbuf *next;
489  /* fields to support TX offloads */
491  union {
492  uint64_t tx_offload;
493  __extension__
494  struct {
495  uint64_t l2_len:7;
499  uint64_t l3_len:9;
500  uint64_t l4_len:8;
501  uint64_t tso_segsz:16;
503  /* fields for TX offloading of tunnels */
504  uint64_t outer_l3_len:9;
505  uint64_t outer_l2_len:7;
507  /* uint64_t unused:8; */
508  };
509  };
510 
513  uint16_t priv_size;
514 
516  uint16_t timesync;
518 
529 static inline void
531 {
532  rte_prefetch0(&m->cacheline0);
533 }
534 
546 static inline void
548 {
549 #if RTE_CACHE_LINE_SIZE == 64
550  rte_prefetch0(&m->cacheline1);
551 #else
552  RTE_SET_USED(m);
553 #endif
554 }
555 
556 
557 static inline uint16_t rte_pktmbuf_priv_size(struct rte_mempool *mp);
558 
567 static inline phys_addr_t
569 {
570  return mb->buf_physaddr + mb->data_off;
571 }
572 
585 static inline phys_addr_t
587 {
588  return mb->buf_physaddr + RTE_PKTMBUF_HEADROOM;
589 }
590 
599 static inline struct rte_mbuf *
601 {
602  return (struct rte_mbuf *)RTE_PTR_SUB(mi->buf_addr, sizeof(*mi) + mi->priv_size);
603 }
604 
613 static inline char *
615 {
616  char *buffer_addr;
617  buffer_addr = (char *)md + sizeof(*md) + rte_pktmbuf_priv_size(md->pool);
618  return buffer_addr;
619 }
620 
624 #define RTE_MBUF_INDIRECT(mb) ((mb)->ol_flags & IND_ATTACHED_MBUF)
625 
629 #define RTE_MBUF_DIRECT(mb) (!RTE_MBUF_INDIRECT(mb))
630 
639  uint16_t mbuf_priv_size;
640 };
641 
642 #ifdef RTE_LIBRTE_MBUF_DEBUG
643 
645 #define __rte_mbuf_sanity_check(m, is_h) rte_mbuf_sanity_check(m, is_h)
646 
647 #else /* RTE_LIBRTE_MBUF_DEBUG */
648 
650 #define __rte_mbuf_sanity_check(m, is_h) do { } while (0)
651 
652 #endif /* RTE_LIBRTE_MBUF_DEBUG */
653 
654 #ifdef RTE_MBUF_REFCNT_ATOMIC
655 
663 static inline uint16_t
664 rte_mbuf_refcnt_read(const struct rte_mbuf *m)
665 {
666  return (uint16_t)(rte_atomic16_read(&m->refcnt_atomic));
667 }
668 
676 static inline void
677 rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
678 {
679  rte_atomic16_set(&m->refcnt_atomic, new_value);
680 }
681 
691 static inline uint16_t
692 rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
693 {
694  /*
695  * The atomic_add is an expensive operation, so we don't want to
696  * call it in the case where we know we are the uniq holder of
697  * this mbuf (i.e. ref_cnt == 1). Otherwise, an atomic
698  * operation has to be used because concurrent accesses on the
699  * reference counter can occur.
700  */
701  if (likely(rte_mbuf_refcnt_read(m) == 1)) {
702  rte_mbuf_refcnt_set(m, 1 + value);
703  return 1 + value;
704  }
705 
706  return (uint16_t)(rte_atomic16_add_return(&m->refcnt_atomic, value));
707 }
708 
709 #else /* ! RTE_MBUF_REFCNT_ATOMIC */
710 
714 static inline uint16_t
715 rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
716 {
717  m->refcnt = (uint16_t)(m->refcnt + value);
718  return m->refcnt;
719 }
720 
724 static inline uint16_t
726 {
727  return m->refcnt;
728 }
729 
733 static inline void
734 rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
735 {
736  m->refcnt = new_value;
737 }
738 
739 #endif /* RTE_MBUF_REFCNT_ATOMIC */
740 
742 #define RTE_MBUF_PREFETCH_TO_FREE(m) do { \
743  if ((m) != NULL) \
744  rte_prefetch0(m); \
745 } while (0)
746 
747 
760 void
761 rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header);
762 
777 static inline struct rte_mbuf *rte_mbuf_raw_alloc(struct rte_mempool *mp)
778 {
779  struct rte_mbuf *m;
780  void *mb = NULL;
781 
782  if (rte_mempool_get(mp, &mb) < 0)
783  return NULL;
784  m = (struct rte_mbuf *)mb;
785  RTE_ASSERT(rte_mbuf_refcnt_read(m) == 0);
786  rte_mbuf_refcnt_set(m, 1);
788 
789  return m;
790 }
791 
800 static inline void __attribute__((always_inline))
801 __rte_mbuf_raw_free(struct rte_mbuf *m)
802 {
803  RTE_ASSERT(rte_mbuf_refcnt_read(m) == 0);
804  rte_mempool_put(m->pool, m);
805 }
806 
807 /* Operations on ctrl mbuf */
808 
828 void rte_ctrlmbuf_init(struct rte_mempool *mp, void *opaque_arg,
829  void *m, unsigned i);
830 
843 #define rte_ctrlmbuf_alloc(mp) rte_pktmbuf_alloc(mp)
844 
851 #define rte_ctrlmbuf_free(m) rte_pktmbuf_free(m)
852 
861 #define rte_ctrlmbuf_data(m) ((char *)((m)->buf_addr) + (m)->data_off)
862 
871 #define rte_ctrlmbuf_len(m) rte_pktmbuf_data_len(m)
872 
882 static inline int
884 {
885  return !!(m->ol_flags & CTRL_MBUF_FLAG);
886 }
887 
888 /* Operations on pkt mbuf */
889 
909 void rte_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg,
910  void *m, unsigned i);
911 
912 
929 void rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg);
930 
966 struct rte_mempool *
967 rte_pktmbuf_pool_create(const char *name, unsigned n,
968  unsigned cache_size, uint16_t priv_size, uint16_t data_room_size,
969  int socket_id);
970 
982 static inline uint16_t
984 {
985  struct rte_pktmbuf_pool_private *mbp_priv;
986 
987  mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
988  return mbp_priv->mbuf_data_room_size;
989 }
990 
1003 static inline uint16_t
1005 {
1006  struct rte_pktmbuf_pool_private *mbp_priv;
1007 
1008  mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
1009  return mbp_priv->mbuf_priv_size;
1010 }
1011 
1020 static inline void rte_pktmbuf_reset_headroom(struct rte_mbuf *m)
1021 {
1022  m->data_off = RTE_MIN(RTE_PKTMBUF_HEADROOM, (uint16_t)m->buf_len);
1023 }
1024 
1033 static inline void rte_pktmbuf_reset(struct rte_mbuf *m)
1034 {
1035  m->next = NULL;
1036  m->pkt_len = 0;
1037  m->tx_offload = 0;
1038  m->vlan_tci = 0;
1039  m->vlan_tci_outer = 0;
1040  m->nb_segs = 1;
1041  m->port = 0xff;
1042 
1043  m->ol_flags = 0;
1044  m->packet_type = 0;
1046 
1047  m->data_len = 0;
1049 }
1050 
1064 static inline struct rte_mbuf *rte_pktmbuf_alloc(struct rte_mempool *mp)
1065 {
1066  struct rte_mbuf *m;
1067  if ((m = rte_mbuf_raw_alloc(mp)) != NULL)
1068  rte_pktmbuf_reset(m);
1069  return m;
1070 }
1071 
1085 static inline int rte_pktmbuf_alloc_bulk(struct rte_mempool *pool,
1086  struct rte_mbuf **mbufs, unsigned count)
1087 {
1088  unsigned idx = 0;
1089  int rc;
1090 
1091  rc = rte_mempool_get_bulk(pool, (void **)mbufs, count);
1092  if (unlikely(rc))
1093  return rc;
1094 
1095  /* To understand duff's device on loop unwinding optimization, see
1096  * https://en.wikipedia.org/wiki/Duff's_device.
1097  * Here while() loop is used rather than do() while{} to avoid extra
1098  * check if count is zero.
1099  */
1100  switch (count % 4) {
1101  case 0:
1102  while (idx != count) {
1103  RTE_ASSERT(rte_mbuf_refcnt_read(mbufs[idx]) == 0);
1104  rte_mbuf_refcnt_set(mbufs[idx], 1);
1105  rte_pktmbuf_reset(mbufs[idx]);
1106  idx++;
1107  case 3:
1108  RTE_ASSERT(rte_mbuf_refcnt_read(mbufs[idx]) == 0);
1109  rte_mbuf_refcnt_set(mbufs[idx], 1);
1110  rte_pktmbuf_reset(mbufs[idx]);
1111  idx++;
1112  case 2:
1113  RTE_ASSERT(rte_mbuf_refcnt_read(mbufs[idx]) == 0);
1114  rte_mbuf_refcnt_set(mbufs[idx], 1);
1115  rte_pktmbuf_reset(mbufs[idx]);
1116  idx++;
1117  case 1:
1118  RTE_ASSERT(rte_mbuf_refcnt_read(mbufs[idx]) == 0);
1119  rte_mbuf_refcnt_set(mbufs[idx], 1);
1120  rte_pktmbuf_reset(mbufs[idx]);
1121  idx++;
1122  }
1123  }
1124  return 0;
1125 }
1126 
1144 static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *m)
1145 {
1146  struct rte_mbuf *md;
1147 
1148  RTE_ASSERT(RTE_MBUF_DIRECT(mi) &&
1149  rte_mbuf_refcnt_read(mi) == 1);
1150 
1151  /* if m is not direct, get the mbuf that embeds the data */
1152  if (RTE_MBUF_DIRECT(m))
1153  md = m;
1154  else
1155  md = rte_mbuf_from_indirect(m);
1156 
1157  rte_mbuf_refcnt_update(md, 1);
1158  mi->priv_size = m->priv_size;
1159  mi->buf_physaddr = m->buf_physaddr;
1160  mi->buf_addr = m->buf_addr;
1161  mi->buf_len = m->buf_len;
1162 
1163  mi->data_off = m->data_off;
1164  mi->data_len = m->data_len;
1165  mi->port = m->port;
1166  mi->vlan_tci = m->vlan_tci;
1167  mi->vlan_tci_outer = m->vlan_tci_outer;
1168  mi->tx_offload = m->tx_offload;
1169  mi->hash = m->hash;
1170 
1171  mi->next = NULL;
1172  mi->pkt_len = mi->data_len;
1173  mi->nb_segs = 1;
1174  mi->ol_flags = m->ol_flags | IND_ATTACHED_MBUF;
1175  mi->packet_type = m->packet_type;
1176 
1177  __rte_mbuf_sanity_check(mi, 1);
1179 }
1180 
1194 static inline void rte_pktmbuf_detach(struct rte_mbuf *m)
1195 {
1196  struct rte_mbuf *md = rte_mbuf_from_indirect(m);
1197  struct rte_mempool *mp = m->pool;
1198  uint32_t mbuf_size, buf_len, priv_size;
1199 
1200  priv_size = rte_pktmbuf_priv_size(mp);
1201  mbuf_size = sizeof(struct rte_mbuf) + priv_size;
1202  buf_len = rte_pktmbuf_data_room_size(mp);
1203 
1204  m->priv_size = priv_size;
1205  m->buf_addr = (char *)m + mbuf_size;
1206  m->buf_physaddr = rte_mempool_virt2phy(mp, m) + mbuf_size;
1207  m->buf_len = (uint16_t)buf_len;
1209  m->data_len = 0;
1210  m->ol_flags = 0;
1211 
1212  if (rte_mbuf_refcnt_update(md, -1) == 0)
1213  __rte_mbuf_raw_free(md);
1214 }
1215 
1216 static inline struct rte_mbuf* __attribute__((always_inline))
1217 __rte_pktmbuf_prefree_seg(struct rte_mbuf *m)
1218 {
1220 
1221  if (likely(rte_mbuf_refcnt_update(m, -1) == 0)) {
1222  /* if this is an indirect mbuf, it is detached. */
1223  if (RTE_MBUF_INDIRECT(m))
1224  rte_pktmbuf_detach(m);
1225  return m;
1226  }
1227  return NULL;
1228 }
1229 
1239 static inline void __attribute__((always_inline))
1241 {
1242  if (likely(NULL != (m = __rte_pktmbuf_prefree_seg(m)))) {
1243  m->next = NULL;
1244  __rte_mbuf_raw_free(m);
1245  }
1246 }
1247 
1257 static inline void rte_pktmbuf_free(struct rte_mbuf *m)
1258 {
1259  struct rte_mbuf *m_next;
1260 
1262 
1263  while (m != NULL) {
1264  m_next = m->next;
1266  m = m_next;
1267  }
1268 }
1269 
1287 static inline struct rte_mbuf *rte_pktmbuf_clone(struct rte_mbuf *md,
1288  struct rte_mempool *mp)
1289 {
1290  struct rte_mbuf *mc, *mi, **prev;
1291  uint32_t pktlen;
1292  uint8_t nseg;
1293 
1294  if (unlikely ((mc = rte_pktmbuf_alloc(mp)) == NULL))
1295  return NULL;
1296 
1297  mi = mc;
1298  prev = &mi->next;
1299  pktlen = md->pkt_len;
1300  nseg = 0;
1301 
1302  do {
1303  nseg++;
1304  rte_pktmbuf_attach(mi, md);
1305  *prev = mi;
1306  prev = &mi->next;
1307  } while ((md = md->next) != NULL &&
1308  (mi = rte_pktmbuf_alloc(mp)) != NULL);
1309 
1310  *prev = NULL;
1311  mc->nb_segs = nseg;
1312  mc->pkt_len = pktlen;
1313 
1314  /* Allocation of new indirect segment failed */
1315  if (unlikely (mi == NULL)) {
1316  rte_pktmbuf_free(mc);
1317  return NULL;
1318  }
1319 
1320  __rte_mbuf_sanity_check(mc, 1);
1321  return mc;
1322 }
1323 
1335 static inline void rte_pktmbuf_refcnt_update(struct rte_mbuf *m, int16_t v)
1336 {
1338 
1339  do {
1340  rte_mbuf_refcnt_update(m, v);
1341  } while ((m = m->next) != NULL);
1342 }
1343 
1352 static inline uint16_t rte_pktmbuf_headroom(const struct rte_mbuf *m)
1353 {
1355  return m->data_off;
1356 }
1357 
1366 static inline uint16_t rte_pktmbuf_tailroom(const struct rte_mbuf *m)
1367 {
1369  return (uint16_t)(m->buf_len - rte_pktmbuf_headroom(m) -
1370  m->data_len);
1371 }
1372 
1381 static inline struct rte_mbuf *rte_pktmbuf_lastseg(struct rte_mbuf *m)
1382 {
1383  struct rte_mbuf *m2 = (struct rte_mbuf *)m;
1384 
1386  while (m2->next != NULL)
1387  m2 = m2->next;
1388  return m2;
1389 }
1390 
1405 #define rte_pktmbuf_mtod_offset(m, t, o) \
1406  ((t)((char *)(m)->buf_addr + (m)->data_off + (o)))
1407 
1420 #define rte_pktmbuf_mtod(m, t) rte_pktmbuf_mtod_offset(m, t, 0)
1421 
1431 #define rte_pktmbuf_mtophys_offset(m, o) \
1432  (phys_addr_t)((m)->buf_physaddr + (m)->data_off + (o))
1433 
1441 #define rte_pktmbuf_mtophys(m) rte_pktmbuf_mtophys_offset(m, 0)
1442 
1451 #define rte_pktmbuf_pkt_len(m) ((m)->pkt_len)
1452 
1461 #define rte_pktmbuf_data_len(m) ((m)->data_len)
1462 
1478 static inline char *rte_pktmbuf_prepend(struct rte_mbuf *m,
1479  uint16_t len)
1480 {
1482 
1483  if (unlikely(len > rte_pktmbuf_headroom(m)))
1484  return NULL;
1485 
1486  m->data_off -= len;
1487  m->data_len = (uint16_t)(m->data_len + len);
1488  m->pkt_len = (m->pkt_len + len);
1489 
1490  return (char *)m->buf_addr + m->data_off;
1491 }
1492 
1508 static inline char *rte_pktmbuf_append(struct rte_mbuf *m, uint16_t len)
1509 {
1510  void *tail;
1511  struct rte_mbuf *m_last;
1512 
1514 
1515  m_last = rte_pktmbuf_lastseg(m);
1516  if (unlikely(len > rte_pktmbuf_tailroom(m_last)))
1517  return NULL;
1518 
1519  tail = (char *)m_last->buf_addr + m_last->data_off + m_last->data_len;
1520  m_last->data_len = (uint16_t)(m_last->data_len + len);
1521  m->pkt_len = (m->pkt_len + len);
1522  return (char*) tail;
1523 }
1524 
1539 static inline char *rte_pktmbuf_adj(struct rte_mbuf *m, uint16_t len)
1540 {
1542 
1543  if (unlikely(len > m->data_len))
1544  return NULL;
1545 
1546  m->data_len = (uint16_t)(m->data_len - len);
1547  m->data_off += len;
1548  m->pkt_len = (m->pkt_len - len);
1549  return (char *)m->buf_addr + m->data_off;
1550 }
1551 
1566 static inline int rte_pktmbuf_trim(struct rte_mbuf *m, uint16_t len)
1567 {
1568  struct rte_mbuf *m_last;
1569 
1571 
1572  m_last = rte_pktmbuf_lastseg(m);
1573  if (unlikely(len > m_last->data_len))
1574  return -1;
1575 
1576  m_last->data_len = (uint16_t)(m_last->data_len - len);
1577  m->pkt_len = (m->pkt_len - len);
1578  return 0;
1579 }
1580 
1590 static inline int rte_pktmbuf_is_contiguous(const struct rte_mbuf *m)
1591 {
1593  return !!(m->nb_segs == 1);
1594 }
1595 
1599 const void *__rte_pktmbuf_read(const struct rte_mbuf *m, uint32_t off,
1600  uint32_t len, void *buf);
1601 
1622 static inline const void *rte_pktmbuf_read(const struct rte_mbuf *m,
1623  uint32_t off, uint32_t len, void *buf)
1624 {
1625  if (likely(off + len <= rte_pktmbuf_data_len(m)))
1626  return rte_pktmbuf_mtod_offset(m, char *, off);
1627  else
1628  return __rte_pktmbuf_read(m, off, len, buf);
1629 }
1630 
1647 static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail)
1648 {
1649  struct rte_mbuf *cur_tail;
1650 
1651  /* Check for number-of-segments-overflow */
1652  if (head->nb_segs + tail->nb_segs >= 1 << (sizeof(head->nb_segs) * 8))
1653  return -EOVERFLOW;
1654 
1655  /* Chain 'tail' onto the old tail */
1656  cur_tail = rte_pktmbuf_lastseg(head);
1657  cur_tail->next = tail;
1658 
1659  /* accumulate number of segments and total length. */
1660  head->nb_segs = (uint8_t)(head->nb_segs + tail->nb_segs);
1661  head->pkt_len += tail->pkt_len;
1662 
1663  /* pkt_len is only set in the head */
1664  tail->pkt_len = tail->data_len;
1665 
1666  return 0;
1667 }
1668 
1679 static inline int
1681 {
1682  uint64_t ol_flags = m->ol_flags;
1683  uint64_t inner_l3_offset = m->l2_len;
1684 
1685  /* Does packet set any of available offloads? */
1686  if (!(ol_flags & PKT_TX_OFFLOAD_MASK))
1687  return 0;
1688 
1689  if (ol_flags & PKT_TX_OUTER_IP_CKSUM)
1690  inner_l3_offset += m->outer_l2_len + m->outer_l3_len;
1691 
1692  /* Headers are fragmented */
1693  if (rte_pktmbuf_data_len(m) < inner_l3_offset + m->l3_len + m->l4_len)
1694  return -ENOTSUP;
1695 
1696  /* IP checksum can be counted only for IPv4 packet */
1697  if ((ol_flags & PKT_TX_IP_CKSUM) && (ol_flags & PKT_TX_IPV6))
1698  return -EINVAL;
1699 
1700  /* IP type not set when required */
1701  if (ol_flags & (PKT_TX_L4_MASK | PKT_TX_TCP_SEG))
1702  if (!(ol_flags & (PKT_TX_IPV4 | PKT_TX_IPV6)))
1703  return -EINVAL;
1704 
1705  /* Check requirements for TSO packet */
1706  if (ol_flags & PKT_TX_TCP_SEG)
1707  if ((m->tso_segsz == 0) ||
1708  ((ol_flags & PKT_TX_IPV4) &&
1709  !(ol_flags & PKT_TX_IP_CKSUM)))
1710  return -EINVAL;
1711 
1712  /* PKT_TX_OUTER_IP_CKSUM set for non outer IPv4 packet. */
1713  if ((ol_flags & PKT_TX_OUTER_IP_CKSUM) &&
1714  !(ol_flags & PKT_TX_OUTER_IPV4))
1715  return -EINVAL;
1716 
1717  return 0;
1718 }
1719 
1732 static inline int
1734 {
1735  int seg_len, copy_len;
1736  struct rte_mbuf *m;
1737  struct rte_mbuf *m_next;
1738  char *buffer;
1739 
1740  if (rte_pktmbuf_is_contiguous(mbuf))
1741  return 0;
1742 
1743  /* Extend first segment to the total packet length */
1744  copy_len = rte_pktmbuf_pkt_len(mbuf) - rte_pktmbuf_data_len(mbuf);
1745 
1746  if (unlikely(copy_len > rte_pktmbuf_tailroom(mbuf)))
1747  return -1;
1748 
1749  buffer = rte_pktmbuf_mtod_offset(mbuf, char *, mbuf->data_len);
1750  mbuf->data_len = (uint16_t)(mbuf->pkt_len);
1751 
1752  /* Append data from next segments to the first one */
1753  m = mbuf->next;
1754  while (m != NULL) {
1755  m_next = m->next;
1756 
1757  seg_len = rte_pktmbuf_data_len(m);
1758  rte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), seg_len);
1759  buffer += seg_len;
1760 
1762  m = m_next;
1763  }
1764 
1765  mbuf->next = NULL;
1766  mbuf->nb_segs = 1;
1767 
1768  return 0;
1769 }
1770 
1785 void rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len);
1786 
1787 #ifdef __cplusplus
1788 }
1789 #endif
1790 
1791 #endif /* _RTE_MBUF_H_ */