DPDK  16.07.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 
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 
64 #ifdef __cplusplus
65 extern "C" {
66 #endif
67 
68 /*
69  * Packet Offload Features Flags. It also carry packet type information.
70  * Critical resources. Both rx/tx shared these bits. Be cautious on any change
71  *
72  * - RX flags start at bit position zero, and get added to the left of previous
73  * flags.
74  * - The most-significant 3 bits are reserved for generic mbuf flags
75  * - TX flags therefore start at bit position 60 (i.e. 63-3), and new flags get
76  * added to the right of the previously defined flags i.e. they should count
77  * downwards, not upwards.
78  *
79  * Keep these flags synchronized with rte_get_rx_ol_flag_name() and
80  * rte_get_tx_ol_flag_name().
81  */
82 
89 #define PKT_RX_VLAN_PKT (1ULL << 0)
90 
91 #define PKT_RX_RSS_HASH (1ULL << 1)
92 #define PKT_RX_FDIR (1ULL << 2)
93 #define PKT_RX_L4_CKSUM_BAD (1ULL << 3)
94 #define PKT_RX_IP_CKSUM_BAD (1ULL << 4)
95 #define PKT_RX_EIP_CKSUM_BAD (1ULL << 5)
102 #define PKT_RX_VLAN_STRIPPED (1ULL << 6)
103 
104 /* hole, some bits can be reused here */
105 
106 #define PKT_RX_IEEE1588_PTP (1ULL << 9)
107 #define PKT_RX_IEEE1588_TMST (1ULL << 10)
108 #define PKT_RX_FDIR_ID (1ULL << 13)
109 #define PKT_RX_FDIR_FLX (1ULL << 14)
118 #define PKT_RX_QINQ_STRIPPED (1ULL << 15)
119 
125 #define PKT_RX_QINQ_PKT PKT_RX_QINQ_STRIPPED
126 
127 /* add new RX flags here */
128 
129 /* add new TX flags here */
130 
134 #define PKT_TX_QINQ_PKT (1ULL << 49)
149 #define PKT_TX_TCP_SEG (1ULL << 50)
150 
151 #define PKT_TX_IEEE1588_TMST (1ULL << 51)
164 #define PKT_TX_L4_NO_CKSUM (0ULL << 52)
165 #define PKT_TX_TCP_CKSUM (1ULL << 52)
166 #define PKT_TX_SCTP_CKSUM (2ULL << 52)
167 #define PKT_TX_UDP_CKSUM (3ULL << 52)
168 #define PKT_TX_L4_MASK (3ULL << 52)
177 #define PKT_TX_IP_CKSUM (1ULL << 54)
178 
185 #define PKT_TX_IPV4 (1ULL << 55)
186 
193 #define PKT_TX_IPV6 (1ULL << 56)
194 
195 #define PKT_TX_VLAN_PKT (1ULL << 57)
205 #define PKT_TX_OUTER_IP_CKSUM (1ULL << 58)
206 
212 #define PKT_TX_OUTER_IPV4 (1ULL << 59)
213 
219 #define PKT_TX_OUTER_IPV6 (1ULL << 60)
220 
221 #define __RESERVED (1ULL << 61)
223 #define IND_ATTACHED_MBUF (1ULL << 62)
225 /* Use final bit of flags to indicate a control mbuf */
226 #define CTRL_MBUF_FLAG (1ULL << 63)
228 /*
229  * 32 bits are divided into several fields to mark packet types. Note that
230  * each field is indexical.
231  * - Bit 3:0 is for L2 types.
232  * - Bit 7:4 is for L3 or outer L3 (for tunneling case) types.
233  * - Bit 11:8 is for L4 or outer L4 (for tunneling case) types.
234  * - Bit 15:12 is for tunnel types.
235  * - Bit 19:16 is for inner L2 types.
236  * - Bit 23:20 is for inner L3 types.
237  * - Bit 27:24 is for inner L4 types.
238  * - Bit 31:28 is reserved.
239  *
240  * To be compatible with Vector PMD, RTE_PTYPE_L3_IPV4, RTE_PTYPE_L3_IPV4_EXT,
241  * RTE_PTYPE_L3_IPV6, RTE_PTYPE_L3_IPV6_EXT, RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP
242  * and RTE_PTYPE_L4_SCTP should be kept as below in a contiguous 7 bits.
243  *
244  * Note that L3 types values are selected for checking IPV4/IPV6 header from
245  * performance point of view. Reading annotations of RTE_ETH_IS_IPV4_HDR and
246  * RTE_ETH_IS_IPV6_HDR is needed for any future changes of L3 type values.
247  *
248  * Note that the packet types of the same packet recognized by different
249  * hardware may be different, as different hardware may have different
250  * capability of packet type recognition.
251  *
252  * examples:
253  * <'ether type'=0x0800
254  * | 'version'=4, 'protocol'=0x29
255  * | 'version'=6, 'next header'=0x3A
256  * | 'ICMPv6 header'>
257  * will be recognized on i40e hardware as packet type combination of,
258  * RTE_PTYPE_L2_ETHER |
259  * RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
260  * RTE_PTYPE_TUNNEL_IP |
261  * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
262  * RTE_PTYPE_INNER_L4_ICMP.
263  *
264  * <'ether type'=0x86DD
265  * | 'version'=6, 'next header'=0x2F
266  * | 'GRE header'
267  * | 'version'=6, 'next header'=0x11
268  * | 'UDP header'>
269  * will be recognized on i40e hardware as packet type combination of,
270  * RTE_PTYPE_L2_ETHER |
271  * RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
272  * RTE_PTYPE_TUNNEL_GRENAT |
273  * RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN |
274  * RTE_PTYPE_INNER_L4_UDP.
275  */
276 #define RTE_PTYPE_UNKNOWN 0x00000000
277 
284 #define RTE_PTYPE_L2_ETHER 0x00000001
285 
291 #define RTE_PTYPE_L2_ETHER_TIMESYNC 0x00000002
292 
298 #define RTE_PTYPE_L2_ETHER_ARP 0x00000003
299 
305 #define RTE_PTYPE_L2_ETHER_LLDP 0x00000004
306 
312 #define RTE_PTYPE_L2_ETHER_NSH 0x00000005
313 
317 #define RTE_PTYPE_L2_MASK 0x0000000f
318 
327 #define RTE_PTYPE_L3_IPV4 0x00000010
328 
337 #define RTE_PTYPE_L3_IPV4_EXT 0x00000030
338 
347 #define RTE_PTYPE_L3_IPV6 0x00000040
348 
357 #define RTE_PTYPE_L3_IPV4_EXT_UNKNOWN 0x00000090
358 
368 #define RTE_PTYPE_L3_IPV6_EXT 0x000000c0
369 
379 #define RTE_PTYPE_L3_IPV6_EXT_UNKNOWN 0x000000e0
380 
384 #define RTE_PTYPE_L3_MASK 0x000000f0
385 
396 #define RTE_PTYPE_L4_TCP 0x00000100
397 
408 #define RTE_PTYPE_L4_UDP 0x00000200
409 
425 #define RTE_PTYPE_L4_FRAG 0x00000300
426 
437 #define RTE_PTYPE_L4_SCTP 0x00000400
438 
449 #define RTE_PTYPE_L4_ICMP 0x00000500
450 
465 #define RTE_PTYPE_L4_NONFRAG 0x00000600
466 
470 #define RTE_PTYPE_L4_MASK 0x00000f00
471 
481 #define RTE_PTYPE_TUNNEL_IP 0x00001000
482 
492 #define RTE_PTYPE_TUNNEL_GRE 0x00002000
493 
505 #define RTE_PTYPE_TUNNEL_VXLAN 0x00003000
506 
519 #define RTE_PTYPE_TUNNEL_NVGRE 0x00004000
520 
532 #define RTE_PTYPE_TUNNEL_GENEVE 0x00005000
533 
539 #define RTE_PTYPE_TUNNEL_GRENAT 0x00006000
540 
543 #define RTE_PTYPE_TUNNEL_MASK 0x0000f000
544 
551 #define RTE_PTYPE_INNER_L2_ETHER 0x00010000
552 
558 #define RTE_PTYPE_INNER_L2_ETHER_VLAN 0x00020000
559 
562 #define RTE_PTYPE_INNER_L2_MASK 0x000f0000
563 
571 #define RTE_PTYPE_INNER_L3_IPV4 0x00100000
572 
580 #define RTE_PTYPE_INNER_L3_IPV4_EXT 0x00200000
581 
589 #define RTE_PTYPE_INNER_L3_IPV6 0x00300000
590 
598 #define RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN 0x00400000
599 
608 #define RTE_PTYPE_INNER_L3_IPV6_EXT 0x00500000
609 
619 #define RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN 0x00600000
620 
623 #define RTE_PTYPE_INNER_L3_MASK 0x00f00000
624 
635 #define RTE_PTYPE_INNER_L4_TCP 0x01000000
636 
647 #define RTE_PTYPE_INNER_L4_UDP 0x02000000
648 
659 #define RTE_PTYPE_INNER_L4_FRAG 0x03000000
660 
671 #define RTE_PTYPE_INNER_L4_SCTP 0x04000000
672 
683 #define RTE_PTYPE_INNER_L4_ICMP 0x05000000
684 
696 #define RTE_PTYPE_INNER_L4_NONFRAG 0x06000000
697 
700 #define RTE_PTYPE_INNER_L4_MASK 0x0f000000
701 
707 #define RTE_ETH_IS_IPV4_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV4)
708 
714 #define RTE_ETH_IS_IPV6_HDR(ptype) ((ptype) & RTE_PTYPE_L3_IPV6)
715 
716 /* Check if it is a tunneling packet */
717 #define RTE_ETH_IS_TUNNEL_PKT(ptype) ((ptype) & (RTE_PTYPE_TUNNEL_MASK | \
718  RTE_PTYPE_INNER_L2_MASK | \
719  RTE_PTYPE_INNER_L3_MASK | \
720  RTE_PTYPE_INNER_L4_MASK))
721 
723 #define RTE_MBUF_PRIV_ALIGN 8
724 
733 const char *rte_get_rx_ol_flag_name(uint64_t mask);
734 
745 const char *rte_get_tx_ol_flag_name(uint64_t mask);
746 
753 #define RTE_MBUF_DEFAULT_DATAROOM 2048
754 #define RTE_MBUF_DEFAULT_BUF_SIZE \
755  (RTE_MBUF_DEFAULT_DATAROOM + RTE_PKTMBUF_HEADROOM)
756 
757 /* define a set of marker types that can be used to refer to set points in the
758  * mbuf */
759 typedef void *MARKER[0];
760 typedef uint8_t MARKER8[0];
761 typedef uint64_t MARKER64[0];
767 struct rte_mbuf {
768  MARKER cacheline0;
769 
770  void *buf_addr;
773  uint16_t buf_len;
775  /* next 6 bytes are initialised on RX descriptor rearm */
776  MARKER8 rearm_data;
777  uint16_t data_off;
778 
787  union {
789  uint16_t refcnt;
790  };
791  uint8_t nb_segs;
792  uint8_t port;
794  uint64_t ol_flags;
796  /* remaining bytes are set on RX when pulling packet from descriptor */
797  MARKER rx_descriptor_fields1;
798 
799  /*
800  * The packet type, which is the combination of outer/inner L2, L3, L4
801  * and tunnel types. The packet_type is about data really present in the
802  * mbuf. Example: if vlan stripping is enabled, a received vlan packet
803  * would have RTE_PTYPE_L2_ETHER and not RTE_PTYPE_L2_VLAN because the
804  * vlan is stripped from the data.
805  */
806  union {
807  uint32_t packet_type;
808  struct {
809  uint32_t l2_type:4;
810  uint32_t l3_type:4;
811  uint32_t l4_type:4;
812  uint32_t tun_type:4;
813  uint32_t inner_l2_type:4;
814  uint32_t inner_l3_type:4;
815  uint32_t inner_l4_type:4;
816  };
817  };
818 
819  uint32_t pkt_len;
820  uint16_t data_len;
822  uint16_t vlan_tci;
823 
824  union {
825  uint32_t rss;
826  struct {
827  union {
828  struct {
829  uint16_t hash;
830  uint16_t id;
831  };
832  uint32_t lo;
834  };
835  uint32_t hi;
838  } fdir;
839  struct {
840  uint32_t lo;
841  uint32_t hi;
842  } sched;
843  uint32_t usr;
844  } hash;
846  uint32_t seqn;
849  uint16_t vlan_tci_outer;
850 
851  /* second cache line - fields only used in slow path or on TX */
852  MARKER cacheline1 __rte_cache_min_aligned;
853 
854  union {
855  void *userdata;
856  uint64_t udata64;
857  };
858 
859  struct rte_mempool *pool;
860  struct rte_mbuf *next;
862  /* fields to support TX offloads */
863  union {
864  uint64_t tx_offload;
865  struct {
866  uint64_t l2_len:7;
867  uint64_t l3_len:9;
868  uint64_t l4_len:8;
869  uint64_t tso_segsz:16;
871  /* fields for TX offloading of tunnels */
872  uint64_t outer_l3_len:9;
873  uint64_t outer_l2_len:7;
875  /* uint64_t unused:8; */
876  };
877  };
878 
881  uint16_t priv_size;
882 
884  uint16_t timesync;
886 
897 static inline void
899 {
900  rte_prefetch0(&m->cacheline0);
901 }
902 
914 static inline void
916 {
917 #if RTE_CACHE_LINE_SIZE == 64
918  rte_prefetch0(&m->cacheline1);
919 #else
920  RTE_SET_USED(m);
921 #endif
922 }
923 
924 
925 static inline uint16_t rte_pktmbuf_priv_size(struct rte_mempool *mp);
926 
935 static inline phys_addr_t
937 {
938  return mb->buf_physaddr + mb->data_off;
939 }
940 
953 static inline phys_addr_t
955 {
956  return mb->buf_physaddr + RTE_PKTMBUF_HEADROOM;
957 }
958 
967 static inline struct rte_mbuf *
969 {
970  return (struct rte_mbuf *)RTE_PTR_SUB(mi->buf_addr, sizeof(*mi) + mi->priv_size);
971 }
972 
981 static inline char *
983 {
984  char *buffer_addr;
985  buffer_addr = (char *)md + sizeof(*md) + rte_pktmbuf_priv_size(md->pool);
986  return buffer_addr;
987 }
988 
992 #define RTE_MBUF_INDIRECT(mb) ((mb)->ol_flags & IND_ATTACHED_MBUF)
993 
997 #define RTE_MBUF_DIRECT(mb) (!RTE_MBUF_INDIRECT(mb))
998 
1007  uint16_t mbuf_priv_size;
1008 };
1009 
1010 #ifdef RTE_LIBRTE_MBUF_DEBUG
1011 
1013 #define __rte_mbuf_sanity_check(m, is_h) rte_mbuf_sanity_check(m, is_h)
1014 
1015 #else /* RTE_LIBRTE_MBUF_DEBUG */
1016 
1018 #define __rte_mbuf_sanity_check(m, is_h) do { } while (0)
1019 
1020 #endif /* RTE_LIBRTE_MBUF_DEBUG */
1021 
1022 #ifdef RTE_MBUF_REFCNT_ATOMIC
1023 
1031 static inline uint16_t
1032 rte_mbuf_refcnt_read(const struct rte_mbuf *m)
1033 {
1034  return (uint16_t)(rte_atomic16_read(&m->refcnt_atomic));
1035 }
1036 
1044 static inline void
1045 rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
1046 {
1047  rte_atomic16_set(&m->refcnt_atomic, new_value);
1048 }
1049 
1059 static inline uint16_t
1060 rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
1061 {
1062  /*
1063  * The atomic_add is an expensive operation, so we don't want to
1064  * call it in the case where we know we are the uniq holder of
1065  * this mbuf (i.e. ref_cnt == 1). Otherwise, an atomic
1066  * operation has to be used because concurrent accesses on the
1067  * reference counter can occur.
1068  */
1069  if (likely(rte_mbuf_refcnt_read(m) == 1)) {
1070  rte_mbuf_refcnt_set(m, 1 + value);
1071  return 1 + value;
1072  }
1073 
1074  return (uint16_t)(rte_atomic16_add_return(&m->refcnt_atomic, value));
1075 }
1076 
1077 #else /* ! RTE_MBUF_REFCNT_ATOMIC */
1078 
1082 static inline uint16_t
1083 rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
1084 {
1085  m->refcnt = (uint16_t)(m->refcnt + value);
1086  return m->refcnt;
1087 }
1088 
1092 static inline uint16_t
1094 {
1095  return m->refcnt;
1096 }
1097 
1101 static inline void
1102 rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
1103 {
1104  m->refcnt = new_value;
1105 }
1106 
1107 #endif /* RTE_MBUF_REFCNT_ATOMIC */
1108 
1110 #define RTE_MBUF_PREFETCH_TO_FREE(m) do { \
1111  if ((m) != NULL) \
1112  rte_prefetch0(m); \
1113 } while (0)
1114 
1115 
1128 void
1129 rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header);
1130 
1145 static inline struct rte_mbuf *rte_mbuf_raw_alloc(struct rte_mempool *mp)
1146 {
1147  struct rte_mbuf *m;
1148  void *mb = NULL;
1149 
1150  if (rte_mempool_get(mp, &mb) < 0)
1151  return NULL;
1152  m = (struct rte_mbuf *)mb;
1153  RTE_ASSERT(rte_mbuf_refcnt_read(m) == 0);
1154  rte_mbuf_refcnt_set(m, 1);
1156 
1157  return m;
1158 }
1159 
1160 /* compat with older versions */
1161 __rte_deprecated static inline struct rte_mbuf *
1162 __rte_mbuf_raw_alloc(struct rte_mempool *mp)
1163 {
1164  return rte_mbuf_raw_alloc(mp);
1165 }
1166 
1175 static inline void __attribute__((always_inline))
1176 __rte_mbuf_raw_free(struct rte_mbuf *m)
1177 {
1178  RTE_ASSERT(rte_mbuf_refcnt_read(m) == 0);
1179  rte_mempool_put(m->pool, m);
1180 }
1181 
1182 /* Operations on ctrl mbuf */
1183 
1203 void rte_ctrlmbuf_init(struct rte_mempool *mp, void *opaque_arg,
1204  void *m, unsigned i);
1205 
1218 #define rte_ctrlmbuf_alloc(mp) rte_pktmbuf_alloc(mp)
1219 
1226 #define rte_ctrlmbuf_free(m) rte_pktmbuf_free(m)
1227 
1236 #define rte_ctrlmbuf_data(m) ((char *)((m)->buf_addr) + (m)->data_off)
1237 
1246 #define rte_ctrlmbuf_len(m) rte_pktmbuf_data_len(m)
1247 
1257 static inline int
1259 {
1260  return !!(m->ol_flags & CTRL_MBUF_FLAG);
1261 }
1262 
1263 /* Operations on pkt mbuf */
1264 
1284 void rte_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg,
1285  void *m, unsigned i);
1286 
1287 
1304 void rte_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg);
1305 
1341 struct rte_mempool *
1342 rte_pktmbuf_pool_create(const char *name, unsigned n,
1343  unsigned cache_size, uint16_t priv_size, uint16_t data_room_size,
1344  int socket_id);
1345 
1357 static inline uint16_t
1359 {
1360  struct rte_pktmbuf_pool_private *mbp_priv;
1361 
1362  mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
1363  return mbp_priv->mbuf_data_room_size;
1364 }
1365 
1378 static inline uint16_t
1380 {
1381  struct rte_pktmbuf_pool_private *mbp_priv;
1382 
1383  mbp_priv = (struct rte_pktmbuf_pool_private *)rte_mempool_get_priv(mp);
1384  return mbp_priv->mbuf_priv_size;
1385 }
1386 
1395 static inline void rte_pktmbuf_reset(struct rte_mbuf *m)
1396 {
1397  m->next = NULL;
1398  m->pkt_len = 0;
1399  m->tx_offload = 0;
1400  m->vlan_tci = 0;
1401  m->vlan_tci_outer = 0;
1402  m->nb_segs = 1;
1403  m->port = 0xff;
1404 
1405  m->ol_flags = 0;
1406  m->packet_type = 0;
1407  m->data_off = (RTE_PKTMBUF_HEADROOM <= m->buf_len) ?
1408  RTE_PKTMBUF_HEADROOM : m->buf_len;
1409 
1410  m->data_len = 0;
1412 }
1413 
1427 static inline struct rte_mbuf *rte_pktmbuf_alloc(struct rte_mempool *mp)
1428 {
1429  struct rte_mbuf *m;
1430  if ((m = rte_mbuf_raw_alloc(mp)) != NULL)
1431  rte_pktmbuf_reset(m);
1432  return m;
1433 }
1434 
1448 static inline int rte_pktmbuf_alloc_bulk(struct rte_mempool *pool,
1449  struct rte_mbuf **mbufs, unsigned count)
1450 {
1451  unsigned idx = 0;
1452  int rc;
1453 
1454  rc = rte_mempool_get_bulk(pool, (void **)mbufs, count);
1455  if (unlikely(rc))
1456  return rc;
1457 
1458  /* To understand duff's device on loop unwinding optimization, see
1459  * https://en.wikipedia.org/wiki/Duff's_device.
1460  * Here while() loop is used rather than do() while{} to avoid extra
1461  * check if count is zero.
1462  */
1463  switch (count % 4) {
1464  case 0:
1465  while (idx != count) {
1466  RTE_ASSERT(rte_mbuf_refcnt_read(mbufs[idx]) == 0);
1467  rte_mbuf_refcnt_set(mbufs[idx], 1);
1468  rte_pktmbuf_reset(mbufs[idx]);
1469  idx++;
1470  case 3:
1471  RTE_ASSERT(rte_mbuf_refcnt_read(mbufs[idx]) == 0);
1472  rte_mbuf_refcnt_set(mbufs[idx], 1);
1473  rte_pktmbuf_reset(mbufs[idx]);
1474  idx++;
1475  case 2:
1476  RTE_ASSERT(rte_mbuf_refcnt_read(mbufs[idx]) == 0);
1477  rte_mbuf_refcnt_set(mbufs[idx], 1);
1478  rte_pktmbuf_reset(mbufs[idx]);
1479  idx++;
1480  case 1:
1481  RTE_ASSERT(rte_mbuf_refcnt_read(mbufs[idx]) == 0);
1482  rte_mbuf_refcnt_set(mbufs[idx], 1);
1483  rte_pktmbuf_reset(mbufs[idx]);
1484  idx++;
1485  }
1486  }
1487  return 0;
1488 }
1489 
1507 static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *m)
1508 {
1509  struct rte_mbuf *md;
1510 
1511  RTE_ASSERT(RTE_MBUF_DIRECT(mi) &&
1512  rte_mbuf_refcnt_read(mi) == 1);
1513 
1514  /* if m is not direct, get the mbuf that embeds the data */
1515  if (RTE_MBUF_DIRECT(m))
1516  md = m;
1517  else
1518  md = rte_mbuf_from_indirect(m);
1519 
1520  rte_mbuf_refcnt_update(md, 1);
1521  mi->priv_size = m->priv_size;
1522  mi->buf_physaddr = m->buf_physaddr;
1523  mi->buf_addr = m->buf_addr;
1524  mi->buf_len = m->buf_len;
1525 
1526  mi->next = m->next;
1527  mi->data_off = m->data_off;
1528  mi->data_len = m->data_len;
1529  mi->port = m->port;
1530  mi->vlan_tci = m->vlan_tci;
1531  mi->vlan_tci_outer = m->vlan_tci_outer;
1532  mi->tx_offload = m->tx_offload;
1533  mi->hash = m->hash;
1534 
1535  mi->next = NULL;
1536  mi->pkt_len = mi->data_len;
1537  mi->nb_segs = 1;
1538  mi->ol_flags = m->ol_flags | IND_ATTACHED_MBUF;
1539  mi->packet_type = m->packet_type;
1540 
1541  __rte_mbuf_sanity_check(mi, 1);
1543 }
1544 
1558 static inline void rte_pktmbuf_detach(struct rte_mbuf *m)
1559 {
1560  struct rte_mbuf *md = rte_mbuf_from_indirect(m);
1561  struct rte_mempool *mp = m->pool;
1562  uint32_t mbuf_size, buf_len, priv_size;
1563 
1564  priv_size = rte_pktmbuf_priv_size(mp);
1565  mbuf_size = sizeof(struct rte_mbuf) + priv_size;
1566  buf_len = rte_pktmbuf_data_room_size(mp);
1567 
1568  m->priv_size = priv_size;
1569  m->buf_addr = (char *)m + mbuf_size;
1570  m->buf_physaddr = rte_mempool_virt2phy(mp, m) + mbuf_size;
1571  m->buf_len = (uint16_t)buf_len;
1572  m->data_off = RTE_MIN(RTE_PKTMBUF_HEADROOM, (uint16_t)m->buf_len);
1573  m->data_len = 0;
1574  m->ol_flags = 0;
1575 
1576  if (rte_mbuf_refcnt_update(md, -1) == 0)
1577  __rte_mbuf_raw_free(md);
1578 }
1579 
1580 static inline struct rte_mbuf* __attribute__((always_inline))
1581 __rte_pktmbuf_prefree_seg(struct rte_mbuf *m)
1582 {
1584 
1585  if (likely(rte_mbuf_refcnt_update(m, -1) == 0)) {
1586  /* if this is an indirect mbuf, it is detached. */
1587  if (RTE_MBUF_INDIRECT(m))
1588  rte_pktmbuf_detach(m);
1589  return m;
1590  }
1591  return NULL;
1592 }
1593 
1603 static inline void __attribute__((always_inline))
1605 {
1606  if (likely(NULL != (m = __rte_pktmbuf_prefree_seg(m)))) {
1607  m->next = NULL;
1608  __rte_mbuf_raw_free(m);
1609  }
1610 }
1611 
1621 static inline void rte_pktmbuf_free(struct rte_mbuf *m)
1622 {
1623  struct rte_mbuf *m_next;
1624 
1626 
1627  while (m != NULL) {
1628  m_next = m->next;
1630  m = m_next;
1631  }
1632 }
1633 
1651 static inline struct rte_mbuf *rte_pktmbuf_clone(struct rte_mbuf *md,
1652  struct rte_mempool *mp)
1653 {
1654  struct rte_mbuf *mc, *mi, **prev;
1655  uint32_t pktlen;
1656  uint8_t nseg;
1657 
1658  if (unlikely ((mc = rte_pktmbuf_alloc(mp)) == NULL))
1659  return NULL;
1660 
1661  mi = mc;
1662  prev = &mi->next;
1663  pktlen = md->pkt_len;
1664  nseg = 0;
1665 
1666  do {
1667  nseg++;
1668  rte_pktmbuf_attach(mi, md);
1669  *prev = mi;
1670  prev = &mi->next;
1671  } while ((md = md->next) != NULL &&
1672  (mi = rte_pktmbuf_alloc(mp)) != NULL);
1673 
1674  *prev = NULL;
1675  mc->nb_segs = nseg;
1676  mc->pkt_len = pktlen;
1677 
1678  /* Allocation of new indirect segment failed */
1679  if (unlikely (mi == NULL)) {
1680  rte_pktmbuf_free(mc);
1681  return NULL;
1682  }
1683 
1684  __rte_mbuf_sanity_check(mc, 1);
1685  return mc;
1686 }
1687 
1699 static inline void rte_pktmbuf_refcnt_update(struct rte_mbuf *m, int16_t v)
1700 {
1702 
1703  do {
1704  rte_mbuf_refcnt_update(m, v);
1705  } while ((m = m->next) != NULL);
1706 }
1707 
1716 static inline uint16_t rte_pktmbuf_headroom(const struct rte_mbuf *m)
1717 {
1719  return m->data_off;
1720 }
1721 
1730 static inline uint16_t rte_pktmbuf_tailroom(const struct rte_mbuf *m)
1731 {
1733  return (uint16_t)(m->buf_len - rte_pktmbuf_headroom(m) -
1734  m->data_len);
1735 }
1736 
1745 static inline struct rte_mbuf *rte_pktmbuf_lastseg(struct rte_mbuf *m)
1746 {
1747  struct rte_mbuf *m2 = (struct rte_mbuf *)m;
1748 
1750  while (m2->next != NULL)
1751  m2 = m2->next;
1752  return m2;
1753 }
1754 
1769 #define rte_pktmbuf_mtod_offset(m, t, o) \
1770  ((t)((char *)(m)->buf_addr + (m)->data_off + (o)))
1771 
1784 #define rte_pktmbuf_mtod(m, t) rte_pktmbuf_mtod_offset(m, t, 0)
1785 
1795 #define rte_pktmbuf_mtophys_offset(m, o) \
1796  (phys_addr_t)((m)->buf_physaddr + (m)->data_off + (o))
1797 
1805 #define rte_pktmbuf_mtophys(m) rte_pktmbuf_mtophys_offset(m, 0)
1806 
1815 #define rte_pktmbuf_pkt_len(m) ((m)->pkt_len)
1816 
1825 #define rte_pktmbuf_data_len(m) ((m)->data_len)
1826 
1842 static inline char *rte_pktmbuf_prepend(struct rte_mbuf *m,
1843  uint16_t len)
1844 {
1846 
1847  if (unlikely(len > rte_pktmbuf_headroom(m)))
1848  return NULL;
1849 
1850  m->data_off -= len;
1851  m->data_len = (uint16_t)(m->data_len + len);
1852  m->pkt_len = (m->pkt_len + len);
1853 
1854  return (char *)m->buf_addr + m->data_off;
1855 }
1856 
1872 static inline char *rte_pktmbuf_append(struct rte_mbuf *m, uint16_t len)
1873 {
1874  void *tail;
1875  struct rte_mbuf *m_last;
1876 
1878 
1879  m_last = rte_pktmbuf_lastseg(m);
1880  if (unlikely(len > rte_pktmbuf_tailroom(m_last)))
1881  return NULL;
1882 
1883  tail = (char *)m_last->buf_addr + m_last->data_off + m_last->data_len;
1884  m_last->data_len = (uint16_t)(m_last->data_len + len);
1885  m->pkt_len = (m->pkt_len + len);
1886  return (char*) tail;
1887 }
1888 
1903 static inline char *rte_pktmbuf_adj(struct rte_mbuf *m, uint16_t len)
1904 {
1906 
1907  if (unlikely(len > m->data_len))
1908  return NULL;
1909 
1910  m->data_len = (uint16_t)(m->data_len - len);
1911  m->data_off += len;
1912  m->pkt_len = (m->pkt_len - len);
1913  return (char *)m->buf_addr + m->data_off;
1914 }
1915 
1930 static inline int rte_pktmbuf_trim(struct rte_mbuf *m, uint16_t len)
1931 {
1932  struct rte_mbuf *m_last;
1933 
1935 
1936  m_last = rte_pktmbuf_lastseg(m);
1937  if (unlikely(len > m_last->data_len))
1938  return -1;
1939 
1940  m_last->data_len = (uint16_t)(m_last->data_len - len);
1941  m->pkt_len = (m->pkt_len - len);
1942  return 0;
1943 }
1944 
1954 static inline int rte_pktmbuf_is_contiguous(const struct rte_mbuf *m)
1955 {
1957  return !!(m->nb_segs == 1);
1958 }
1959 
1976 static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail)
1977 {
1978  struct rte_mbuf *cur_tail;
1979 
1980  /* Check for number-of-segments-overflow */
1981  if (head->nb_segs + tail->nb_segs >= 1 << (sizeof(head->nb_segs) * 8))
1982  return -EOVERFLOW;
1983 
1984  /* Chain 'tail' onto the old tail */
1985  cur_tail = rte_pktmbuf_lastseg(head);
1986  cur_tail->next = tail;
1987 
1988  /* accumulate number of segments and total length. */
1989  head->nb_segs = (uint8_t)(head->nb_segs + tail->nb_segs);
1990  head->pkt_len += tail->pkt_len;
1991 
1992  /* pkt_len is only set in the head */
1993  tail->pkt_len = tail->data_len;
1994 
1995  return 0;
1996 }
1997 
2012 void rte_pktmbuf_dump(FILE *f, const struct rte_mbuf *m, unsigned dump_len);
2013 
2014 #ifdef __cplusplus
2015 }
2016 #endif
2017 
2018 #endif /* _RTE_MBUF_H_ */