[dpdk-dev] [PATCH v2 1/6] mbuf: add buffer offset field for flexible indirection
Yongseok Koh
yskoh at mellanox.com
Mon Apr 2 20:50:03 CEST 2018
When attaching a mbuf, indirect mbuf has to point to start of buffer of
direct mbuf. By adding buf_off field to rte_mbuf, this becomes more
flexible. Indirect mbuf can point to any part of direct mbuf by calling
rte_pktmbuf_attach_at().
Possible use-cases could be:
- If a packet has multiple layers of encapsulation, multiple indirect
buffers can reference different layers of the encapsulated packet.
- A large direct mbuf can even contain multiple packets in series and
each packet can be referenced by multiple mbuf indirections.
Signed-off-by: Yongseok Koh <yskoh at mellanox.com>
---
lib/librte_mbuf/rte_mbuf.h | 158 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 157 insertions(+), 1 deletion(-)
diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
index 62740254d..053db32d0 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -559,6 +559,11 @@ struct rte_mbuf {
};
};
+ /** Buffer offset of direct mbuf if attached. Indirect mbuf can point to
+ * any part of direct mbuf.
+ */
+ uint16_t buf_off;
+
/** Size of the application private data. In case of an indirect
* mbuf, it stores the direct mbuf private data size. */
uint16_t priv_size;
@@ -671,7 +676,9 @@ rte_mbuf_data_dma_addr_default(const struct rte_mbuf *mb)
static inline struct rte_mbuf *
rte_mbuf_from_indirect(struct rte_mbuf *mi)
{
- return (struct rte_mbuf *)RTE_PTR_SUB(mi->buf_addr, sizeof(*mi) + mi->priv_size);
+ return (struct rte_mbuf *)
+ RTE_PTR_SUB(mi->buf_addr,
+ sizeof(*mi) + mi->priv_size + mi->buf_off);
}
/**
@@ -1281,6 +1288,98 @@ static inline int rte_pktmbuf_alloc_bulk(struct rte_mempool *pool,
}
/**
+ * Adjust tailroom of indirect mbuf. If offset is positive, enlarge the
+ * tailroom of the mbuf. If negative, shrink the tailroom.
+ *
+ * If length is out of range, then the function will fail and return -1,
+ * without modifying the indirect mbuf.
+ *
+ * @param mi
+ * The indirect packet mbuf.
+ * @param len
+ * The amount of length to adjust (in bytes).
+ * @return
+ * - 0: On success.
+ * - -1: On error.
+ */
+static inline int rte_pktmbuf_adj_indirect_tail(struct rte_mbuf *mi, int len)
+{
+ struct rte_mbuf *md;
+ uint16_t tailroom;
+ int delta;
+
+ RTE_ASSERT(RTE_MBUF_INDIRECT(mi));
+
+ md = rte_mbuf_from_indirect(mi);
+ if (unlikely(mi->buf_len + len <= 0 ||
+ mi->buf_off + mi->buf_len + len >= md->buf_len))
+ return -1;
+
+ mi->buf_len += len;
+
+ tailroom = mi->buf_len - mi->data_off - mi->data_len;
+ delta = tailroom + len;
+ if (delta > 0) {
+ /* Adjust tailroom */
+ delta = 0;
+ } else if (delta + mi->data_len < 0) {
+ /* No data */
+ mi->data_off += delta + mi->data_len;
+ delta = mi->data_len;
+ }
+ mi->data_len += delta;
+ mi->pkt_len += delta;
+ return 0;
+}
+
+/**
+ * Shift buffer reference of indirect mbuf. If offset is positive, push
+ * the offset of the mbuf. If negative, pull the offset.
+ *
+ * Returns a pointer to the start address of the new data area. If offset
+ * is out of range, then the function will fail and return NULL, without
+ * modifying the indirect mbuf.
+ *
+ * @param mi
+ * The indirect packet mbuf.
+ * @param off
+ * The amount of offset to adjust (in bytes).
+ * @return
+ * A pointer to the new start of the data.
+ */
+static inline char *rte_pktmbuf_adj_indirect_head(struct rte_mbuf *mi, int off)
+{
+ int delta;
+
+ RTE_ASSERT(RTE_MBUF_INDIRECT(mi));
+
+ if (unlikely(off >= mi->buf_len || mi->buf_off + off < 0))
+ return NULL;
+
+ mi->buf_iova += off;
+ mi->buf_addr = (char *)mi->buf_addr + off;
+ mi->buf_len -= off;
+ mi->buf_off += off;
+
+ delta = off - mi->data_off;
+ if (delta < 0) {
+ /* Adjust headroom */
+ mi->data_off -= off;
+ delta = 0;
+ } else if (delta < mi->data_len) {
+ /* No headroom */
+ mi->data_off = 0;
+ } else {
+ /* No data */
+ mi->data_off = 0;
+ delta = mi->data_len;
+ }
+ mi->data_len -= delta;
+ mi->pkt_len -= delta;
+ return (char *)mi->buf_addr + mi->data_off;
+}
+
+/**
* Attach packet mbuf to another packet mbuf.
*
* After attachment we refer the mbuf we attached as 'indirect',
@@ -1315,6 +1414,7 @@ static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *m)
mi->buf_iova = m->buf_iova;
mi->buf_addr = m->buf_addr;
mi->buf_len = m->buf_len;
+ mi->buf_off = 0;
mi->data_off = m->data_off;
mi->data_len = m->data_len;
@@ -1336,6 +1436,62 @@ static inline void rte_pktmbuf_attach(struct rte_mbuf *mi, struct rte_mbuf *m)
}
/**
+ * Attach packet mbuf to another packet mbuf pointing by given offset.
+ *
+ * After attachment we refer the mbuf we attached as 'indirect',
+ * while mbuf we attached to as 'direct'.
+ *
+ * The indirect mbuf can reference to anywhere in the buffer of the direct
+ * mbuf by the given offset. And the indirect mbuf is also be trimmed by
+ * the given buffer length.
+ *
+ * As a result, if a direct mbuf has multiple layers of encapsulation,
+ * multiple indirect buffers can reference different layers of the packet.
+ * Or, a large direct mbuf can even contain multiple packets in series and
+ * each packet can be referenced by multiple mbuf indirections.
+ *
+ * Returns a pointer to the start address of the new data area. If offset
+ * or buffer length is out of range, then the function will fail and return
+ * NULL, without attaching the mbuf.
+ *
+ * @param mi
+ * The indirect packet mbuf.
+ * @param m
+ * The packet mbuf we're attaching to.
+ * @param off
+ * The amount of offset to push (in bytes).
+ * @param buf_len
+ * The buffer length of the indirect mbuf (in bytes).
+ * @return
+ * A pointer to the new start of the data.
+ */
+static inline char *rte_pktmbuf_attach_at(struct rte_mbuf *mi,
+ struct rte_mbuf *m, uint16_t off, uint16_t buf_len)
+{
+ struct rte_mbuf *md;
+ char *ret;
+
+ if (RTE_MBUF_DIRECT(m))
+ md = m;
+ else
+ md = rte_mbuf_from_indirect(m);
+
+ if (off + buf_len > md->buf_len)
+ return NULL;
+
+ rte_pktmbuf_attach(mi, m);
+
+ /* Push reference of indirect mbuf */
+ ret = rte_pktmbuf_adj_indirect_head(mi, off);
+ RTE_ASSERT(ret != NULL);
+
+ /* Trim reference of indirect mbuf */
+ rte_pktmbuf_adj_indirect_tail(mi, off + buf_len - md->buf_len);
+
+ return ret;
+}
+
+/**
* Detach an indirect packet mbuf.
*
* - restore original mbuf address and length values.
--
2.11.0
More information about the dev
mailing list