mbuf: redefine packet type
[dpdk.git] / lib / librte_mbuf / rte_mbuf.h
index 17d39ae..dddad96 100644 (file)
@@ -54,6 +54,7 @@
  */
 
 #include <stdint.h>
+#include <rte_common.h>
 #include <rte_mempool.h>
 #include <rte_memory.h>
 #include <rte_atomic.h>
@@ -101,10 +102,16 @@ extern "C" {
 #define PKT_RX_TUNNEL_IPV6_HDR (1ULL << 12) /**< RX tunnel packet with IPv6 header. */
 #define PKT_RX_FDIR_ID       (1ULL << 13) /**< FD id reported if FDIR match. */
 #define PKT_RX_FDIR_FLX      (1ULL << 14) /**< Flexible bytes reported if FDIR match. */
+#define PKT_RX_QINQ_PKT      (1ULL << 15)  /**< RX packet with double VLAN stripped. */
 /* add new RX flags here */
 
 /* add new TX flags here */
 
+/**
+ * Second VLAN insertion (QinQ) flag.
+ */
+#define PKT_TX_QINQ_PKT    (1ULL << 49)   /**< TX packet with double VLAN inserted. */
+
 /**
  * TCP segmentation offload. To enable this offload feature for a
  * packet to be transmitted on hardware supporting TSO:
@@ -217,6 +224,16 @@ const char *rte_get_rx_ol_flag_name(uint64_t mask);
  */
 const char *rte_get_tx_ol_flag_name(uint64_t mask);
 
+/**
+ * Some NICs need at least 2KB buffer to RX standard Ethernet frame without
+ * splitting it into multiple segments.
+ * So, for mbufs that planned to be involved into RX/TX, the recommended
+ * minimal buffer length is 2KB + RTE_PKTMBUF_HEADROOM.
+ */
+#define        RTE_MBUF_DEFAULT_DATAROOM       2048
+#define        RTE_MBUF_DEFAULT_BUF_SIZE       \
+       (RTE_MBUF_DEFAULT_DATAROOM + RTE_PKTMBUF_HEADROOM)
+
 /* define a set of marker types that can be used to refer to set points in the
  * mbuf */
 typedef void    *MARKER[0];   /**< generic marker for a point in a structure */
@@ -259,6 +276,28 @@ struct rte_mbuf {
        /* remaining bytes are set on RX when pulling packet from descriptor */
        MARKER rx_descriptor_fields1;
 
+#ifdef RTE_NEXT_ABI
+       /*
+        * The packet type, which is the combination of outer/inner L2, L3, L4
+        * and tunnel types.
+        */
+       union {
+               uint32_t packet_type; /**< L2/L3/L4 and tunnel information. */
+               struct {
+                       uint32_t l2_type:4; /**< (Outer) L2 type. */
+                       uint32_t l3_type:4; /**< (Outer) L3 type. */
+                       uint32_t l4_type:4; /**< (Outer) L4 type. */
+                       uint32_t tun_type:4; /**< Tunnel type. */
+                       uint32_t inner_l2_type:4; /**< Inner L2 type. */
+                       uint32_t inner_l3_type:4; /**< Inner L3 type. */
+                       uint32_t inner_l4_type:4; /**< Inner L4 type. */
+               };
+       };
+
+       uint32_t pkt_len;         /**< Total pkt len: sum of all segments. */
+       uint16_t data_len;        /**< Amount of data in segment buffer. */
+       uint16_t vlan_tci;        /**< VLAN Tag Control Identifier (CPU order) */
+#else /* RTE_NEXT_ABI */
        /**
         * The packet type, which is used to indicate ordinary packet and also
         * tunneled packet format, i.e. each number is represented a type of
@@ -269,7 +308,8 @@ struct rte_mbuf {
        uint16_t data_len;        /**< Amount of data in segment buffer. */
        uint32_t pkt_len;         /**< Total pkt len: sum of all segments. */
        uint16_t vlan_tci;        /**< VLAN Tag Control Identifier (CPU order) */
-       uint16_t reserved;
+       uint16_t vlan_tci_outer;  /**< Outer VLAN Tag Control Identifier (CPU order) */
+#endif /* RTE_NEXT_ABI */
        union {
                uint32_t rss;     /**< RSS hash result if RSS enabled */
                struct {
@@ -290,6 +330,9 @@ struct rte_mbuf {
        } hash;                   /**< hash information */
 
        uint32_t seqn; /**< Sequence number. See also rte_reorder_insert() */
+#ifdef RTE_NEXT_ABI
+       uint16_t vlan_tci_outer;  /**< Outer VLAN Tag Control Identifier (CPU order) */
+#endif /* RTE_NEXT_ABI */
 
        /* second cache line - fields only used in slow path or on TX */
        MARKER cacheline1 __rte_cache_aligned;
@@ -322,6 +365,9 @@ struct rte_mbuf {
        /** Size of the application private data. In case of an indirect
         * mbuf, it stores the direct mbuf private data size. */
        uint16_t priv_size;
+
+       /** Timesync flags for use with IEEE1588. */
+       uint16_t timesync;
 } __rte_cache_aligned;
 
 static inline uint16_t rte_pktmbuf_priv_size(struct rte_mempool *mp);
@@ -337,13 +383,7 @@ static inline uint16_t rte_pktmbuf_priv_size(struct rte_mempool *mp);
 static inline struct rte_mbuf *
 rte_mbuf_from_indirect(struct rte_mbuf *mi)
 {
-       struct rte_mbuf *md;
-
-       /* mi->buf_addr and mi->priv_size correspond to buffer and
-        * private size of the direct mbuf */
-       md = (struct rte_mbuf *)((char *)mi->buf_addr - sizeof(*mi) -
-               mi->priv_size);
-       return md;
+       return RTE_PTR_SUB(mi->buf_addr, sizeof(*mi) + mi->priv_size);
 }
 
 /**
@@ -415,21 +455,6 @@ if (!(exp)) {                                                        \
 
 #ifdef RTE_MBUF_REFCNT_ATOMIC
 
-/**
- * Adds given value to an mbuf's refcnt and returns its new value.
- * @param m
- *   Mbuf to update
- * @param value
- *   Value to add/subtract
- * @return
- *   Updated value
- */
-static inline uint16_t
-rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
-{
-       return (uint16_t)(rte_atomic16_add_return(&m->refcnt_atomic, value));
-}
-
 /**
  * Reads the value of an mbuf's refcnt.
  * @param m
@@ -456,6 +481,33 @@ rte_mbuf_refcnt_set(struct rte_mbuf *m, uint16_t new_value)
        rte_atomic16_set(&m->refcnt_atomic, new_value);
 }
 
+/**
+ * Adds given value to an mbuf's refcnt and returns its new value.
+ * @param m
+ *   Mbuf to update
+ * @param value
+ *   Value to add/subtract
+ * @return
+ *   Updated value
+ */
+static inline uint16_t
+rte_mbuf_refcnt_update(struct rte_mbuf *m, int16_t value)
+{
+       /*
+        * The atomic_add is an expensive operation, so we don't want to
+        * call it in the case where we know we are the uniq holder of
+        * this mbuf (i.e. ref_cnt == 1). Otherwise, an atomic
+        * operation has to be used because concurrent accesses on the
+        * reference counter can occur.
+        */
+       if (likely(rte_mbuf_refcnt_read(m) == 1)) {
+               rte_mbuf_refcnt_set(m, 1 + value);
+               return 1 + value;
+       }
+
+       return (uint16_t)(rte_atomic16_add_return(&m->refcnt_atomic, value));
+}
+
 #else /* ! RTE_MBUF_REFCNT_ATOMIC */
 
 /**
@@ -530,7 +582,7 @@ static inline struct rte_mbuf *__rte_mbuf_raw_alloc(struct rte_mempool *mp)
        m = (struct rte_mbuf *)mb;
        RTE_MBUF_ASSERT(rte_mbuf_refcnt_read(m) == 0);
        rte_mbuf_refcnt_set(m, 1);
-       return (m);
+       return m;
 }
 
 /**
@@ -626,7 +678,7 @@ void rte_ctrlmbuf_init(struct rte_mempool *mp, void *opaque_arg,
 static inline int
 rte_is_ctrlmbuf(struct rte_mbuf *m)
 {
-       return (!!(m->ol_flags & CTRL_MBUF_FLAG));
+       return !!(m->ol_flags & CTRL_MBUF_FLAG);
 }
 
 /* Operations on pkt mbuf */
@@ -767,6 +819,7 @@ static inline void rte_pktmbuf_reset(struct rte_mbuf *m)
        m->pkt_len = 0;
        m->tx_offload = 0;
        m->vlan_tci = 0;
+       m->vlan_tci_outer = 0;
        m->nb_segs = 1;
        m->port = 0xff;
 
@@ -797,7 +850,7 @@ static inline struct rte_mbuf *rte_pktmbuf_alloc(struct rte_mempool *mp)
        struct rte_mbuf *m;
        if ((m = __rte_mbuf_raw_alloc(mp)) != NULL)
                rte_pktmbuf_reset(m);
-       return (m);
+       return m;
 }
 
 /**
@@ -806,44 +859,51 @@ static inline struct rte_mbuf *rte_pktmbuf_alloc(struct rte_mempool *mp)
  * After attachment we refer the mbuf we attached as 'indirect',
  * while mbuf we attached to as 'direct'.
  * Right now, not supported:
- *  - attachment to indirect mbuf (e.g. - md  has to be direct).
  *  - attachment for already indirect mbuf (e.g. - mi has to be direct).
  *  - mbuf we trying to attach (mi) is used by someone else
  *    e.g. it's reference counter is greater then 1.
  *
  * @param mi
  *   The indirect packet mbuf.
- * @param md
- *   The direct packet mbuf.
+ * @param m
+ *   The packet mbuf we're attaching to.
  */
-static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *md)
+static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *m)
 {
-       RTE_MBUF_ASSERT(RTE_MBUF_DIRECT(md) &&
-           RTE_MBUF_DIRECT(mi) &&
+       struct rte_mbuf *md;
+
+       RTE_MBUF_ASSERT(RTE_MBUF_DIRECT(mi) &&
            rte_mbuf_refcnt_read(mi) == 1);
 
+       /* if m is not direct, get the mbuf that embeds the data */
+       if (RTE_MBUF_DIRECT(m))
+               md = m;
+       else
+               md = rte_mbuf_from_indirect(m);
+
        rte_mbuf_refcnt_update(md, 1);
-       mi->buf_physaddr = md->buf_physaddr;
-       mi->buf_addr = md->buf_addr;
-       mi->buf_len = md->buf_len;
-       mi->priv_size = md->priv_size;
-
-       mi->next = md->next;
-       mi->data_off = md->data_off;
-       mi->data_len = md->data_len;
-       mi->port = md->port;
-       mi->vlan_tci = md->vlan_tci;
-       mi->tx_offload = md->tx_offload;
-       mi->hash = md->hash;
+       mi->priv_size = m->priv_size;
+       mi->buf_physaddr = m->buf_physaddr;
+       mi->buf_addr = m->buf_addr;
+       mi->buf_len = m->buf_len;
+
+       mi->next = m->next;
+       mi->data_off = m->data_off;
+       mi->data_len = m->data_len;
+       mi->port = m->port;
+       mi->vlan_tci = m->vlan_tci;
+       mi->vlan_tci_outer = m->vlan_tci_outer;
+       mi->tx_offload = m->tx_offload;
+       mi->hash = m->hash;
 
        mi->next = NULL;
        mi->pkt_len = mi->data_len;
        mi->nb_segs = 1;
-       mi->ol_flags = md->ol_flags | IND_ATTACHED_MBUF;
-       mi->packet_type = md->packet_type;
+       mi->ol_flags = m->ol_flags | IND_ATTACHED_MBUF;
+       mi->packet_type = m->packet_type;
 
        __rte_mbuf_sanity_check(mi, 1);
-       __rte_mbuf_sanity_check(md, 0);
+       __rte_mbuf_sanity_check(m, 0);
 }
 
 /**
@@ -879,20 +939,7 @@ __rte_pktmbuf_prefree_seg(struct rte_mbuf *m)
 {
        __rte_mbuf_sanity_check(m, 0);
 
-       /*
-        * Check to see if this is the last reference to the mbuf.
-        * Note: the double check here is deliberate. If the ref_cnt is "atomic"
-        * the call to "refcnt_update" is a very expensive operation, so we
-        * don't want to call it in the case where we know we are the holder
-        * of the last reference to this mbuf i.e. ref_cnt == 1.
-        * If however, ref_cnt != 1, it's still possible that we may still be
-        * the final decrementer of the count, so we need to check that
-        * result also, to make sure the mbuf is freed properly.
-        */
-       if (likely (rte_mbuf_refcnt_read(m) == 1) ||
-                       likely (rte_mbuf_refcnt_update(m, -1) == 0)) {
-
-               rte_mbuf_refcnt_set(m, 0);
+       if (likely(rte_mbuf_refcnt_update(m, -1) == 0)) {
 
                /* if this is an indirect mbuf, then
                 *  - detach mbuf
@@ -904,9 +951,9 @@ __rte_pktmbuf_prefree_seg(struct rte_mbuf *m)
                        if (rte_mbuf_refcnt_update(md, -1) == 0)
                                __rte_mbuf_raw_free(md);
                }
-               return(m);
+               return m;
        }
-       return (NULL);
+       return NULL;
 }
 
 /**
@@ -974,7 +1021,7 @@ static inline struct rte_mbuf *rte_pktmbuf_clone(struct rte_mbuf *md,
        uint8_t nseg;
 
        if (unlikely ((mc = rte_pktmbuf_alloc(mp)) == NULL))
-               return (NULL);
+               return NULL;
 
        mi = mc;
        prev = &mi->next;
@@ -996,11 +1043,11 @@ static inline struct rte_mbuf *rte_pktmbuf_clone(struct rte_mbuf *md,
        /* Allocation of new indirect segment failed */
        if (unlikely (mi == NULL)) {
                rte_pktmbuf_free(mc);
-               return (NULL);
+               return NULL;
        }
 
        __rte_mbuf_sanity_check(mc, 1);
-       return (mc);
+       return mc;
 }
 
 /**
@@ -1070,19 +1117,36 @@ static inline struct rte_mbuf *rte_pktmbuf_lastseg(struct rte_mbuf *m)
        return m2;
 }
 
+/**
+ * A macro that points to an offset into the data in the mbuf.
+ *
+ * The returned pointer is cast to type t. Before using this
+ * function, the user must ensure that the first segment is large
+ * enough to accommodate its data.
+ *
+ * @param m
+ *   The packet mbuf.
+ * @param o
+ *   The offset into the mbuf data.
+ * @param t
+ *   The type to cast the result into.
+ */
+#define rte_pktmbuf_mtod_offset(m, t, o)       \
+       ((t)((char *)(m)->buf_addr + (m)->data_off + (o)))
+
 /**
  * A macro that points to the start of the data in the mbuf.
  *
  * The returned pointer is cast to type t. Before using this
- * function, the user must ensure that m_headlen(m) is large enough to
- * read its data.
+ * function, the user must ensure that the first segment is large
+ * enough to accommodate its data.
  *
  * @param m
  *   The packet mbuf.
  * @param t
  *   The type to cast the result into.
  */
-#define rte_pktmbuf_mtod(m, t) ((t)((char *)(m)->buf_addr + (m)->data_off))
+#define rte_pktmbuf_mtod(m, t) rte_pktmbuf_mtod_offset(m, t, 0)
 
 /**
  * A macro that returns the length of the packet.